/******************************************************************************* * 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/embeddedMap2.h" namespace CGoGN { Dart EmbeddedMap2::newFace(unsigned int nbEdges, bool withBoundary) { Dart d = Map2::newFace(nbEdges, withBoundary); if(withBoundary) { if (isOrbitEmbedded()) { Traversor2FV t(*this, d); for(Dart it = t.begin(); it != t.end(); it = t.next()) initOrbitEmbeddingNewCell(it) ; } if(isOrbitEmbedded()) { Traversor2FE t(*this, d); for(Dart it = t.begin(); it != t.end(); it = t.next()) initOrbitEmbeddingNewCell(it) ; } if(isOrbitEmbedded()) { initOrbitEmbeddingNewCell(d) ; initOrbitEmbeddingNewCell(phi2(d)) ; } } return d ; } void EmbeddedMap2::splitVertex(Dart d, Dart e) { Dart dd = phi2(d) ; Dart ee = phi2(e) ; Map2::splitVertex(d, e) ; if (isOrbitEmbedded()) { initDartEmbedding(phi1(dd), getEmbedding(d)) ; setOrbitEmbeddingOnNewCell(e) ; copyCell(e, d) ; } if(isOrbitEmbedded()) { initOrbitEmbeddingNewCell(phi1(dd)) ; } if(isOrbitEmbedded()) { initDartEmbedding(phi1(dd), getEmbedding(dd)) ; initDartEmbedding(phi1(ee), getEmbedding(ee)) ; } } Dart EmbeddedMap2::deleteVertex(Dart d) { Dart f = Map2::deleteVertex(d) ; if(f != NIL) { if (isOrbitEmbedded()) { setOrbitEmbedding(f, getEmbedding(f)) ; } } return f ; } Dart EmbeddedMap2::cutEdge(Dart d) { Dart nd = Map2::cutEdge(d) ; if(isOrbitEmbedded()) { initOrbitEmbeddingNewCell(nd) ; } if (isOrbitEmbedded()) { initDartEmbedding(phi2(d), getEmbedding(d)) ; setOrbitEmbeddingOnNewCell(nd) ; copyCell(nd, d) ; } if(isOrbitEmbedded()) { initDartEmbedding(nd, getEmbedding(d)) ; Dart e = phi2(nd) ; initDartEmbedding(phi1(e), getEmbedding(e)) ; } return nd; } bool EmbeddedMap2::uncutEdge(Dart d) { if(Map2::uncutEdge(d)) { if(isOrbitEmbedded()) { copyDartEmbedding(phi2(d), d) ; } return true ; } return false ; } bool EmbeddedMap2::edgeCanCollapse(Dart d) { if(isBoundaryVertex(d) || isBoundaryVertex(phi1(d))) return false ; unsigned int val_v1 = vertexDegree(d) ; unsigned int val_v2 = vertexDegree(phi1(d)) ; if(val_v1 + val_v2 < 8 || val_v1 + val_v2 > 14) return false ; if(faceDegree(d) == 3) { if(vertexDegree(phi_1(d)) < 4) return false ; } Dart dd = phi2(d) ; if(faceDegree(dd) == 3) { if(vertexDegree(phi_1(dd)) < 4) return false ; } // Check vertex sharing condition std::vector vu1 ; vu1.reserve(32) ; Dart vit1 = alpha1(alpha1(d)) ; Dart end = phi1(dd) ; do { unsigned int ve = getEmbedding(phi2(vit1)) ; vu1.push_back(ve) ; vit1 = alpha1(vit1) ; } while(vit1 != end) ; end = phi1(d) ; Dart vit2 = alpha1(alpha1(dd)) ; do { unsigned int ve = getEmbedding(phi2(vit2)) ; std::vector::iterator it = std::find(vu1.begin(), vu1.end(), ve) ; if(it != vu1.end()) return false ; vit2 = alpha1(vit2) ; } while(vit2 != end) ; return true ; } Dart EmbeddedMap2::collapseEdge(Dart d, bool delDegenerateFaces) { unsigned int vEmb = EMBNULL ; if (isOrbitEmbedded()) { vEmb = getEmbedding(d) ; } Dart dV = Map2::collapseEdge(d, delDegenerateFaces); if (isOrbitEmbedded()) { setOrbitEmbedding(dV, vEmb) ; } return dV ; } bool EmbeddedMap2::flipEdge(Dart d) { if(Map2::flipEdge(d)) { Dart e = phi2(d) ; if (isOrbitEmbedded()) { copyDartEmbedding(d, phi1(e)) ; copyDartEmbedding(e, phi1(d)) ; } if (isOrbitEmbedded()) { copyDartEmbedding(phi_1(d), d) ; copyDartEmbedding(phi_1(e), e) ; } return true ; } return false ; } bool EmbeddedMap2::flipBackEdge(Dart d) { if(Map2::flipBackEdge(d)) { Dart e = phi2(d) ; if (isOrbitEmbedded()) { copyDartEmbedding(d, phi1(e)) ; copyDartEmbedding(e, phi1(d)) ; } if (isOrbitEmbedded()) { copyDartEmbedding(phi1(d), d) ; copyDartEmbedding(phi1(e), e) ; } return true ; } return false ; } void EmbeddedMap2::swapEdges(Dart d, Dart e) { Dart d2 = phi2(d); Dart e2 = phi2(e); Map2::swapEdges(d,e); if(isOrbitEmbedded()) { copyDartEmbedding(d, phi2(phi_1(d))); copyDartEmbedding(e, phi2(phi_1(e))); copyDartEmbedding(d2, phi2(phi_1(d2))); copyDartEmbedding(e2, phi2(phi_1(e2))); } if(isOrbitEmbedded()) { } if(isOrbitEmbedded()) setOrbitEmbeddingOnNewCell(d); } void EmbeddedMap2::sewFaces(Dart d, Dart e, bool withBoundary) { if (!withBoundary) { Map2::sewFaces(d, e, false) ; return ; } Map2::sewFaces(d, e, withBoundary) ; if (isOrbitEmbedded()) { setOrbitEmbedding(d, getEmbedding(d)) ; setOrbitEmbedding(e, getEmbedding(phi1(d))) ; } if (isOrbitEmbedded()) { copyDartEmbedding(e, d) ; } } void EmbeddedMap2::unsewFaces(Dart d, bool withBoundary) { if (!withBoundary) { Map2::unsewFaces(d, false) ; return ; } Dart e = phi2(d) ; Map2::unsewFaces(d) ; if (isOrbitEmbedded()) { Dart ee = phi1(e) ; if(!sameVertex(d, ee)) { setOrbitEmbeddingOnNewCell(ee); copyCell(ee, d); } Dart dd = phi1(d) ; if(!sameVertex(e, dd)) { setOrbitEmbeddingOnNewCell(dd); copyCell(dd, e); } } if (isOrbitEmbedded()) { setOrbitEmbeddingOnNewCell(e); copyCell(e, d); } } bool EmbeddedMap2::collapseDegeneratedFace(Dart d) { Dart e = phi2(d) ; bool updateEdgeEmb = false ; if(phi1(d) != d) updateEdgeEmb = true ; if(Map2::collapseDegeneratedFace(d)) { if (isOrbitEmbedded() && updateEdgeEmb) { copyDartEmbedding(phi2(e), e) ; } return true ; } return false ; } void EmbeddedMap2::splitFace(Dart d, Dart e) { Map2::splitFace(d, e) ; if (isOrbitEmbedded()) { initDartEmbedding(phi_1(e), getEmbedding(d)) ; initDartEmbedding(phi_1(d), getEmbedding(e)) ; } if(isOrbitEmbedded()) { initOrbitEmbeddingNewCell(phi_1(d)) ; } if (isOrbitEmbedded()) { initDartEmbedding(phi_1(d), getEmbedding(d)) ; setOrbitEmbeddingOnNewCell(e) ; copyCell(e, d) ; } } bool EmbeddedMap2::mergeFaces(Dart d) { Dart dNext = phi1(d) ; if(Map2::mergeFaces(d)) { if (isOrbitEmbedded()) { setOrbitEmbedding(dNext, getEmbedding(dNext)) ; } return true ; } return false ; } bool EmbeddedMap2::mergeVolumes(Dart d, Dart e) { std::vector darts ; std::vector vEmb ; vEmb.reserve(32) ; std::vector eEmb ; eEmb.reserve(32) ; Dart fit = d ; do { darts.push_back(phi2(fit)) ; if (isOrbitEmbedded()) { vEmb.push_back(getEmbedding(phi2(fit))) ; } if (isOrbitEmbedded()) { eEmb.push_back(getEmbedding(fit)) ; } fit = phi1(fit) ; } while (fit != d) ; if(Map2::mergeVolumes(d, e)) { for(unsigned int i = 0; i < darts.size(); ++i) { if (isOrbitEmbedded()) { setOrbitEmbedding(darts[i], vEmb[i]) ; } if (isOrbitEmbedded()) { setOrbitEmbedding(darts[i], eEmb[i]) ; } } return true ; } return false ; } void EmbeddedMap2::splitSurface(std::vector& vd, bool firstSideClosed, bool secondSideClosed) { std::vector darts ; darts.reserve(vd.size()); // save the edge neighbors darts for(std::vector::iterator it = vd.begin() ; it != vd.end() ; ++it) { darts.push_back(phi2(*it)); } assert(darts.size() == vd.size()); Map2::splitSurface(vd, firstSideClosed, secondSideClosed); // follow the edge path a second time to embed the vertex, edge and volume orbits for(unsigned int i = 0; i < vd.size(); ++i) { Dart dit = vd[i]; Dart dit2 = darts[i]; // embed the vertex embedded from the origin volume to the new darts if(isOrbitEmbedded()) { initDartEmbedding(phi2(dit), getEmbedding(phi1(dit))); initDartEmbedding(phi2(dit2), getEmbedding(phi1(dit2))); } // embed the edge embedded from the origin volume to the new darts if(isOrbitEmbedded()) { initDartEmbedding(phi2(dit), getEmbedding(dit)); setOrbitEmbeddingOnNewCell(phi2(dit2)); copyCell(dit2, dit); } // embed the volume embedded from the origin volume to the new darts if(isOrbitEmbedded()) { initDartEmbedding(phi2(dit), getEmbedding(dit)); initDartEmbedding(phi2(dit2), getEmbedding(dit2)); } } } unsigned int EmbeddedMap2::closeHole(Dart d, bool forboundary) { unsigned int nbE = Map2::closeHole(d, forboundary) ; Dart dd = phi2(d) ; Dart f = dd ; do { if (isOrbitEmbedded()) { initDartEmbedding(f, getEmbedding(phi1(phi2(f)))) ; } if (isOrbitEmbedded()) { initDartEmbedding(f, getEmbedding(phi2(f))) ; } f = phi1(f) ; } while(dd != f) ; if(isOrbitEmbedded()) { initOrbitEmbeddingNewCell(dd) ; } return nbE ; } bool EmbeddedMap2::check() { bool topo = Map2::check() ; if (!topo) return false ; CGoGNout << "Check: embedding begin" << CGoGNendl ; for(Dart d = begin(); d != end(); next(d)) { if (isOrbitEmbedded()) { if (getEmbedding(d) != getEmbedding(alpha1(d))) { CGoGNout << "Check: different embeddings on vertex" << CGoGNendl ; return false ; } } if (isOrbitEmbedded()) { if (getEmbedding(d) != getEmbedding(phi2(d))) { CGoGNout << "Check: different embeddings on edge" << CGoGNendl ; return false ; } } // if (isOrbitEmbedded(ORIENTED_FACE)) // { // if (getEmbedding(ORIENTED_FACE, d) != getEmbedding(ORIENTED_FACE, phi1(d))) // { // CGoGNout << "Check: different embeddings on oriented face" << CGoGNendl ; // return false ; // } // } if (isOrbitEmbedded()) { if (getEmbedding(d) != getEmbedding(phi1(d))) { CGoGNout << "Check: different embeddings on face" << CGoGNendl ; return false ; } } } CGoGNout << "Check: embedding ok" << CGoGNendl ; std::cout << "nb vertex orbits : " << getNbOrbits() << std::endl ; std::cout << "nb vertex cells : " << m_attribs[VERTEX].size() << std::endl ; std::cout << "nb edge orbits : " << getNbOrbits() << std::endl ; std::cout << "nb edge cells : " << m_attribs[EDGE].size() << std::endl ; std::cout << "nb face orbits : " << getNbOrbits() << std::endl ; std::cout << "nb face cells : " << m_attribs[FACE].size() << std::endl ; return true ; } } // namespace CGoGN