diff --git a/include/Topology/map/map1.h b/include/Topology/map/map1.h index 1a86d4f7055b9378165d90880360a289bf1a4e78..7ec952811ab7cc7d888d3f8b3ae04e886f8966d3 100644 --- a/include/Topology/map/map1.h +++ b/include/Topology/map/map1.h @@ -114,6 +114,12 @@ public: */ Dart newFace(unsigned int nbEdges) ; + //! Create an new face for boundary (marked) + /*! @param nbEdges the number of edges + * @return return a dart of the face + */ + Dart newBoundaryFace(unsigned nbEdges); + //! Delete an oriented face erasing all its darts /*! @param d a dart of the face */ diff --git a/include/Topology/map/map2.h b/include/Topology/map/map2.h index d57d221fab3ebe3f672108c25916d0d85b2d17d8..bec4d8aedb96b1fd7d2bb1b540a21fede865d104 100644 --- a/include/Topology/map/map2.h +++ b/include/Topology/map/map2.h @@ -95,13 +95,15 @@ protected: */ void phi2unsew(Dart d); - //! merge a face that has been tag as boundary with existing boundary if needed /* @param d a dart of the face */ void mergeFacewithBoundary(Dart d); - + /** + * merge two faces of boundary + */ + void mergeBoundaryFaces(Dart dd, Dart ee); /*! @name Generator and Deletor * To generate or delete faces in a 2-map @@ -256,7 +258,7 @@ public: * create a symetric to construct a polyedron * @param d a dart from the vertex */ - void explodPolyhedron(Dart d); +// void explodPolyhedron(Dart d); //TODO modification for new boundary managing method ??? //! Merge two volumes along two faces. /*! Works only if the two faces have the same number of edges. @@ -328,6 +330,17 @@ public: */ bool isBoundaryVertex(Dart d) ; + /** + * find the dart of vertex that belong to the boundary + */ + Dart findBoundaryVertex(Dart d); + + /** + * tell if the vertex of d is on the boundary of the map + */ + bool isBoundaryEdge(Dart d) ; // OK boundary + + //! Follow the boundary of a surface as if it was a oriented face. /*! This operation alternate phi1 and phi2 operator until another * boudary dart is reached. @@ -396,6 +409,31 @@ public: bool foreach_dart_of_link(Dart d, unsigned int orbit, FunctorType& f, unsigned int thread=0); //@} + + //@{ + //! Close a topological hole (a sequence of connected fixed point of phi2). DO NO USE, only for import algorithm + /*! \pre dart d MUST be fixed point of phi2 relation + * Add a face to the map that closes the hole. + * The darts of this face are marked with holeMarker. + * @param d a dart of the hole (with phi2(d)==d) + * @return the degree of the created face + */ + virtual unsigned int closeHole(Dart d); + + + //! Close the map removing topological holes: DO NO USE, only for import algorithm + /*! Add faces to the map that close every existing hole. + * These faces are marked. + * \warning The embeddings of vertices are not updated + */ + void closeMap(); +// void closeMap(DartMarker& marker); + + /** + * sew oriented face, DO NO USE, only for import algorithm + */ + void sewOrientedFaces(Dart d, Dart e); + //@} }; } // namespace CGoGN diff --git a/src/Topology/map/map1.cpp b/src/Topology/map/map1.cpp index 8d2b47d08a5d63f53a108ccbf019dfe624e80a7b..8c0dc5ca04b28b98367568528428ae58ce215523 100644 --- a/src/Topology/map/map1.cpp +++ b/src/Topology/map/map1.cpp @@ -40,6 +40,17 @@ Dart Map1::newOrientedFace(unsigned nbEdges) return d ; } +Dart Map1::newBoundaryFace(unsigned nbEdges) +{ + assert(nbEdges > 0 || !"Cannot create a face with no edge") ; + Dart d = newDart() ; // Create the first edge + boundaryMark(d); + for (unsigned int i = 1 ; i < nbEdges ; ++i) + Map1::cutEdge(d) ; // Subdivide nbEdges-1 times this edge + return d ; +} + + void Map1::deleteOrientedFace(Dart d) { Dart e = phi1(d) ; diff --git a/src/Topology/map/map2.cpp b/src/Topology/map/map2.cpp index ac5f74f8731da4a157722025162290c0542043ea..e5f67b1f981e80d9d58ae00b678f86faa4fea140 100644 --- a/src/Topology/map/map2.cpp +++ b/src/Topology/map/map2.cpp @@ -31,6 +31,15 @@ namespace CGoGN * To generate or delete faces in a 2-map *************************************************************************/ +void Map2::mergeBoundaryFaces(Dart dd, Dart ee) +{ + if (ee != phi_1(dd)) + phi1sew(ee, phi_1(dd)) ; + if (ee != phi_1(dd)) + phi1sew(ee, phi_1(dd)) ; + Map1::deleteOrientedFace(dd) ; +} + void Map2::mergeFacewithBoundary(Dart d) { Dart e = d ; @@ -52,7 +61,6 @@ void Map2::mergeFacewithBoundary(Dart d) } while (e != d) ; } - void Map2::deleteOrientedFace(Dart d) { // tag face in boundary @@ -61,6 +69,13 @@ void Map2::deleteOrientedFace(Dart d) } +void Map2::sewOrientedFaces(Dart d, Dart e) +{ + assert(phi2(d)==d && phi2(e)==e); + // sewing the faces + phi2sew(d, e); +} + /*! @name Topological Operators * Topological operations on 2-maps *************************************************************************/ @@ -112,9 +127,6 @@ void Map2::cutEdge(Dart d) // phi2sew(e, nd); // } - // TODISCUSS: it is not allowed to cut an edge of boundary - assert(!isBoundaryMarked(d)); - Map1::cutEdge(d); // Cut the 1-edge of d Dart e = phi2(d); Map1::cutEdge(e); // Cut the 1-edge of phi2(d) @@ -127,12 +139,6 @@ void Map2::cutEdge(Dart d) phi2sew(d, ne); // Correct the phi2 links phi2sew(e, nd); - if (isBoundaryMarked(e)) - boundaryMark(ne); - -// if (isBoundaryMarked(d)) -// boundaryMark(nd); - } void Map2::uncutEdge(Dart d) @@ -163,7 +169,6 @@ void Map2::uncutEdge(Dart d) phi2sew(d, e) ; } - Dart Map2::collapseEdge(Dart d, bool delDegenerateFaces) { // Dart resV ; @@ -214,8 +219,8 @@ Dart Map2::collapseEdge(Dart d, bool delDegenerateFaces) // // return resV ; - Dart resV=Dart::nil() ; + Dart e = phi2(d); phi2unsew(d); // Unlink the opposite edges @@ -223,7 +228,8 @@ Dart Map2::collapseEdge(Dart d, bool delDegenerateFaces) { Dart f = phi1(e) ; Map1::collapseEdge(e) ; // Collapse edge e - collapseDegeneratedFace(f) ;// and collapse its face if degenerated + if (f!=e) + collapseDegeneratedFace(f) ;// and collapse its face if degenerated } else { @@ -246,35 +252,45 @@ Dart Map2::collapseEdge(Dart d, bool delDegenerateFaces) Map1::collapseEdge(e) ; // Just collapse edge e } - Dart f = phi1(d) ; - Dart g = phi_1(d) ; - - if(resV == Dart::nil()) - { - if(!isFaceTriangle(d)) - resV = f ; - else if(phi2(g) != g) - resV = phi2(g) ; - else if(phi2(f) != f) - resV = phi1(phi2(f)) ; - } - - if (f != d && delDegenerateFaces) + if (isBoundaryMarked(d)) { + Dart f = phi1(d) ; Map1::collapseEdge(d) ; // Collapse edge d - collapseDegeneratedFace(f) ;// and collapse its face if degenerated + if (f!=d) + collapseDegeneratedFace(f) ;// and collapse its face if degenerated } else - Map1::collapseEdge(d) ; // Just collapse edge d + { + Dart f = phi1(d) ; + Dart g = phi_1(d) ; + + if(resV == Dart::nil()) + { + if(f != e && !isFaceTriangle(d)) + resV = f ; + else if(phi2(g) != g) + resV = phi2(g) ; + else if(f != e && phi2(f) != f) + resV = phi1(phi2(f)) ; + } + + if (f != d && delDegenerateFaces) + { + Map1::collapseEdge(d) ; // Collapse edge d + collapseDegeneratedFace(f) ;// and collapse its face if degenerated + } + else + Map1::collapseEdge(d) ; // Just collapse edge d + } return resV ; } bool Map2::flipEdge(Dart d) { - Dart e = phi2(d); // Test if an opposite - if (!isBoundaryMarked(e)) // edge exists + if (!isBoundaryEdge(d)) { + Dart e = phi2(d); Dart dNext = phi1(d); Dart eNext = phi1(e); Dart dPrev = phi_1(d); @@ -290,9 +306,9 @@ bool Map2::flipEdge(Dart d) bool Map2::flipBackEdge(Dart d) { - Dart e = phi2(d); // Test if an opposite - if (!isBoundaryMarked(e)) // edge exists + if (!isBoundaryEdge(d)) { + Dart e = phi2(d); Dart dNext = phi1(d); Dart eNext = phi1(e); Dart dPrev = phi_1(d); @@ -323,26 +339,41 @@ void Map2::removeEdgeFromVertex(Dart d) void Map2::sewFaces(Dart d, Dart e) { Dart dd = phi2(d); - Dart ee = phi2(ee); + Dart ee = phi2(e); // unsew from boundary phi2unsew(d); phi2unsew(e); - // remove boundary edge - if (ee != phi_1(dd)) - phi1sew(ee, phi_1(dd)) ; - if (ee != phi_1(dd)) - phi1sew(ee, phi_1(dd)) ; - Map1::deleteOrientedFace(d) ; + // remove boundary edge (could be a Map1::mergeFaces without assert ?) + mergeBoundaryFaces(dd,ee); - // main sewing + // sewing the faces phi2sew(d, e); } void Map2::unsewFaces(Dart d) { - // TODO + Dart dd = phi2(d); + + Dart e = newBoundaryFace(2); + + if (isBoundaryVertex(d)) + { + Dart f = findBoundaryVertex(d); + phi1sew(e,phi_1(f)); + } + + if (isBoundaryVertex(dd)) + { + Dart f = findBoundaryVertex(dd); + phi1sew(phi_1(e),phi_1(f)); + } + phi2unsew(d); + // sew faces to the boundary + phi2sew(d,e); + phi2sew(dd,phi1(e)); + } bool Map2::collapseDegeneratedFace(Dart d) @@ -370,9 +401,9 @@ void Map2::splitFace(Dart d, Dart e) bool Map2::mergeFaces(Dart d) { - Dart e = phi2(d) ; - if (!isBoundaryMarked(e)) + if (!isBoundaryEdge(d)) { + Dart e = phi2(d) ; phi2unsew(d); // unsew the face of d Map1::mergeFaces(d, e); // merge the two faces along edges of d and e return true ; @@ -382,7 +413,33 @@ bool Map2::mergeFaces(Dart d) void Map2::extractTrianglePair(Dart d) { - assert(isFaceTriangle(d)) ; +// assert(isFaceTriangle(d)) ; +// Dart e = phi2(d) ; +// if(e != d) +// { +// assert(isFaceTriangle(e)) ; +// Dart e1 = phi2(phi1(e)) ; +// Dart e2 = phi2(phi_1(e)) ; +// phi2unsew(e1) ; +// phi2unsew(e2) ; +// phi2sew(e1, e2) ; +// } +// Dart d1 = phi2(phi1(d)) ; +// Dart d2 = phi2(phi_1(d)) ; +// phi2unsew(d1) ; +// phi2unsew(d2) ; +// phi2sew(d1, d2) ; + + if (!isBoundaryMarked(d)) + { + assert(isFaceTriangle(d)) ; + Dart d1 = phi2(phi1(d)) ; + Dart d2 = phi2(phi_1(d)) ; + phi2unsew(d1) ; + phi2unsew(d2) ; + phi2sew(d1, d2) ; + } + Dart e = phi2(d) ; if (!isBoundaryMarked(e)) { @@ -393,20 +450,34 @@ void Map2::extractTrianglePair(Dart d) phi2unsew(e2) ; phi2sew(e1, e2) ; } - Dart d1 = phi2(phi1(d)) ; - Dart d2 = phi2(phi_1(d)) ; - phi2unsew(d1) ; - phi2unsew(d2) ; - phi2sew(d1, d2) ; + } void Map2::insertTrianglePair(Dart d, Dart v1, Dart v2) { +// assert(sameOrientedVertex(v1, v2)) ; +// assert((v1 != v2 && phi2(d) != d) || (v1 == v2 && phi2(d) == d)) ; +// assert(isFaceTriangle(d) && phi2(phi1(d)) == phi1(d) && phi2(phi_1(d)) == phi_1(d)) ; +// Dart e = phi2(d) ; +// if(e != d && v1 != v2) +// { +// assert(isFaceTriangle(e) && phi2(phi1(e)) == phi1(e) && phi2(phi_1(e)) == phi_1(e)) ; +// Dart vv2 = phi2(v2) ; +// phi2unsew(v2) ; +// phi2sew(phi_1(e), v2) ; +// phi2sew(phi1(e), vv2) ; +// } +// Dart vv1 = phi2(v1) ; +// phi2unsew(v1) ; +// phi2sew(phi_1(d), v1) ; +// phi2sew(phi1(d), vv1) ; + + assert(sameOrientedVertex(v1, v2)) ; assert((v1 != v2 && !isBoundaryMarked(d)) || (v1 == v2 && isBoundaryMarked(d))) ; assert(isFaceTriangle(d) && isBoundaryMarked(phi1(d)) && isBoundaryMarked(phi_1(d)) ) ; Dart e = phi2(d) ; - if( !isBoundaryMarked(e) && v1 != v2) + if (!isBoundaryEdge(d) && v1 != v2) { assert( isFaceTriangle(e) && isBoundaryMarked(phi1(e)) && isBoundaryMarked(phi_1(e)) ) ; Dart vv2 = phi2(v2) ; @@ -440,10 +511,68 @@ void Map2::unsewAroundVertex(Dart d) while(e != d); } +//void Map2::explodPolyhedron(Dart d) +//{ +// unsewAroundVertex(d); +//// closeHole(phi1(d)); +// +// //Recherche du (ou un des) sommet oppose +// //tourner autour du sommet +// //si quad alors sommet oppose +// // +// //si pas de quad alors un sommet du trian +// +// // +//} + bool Map2::mergeVolumes(Dart d, Dart e) { +// // First traversal of both faces to check the face sizes +// // and stored their edges to efficiently access them further +// std::vector dDarts; +// std::vector eDarts; +// dDarts.reserve(16); // usual faces have less than 16 edges +// eDarts.reserve(16); +// +// Dart dFit = d ; +// Dart eFit = phi1(e) ; // must take phi1 because of the use +// do // of reverse iterator for sewing loop +// { +// dDarts.push_back(dFit) ; +// dFit = phi1(dFit) ; +// } while(dFit != d) ; +// do +// { +// eDarts.push_back(eFit) ; +// eFit = phi1(eFit) ; +// } while(eFit != phi1(e)) ; +// +// if(dDarts.size() != eDarts.size()) +// return false ; +// +// // Make the sewing: take darts in initial order (clockwise) in first face +// // and take darts in reverse order (counter-clockwise) in the second face +// std::vector::iterator dIt; +// std::vector::reverse_iterator eIt; +// for (dIt = dDarts.begin(), eIt = eDarts.rbegin(); dIt != dDarts.end(); ++dIt, ++eIt) +// { +// Dart d2 = phi2(*dIt); // Search the faces adjacent to dNext and eNext +// Dart e2 = phi2(*eIt); +// if (d2 != *dIt) phi2unsew(d2); // Unlink the two adjacent faces from dNext and eNext +// if (e2 != *eIt) phi2unsew(e2); +// if (d2 != *dIt && e2 != *eIt) phi2sew(d2,e2); // Link the two adjacent faces together if they exists +// } +// Map1::deleteOrientedFace(d); // Delete the two alone faces +// Map1::deleteOrientedFace(e); +// +// return true ; + + if (isBoundaryMarked(d) || isBoundaryMarked(e)) + return false; + // First traversal of both faces to check the face sizes // and stored their edges to efficiently access them further + std::vector dDarts; std::vector eDarts; dDarts.reserve(16); // usual faces have less than 16 edges @@ -473,9 +602,11 @@ bool Map2::mergeVolumes(Dart d, Dart e) { Dart d2 = phi2(*dIt); // Search the faces adjacent to dNext and eNext Dart e2 = phi2(*eIt); - if (d2 != *dIt) phi2unsew(d2); // Unlink the two adjacent faces from dNext and eNext - if (e2 != *eIt) phi2unsew(e2); - if (d2 != *dIt && e2 != *eIt) phi2sew(d2,e2); // Link the two adjacent faces together if they exists + phi2unsew(d2); // Unlink the two adjacent faces from dNext and eNext + phi2unsew(e2); + phi2sew(d2,e2); // Link the two adjacent faces together + if (isBoundaryMarked(d2) && isBoundaryMarked(e2)) + mergeBoundaryFaces(d2,e2); } Map1::deleteOrientedFace(d); // Delete the two alone faces Map1::deleteOrientedFace(e); @@ -520,15 +651,26 @@ unsigned int Map2::closeHole(Dart d) return countEdges ; } -void Map2::closeMap(DartMarker& marker) -{ - // Search the map for topological holes (fixed point for phi2) +//void Map2::closeMap(DartMarker& marker) +//{ +// // Search the map for topological holes (fixed point for phi2) +// for (Dart d = begin(); d != end(); next(d)) +// { +// if (phi2(d) == d) +// { +// closeHole(d); +// marker.markOrbit(FACE, phi2(d)) ; +// } +// } +// +void Map2::closeMap() +{ // Search the map for topological holes (fixed point for phi2) for (Dart d = begin(); d != end(); next(d)) { if (phi2(d) == d) { closeHole(d); - marker.markOrbit(FACE, phi2(d)) ; + boundaryMarkOrbit(FACE,phi2(d)); } } } @@ -577,6 +719,36 @@ unsigned int Map2::vertexDegree(Dart d) unsigned int Map2::volumeDegree(Dart d) { +// unsigned int count = 0; +// DartMarkerStore mark(*this); // Lock a marker +// +// std::vector visitedFaces; // Faces that are traversed +// visitedFaces.reserve(16); +// visitedFaces.push_back(d); // Start with the face of d +// std::vector::iterator face; +// +// // For every face added to the list +// for (face = visitedFaces.begin(); face != visitedFaces.end(); ++face) +// { +// if (!mark.isMarked(*face)) // Face has not been visited yet +// { +// ++count; +// +// Dart dNext = *face ; +// do +// { +// mark.mark(dNext); // Mark +// Dart adj = phi2(dNext); // Get adjacent face +// if (adj != dNext && !mark.isMarked(adj)) +// visitedFaces.push_back(adj); // Add it +// dNext = phi1(dNext); +// } while(dNext != *face); +// } +// } +// +// return count; + + unsigned int count = 0; DartMarkerStore mark(*this); // Lock a marker @@ -586,25 +758,27 @@ unsigned int Map2::volumeDegree(Dart d) std::vector::iterator face; // For every face added to the list - for (face = visitedFaces.begin(); face != visitedFaces.end(); ++face) + for (unsigned int i=0; i != visitedFaces.size(); ++i) { - if (!mark.isMarked(*face)) // Face has not been visited yet + Dart df = visitedFaces[i]; + if (!isBoundaryMarked(df) && !mark.isMarked(df)) // Face has not been visited yet { ++count; - Dart dNext = *face ; + Dart dNext = df ; do { mark.mark(dNext); // Mark Dart adj = phi2(dNext); // Get adjacent face - if (adj != dNext && !mark.isMarked(adj)) + if ( !isBoundaryMarked(adj) && !mark.isMarked(adj) ) visitedFaces.push_back(adj); // Add it dNext = phi1(dNext); - } while(dNext != *face); + } while(dNext != df); } } return count; + } bool Map2::isBoundaryVertex(Dart d) @@ -621,14 +795,33 @@ bool Map2::isBoundaryVertex(Dart d) Dart dNext = d ; do { - if (isBoundaryMarked(phi2(dNext))) + if (isBoundaryMarked(dNext)) return true ; dNext = alpha1(dNext) ; } while (dNext != d) ; return false ; +} + +Dart Map2::findBoundaryVertex(Dart d) +{ + Dart dNext = d ; + do + { + if (isBoundaryMarked(dNext)) + return dNext ; + dNext = alpha1(dNext) ; + } while (dNext != d) ; + return Dart::nil(); +} + +bool Map2::isBoundaryEdge(Dart d) +{ + Dart e = phi2(d); + return isBoundaryMarked(e) || isBoundaryMarked(d); } + Dart Map2::nextOnBoundary(Dart d) { // assert(phi2(d) == d); // Only work on boundary dart @@ -660,11 +853,15 @@ bool Map2::isTriangular() if(!m.isMarked(d)) { m.markOrbit(FACE, d) ; - Dart dd = d ; - bool t = isFaceTriangle(d) ; - if(!t) + Dart dd = d ; // ??? + + if (!isBoundaryMarked(d)) { - return false ; + bool t = isFaceTriangle(d) ; + if(!t) + { + return false ; + } } } } @@ -731,18 +928,23 @@ bool Map2::foreach_dart_of_vertex(Dart d, FunctorType& f, unsigned int thread) dNext = alpha1(dNext); } while (dNext != d); return false; + } bool Map2::foreach_dart_of_edge(Dart d, FunctorType& fonct, unsigned int thread) { +// if (fonct(d)) +// return true; +// +// Dart d2 = phi2(d); +// if (d2 != d) +// return fonct(d2); +// else +// return false; + if (fonct(d)) return true; - - Dart d2 = phi2(d); - if (d2 != d) - return fonct(d2); - else - return false; + return fonct(phi2(d)); } bool Map2::foreach_dart_of_oriented_volume(Dart d, FunctorType& f, unsigned int thread)