Commit 8dd3610a authored by untereiner's avatar untereiner
Browse files

subdivision generalisee de polyhedres (solides de platon + quelques uns)

parent 21488e7c
...@@ -45,13 +45,16 @@ template <typename PFP> ...@@ -45,13 +45,16 @@ template <typename PFP>
void subdivideEdge(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position) ; void subdivideEdge(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position) ;
template <typename PFP> template <typename PFP>
void subdivideFace(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position, SubdivideType sType = S_QUAD); void subdivideFace(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position);
template <typename PFP> template <typename PFP>
Dart subdivideVolume(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position); Dart subdivideVolume(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position);
template <typename PFP> template <typename PFP>
void subdivideLoop(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position); Dart subdivideVolumeGen(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position);
//template <typename PFP>
//void subdivideLoop(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position);
template <typename PFP> template <typename PFP>
void coarsenEdge(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position); void coarsenEdge(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position);
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "Algo/Geometry/centroid.h" #include "Algo/Geometry/centroid.h"
#include "Algo/Modelisation/subdivision.h" #include "Algo/Modelisation/subdivision.h"
#include "Algo/Modelisation/extrusion.h"
namespace CGoGN namespace CGoGN
{ {
...@@ -66,7 +67,7 @@ void subdivideEdge(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position ...@@ -66,7 +67,7 @@ void subdivideEdge(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position
} }
template <typename PFP> template <typename PFP>
void subdivideFace(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position, SubdivideType sType) void subdivideFace(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position)
{ {
assert(map.getDartLevel(d) <= map.getCurrentLevel() || !"Access to a dart introduced after current level") ; assert(map.getDartLevel(d) <= map.getCurrentLevel() || !"Access to a dart introduced after current level") ;
assert(!map.faceIsSubdivided(d) || !"Trying to subdivide an already subdivided face") ; assert(!map.faceIsSubdivided(d) || !"Trying to subdivide an already subdivided face") ;
...@@ -94,7 +95,7 @@ void subdivideFace(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position ...@@ -94,7 +95,7 @@ void subdivideFace(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position
Dart res; Dart res;
if(degree == 3 && sType == S_TRI) //subdiviser une face triangulaire if(degree == 3) //subdiviser une face triangulaire
{ {
Dart dd = map.phi1(old) ; Dart dd = map.phi1(old) ;
Dart e = map.phi1(map.phi1(dd)) ; Dart e = map.phi1(map.phi1(dd)) ;
...@@ -167,8 +168,11 @@ void subdivideFace(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position ...@@ -167,8 +168,11 @@ void subdivideFace(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position
map.setCurrentLevel(cur) ; map.setCurrentLevel(cur) ;
} }
template <typename PFP> template <typename PFP>
Dart subdivideVolume(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position) Dart subdivideVolumeGen(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position)
{ {
assert(map.getDartLevel(d) <= map.getCurrentLevel() || !"Access to a dart introduced after current level") ; assert(map.getDartLevel(d) <= map.getCurrentLevel() || !"Access to a dart introduced after current level") ;
assert(!map.volumeIsSubdivided(d) || !"Trying to subdivide an already subdivided volume") ; assert(!map.volumeIsSubdivided(d) || !"Trying to subdivide an already subdivided volume") ;
...@@ -179,7 +183,6 @@ Dart subdivideVolume(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& positi ...@@ -179,7 +183,6 @@ Dart subdivideVolume(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& positi
unsigned int cur = map.getCurrentLevel(); unsigned int cur = map.getCurrentLevel();
map.setCurrentLevel(vLevel); map.setCurrentLevel(vLevel);
/* /*
* au niveau du volume courant i * au niveau du volume courant i
* stockage d'un brin de chaque face de celui-ci * stockage d'un brin de chaque face de celui-ci
...@@ -235,10 +238,13 @@ Dart subdivideVolume(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& positi ...@@ -235,10 +238,13 @@ Dart subdivideVolume(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& positi
/* /*
* Subdivision * Subdivision
*/ */
//Store the darts from quadrangulated faces //Store the darts from quadrangulated faces
std::vector<std::pair<Dart,Dart> > subdividedfaces; std::vector<std::pair<Dart,Dart> > subdividedfacesQ;
subdividedfaces.reserve(25); subdividedfacesQ.reserve(25);
std::vector<std::pair<Dart,Dart> > subdividedfacesT;
subdividedfacesT.reserve(25);
//First step : subdivide edges and faces //First step : subdivide edges and faces
//creates a i+1 edge level and i+1 face level //creates a i+1 edge level and i+1 face level
...@@ -250,6 +256,7 @@ Dart subdivideVolume(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& positi ...@@ -250,6 +256,7 @@ Dart subdivideVolume(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& positi
if(!map.faceIsSubdivided(d)) if(!map.faceIsSubdivided(d))
Algo::IHM::subdivideFace<PFP>(map, d, position); Algo::IHM::subdivideFace<PFP>(map, d, position);
//save a dart from the subdivided face //save a dart from the subdivided face
unsigned int cur = map.getCurrentLevel() ; unsigned int cur = map.getCurrentLevel() ;
...@@ -257,14 +264,32 @@ Dart subdivideVolume(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& positi ...@@ -257,14 +264,32 @@ Dart subdivideVolume(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& positi
map.setCurrentLevel(fLevel) ; map.setCurrentLevel(fLevel) ;
//le brin est forcement du niveau cur
Dart cf = map.phi1(d); //test si la face est triangulaire ou non
Dart e = cf; if(map.phi1(map.phi1(map.phi1(d))) == d)
do {
std::cout << "trian" << std::endl;
Dart cf = map.phi2(map.phi1(d));
Dart e = cf;
do
{
subdividedfacesT.push_back(std::pair<Dart,Dart>(e,map.phi2(e)));
e = map.phi1(e);
}while (e != cf);
}
else
{ {
subdividedfaces.push_back(std::pair<Dart,Dart>(e,map.phi2(e))); std::cout << "quad" << std::endl;
e = map.phi2(map.phi1(e)); Dart cf = map.phi1(d);
}while (e != cf); Dart e = cf;
do
{
subdividedfacesQ.push_back(std::pair<Dart,Dart>(e,map.phi2(e)));
e = map.phi2(map.phi1(e));
}while (e != cf);
}
map.setCurrentLevel(cur); map.setCurrentLevel(cur);
} }
...@@ -277,17 +302,21 @@ Dart subdivideVolume(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& positi ...@@ -277,17 +302,21 @@ Dart subdivideVolume(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& positi
//Second step : deconnect each corner, close each hole, subdivide each new face into 3 //Second step : deconnect each corner, close each hole, subdivide each new face into 3
for (std::vector<Dart>::iterator edge = oldEdges.begin(); edge != oldEdges.end(); ++edge) for (std::vector<Dart>::iterator edge = oldEdges.begin(); edge != oldEdges.end(); ++edge)
{ {
//std::vector<Dart>::iterator edge = oldEdges.begin();
Dart e = *edge; Dart e = *edge;
Dart f1 = map.phi1(*edge); Dart f1 = map.phi1(*edge);
Dart f2 = map.phi2(f1);
do do
{ {
map.unsewFaces(map.phi1(map.phi1(e))); if(map.phi1(map.phi1(map.phi1(e))) != e)
{
map.unsewFaces(map.phi1(map.phi1(e))); //remplacer par une boucle qui découd toute la face et non juste une face carre (jusqu'a phi_1(e))
}
map.unsewFaces(map.phi1(e));
//TODO utile ?
//if(map.phi2(map.phi1(e)) != map.phi1(e))
map.unsewFaces(map.phi1(e));
e = map.phi2(map.phi_1(e)); e = map.phi2(map.phi_1(e));
} }
...@@ -295,89 +324,339 @@ Dart subdivideVolume(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& positi ...@@ -295,89 +324,339 @@ Dart subdivideVolume(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& positi
map.closeHole(f1); map.closeHole(f1);
Dart old = map.phi2(map.phi1(e)); //degree du sommet exterieur
Dart dd = map.phi1(map.phi1(old)) ; unsigned int cornerDegree = map.Map2::vertexDegree(*edge);
map.splitFace(old,dd) ;
Dart ne = map.phi1(map.phi1(old)) ; //tourner autour du sommet pour connaitre le brin d'un sommet de valence < cornerDegree
bool found = false;
Dart stop = e;
do
{
map.cutEdge(ne); if(map.Map2::vertexDegree(map.phi2(map.phi1(e))) < cornerDegree)
position[map.phi1(ne)] = volCenter; //plonger a la fin de la boucle ???? {
newEdges.push_back(ne); stop = map.phi2(map.phi1(e));
newEdges.push_back(map.phi1(ne)); found = true;
}
e = map.phi2(map.phi_1(e));
}
while(!found && e != *edge);
Dart stop = map.phi2(map.phi1(ne)); //si il existe un sommet de degre inferieur au degree du coin
ne = map.phi2(ne); if(found)
do
{ {
dd = map.phi1(map.phi1(map.phi1(ne))); //chercher le brin de faible degree suivant
bool found2 = false;
Dart dd = map.phi1(stop);
do
{
if(map.Map2::vertexDegree(dd) < cornerDegree)
found2 = true;
else
dd = map.phi1(dd);
}
while(!found2);
//cas de la pyramide
if(dd == stop)
{
std::cout << "pyramide" << std::endl;
map.splitFace(dd, map.phi1(map.phi1(dd)));
//tester si besoin de fermer f2 (par exemple pas besoin pour hexa... mais pour tet, octa, prisme oui)
//map.closeHole(f2);
//retenir un truc pour le sew/unsew final de l'octa au milieu
}
else
{
map.splitFace(dd, stop);
//calcul de la taille des faces de chaque cote de stop
if(!( (map.Map2::faceDegree(map.phi_1(stop)) == 3 && map.Map2::faceDegree(map.phi2(map.phi_1(stop))) == 4) ||
(map.Map2::faceDegree(map.phi_1(stop)) == 4 && map.Map2::faceDegree(map.phi2(map.phi_1(stop))) == 3) ))
{
std::cout << "octaedre ou hexaedre" << std::endl;
Dart ne = map.phi_1(stop) ;
map.cutEdge(ne);
position[map.phi1(ne)] = volCenter;
stop = map.phi2(map.phi1(ne));
bool finished = false;
Dart it = map.phi2(ne);
do
{
//chercher le brin de faible degree suivant
bool found2 = false;
Dart dd = map.phi1(it);
do
{
if(dd == stop)
finished = true;
else if(map.Map2::vertexDegree(dd) < cornerDegree)
found2 = true;
else
dd = map.phi1(dd);
}
while(!found2 & !finished);
if(found2)
{
map.splitFace(it,dd);
}
it = map.phi_1(dd);
if(it == stop)
finished = true;
}
while(!finished);
//A Verifier !! }
map.splitFace(ne, dd) ; else
{
std::cout << "prisme" << std::endl;
//tester si besoin de fermer f2 (par exemple pas besoin pour hexa... mais pour tet, octa, prisme oui)
//map.closeHole(f2);
}
newEdges.push_back(map.phi1(dd)); }
ne = map.phi2(map.phi_1(ne));
dd = map.phi1(map.phi1(dd));
} }
while(dd != stop); //sinon cas du tetraedre
else
{
std::cout << "tetraedre" << std::endl;
//tester si besoin de fermer f2 (par exemple pas besoin pour hexa... mais pour tet, octa, prisme oui)
//map.closeHole(f2);
}
} }
//Third step : 3-sew internal faces std::cout << "1ere etape finished" << std::endl;
for (std::vector<std::pair<Dart,Dart> >::iterator it = subdividedfaces.begin(); it != subdividedfaces.end(); ++it)
CellMarker mtf(map, FACE);
//Etape 2
for (std::vector<std::pair<Dart,Dart> >::iterator edges = subdividedfacesT.begin(); edges != subdividedfacesT.end(); ++edges)
{ {
Dart f1 = (*it).first; Dart f1 = (*edges).first;
Dart f2 = (*it).second; Dart f2 = (*edges).second;
if(map.phi3(map.phi2(f1)) == map.phi2(f1) && map.phi3(map.phi2(f2)) == map.phi2(f2)) //Fonction isTetrahedron ??
// //if(Algo::Modelisation::Tetrahedron::isTetrahedron<PFP>(map,f2))
if( (map.Map2::faceDegree(f2) == 3 && map.Map2::faceDegree(map.phi2(f2)) == 3 &&
map.Map2::faceDegree(map.phi2(map.phi_1(f2))) == 3) && map.Map2::vertexDegree(f2) == 3)
{
std::cout << "ajout d'une face" << std::endl;
if(map.phi3(map.phi2(f2)) == map.phi2(f2))
{
Dart nf = map.newFace(3);
map.sewVolumes(map.phi2(f2),nf);
}
if(map.phi2(map.phi3(map.phi2(f2))) == map.phi3(map.phi2(f2)))
{
map.sewFaces(map.phi3(map.phi2(f2)), f1);
}
}
else
{
if(!mtf.isMarked(f1))
{
mtf.mark(f1);
map.closeHole(f1);
if(map.Map2::faceDegree(map.phi2(f2)) == 3)
{
std::cout << "ajout d'un tetraedre" << std::endl;
Dart x = Algo::Modelisation::trianguleFace<PFP>(map, map.phi2(f1));
position[x] = volCenter;
}
else
{
std::cout << "ajout d'un prisme" << std::endl;
//Dart x = Algo::Modelisation::extrudeFace<PFP>(map,position,map.phi2(f1),5.0);
Dart c = Algo::Modelisation::trianguleFace<PFP>(map, map.phi2(f1));
Dart cc = c;
// cut edges
do
{
typename PFP::VEC3 p1 = position[cc] ;
typename PFP::VEC3 p2 = position[map.phi1(cc)] ;
map.cutEdge(cc);
position[map.phi1(cc)] = (p1 + p2) * typename PFP::REAL(0.5) ;
cc = map.phi2(map.phi_1(cc));
}while (cc != c);
// cut faces
do
{
Dart d1 = map.phi1(cc);
Dart d2 = map.phi_1(cc);
map.splitFace(d1,d2);
cc = map.phi2(map.phi_1(cc));//map.Map2::alpha1(cc);
}while (cc != c);
//merge central faces by removing edges
bool notFinished=true;
do
{
Dart d1 = map.Map2::alpha1(cc);
if (d1 == cc) // last edge is pending edge inside of face
notFinished = false;
map.deleteFace(cc);
cc = d1;
} while (notFinished);
map.closeHole(map.phi1(map.phi1(map.phi2(f1))));
}
}
}
}
std::cout << "2e etape finished" << std::endl;
{
//Third step : 3-sew internal faces
for (std::vector<std::pair<Dart,Dart> >::iterator it = subdividedfacesT.begin(); it != subdividedfacesT.end(); ++it)
{ {
Dart f1 = (*it).first;
Dart f2 = (*it).second;
if(map.phi3(map.phi2(f1)) == map.phi2(f1) && map.phi3(map.phi2(f2)) == map.phi2(f2))
{
//id pour toutes les faces interieures //id pour toutes les faces interieures
map.sewVolumes(map.phi2(f1), map.phi2(f2)); map.sewVolumes(map.phi2(f2), map.phi2(f1));
//Fais a la couture !!!!! //Fais a la couture !!!!!
unsigned int idface = map.getNewFaceId(); unsigned int idface = map.getNewFaceId();
map.setFaceId(map.phi2(f1),idface, FACE); map.setFaceId(map.phi2(f1),idface, FACE);
}
//FAIS a la couture !!!!!!!
//id pour toutes les aretes exterieurs des faces quadrangulees
unsigned int idedge = map.getEdgeId(f1);
map.setEdgeId(map.phi2(f1), idedge, DART);
map.setEdgeId( map.phi2(f2), idedge, DART);
} }
//FAIS a la couture !!!!!!! //LA copie de L'id est a gerer avec le sewVolumes normalement !!!!!!
//id pour toutes les aretes exterieurs des faces quadrangulees //id pour les aretes interieurs : (i.e. 16 pour un octa)
unsigned int idedge = map.getEdgeId(f1); DartMarker mne(map);
map.setEdgeId(map.phi2(f1), idedge, DART); for(std::vector<Dart>::iterator it = newEdges.begin() ; it != newEdges.end() ; ++it)
map.setEdgeId( map.phi2(f2), idedge, DART); {
if(!mne.isMarked(*it))
{
unsigned int idedge = map.getNewEdgeId();
map.setEdgeId(*it, idedge, EDGE);
mne.markOrbit(EDGE,*it);
}
}
} }
//LA copie de L'id est a gerer avec le sewVolumes normalement !!!!!!
//id pour les aretes interieurs : (i.e. 6 pour un hexa)
DartMarker mne(map);
for(std::vector<Dart>::iterator it = newEdges.begin() ; it != newEdges.end() ; ++it)
{ {
if(!mne.isMarked(*it)) //Third step : 3-sew internal faces
for (std::vector<std::pair<Dart,Dart> >::iterator it = subdividedfacesQ.begin(); it != subdividedfacesQ.end(); ++it)
{ {
unsigned int idedge = map.getNewEdgeId(); Dart f1 = (*it).first;
map.setEdgeId(*it, idedge, EDGE); Dart f2 = (*it).second;
mne.markOrbit(EDGE,*it);
if(map.phi3(map.phi2(f1)) == map.phi2(f1) && map.phi3(map.phi2(f2)) == map.phi2(f2))
{
//id pour toutes les faces interieures
map.sewVolumes(map.phi2(f2), map.phi2(f1));
//Fais a la couture !!!!!
unsigned int idface = map.getNewFaceId();
map.setFaceId(map.phi2(f1),idface, FACE);
}
//FAIS a la couture !!!!!!!
//id pour toutes les aretes exterieurs des faces quadrangulees
unsigned int idedge = map.getEdgeId(f1);
map.setEdgeId(map.phi2(f1), idedge, DART);
map.setEdgeId( map.phi2(f2), idedge, DART);
}
//LA copie de L'id est a gerer avec le sewVolumes normalement !!!!!!
//id pour les aretes interieurs : (i.e. 16 pour un octa)
DartMarker mne(map);
for(std::vector<Dart>::iterator it = newEdges.begin() ; it != newEdges.end() ; ++it)
{
if(!mne.isMarked(*it))
{
unsigned int idedge = map.getNewEdgeId();
map.setEdgeId(*it, idedge, EDGE);
mne.markOrbit(EDGE,*it);
}
}
}
for (std::vector<std::pair<Dart,Dart> >::iterator it = subdividedfacesT.begin(); it != subdividedfacesT.end(); ++it)
{
Dart f1 = (*it).first;
Dart f2 = (*it).second;
if( !(map.Map2::faceDegree(f2) == 3 && map.Map2::faceDegree(map.phi2(f2)) == 3 &&
map.Map2::faceDegree(map.phi2(map.phi1(f2))) == 3 && map.Map2::faceDegree(map.phi2(map.phi_1(f2))) == 3))
{
if(map.phi2(map.phi1(map.phi1(map.phi2(f1)))) == map.phi3(map.phi2(map.phi1(map.phi1(map.phi2(f1))))) &&
map.phi2(map.phi3(map.phi2(map.phi3(map.phi2(map.phi3(map.phi2(map.phi2(map.phi1(map.phi1(map.phi2(f1))))))))))) ==
map.phi3(map.phi2(map.phi3(map.phi2(map.phi3(map.phi2(map.phi3(map.phi2(map.phi2(map.phi1(map.phi1(map.phi2(f1))))))))))))
)
{
map.sewVolumes(map.phi2(map.phi3(map.phi2(map.phi3(map.phi2(map.phi3(map.phi1(map.phi1(map.phi2(f1))))))))),
map.phi2(map.phi1(map.phi1(map.phi2(f1)))));
}
} }
} }