/******************************************************************************* * CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * * version 0.1 * * Copyright (C) 2009-2012, 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.unistra.fr/ * * Contact information: cgogn@unistra.fr * * * *******************************************************************************/ #include #include #include "Topology/map/embeddedMap3.h" #include "Topology/generic/traversor/traversor3.h" namespace CGoGN { //TODO Dart EmbeddedMap3::splitVertex(std::vector& vd) { Dart d = vd.front(); Dart d2 = phi1(phi2(d)); Dart dres = Map3::splitVertex(vd); if(isOrbitEmbedded()) { Algo::Topo::setOrbitEmbeddingOnNewCell(*this, d2); Algo::Topo::copyCellAttributes(*this, d2, d); Algo::Topo::setOrbitEmbedding(*this, d, getEmbedding(d)); } if(isOrbitEmbedded()) Algo::Topo::initOrbitEmbeddingOnNewCell(*this, dres) ; // TODO : check if dres is a dart of the new edge if(isOrbitEmbedded()) { for(std::vector::iterator it = vd.begin() ; it != vd.end() ; ++it) Algo::Topo::setOrbitEmbedding(*this, *it, getEmbedding(*it)) ; } return dres; } //TODO Dart EmbeddedMap3::deleteVertex(Dart d) { Dart v = Map3::deleteVertex(d) ; if(v != NIL) { if (isOrbitEmbedded()) { Algo::Topo::setOrbitEmbedding(*this, v, getEmbedding(v)) ; } } return v ; } Dart EmbeddedMap3::cutEdge(Dart d) { Dart nd = Map3::cutEdge(d); // if(isOrbitEmbedded()) // { // initOrbitEmbeddingNewCell(nd) ; // } if(isOrbitEmbedded()) { // embed the new darts created in the cut edge Algo::Topo::setOrbitEmbedding(*this, d, getEmbedding(d)) ; // embed a new cell for the new edge and copy the attributes' line (c) Lionel Algo::Topo::setOrbitEmbeddingOnNewCell(*this, nd) ; Algo::Topo::copyCellAttributes(*this, nd, d) ; } if(isOrbitEmbedded()) { Dart f = d; do { Dart f1 = phi1(f) ; copyDartEmbedding(f1, f); Dart e = phi3(f1); copyDartEmbedding(phi1(e), e); f = alpha2(f); } while(f != d); } if(isOrbitEmbedded()) { Dart f = d; do { unsigned int fEmb = getEmbedding(f) ; setDartEmbedding(phi1(f), fEmb); setDartEmbedding(phi3(f), fEmb); f = alpha2(f); } while(f != d); } if(isOrbitEmbedded()) { Dart f = d; do { unsigned int vEmb = getEmbedding(f) ; setDartEmbedding(phi1(f), vEmb); setDartEmbedding(phi2(f), vEmb); f = alpha2(f); } while(f != d); } return nd ; } bool EmbeddedMap3::uncutEdge(Dart d) { if(Map3::uncutEdge(d)) { //embed all darts from the old two edges to one of the two edge embedding if(isOrbitEmbedded()) { Algo::Topo::setOrbitEmbedding(*this, d, getEmbedding(d)) ; } return true ; } return false ; } Dart EmbeddedMap3::deleteEdge(Dart d) { Dart v = Map3::deleteEdge(d) ; if(v != NIL) { if(isOrbitEmbedded()) { Algo::Topo::setOrbitEmbedding(*this, v, getEmbedding(v)) ; } } return v; } bool EmbeddedMap3::edgeCanCollapse(Dart d) { // if(isBoundaryVertex(d) || isBoundaryVertex(phi1(d))) // return false; // // if(isBoundaryEdge(d)) // return false; CellMarkerStore mv(*this); Traversor3VVaE t3VVaE_v1(*this,d); for(Dart dit = t3VVaE_v1.begin() ; dit != t3VVaE_v1.end() ; dit = t3VVaE_v1.next()) { mv.mark(dit); } Traversor3EW t3EW(*this,d); for(Dart dit = t3EW.begin() ; dit != t3EW.end() ; dit = t3EW.next()) { mv.unmark(phi_1(dit)); mv.unmark(phi_1(phi2(dit))); } Traversor3VVaE t3VVaE_v2(*this,phi2(d)); for(Dart dit = t3VVaE_v2.begin() ; dit != t3VVaE_v2.end() ; dit = t3VVaE_v2.next()) { if(mv.isMarked(dit)) return false; } return true; } Dart EmbeddedMap3::collapseEdge(Dart d, bool delDegenerateVolumes) { unsigned int vEmb = getEmbedding(d) ; Dart d2 = phi2(phi_1(d)) ; Dart dd2 = phi2(phi_1(phi2(d))) ; Dart resV = Map3::collapseEdge(d, delDegenerateVolumes); if(resV != NIL) { if(isOrbitEmbedded()) { Algo::Topo::setOrbitEmbedding(*this, resV, vEmb); } if(isOrbitEmbedded()) { Algo::Topo::setOrbitEmbedding(*this, d2, getEmbedding(d2)); Algo::Topo::setOrbitEmbedding(*this, dd2, getEmbedding(dd2)); } } return resV; } void EmbeddedMap3::splitFace(Dart d, Dart e) { Dart dd = phi1(phi3(d)); Dart ee = phi1(phi3(e)); Map3::splitFace(d, e); if(isOrbitEmbedded()) { unsigned int vEmb1 = getEmbedding(d) ; unsigned int vEmb2 = getEmbedding(e) ; setDartEmbedding(phi_1(e), vEmb1); setDartEmbedding(phi_1(ee), vEmb1); setDartEmbedding(phi_1(d), vEmb2); setDartEmbedding(phi_1(dd), vEmb2); } // if(isOrbitEmbedded()) // { // initOrbitEmbeddingNewCell(phi_1(d)) ; // } if(isOrbitEmbedded()) { copyDartEmbedding(phi_1(d), d) ; Algo::Topo::setOrbitEmbeddingOnNewCell(*this, e) ; Algo::Topo::copyCellAttributes(*this, e, d) ; copyDartEmbedding(phi_1(dd), dd) ; Algo::Topo::setOrbitEmbeddingOnNewCell(*this, ee) ; Algo::Topo::copyCellAttributes(*this, ee, dd) ; } if(isOrbitEmbedded()) { unsigned int fEmb = getEmbedding(d) ; setDartEmbedding(phi_1(d), fEmb) ; setDartEmbedding(phi_1(ee), fEmb) ; Algo::Topo::setOrbitEmbeddingOnNewCell(*this, e); Algo::Topo::copyCellAttributes(*this, e, d); } if(isOrbitEmbedded()) { unsigned int vEmb1 = getEmbedding(d) ; setDartEmbedding(phi_1(d), vEmb1); setDartEmbedding(phi_1(e), vEmb1); unsigned int vEmb2 = getEmbedding(dd) ; setDartEmbedding(phi_1(dd), vEmb2); setDartEmbedding(phi_1(ee), vEmb2); } } bool EmbeddedMap3::mergeFaces(Dart d) { Dart d1 = phi1(d); if(Map3::mergeFaces(d)) { if(isOrbitEmbedded()) { Algo::Topo::setOrbitEmbedding(*this, d1, getEmbedding(d1)) ; } if(isOrbitEmbedded()) { Algo::Topo::setOrbitEmbedding(*this, d1, getEmbedding(d1)) ; } return true; } return false; } //! /*! * */ Dart EmbeddedMap3::collapseFace(Dart d, bool delDegenerateVolumes) { unsigned int vEmb = getEmbedding(d) ; Dart resV = Map3::collapseFace(d, delDegenerateVolumes); if(resV != NIL) { if(isOrbitEmbedded()) { Algo::Topo::setOrbitEmbedding(*this, resV, vEmb); } } return resV; } void EmbeddedMap3::sewVolumes(Dart d, Dart e, bool withBoundary) { if (!withBoundary) { Map3::sewVolumes(d, e, false) ; return ; } Map3::sewVolumes(d, e, withBoundary); // embed the vertex orbits from the oriented face with dart e // with vertex orbits value from oriented face with dart d if (isOrbitEmbedded()) { Dart it = d ; do { Algo::Topo::setOrbitEmbedding(*this, it, getEmbedding(it)) ; it = phi1(it) ; } while(it != d) ; } // embed the new edge orbit with the old edge orbit value // for all the face if (isOrbitEmbedded()) { Dart it = d ; do { Algo::Topo::setOrbitEmbedding(*this, it, getEmbedding(it)) ; it = phi1(it) ; } while(it != d) ; } // embed the face orbit from the volume sewn if (isOrbitEmbedded()) { Algo::Topo::setOrbitEmbedding(*this, e, getEmbedding(d)) ; } } void EmbeddedMap3::unsewVolumes(Dart d, bool withBoundary) { if (!withBoundary) { Map3::unsewVolumes(d, false) ; return ; } Dart dd = alpha1(d); unsigned int fEmb = EMBNULL ; if(isOrbitEmbedded()) fEmb = getEmbedding(d) ; Map3::unsewVolumes(d); Dart dit = d; do { // embed the unsewn vertex orbit with the vertex embedding if it is deconnected if(isOrbitEmbedded()) { if(!sameVertex(dit, dd)) { Algo::Topo::setOrbitEmbedding(*this, dit, getEmbedding(dit)) ; Algo::Topo::setOrbitEmbeddingOnNewCell(*this, dd); Algo::Topo::copyCellAttributes(*this, dd, dit); } else { Algo::Topo::setOrbitEmbedding(*this, dit, getEmbedding(dit)) ; } } dd = phi_1(dd); // embed the unsewn edge with the edge embedding if it is deconnected if(isOrbitEmbedded()) { if(!sameEdge(dit, dd)) { Algo::Topo::setOrbitEmbeddingOnNewCell(*this, dd); Algo::Topo::copyCellAttributes(*this, dd, dit); copyDartEmbedding(phi3(dit), dit) ; } else { unsigned int eEmb = getEmbedding(dit) ; setDartEmbedding(phi3(dit), eEmb) ; setDartEmbedding(alpha_2(dit), eEmb) ; } } if(isOrbitEmbedded()) { setDartEmbedding(phi3(dit), fEmb) ; } dit = phi1(dit); } while(dit != d); // embed the unsewn face with the face embedding if (isOrbitEmbedded()) { Algo::Topo::setOrbitEmbeddingOnNewCell(*this, dd); Algo::Topo::copyCellAttributes(*this, dd, d); } } bool EmbeddedMap3::mergeVolumes(Dart d, bool deleteFace) { Dart d2 = phi2(d); if(Map3::mergeVolumes(d, deleteFace)) { if (isOrbitEmbedded()) { Algo::Topo::setOrbitEmbedding(*this, d2, getEmbedding(d2)) ; } return true; } return false; } void EmbeddedMap3::splitVolume(std::vector& vd) { Map3::splitVolume(vd); // follow the edge path a second time to embed the vertex, edge and volume orbits for(std::vector::iterator it = vd.begin() ; it != vd.end() ; ++it) { Dart dit = *it; Dart dit23 = phi3(phi2(dit)); // embed the vertex embedded from the origin volume to the new darts if(isOrbitEmbedded()) { copyDartEmbedding(dit23, dit); copyDartEmbedding(phi2(dit), phi1(dit)); } // embed the edge embedded from the origin volume to the new darts if(isOrbitEmbedded()) { Algo::Topo::setOrbitEmbeddingOnNewCell(*this, dit23) ; Algo::Topo::copyCellAttributes(*this, dit23, dit) ; copyDartEmbedding(phi2(dit), dit); } // embed the edge embedded from the origin volume to the new darts if(isOrbitEmbedded()) { unsigned int eEmb = getEmbedding(dit) ; setDartEmbedding(dit23, eEmb); setDartEmbedding(phi2(dit), eEmb); } // embed the volume embedded from the origin volume to the new darts if(isOrbitEmbedded()) { copyDartEmbedding(phi2(dit), dit); } } if(isOrbitEmbedded()) { Dart v = vd.front() ; Dart v23 = phi3(phi2(v)); Algo::Topo::setOrbitEmbeddingOnNewCell(*this, v23) ; Algo::Topo::copyCellAttributes(*this, v23, v) ; } } //! Split a volume into two volumes along a edge path and add the given face between void EmbeddedMap3::splitVolumeWithFace(std::vector& vd, Dart d) { Map3::splitVolumeWithFace(vd,d); // follow the edge path a second time to embed the vertex, edge and volume orbits for(std::vector::iterator it = vd.begin() ; it != vd.end() ; ++it) { Dart dit = *it; Dart dit23 = phi3(phi2(dit)); // embed the vertex embedded from the origin volume to the new darts if(isOrbitEmbedded()) { copyDartEmbedding(dit23, dit); copyDartEmbedding(phi2(dit), phi1(dit)); } // embed the edge embedded from the origin volume to the new darts if(isOrbitEmbedded()) { Algo::Topo::setOrbitEmbeddingOnNewCell(*this, dit23) ; Algo::Topo::copyCellAttributes(*this, dit23, dit) ; copyDartEmbedding(phi2(dit), dit); } // embed the edge embedded from the origin volume to the new darts if(isOrbitEmbedded()) { unsigned int eEmb = getEmbedding(dit) ; setDartEmbedding(dit23, eEmb); setDartEmbedding(phi2(dit), eEmb); } // embed the volume embedded from the origin volume to the new darts if(isOrbitEmbedded()) { copyDartEmbedding(phi2(dit), dit); } } if(isOrbitEmbedded()) { Dart v = vd.front() ; Dart v23 = phi3(phi2(v)); Algo::Topo::setOrbitEmbeddingOnNewCell(*this, v23) ; Algo::Topo::copyCellAttributes(*this, v23, v) ; } } Dart EmbeddedMap3::collapseVolume(Dart d, bool delDegenerateVolumes) { unsigned int vEmb = getEmbedding(d) ; Dart resV = Map3::collapseVolume(d, delDegenerateVolumes); if(resV != NIL) { if(isOrbitEmbedded()) { Algo::Topo::setOrbitEmbedding(*this, resV, vEmb); } } return resV; } unsigned int EmbeddedMap3::closeHole(Dart d) { unsigned int nbF = Map3::closeHole(d) ; DartMarkerStore mark(*this); // Lock a marker std::vector visitedFaces; // Faces that are traversed visitedFaces.reserve(1024) ; visitedFaces.push_back(phi3(d));// Start with the face of d mark.markOrbit(phi3(d)) ; // For every face added to the list for(unsigned int i = 0; i < visitedFaces.size(); ++i) { Dart it = visitedFaces[i] ; Dart f = it ; do { if(isOrbitEmbedded()) { copyDartEmbedding(f, alpha1(f)) ; } if(isOrbitEmbedded()) { copyDartEmbedding(f, phi3(f)) ; } if(isOrbitEmbedded()) { copyDartEmbedding(f, phi3(f)) ; } Dart adj = phi2(f); // Get adjacent face if (!mark.isMarked(adj)) { visitedFaces.push_back(adj); // Add it mark.markOrbit(adj) ; } f = phi1(f) ; } while(f != it) ; } return nbF ; } bool EmbeddedMap3::check() { std::cout << "nb vertex orbits : " << Algo::Topo::getNbOrbits(*this) << std::endl ; std::cout << "nb vertex cells : " << m_attribs[VERTEX].size() << std::endl ; std::cout << "nb edge orbits : " << Algo::Topo::getNbOrbits(*this) << std::endl ; std::cout << "nb edge cells : " << m_attribs[EDGE].size() << std::endl ; std::cout << "nb face orbits : " << Algo::Topo::getNbOrbits(*this) << std::endl ; std::cout << "nb face cells : " << m_attribs[FACE].size() << std::endl ; std::cout << "nb volume orbits : " << Algo::Topo::getNbOrbits(*this) << std::endl ; std::cout << "nb volume cells : " << m_attribs[VOLUME].size() << std::endl ; bool topo = Map3::check() ; if (!topo) return false ; std::cout << "Check: embedding begin" << std::endl ; for(Dart d = begin(); d != end(); next(d)) { if(isOrbitEmbedded()) { if( getEmbedding(d) != getEmbedding(alpha1(d))) { std::cout << "Embedding Check : different embeddings on vertex (alpha1(d) != d)" << std::endl ; return false ; } if(getEmbedding(d) != getEmbedding(alpha2(d)) ) { std::cout << "Embedding Check : different embeddings on vertex (alpha2(d) != d)" << std::endl ; return false ; } } if(isOrbitEmbedded()) { if( getEmbedding(d) != getEmbedding(phi2(d)) || getEmbedding(d) != getEmbedding(phi3(d)) ) { std::cout << "Embedding Check : different embeddings on edge" << std::endl ; return false ; } } if (isOrbitEmbedded()) { if (getEmbedding(d) != getEmbedding(phi1(d))) { CGoGNout << "Check: different embeddings on oriented face" << CGoGNendl ; return false ; } } if (isOrbitEmbedded()) { if( getEmbedding(d) != getEmbedding(phi1(d)) || getEmbedding(d) != getEmbedding(phi3(d)) ) { CGoGNout << "Check: different embeddings on face" << CGoGNendl ; return false ; } } if (isOrbitEmbedded()) { if( getEmbedding(d) != getEmbedding(phi1(d)) || getEmbedding(d) != getEmbedding(phi2(d)) ) { CGoGNout << "Check: different embeddings on volume" << CGoGNendl ; return false ; } } } std::cout << "Check: embedding ok" << std::endl ; return true ; } } // namespace CGoGN