diff --git a/Apps/Tuto/stage_shader.h b/Apps/Tuto/stage_shader.h index 22f86d73f9a2091eda73c6b5e8d839f57153cb26..83577d1aa23edb4aa840a4e1da160716b79ed035 100644 --- a/Apps/Tuto/stage_shader.h +++ b/Apps/Tuto/stage_shader.h @@ -49,6 +49,8 @@ #include "Algo/Render/GL2/topo3Render.h" #include "Utils/Shaders/shaderSimpleColor.h" + + #include "Utils/cgognStream.h" #include "Utils/drawer.h" diff --git a/include/Algo/BooleanOperator/mergeVertices.h b/include/Algo/BooleanOperator/mergeVertices.h new file mode 100644 index 0000000000000000000000000000000000000000..b6c55245891a6c2c9601c58c877fd4d5406e2e06 --- /dev/null +++ b/include/Algo/BooleanOperator/mergeVertices.h @@ -0,0 +1,55 @@ +/******************************************************************************* +* 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 * +* * +*******************************************************************************/ + +#ifndef __ALGO_BOOLEANOPERATOR_VERTICES_H__ +#define __ALGO_BOOLEANOPERATOR_VERTICES_H__ + +#include "Geometry/basic.h" +#include "Geometry/inclusion.h" +#include "Geometry/orientation.h" + +namespace CGoGN +{ + +namespace Algo +{ + +namespace BooleanOperator +{ + +template +void mergeVertex(typename PFP::MAP& map, const typename PFP::TVEC3& positions, Dart d, Dart e); + +template +void mergeVertices(typename PFP::MAP& map, const typename PFP::TVEC3& positions); + +} + +} + +} + +#include "mergeVertices.hpp" + +#endif diff --git a/include/Algo/BooleanOperator/mergeVertices.hpp b/include/Algo/BooleanOperator/mergeVertices.hpp new file mode 100644 index 0000000000000000000000000000000000000000..572cd0740995b877896cc7c2cd40718e3c38dbe3 --- /dev/null +++ b/include/Algo/BooleanOperator/mergeVertices.hpp @@ -0,0 +1,82 @@ +/******************************************************************************* +* 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 * +* * +*******************************************************************************/ + +namespace CGoGN +{ + +namespace Algo +{ + +namespace BooleanOperator +{ + +template +void mergeVertex(typename PFP::MAP& map, const typename PFP::TVEC3& positions, Dart d, Dart e) +{ + assert(Geom::arePointsEquals(positions[d],positions[e]) && !map.sameVertex(d,e)); + Dart dd; + do + { + dd = map.alpha1(d); + map.removeEdgeFromVertex(dd); + Dart ee = e; + do + { + if(Geom::testOrientation2D(positions[map.phi1(dd)],positions[ee],positions[map.phi1(ee)])!=Geom::RIGHT + && Geom::testOrientation2D(positions[map.phi1(dd)],positions[ee],positions[map.phi1(map.alpha1(ee))])==Geom::RIGHT) + { + break; + } + ee = map.alpha1(ee); + } while(ee != e); + map.insertEdgeInVertex(ee,dd); + } while(dd!=d); +} + +template +void mergeVertices(typename PFP::MAP& map, const typename PFP::TVEC3& positions) +{ + for(Dart d = map.begin() ; d != map.end() ; map.next(d)) + { + CellMarker vM(map,VERTEX); + vM.mark(d); + for(Dart dd = map.begin() ; dd != map.end() ; map.next(dd)) + { + if(!vM.isMarked(dd)) + { + vM.mark(dd); + if(Geom::arePointsEquals(positions[d],positions[dd])) + { + mergeVertex(map,positions,d,dd); + } + } + } + } +} + +} + +} + +} diff --git a/include/Algo/Export/exportPov.h b/include/Algo/Export/exportPov.h index 0b97ad352cc8e66acf72e1ac1dc846d6c52a56a7..67acd12598a074b8ade320bd40aa47a57076fb98 100644 --- a/include/Algo/Export/exportPov.h +++ b/include/Algo/Export/exportPov.h @@ -95,7 +95,7 @@ void exportMeshWire(std::ofstream& out, typename PFP::MAP& map, typename PFP::TV if(position[dd][0]!=position[map.phi1(dd)][0] || position[dd][1]!=position[map.phi1(dd)][1] || position[dd][2]!=position[map.phi1(dd)][2]) { out << "cylinder{ " << std::endl; out << "<" << position[dd][0] << "," << position[dd][2] << "," << position[dd][1] << ">," << std::endl; - out << "<" << position[map.phi1(dd)][0] << "," << position[map.phi1(dd)][2] << "," << position[map.phi1(dd)][1] << ">, 0.5" << std::endl; + out << "<" << position[map.phi1(dd)][0] << "," << position[map.phi1(dd)][2] << "," << position[map.phi1(dd)][1] << ">, 1.5" << std::endl; out << "}" << std::endl; } dd = map.phi1(dd); diff --git a/include/Algo/Geometry/intersection.hpp b/include/Algo/Geometry/intersection.hpp index d03d7b86bfab128a652bdaffebcda36f10f04468..b66a9aa33645d652e3618ba211ab4a0ce32f634a 100644 --- a/include/Algo/Geometry/intersection.hpp +++ b/include/Algo/Geometry/intersection.hpp @@ -24,6 +24,7 @@ #include "Algo/Geometry/normal.h" #include "Algo/Geometry/centroid.h" +#include "intersection.h" #include @@ -37,17 +38,18 @@ namespace Geometry { template -bool intersectionLineConvexFace(typename PFP::MAP& map, Dart d, const typename PFP::TVEC3& position, const typename PFP::VEC3& P, const typename PFP::VEC3& Dir, typename PFP::VEC3& Inter) +bool intersectionLineConvexFace(typename PFP::MAP& map, Dart d, const typename PFP::TVEC3& positions, const typename PFP::VEC3& P, const typename PFP::VEC3& Dir, typename PFP::VEC3& Inter) { + typedef typename PFP::VEC3 VEC3 ; const float SMALL_NUM = std::numeric_limits::min() * 5.0f; - VEC3 p1 = position[d]; - VEC3 n = faceNormal(map, d, position); + VEC3 p1 = positions[d]; + VEC3 n = faceNormal(map,d,positions); VEC3 w0 = P - p1; - float a = -(n * w0); - float b = n * Dir; + float a = -(n*w0); + float b = n*Dir; if (fabs(b) < SMALL_NUM) return false; @@ -56,7 +58,7 @@ bool intersectionLineConvexFace(typename PFP::MAP& map, Dart d, const typename P Inter = P + r * Dir; // intersect point of ray and plane // is I inside the face? - VEC3 p2 = position[map.phi1(d)]; + VEC3 p2 = positions[map.phi1(d)]; VEC3 v = p2 - p1 ; VEC3 vInter = Inter - p1; float dirV = v * vInter; @@ -67,7 +69,7 @@ bool intersectionLineConvexFace(typename PFP::MAP& map, Dart d, const typename P while(it != d) { p1 = p2; - p2 = position[map.phi1(it)]; + p2 = positions[map.phi1(it)]; v = p2 - p1; vInter = Inter - p1; float dirD = v * vInter; @@ -83,22 +85,22 @@ bool intersectionLineConvexFace(typename PFP::MAP& map, Dart d, const typename P } template -bool intersectionSegmentConvexFace(typename PFP::MAP& map, Dart d, const typename PFP::TVEC3& position, const typename PFP::VEC3& PA, const typename PFP::VEC3& PB, typename PFP::VEC3& Inter) +bool intersectionSegmentConvexFace(typename PFP::MAP& map, Dart d, const typename PFP::TVEC3& positions, const typename PFP::VEC3& PA, const typename PFP::VEC3& PB, typename PFP::VEC3& Inter) { typename PFP::VEC3 dir = PB - PA; - if (intersectionLineConvexFace(map, d, position, PA, dir, Inter)) + if (intersectionLineConvexFace(map,d,positions,PA,dir,Inter)) { typename PFP::VEC3 dirA = PA - Inter; - typename PFP::VEC3 dirB = PB - Inter; + typename PFP::VEC3 dirB = PB -Inter; - if (dirA * dirB < 0) + if ( (dirA*dirB) < 0 ) return true; } return false; } template -bool areTrianglesInIntersection(typename PFP::MAP& map, Dart tri1, Dart tri2, const typename PFP::TVEC3& position) +bool areTrianglesInIntersection(typename PFP::MAP& map, Dart tri1, Dart tri2, const typename PFP::TVEC3& positions) { typedef typename PFP::VEC3 VEC3 ; @@ -107,8 +109,8 @@ bool areTrianglesInIntersection(typename PFP::MAP& map, Dart tri1, Dart tri2, co VEC3 tris2[3]; for (unsigned int i = 0; i < 3; ++i) { - tris1[i] = position[tri1]; - tris2[i] = position[tri2]; + tris1[i] = positions[tri1]; + tris2[i] = positions[tri2]; tri1 = map.phi1(tri1); tri2 = map.phi1(tri2); } @@ -165,8 +167,8 @@ bool areTrianglesInIntersection(typename PFP::MAP& map, Dart tri1, Dart tri2, co // return isSegmentInTriangle2D(inter1,inter2,tris2[0],tris2[1],triS2[2],nTri2); //compute face normal - VEC3 normale1 = faceNormal(map, tri1, position); - VEC3 bary1 = faceCentroid(map, tri1, position); + VEC3 normale1 = faceNormal(map,tri1,positions); + VEC3 bary1 = faceCentroid(map,tri1,positions); int pos = 0; int neg = 0; @@ -186,8 +188,8 @@ bool areTrianglesInIntersection(typename PFP::MAP& map, Dart tri1, Dart tri2, co return false; //same for the second triangle - VEC3 normale2 = faceNormal(map, tri2, position); - VEC3 bary2 = faceCentroid(map, tri2, position); + VEC3 normale2 = faceNormal(map,tri2,positions); + VEC3 bary2 = faceCentroid(map,tri2,positions); pos = 0; neg = 0; for (unsigned int i = 0; i < 3 ; ++i) @@ -208,7 +210,7 @@ bool areTrianglesInIntersection(typename PFP::MAP& map, Dart tri1, Dart tri2, co for (unsigned int i = 0; i < 3 && !intersection; ++i) { VEC3 inter; - intersection = Geom::intersectionSegmentTriangle(tris1[i], tris1[(i+1)%3], tris2[0], tris2[1], tris2[2], inter); + intersection = Geom::intersectionSegmentTriangle(tris1[i],tris1[(i+1)%3],tris2[0],tris2[1],tris2[2],inter); } if (intersection) @@ -217,34 +219,14 @@ bool areTrianglesInIntersection(typename PFP::MAP& map, Dart tri1, Dart tri2, co for (unsigned int i = 0; i < 3 && !intersection; ++i) { VEC3 inter; - intersection = Geom::intersectionSegmentTriangle(tris2[i], tris2[(i+1)%3], tris1[0], tris1[1], tris1[2], inter); + intersection = Geom::intersectionSegmentTriangle(tris2[i],tris2[(i+1)%3],tris1[0],tris1[1],tris1[2],inter); } return intersection; } -template -bool intersectionSphereEdge(typename PFP::MAP& map, typename PFP::VEC3& center, typename PFP::REAL radius, Dart d, const typename PFP::TVEC3& position, typename PFP::REAL& alpha) -{ - typedef typename PFP::VEC3 VEC3 ; - typedef typename PFP::REAL REAL ; - - const typename PFP::VEC3& p1 = position[d]; - const typename PFP::VEC3& p2 = position[map.phi1(d)]; - if(Geom::isPointInSphere(p1, center, radius) && !Geom::isPointInSphere(p2, center, radius)) - { - VEC3 p = p1 - center; - VEC3 qminusp = p2 - center - p; - REAL s = p * qminusp; - REAL n2 = qminusp.norm2(); - alpha = (- s + sqrt(s*s + n2 * (radius*radius - p.norm2()))) / n2; - return true ; - } - return false ; } -} // namespace Geometry - -} // namespace Algo +} -} // namespace CGoGN +} diff --git a/include/Algo/ImplicitHierarchicalMesh/subdivision3.h b/include/Algo/ImplicitHierarchicalMesh/subdivision3.h index 586b0d822543f0bea52f5d8f1b17636dcbb691e8..40de7c90a8e7b31cbb2c200aa39c81176d3e1161 100644 --- a/include/Algo/ImplicitHierarchicalMesh/subdivision3.h +++ b/include/Algo/ImplicitHierarchicalMesh/subdivision3.h @@ -62,6 +62,15 @@ void coarsenFace(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position); template void coarsenVolume(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position); +/*********************************************************************************** + * Raffinement + ***********************************************************************************/ +/* + * Un brin de la face oppose aux faces a spliter + */ +template +void splitVolume(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position); + /******************************************************* * */ diff --git a/include/Algo/ImplicitHierarchicalMesh/subdivision3.hpp b/include/Algo/ImplicitHierarchicalMesh/subdivision3.hpp index 1bd9353da6124f04d6eb8bdd784a65e9a1145935..c47542cb3e98bee9f2ade9df946a0bdd60010ee1 100644 --- a/include/Algo/ImplicitHierarchicalMesh/subdivision3.hpp +++ b/include/Algo/ImplicitHierarchicalMesh/subdivision3.hpp @@ -173,12 +173,11 @@ Dart subdivideVolume(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& positi 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") ; - unsigned int vLevel = map.volumeLevel(d) ; - Dart old = map.volumeOldestDart(d) ; - - unsigned int cur = map.getCurrentLevel() ; - map.setCurrentLevel(vLevel) ; // go to the level of the face to subdivide its edges + unsigned int vLevel = map.volumeLevel(d); + Dart old = map.volumeOldestDart(d); + unsigned int cur = map.getCurrentLevel(); + map.setCurrentLevel(vLevel); /* * au niveau du volume courant i @@ -740,10 +739,81 @@ void coarsenVolume(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position } /*********************************************************************************** + * Raffinement + ***********************************************************************************/ +template +void splitVolume(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.volumeIsSubdivided(d) || !"Trying to subdivide an already subdivided volume") ; + + unsigned int cur = map.getCurrentLevel() ; + unsigned int vLevel = map.volumeLevel(d) ; + map.setCurrentLevel(vLevel) ; + + // 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); + + unsigned int fLevel = map.faceLevel(map.phi1(d)); + map.setCurrentLevel(fLevel+1) ; // go to the level of the face to subdivide its edges + Dart neighboordVolume = map.phi1(map.phi1(map.phi2(d))); + //map.setCurrentLevel(cur) ; // go to the next level to perform volume subdivision + + //Split the faces and open the midlle + do + { + Dart t2 = map.phi2(t); + + unsigned int fLevel = map.faceLevel(t2) ; + map.setCurrentLevel(fLevel+1) ; // go to the level of the face to subdivide its edges + + Dart face2 = map.phi1(map.phi1(t2)); + map.splitFace(map.phi_1(t2), face2); + map.unsewFaces(map.phi1(map.phi1(t2))); + + //id de face pour les 2 nouveaux brins + unsigned int idface = map.getFaceId(t2); + map.setFaceId(map.phi1(map.phi1(t2)), idface, DART); + map.setFaceId(map.phi_1(face2), idface, DART); + + t = map.phi1(t); + } + while(t != d); + + //close the middle to create volumes & sew them + map.setCurrentLevel(vLevel + 1) ; // go to the next level to perform volume subdivision + + 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))); + + unsigned int idface = map.getNewFaceId(); + map.setFaceId(map.phi2(map.phi_1(neighboordVolume)), idface, FACE); + + do + { + Dart t211 = map.phi1(map.phi1(map.phi2(t))); + + unsigned int idedge = map.getNewEdgeId(); + map.setEdgeId(t211, idedge, EDGE); + t = map.phi1(t); + } + while(t != d); + + map.setCurrentLevel(cur) ; +} + +/************************************************************************************* * */ - template void subdivideVolume(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position, SubdivideType sType) { diff --git a/include/Algo/Import/importSvg.h b/include/Algo/Import/importSvg.h new file mode 100644 index 0000000000000000000000000000000000000000..fe5ff9df0de4955fcd1a3c5e71e100557034196c --- /dev/null +++ b/include/Algo/Import/importSvg.h @@ -0,0 +1,47 @@ +#ifndef __IMPORTSVG_H__ +#define __IMPORTSVG_H__ + +namespace CGoGN +{ + +namespace Algo +{ + +namespace Import +{ + +/** + * check if an xml node has a given name + * @param node the xml node + * @param name the name + * @ return true if node has the good name + */ +bool checkXmlNode(xmlNodePtr node, const std::string& name); + +template +bool importSVG(typename PFP::MAP& map, const std::string& filename, typename PFP::TVEC3& position, CellMarker& polygons); + + +/** + * + */ + +template +bool readSVG(const std::string& filename, std::vector > &allPoly); + +template +bool importBB(const std::string& filename, std::vector > &bb); + +template +bool importSVG(typename PFP::MAP& map, const std::string& filename, std::vector& attrNames); + + +} + +} + +} + +#include "Algo/Import/importSvg.hpp" + +#endif diff --git a/include/Algo/Import/importSvg.hpp b/include/Algo/Import/importSvg.hpp new file mode 100644 index 0000000000000000000000000000000000000000..adf107cfc2e0f94304fdc9485065ff65d1a52ae6 --- /dev/null +++ b/include/Algo/Import/importSvg.hpp @@ -0,0 +1,698 @@ +#include +#include "Geometry/bounding_box.h" +#include "Geometry/plane_3d.h" +#include "Algo/BooleanOperator/mergeVertices.h" +#include + +namespace CGoGN +{ + +namespace Algo +{ + +namespace Import +{ + +inline bool checkXmlNode(xmlNodePtr node, const std::string& name) +{ + return (strcmp((char*)(node->name),(char*)(name.c_str())) == 0); +} + +template +inline bool valueOf(const std::string &s, T &obj) +{ + std::istringstream is(s); + return is >> obj; +} + +template +bool posSort(const std::pair& a1, const std::pair& a2) +{ + VEC v1 = a1.first; + VEC v2 = a2.first; + return v1[0] < v2[0] || (v1[0] == v2[0] && v1[1] < v2[1]); +} + +template +void getPolygonFromSVG(std::string allcoords, std::vector& curPoly, bool& closedPoly) +{ + closedPoly=false; + std::stringstream is(allcoords); + bool relative=false; + bool push_point; + std::string coord; + int mode = -1; + + while ( std::getline( is, coord, ' ' ) ) + { + float x,y; + push_point=false; + + if(coord[0]=='m' || coord[0]=='l' || coord[0]=='t') //start point, line or quadratic bezier curve + { + mode = 0; +// std::cout << "relative coordinates" << std::endl; + relative=true; + } + else if(coord[0]=='M' || coord[0] == 'L' || coord[0]=='T') //same in absolute coordinates + { +// std::cout << "absolute coordinates" << std::endl; + mode = 1; + relative=false; + } + else if(coord[0]=='h' || coord[0] == 'H') //horizontal line + { + mode = 2; + relative=(coord[0]=='h'); + } + else if(coord[0]=='v' || coord[0] == 'V') //vertical line + { +// std::cout << "vertical line" << std::endl; + mode = 3; + relative=(coord[0]=='v'); + } + else if(coord[0]=='c' || coord[0] == 'C') //bezier curve + { +// std::cout << "bezier line" << std::endl; + mode = 4; + relative=(coord[0]=='c'); + } + else if(coord[0]=='s' || coord[0] == 'S' || coord[0]=='q' || coord[0] == 'Q') //bezier curve 2 + { +// std::cout << "bezier line 2" << std::endl; + mode = 5; + relative= ((coord[0]=='s') || (coord[0]=='q')); + } + else if(coord[0]=='a' || coord[0] == 'A') //elliptic arc + { +// std::cout << "elliptic arc" << std::endl; + mode =6; + relative= (coord[0]=='a'); + } + else if(coord[0]=='z') + { +// std::cout << "the end" << std::endl; + closedPoly = true; + } + else //coordinates + { + switch(mode) + { + case 0 : //relative + break; + case 1 : //absolute + break; + case 2 : //horizontal + { + std::stringstream streamCoord(coord); + std::string xS; + std::getline(streamCoord, xS, ',' ); + + valueOf(xS,x); + + VEC3 previous = (curPoly)[(curPoly).size()-1]; + y = previous[1]; + + push_point=true; + } + break; + case 3 : //vertical + { + std::stringstream streamCoord(coord); + std::string yS; + std::getline(streamCoord, yS, ',' ); + + valueOf(yS,y); + + typename PFP::VEC3 previous = (curPoly)[(curPoly).size()-1]; + x = previous[0]; + + push_point=true; + } + break; + case 4 : //bezier + { + std::getline( is, coord, ' ' ); //ignore first control point + std::getline( is, coord, ' ' ); //ignore second control point + } + break; + case 5 : //bezier 2 + { + std::getline( is, coord, ' ' ); //ignore control point + + } + break; + case 6 : //elliptic + std::getline( is, coord, ' ' ); //ignore rx + std::getline( is, coord, ' ' ); //ignore ry + std::getline( is, coord, ' ' ); //ignore x-rotation + std::getline( is, coord, ' ' ); //ignore large arc flag + std::getline( is, coord, ' ' ); //ignore sweep flag + break; + } + + std::stringstream streamCoord(coord); + std::string xS,yS; + std::getline(streamCoord, xS, ',' ); + std::getline(streamCoord, yS, ',' ); + + valueOf(xS,x); + valueOf(yS,y); + + push_point = true; + } + + //if there is a point to push + if(push_point) + { + + VEC3 previous; + + if(curPoly.size()>0) + previous = (curPoly)[(curPoly).size()-1]; + + if(relative) + { + x += previous[0]; + y += previous[1]; + } + +// std::cout << "coord " << x << " " << y << std::endl; + + if(curPoly.size()==0 || (curPoly.size()>0 && (x!=previous[0] || y!= previous[1]))) + curPoly.push_back(VEC3(x,y,0)); + } + } +} + +template +bool importSVG(typename PFP::MAP& map, const std::string& filename, typename PFP::TVEC3& position, CellMarker& polygons, CellMarker& polygonsFaces) +{ + typedef typename PFP::VEC3 VEC3; + typedef std::vector POLYGON; + + xmlDocPtr doc = xmlReadFile(filename.c_str(), NULL, 0); + xmlNodePtr map_node = xmlDocGetRootElement(doc); + + if (!checkXmlNode(map_node,"svg")) + { + CGoGNerr << "Wrong xml format: Root node != svg"<< CGoGNendl; + return false; + } + + std::vector allPoly; + std::vector allBrokenLines; + std::vector allBrokenLinesWidth; + bool closedPoly; + + for (xmlNode* cur_node = map_node->children; cur_node; cur_node = cur_node->next) + { + // for each layer + if (checkXmlNode(cur_node, "g")) + { +// CGoGNout << "----load layer----"<< CGoGNendl; + + for (xmlNode* cur_path = cur_node->children ; cur_path; cur_path = cur_path->next) + { + if (checkXmlNode(cur_path, "path")) + { + POLYGON curPoly; +// CGoGNout << "--load a path--"<< CGoGNendl; + xmlChar* prop = xmlGetProp(cur_path, BAD_CAST "d"); + std::string allcoords((reinterpret_cast(prop))); + getPolygonFromSVG(allcoords,curPoly,closedPoly); + + //check orientation : set in CCW + if(curPoly.size()>2) + { + VEC3 v1(curPoly[1]-curPoly[0]); + VEC3 v2(curPoly[2]-curPoly[1]); + if((v1^v2)[2]>0) + { + std::reverse(curPoly.begin(), curPoly.end()); + } + } + + if(closedPoly) + allPoly.push_back(curPoly); + else + { + allBrokenLines.push_back(curPoly); + xmlChar* prop = xmlGetProp(cur_path, BAD_CAST "style"); + std::string allstyle((reinterpret_cast(prop))); + std::stringstream is(allstyle); + std::string style; + while ( std::getline( is, style, ';' ) ) + { + if(style.find("stroke-width:")!=std::string::npos) + { + std::stringstream isSize(style); + std::getline( isSize, style, ':' ); + float sizeOfLine; + isSize >> sizeOfLine; + allBrokenLinesWidth.push_back(sizeOfLine); + } + } + } + } + } + } + else + { + xmlNode* cur_path = cur_node; + if (checkXmlNode(cur_path, "path")) + { + POLYGON curPoly; +// CGoGNout << "--load a path--"<< CGoGNendl; + xmlChar* prop = xmlGetProp(cur_path, BAD_CAST "d"); + std::string allcoords((reinterpret_cast(prop))); + getPolygonFromSVG(allcoords,curPoly,closedPoly); + + //check orientation : set in CCW + if(curPoly.size()>2) + { + VEC3 v1(curPoly[1]-curPoly[0]); + VEC3 v2(curPoly[2]-curPoly[1]); + if((v1^v2)[2]>0) + { + std::reverse(curPoly.begin(), curPoly.end()); + } + } + + if(closedPoly) + allPoly.push_back(curPoly); + else + { + allBrokenLines.push_back(curPoly); + xmlChar* prop = xmlGetProp(cur_path, BAD_CAST "style"); + std::string allstyle((reinterpret_cast(prop))); + std::stringstream is(allstyle); + std::string style; + while ( std::getline( is, style, ';' ) ) + { + if(style.find("stroke-width:")!=std::string::npos) + { + std::stringstream isSize(style); + std::getline( isSize, style, ':' ); + float sizeOfLine; + isSize >> sizeOfLine; + std::cout << "sizeOfLine : " << sizeOfLine << std::endl; + allBrokenLinesWidth.push_back(sizeOfLine); + } + } + } + } + } + } + + xmlFreeDoc(doc); + + Geom::BoundingBox * bb; + if(allBrokenLines.size()>0) + bb = new Geom::BoundingBox(*(allBrokenLines.begin()->begin())); + else if(allPoly.size()>0) + bb = new Geom::BoundingBox(*(allPoly.begin()->begin())); + else + { + std::cerr << " no usable data in svg file " << std::endl; + return false; + } + + CellMarker brokenMark(map,EDGE); + AttributeHandler edgeWidth = map.template addAttribute(EDGE, "width"); + AttributeHandler > > edgePlanes = map.template addAttribute > >(EDGE, "planes"); + + ///////////////////////////////////////////////////////////////////////////////////////////// + //create broken lines + DartMarker brokenL(map); + + std::vector::iterator itW = allBrokenLinesWidth.begin(); + for(typename std::vector::iterator it = allBrokenLines.begin() ; it != allBrokenLines.end() ; ++it) + { + if(it->size()<2) + { + it = allBrokenLines.erase(it); + itW = allBrokenLinesWidth.erase(itW); + } + else + { + unsigned int faceDegree = it->size()*2-2; + Dart d = map.newFace(faceDegree); + + polygonsFaces.mark(d); + + Dart d1=d; + Dart d_1=map.phi_1(d); + for(unsigned int i = 0; ibegin(); emb != it->end() ; emb++) + { + bb->addPoint(*emb); + position[dd] = *emb; + dd = map.phi1(dd); + } + +// do +// { +// bb->addPoint(*emb); +// position[dd] = *emb; +// std::cout << "emb " << *emb << std::endl; +// emb++; +// dd = map.phi1(dd); +// } while(dd!=map.phi_1(d)); + + } + + itW++; + } + + ///////////////////////////////////////////////////////////////////////////////////////////// + //create polygons + typename std::vector::iterator it; + for(it = allPoly.begin() ; it != allPoly.end() ; ++it) + { + + if(it->size()<4) + { + it = allPoly.erase(it); + } + else + { + Dart d = map.newFace(it->size()-1); +// std::cout << "newFace1 " << it->size()-1 << std::endl; + polygonsFaces.mark(d); + + Dart dd = d; + typename POLYGON::iterator emb = it->begin(); + do + { + bb->addPoint(*emb); + position[dd] = *emb; + emb++; + dd = map.phi1(dd); + } while(dd!=d); + } + } + + for(Dart d = map.begin();d != map.end(); map.next(d)) + { + if(position[d][0] == position[map.phi1(d)][0] && position[d][1] == position[map.phi1(d)][1]) + std::cout << "prob d " << d << std::endl; + } + + DartMarker inside(map); + + for(Dart d = map.begin(); d != map.end(); map.next(d)) + { + polygons.mark(d); + inside.mark(d); + } + + DartMarker close(map); + map.closeMap(close); + + Algo::BooleanOperator::mergeVertices(map,position); + + ///////////////////////////////////////////////////////////////////////////////////////////// + //add bounding box + + CellMarker boundingBox(map,VERTEX); +// Dart dBorder = map.newFace(4); +// +// VEC3 bbCenter = bb->center(); +// VEC3 bmin = bb->min(); +// bmin += 0.3f*(bmin-bbCenter); +// VEC3 bmax = bb->max(); +// bmax -= 0.3f*(bmin-bbCenter); +// +// position[dBorder] = bmin; +// position[map.phi1(dBorder)] = VEC3(bmax[0],bmin[1],0); +// position[map.phi1(map.phi1(dBorder))] = VEC3(bmax[0],bmax[1],0); +// position[map.phi_1(dBorder)] = VEC3(bmin[0],bmax[1],0); +// +// Dart d = dBorder; +// do +// { +// boundingBox.mark(d); +// d = map.phi1(d); +// } while(d!=dBorder); + + ///////////////////////////////////////////////////////////////////////////////////////////// + //cut the edges to have a more regular sampling +// float maxDist=60.0f; +// CellMarker treated(map,EDGE); +// for(Dart d = map.begin(); d != map.end(); map.next(d)) +// { +// if(!treated.isMarked(d)) +// { +// treated.mark(d); +// VEC3 p1 =position[d]; +// VEC3 p2 =position[map.phi1(d)]; +// +// if((p1-p2).norm()>maxDist) +// { +// unsigned int nbSeg = ((p1-p2).norm())/int(maxDist); +// for(unsigned int i=0;i we convert broken lines to faces to represent their width + // -> the intersection are then closed + + Dart d1 = d; + Dart d2 = map.phi2(d1); + VEC3 p1 = position[d1]; + VEC3 p2 = position[d2]; + float width = edgeWidth[d1]/2.0f; + if(width==0) + std::cout << "importSVG : error width of path is equal to zero" << std::endl; + + VEC3 v = p2-p1; + map.unsewFaces(d1); + + Dart dN = map.newFace(4); + + //take the orthogonal direction to the path to apply width afterward + VEC3 ortho = v^VEC3(0,0,1); + ortho.normalize(); + v.normalize(); + + //if the valence of one of the vertex is equal to one + //cut the edge to insert the quadrangular face + if(map.alpha1(d1)==d1) + { + map.cutEdge(d2); + + brokenL.mark(map.phi1(d2)); + eMTreated.mark(map.phi1(d2)); + map.sewFaces(map.phi_1(d1),map.phi1(dN)); + + position[map.phi_1(d1)]=p1; + edgePlanes[map.phi_1(d1)] = Geom::Plane3D(v,p1); + } + + if(map.alpha1(d2)==d2) + { + map.cutEdge(d1); + brokenL.mark(map.phi1(d1)); + eMTreated.mark(map.phi1(d1)); + + map.sewFaces(map.phi_1(d2), map.phi_1(dN)); + + position[map.phi_1(d2)]=p2; + edgePlanes[map.phi_1(d2)] = Geom::Plane3D(-1.0f*v, p2); + } + + map.sewFaces(d1, dN); + map.sewFaces(d2, map.phi1(map.phi1(dN))); + + edgePlanes[d1] = Geom::Plane3D(ortho, p1-(width*ortho)); + edgePlanes[d2] = Geom::Plane3D(-1.0f*ortho, p2+(width*ortho)); + } + } + + //close the intersections + for(Dart d = map.begin();d != map.end(); map.next(d)) + { + if(d==map.phi2(d)) + map.closeHole(d); + } + + //embed the path + for(Dart d = map.begin();d != map.end(); map.next(d)) + { + if(brokenL.isMarked(d)) + { + Geom::Plane3D pl = edgePlanes[d]; + + VEC3 pos = position[d]; + pl.project(pos); + pl = edgePlanes[map.phi_1(d)]; + + pl.project(pos); + position[d] = pos; + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////// + //process polygons + + +// std::vector > toConnect; +// CellMarker connected(map,VERTEX); +// for(Dart d = map.begin(); d != map.end(); map.next(d)) +// { +// if( ((!boundingBox.isMarked(d) && !inside.isMarked(d)) || (boundingBox.isMarked(d) && inside.isMarked(d))) +// && !connected.isMarked(d) +// ) +// { +// connected.mark(d); +// toConnect.push_back(std::make_pair(position[d],d)); +// } +// } +// +// std::sort(toConnect.begin(), toConnect.end(),posSort); +// +// for(typename std::vector >::iterator it = toConnect.begin(); it != toConnect.end() ; ++it) +// { +// Dart d = it->second; +// typename std::vector >::iterator it2 = it+1; +// if(it2!= toConnect.end()) +// { +// Dart dd = it2->second; +// if(!map.sameFace(map.phi2(d),map.phi2(dd))) +// { +// if(!map.sameFace(dd,d)) { +// std::cout << "link" << std::endl; +// map.linkVertices(dd,d); +// } +// else +// { +// map.splitFace(dd,d); +// std::cout << "split" << std::endl; +// } +// } +// } +// +// } + +// CellMarker connected(map,VERTEX); +// unsigned int i=0; +// for(Dart d = map.begin();d != map.end(); map.next(d)) +// { +// if(!connected.isMarked(d) && !boundingBox.isMarked(d) && !inside.isMarked(d)) +// { +// i++; +// Dart dMin=map.end(); +// float distMin = std::numeric_limits::max(); +// for(Dart dd = map.begin(); dd != map.end(); map.next(dd)) +// { +// if( ( +// (boundingBox.isMarked(dd) && inside.isMarked(dd)) +// || (!boundingBox.isMarked(dd) && !inside.isMarked(dd)) +// ) +// && !map.sameFace(map.phi2(d),map.phi2(dd))) +// { +// if(Geom::testOrientation2D(position[dd], position[d], position[map.phi1(d)]) == Geom::LEFT +// && Geom::testOrientation2D(position[dd], position[d], position[map.phi_1(d)]) == Geom::RIGHT) +// { +// float dist = (position[dd]-position[d]).norm(); +// if(dist::intersectLineEdge(const VEC3& pA, const Geom::intersection2DSegmentSegment(pA,pB,q1,q2,Inter); -// if(VEC3(Inter-pA).norm()>VEC3(pA-pB).norm()) { -// CGoGNout << "probleme : " << pA << "/" << pB << "/" << q1 << "/" << q2 << "/" << Inter << CGoGNendl; -// CGoGNout << "isPointOnHalf " << Algo::Geometry::isPointOnHalfEdge(m,d,m_positions,Inter) << CGoGNendl; -// CGoGNout << "isPointOnHalf " << Algo::Geometry::isPointOnHalfEdge(m,m.phi1(d),m_positions,Inter) << CGoGNendl; -// } - return Inter; } @@ -74,6 +68,7 @@ void ParticleCell2D::vertexState(const VEC3& current) if(Algo::Geometry::isPointOnVertex(m,d,m_positions,current)) { state = VERTEX; + m_position = current; return; } else @@ -101,6 +96,7 @@ void ParticleCell2D::vertexState(const VEC3& current) } else { + m_position = current; state = VERTEX; return; } @@ -176,6 +172,85 @@ void ParticleCell2D::edgeState(const VEC3& current, Geom::Orientation2D sid vertexState(current); return; } + + m_position = current; +} + +template +Dart ParticleCell2D::faceOrientationState(const VEC3& toward) +{ + #ifdef DEBUG + CGoGNout << "faceOrientationState" << d << CGoGNendl; + #endif + + assert(std::isfinite(m_position[0]) && std::isfinite(m_position[1]) && std::isfinite(m_position[2])); + assert(std::isfinite(toward[0]) && std::isfinite(toward[1]) && std::isfinite(toward[2])); + + Dart res = d; + Dart dd = d; + float wsoe = getOrientationFace(toward, m_position, m.phi1(res)); + + // orientation step + if(wsoe != Geom::RIGHT) + { + res = m.phi1(res); + wsoe = getOrientationFace(toward, m_position, m.phi1(res)); + while(wsoe != Geom::RIGHT && dd != res) + { + res = m.phi1(res); + wsoe = getOrientationFace(toward, m_position, m.phi1(res)); + } + + // source and position to reach are the same : verify if no edge is crossed due to numerical approximation + if(dd == res) + { + do + { + switch (getOrientationEdge(toward, res)) + { + case Geom::LEFT: res = m.phi1(res); + break; + case Geom::ALIGNED: + return res; + case Geom::RIGHT: + return res; + } + } while(res != dd); + return res; + } + } + else + { + wsoe = getOrientationFace(toward,m_position,d); + while(wsoe == Geom::RIGHT && m.phi_1(res) != dd) + { + res = m.phi_1(res); + wsoe = getOrientationFace(toward, m_position, res); + } + + // in case of numerical incoherence + if(m.phi_1(res) == dd && wsoe == Geom::RIGHT) + { + res = m.phi_1(res); + do + { + switch (getOrientationEdge(toward, res)) + { + case Geom::LEFT : + res = m.phi1(res); + break; + case Geom::ALIGNED : + return res; + case Geom::RIGHT : + return res; + } + } while(res != dd); + + return res; + } + } + + return res; } template @@ -215,10 +290,11 @@ void ParticleCell2D::faceState(const VEC3& current) case Geom::ALIGNED: m_position = current; edgeState(current); return; - case Geom::RIGHT: CGoGNout << "smthg went bad " << m_position << " " << current << CGoGNendl; - CGoGNout << "d1 " << m_positions[d] << " d2 " << m_positions[m.phi1(d)] << CGoGNendl; + case Geom::RIGHT: +// CGoGNout << "smthg went bad " << m_position << " " << current << CGoGNendl; +// CGoGNout << "d1 " << m_positions[d] << " d2 " << m_positions[m.phi1(d)] << CGoGNendl; m_position = intersectLineEdge(current, m_position, d); - CGoGNout << " " << m_position << CGoGNendl; +// CGoGNout << " " << m_position << CGoGNendl; edgeState(current,Geom::RIGHT); return; @@ -265,7 +341,7 @@ void ParticleCell2D::faceState(const VEC3& current) edgeState(current); return; case Geom::RIGHT : - CGoGNout << "smthg went bad(2) " << m_position << CGoGNendl; +// CGoGNout << "smthg went bad(2) " << m_position << CGoGNendl; m_position = intersectLineEdge(current, m_position, d); // CGoGNout << " " << m_position << CGoGNendl; edgeState(current, Geom::RIGHT); @@ -300,6 +376,7 @@ void ParticleCell2D::faceState(const VEC3& current) default : if(wsoe == Geom::ALIGNED) { + d = m.phi1(d); //to check m_position = m_positions[d]; vertexState(current); } diff --git a/include/Container/fakeAttribute.h b/include/Container/fakeAttribute.h index 547f00bbd4a2242284bede8a8afdb3d33292409d..4871422f01c2e2954ee9eca9af23ef3d766eea25 100644 --- a/include/Container/fakeAttribute.h +++ b/include/Container/fakeAttribute.h @@ -69,7 +69,7 @@ public: NoMathNameAttribute(const T& att): T(att) {} - NoMathNameAttribute& operator = (const T& fa) { *this = NoMathNameAttribute(fa); } + NoMathNameAttribute& operator = (const T& fa) { return *this = NoMathNameAttribute(fa); } void operator += (const NoMathNameAttribute& fa) {} void operator -= (const NoMathNameAttribute& fa) {} void operator *= (double v) {} diff --git a/include/Geometry/bounding_box.h b/include/Geometry/bounding_box.h index eac3c73378300f51bbb3ca972f410a0139fae2f4..06626778c33cc2968b9afc212b6b69b9eddaf116 100644 --- a/include/Geometry/bounding_box.h +++ b/include/Geometry/bounding_box.h @@ -71,6 +71,8 @@ class BoundingBox VEC center() const ; + bool isInitialized() const ; + /**********************************************/ /* FUNCTIONS */ /**********************************************/ diff --git a/include/Geometry/bounding_box.hpp b/include/Geometry/bounding_box.hpp index 960e0953b6eac4d2235e000ad51f0e0c382880b4..5be1369dca3d1ecfa8572da72be7ad1ac542eca7 100644 --- a/include/Geometry/bounding_box.hpp +++ b/include/Geometry/bounding_box.hpp @@ -118,6 +118,12 @@ VEC BoundingBox::center() const return center ; } +template +bool BoundingBox::isInitialized() const +{ + return m_initialized; +} + /**********************************************/ /* FUNCTIONS */ /**********************************************/ diff --git a/include/Geometry/intersection.hpp b/include/Geometry/intersection.hpp index b0b98b35f8c12285dc0443965c00347e8835bf7f..90d010406c526fc5e0444c97bbe3585155b63545 100644 --- a/include/Geometry/intersection.hpp +++ b/include/Geometry/intersection.hpp @@ -78,7 +78,7 @@ Intersection intersectionLineTriangle(const VEC3& P, const VEC3& Dir, const VEC3 #define PRECISION 1e-20 if(fabs(b) < PRECISION) //ray parallel to triangle - return NO_INTERSECTION ; + return NO_INTERSECTION ; #undef PRECISION T r = a / b ; @@ -282,62 +282,75 @@ Intersection intersectionSegmentTriangle(const VEC3& PA, const VEC3& PB, const V // } template -Intersection intersectionPlaneRay(const PLANE3D& pl, const VEC3& p1, const VEC3& dir, VEC3& Inter) +Intersection intersectionPlaneRay(const PLANE3D& pl,const VEC3& p1,const VEC3& dir, VEC3& Inter) { - typename VEC3::DATA_TYPE denom = pl.normal() * dir; + typename VEC3::DATA_TYPE denom = pl.normal()*dir; - if(denom == 0) + if(denom==0) { - if(pl.distance(p1) == 0) + if(pl.distance(p1)==0) { - Inter = p1; - return FACE_INTERSECTION; + Inter = p1; + return FACE_INTERSECTION; } else return NO_INTERSECTION; } - typename VEC3::DATA_TYPE isect = ( pl.normal() * (pl.normal() * -1.0f * pl.d() - p1) ) / denom; + typename VEC3::DATA_TYPE isect = ( pl.normal() * (pl.normal()*-1.0f*pl.d()-p1) ) / denom; Inter = p1 + dir * isect; if(0.0f <= isect) + { return FACE_INTERSECTION; + } return NO_INTERSECTION; } template -Intersection intersection2DSegmentSegment(const VEC3& PA, const VEC3& PB, const VEC3& QA, const VEC3& QB, VEC3& Inter) +Intersection intersection2DSegmentSegment(const VEC3& PA, const VEC3& PB, const VEC3& QA, const VEC3& QB, VEC3& Inter) { typedef typename VEC3::DATA_TYPE T ; - VEC3 vp1p2(PB); - vp1p2 -= PA; - VEC3 vq1q2(QB); - vq1q2 -= QA; - VEC3 vp1q1(QA); - vp1q1 -= PA; - T delta = vp1p2[0] * vq1q2[1] - vp1p2[1] * vq1q2[0]; - T coeff = vp1q1[0] * vq1q2[1] - vp1q1[1] * vq1q2[0]; - Inter = VEC3( - (PA[0] * delta + vp1p2[0] * coeff) / delta, - (PA[1] * delta + vp1p2[1] * coeff) / delta, - (PA[2] * delta + vp1p2[2] * coeff) / delta - ); + VEC3 vp1p2 = PB - PA; + VEC3 vq1q2 = QB - QA; + VEC3 vp1q1 = QA - PA; + T delta = vp1p2[0]*vq1q2[1]- vp1p2[1]*vq1q2[0]; + T coeff = vp1q1[0]*vq1q2[1]- vp1q1[1]*vq1q2[0]; + + if(delta==0) //parallel + { + //test if collinear + if(coeff==0) + { + //collinear + //TODO : check if there is a common point between the two edges + Inter = QA; + return EDGE_INTERSECTION; + } + else + return NO_INTERSECTION; + } + else + Inter = VEC3((PA[0]*delta+vp1p2[0]*coeff)/delta,(PA[1]*delta+vp1p2[1]*coeff)/delta,(PA[2]*delta+vp1p2[2]*coeff)/delta); + //test if inter point is outside the edges - if( - (Inter[0] < PA[0] && Inter[0] < PB[0]) || (Inter[0] > PA[0] && Inter[0] > PB[0]) || - (Inter[0] < QA[0] && Inter[0] < QB[0]) || (Inter[0] > QA[0] && Inter[0] > QB[0]) || - (Inter[1] < PA[1] && Inter[1] < PB[1]) || (Inter[1] > PA[1] && Inter[1] > PB[1]) || - (Inter[1] < QA[1] && Inter[1] < QB[1]) || (Inter[1] > QA[1] && Inter[1] > QB[1]) + if( (Inter[0]PA[0] && Inter[0]>PB[0]) + || (Inter[0]QA[0] && Inter[0]>QB[0]) + || (Inter[1]PA[1] && Inter[1]>PB[1]) + || (Inter[1]QA[1] && Inter[1]>QB[1]) ) return NO_INTERSECTION; + if(Geom::arePointsEquals(PA,Inter) || Geom::arePointsEquals(PB,Inter) || Geom::arePointsEquals(QA,Inter) || Geom::arePointsEquals(QB,Inter)) + return VERTEX_INTERSECTION; + return EDGE_INTERSECTION; } -} // namespace Geom +} -} // namespace CGoGN +} diff --git a/include/Geometry/plane_3d.h b/include/Geometry/plane_3d.h index 6bd55eddc276c813b8f8584f28fcf15229051807..2a8afe80c0cefd816dead6013edf363fe416a0b8 100644 --- a/include/Geometry/plane_3d.h +++ b/include/Geometry/plane_3d.h @@ -45,11 +45,14 @@ template class Plane3D { public: + + static std::string CGoGNnameOfType() ; + /**********************************************/ /* CONSTRUCTORS */ /**********************************************/ - Plane3D(); + Plane3D(int d = 0); Plane3D(const Plane3D& p); diff --git a/include/Geometry/plane_3d.hpp b/include/Geometry/plane_3d.hpp index 02adf79ee99cf6b328c01fb3522f6239f7b5e4db..177910272b7f8d618bb9abd8e5668d60fdab37b9 100644 --- a/include/Geometry/plane_3d.hpp +++ b/include/Geometry/plane_3d.hpp @@ -28,13 +28,25 @@ namespace CGoGN namespace Geom { +template +std::string Plane3D::CGoGNnameOfType() +{ + std::stringstream ss ; + ss << "Geom::Plane3D<" ; + ss << nameOfType(T()) ; + ss << ">" ; + + return ss.str() ; +} + /**********************************************/ /* CONSTRUCTORS */ /**********************************************/ template -Plane3D::Plane3D() -{} +Plane3D::Plane3D(int d) : +m_normal(0), m_d(d) +{ } template Plane3D::Plane3D(const Plane3D& p) @@ -110,7 +122,7 @@ void Plane3D::project(Vector<3,T>& p) const T d = -distance(p) ; if(abs(d) > PRECISION) { - Vector<3,T> v = m_normal / d ; + Vector<3,T> v = m_normal * d ; p += v ; } #undef PRECISION diff --git a/include/Topology/generic/attributeHandler.h b/include/Topology/generic/attributeHandler.h index 835c38ae3fa2298d642f3a5606b82e64c849351b..717e7dec82866ac569b8d1b70a70108e5c5e96f1 100644 --- a/include/Topology/generic/attributeHandler.h +++ b/include/Topology/generic/attributeHandler.h @@ -138,7 +138,7 @@ public: unsigned int insert(const T& elt) ; /** - * insert un element with default value (warning we add here a complete line in container) + * insert an element with default value (warning we add here a complete line in container) */ unsigned int newElt() ; diff --git a/include/Topology/generic/embeddedMap2.h b/include/Topology/generic/embeddedMap2.h index d679ba140340163907c2b0d42ecf3d75c5a8c293..9d1b8515d0cc6fd4561a01f4f1308b95fac555ce 100644 --- a/include/Topology/generic/embeddedMap2.h +++ b/include/Topology/generic/embeddedMap2.h @@ -49,6 +49,12 @@ public: */ virtual bool deleteVertex(Dart d) ; + /** + * No attribute is attached to the new edge + * The attributes attached to the face of dart d are kept on the resulting face + */ + virtual void linkVertices(Dart d, Dart e) ; + /** * No attribute is attached to the new vertex * The attributes attached to the old edge are duplicated on both resulting edges @@ -84,6 +90,18 @@ public: */ virtual bool flipBackEdge(Dart d) ; + /** + * The attributes attached to the vertex of dart d are kept on the resulting vertex + * The attributes attached to the face of dart d are overwritten on the face of dart e + */ + virtual void insertEdgeInVertex(Dart d, Dart e); + + /** + * The attributes attached to the vertex of dart d are kept on the resulting vertex + * The attributes attached to the face of dart d are overwritten on the face of dart e + */ + virtual void removeEdgeFromVertex(Dart d); + /** * The attributes attached to the vertices of the edge of d are kept on the vertices of the resulting edge * The attributes attached to the edge of d are kept on the resulting edge diff --git a/include/Topology/generic/embeddedMap2.hpp b/include/Topology/generic/embeddedMap2.hpp index 3915afe680010844f2f46068aaf27c07aa44cf3e..50dafbcb39d9d9d07f838f689061e3989cbad7de 100644 --- a/include/Topology/generic/embeddedMap2.hpp +++ b/include/Topology/generic/embeddedMap2.hpp @@ -66,6 +66,25 @@ bool EmbeddedMap2::deleteVertex(Dart d) return false ; } +template +void EmbeddedMap2::linkVertices(Dart d, Dart e) +{ + Dart dNext = MAP2::phi1(d) ; + + MAP2::linkVertices(d,e); + + if (MAP2::isOrbitEmbedded(VERTEX)) + { + MAP2::copyDartEmbedding(VERTEX, MAP2::phi_1(e), d) ; + MAP2::copyDartEmbedding(VERTEX, MAP2::phi_1(d), e) ; + } + + if (MAP2::isOrbitEmbedded(FACE)) + { + MAP2::embedOrbit(FACE, dNext, MAP2::getEmbedding(FACE, dNext)) ; + } +} + template void EmbeddedMap2::cutEdge(Dart d) { @@ -218,6 +237,57 @@ bool EmbeddedMap2::flipBackEdge(Dart d) return false ; } +template +void EmbeddedMap2::insertEdgeInVertex(Dart d, Dart e) +{ + MAP2::insertEdgeInVertex(d, e); + + if (MAP2::isOrbitEmbedded(VERTEX)) + { + MAP2::copyDartEmbedding(VERTEX, e, d) ; + } + + if (MAP2::isOrbitEmbedded(FACE)) + { + if(!MAP2::sameFace(d,e)) + { + MAP2::embedNewCell(FACE, e); + MAP2::copyCell(FACE, e, d) ; + } + else + { + MAP2::embedOrbit(FACE, d, MAP2::getEmbedding(FACE, d)) ; + } + } +} + +template +void EmbeddedMap2::removeEdgeFromVertex(Dart d) +{ + Dart dPrev = MAP2::alpha_1(d); + + MAP2::removeEdgeFromVertex(d); + + if (MAP2::isOrbitEmbedded(VERTEX)) + { + MAP2::embedNewCell(VERTEX, d); + MAP2::copyCell(VERTEX, d, dPrev); + } + + if (MAP2::isOrbitEmbedded(FACE)) + { + if(!MAP2::sameFace(d, dPrev)) + { + MAP2::embedNewCell(FACE, d); + MAP2::copyCell(FACE, d, dPrev) ; + } + else + { + MAP2::embedOrbit(FACE, d, MAP2::getEmbedding(FACE, d)) ; + } + } +} + template void EmbeddedMap2::sewFaces(Dart d, Dart e) { diff --git a/include/Topology/generic/embeddedMap3.h b/include/Topology/generic/embeddedMap3.h index 1732b1281e0ab59603435f1ccc316befb71671bc..bfd375c56ce75e0cceecb246c64165bc17f5fff0 100644 --- a/include/Topology/generic/embeddedMap3.h +++ b/include/Topology/generic/embeddedMap3.h @@ -100,6 +100,9 @@ public: virtual unsigned int closeHole(Dart d); virtual void closeMap(DartMarker &marker); + + + virtual bool check(); } ; } // namespace CGoGN diff --git a/include/Topology/generic/embeddedMap3.hpp b/include/Topology/generic/embeddedMap3.hpp index 2e130cb93a16565cc4fbe69db0ebc51a1c7427d6..115b8f1bb18fb9de5f7491a9b156b4059cde7ef3 100644 --- a/include/Topology/generic/embeddedMap3.hpp +++ b/include/Topology/generic/embeddedMap3.hpp @@ -128,8 +128,8 @@ void EmbeddedMap3::splitFace(Dart d, Dart e) if(MAP3::isOrbitEmbedded(VERTEX)) { - MAP3::copyDartEmbedding(VERTEX, MAP3::phi2(MAP3::phi_1(d)), d); - MAP3::copyDartEmbedding(VERTEX, MAP3::phi2(MAP3::phi_1(e)), e); + MAP3::copyDartEmbedding(VERTEX, MAP3::phi2(MAP3::phi_1(d)), d); + MAP3::copyDartEmbedding(VERTEX, MAP3::phi2(MAP3::phi_1(e)), e); if(MAP3::phi3(d) != d) { @@ -310,4 +310,52 @@ void EmbeddedMap3::closeMap(DartMarker &marker) } +template +bool EmbeddedMap3::check() +{ + bool topo = MAP3::check() ; + if (!topo) + return false ; + + CGoGNout << "Check: embedding begin" << CGoGNendl ; + for(Dart d = MAP3::begin(); d != MAP3::end(); MAP3::next(d)) + { + if (MAP3::isOrbitEmbedded(VERTEX)) + { + if (MAP3::phi2(MAP3::phi_1(d)) != MAP3::phi_1(d) && MAP3::getEmbedding(VERTEX, d) != MAP3::getEmbedding(VERTEX, MAP3::phi2(MAP3::phi_1(d)))) + { + CGoGNout << "Check: different embeddings on vertex" << CGoGNendl ; + return false ; + } + + if(MAP3::phi3(d) != d && MAP3::getEmbedding(VERTEX, d) != MAP3::getEmbedding(VERTEX, MAP3::phi3(MAP3::phi2(d)))) + { + CGoGNout << "Check: different embeddings on vertex in the 2 oriented faces" << CGoGNendl ; + return false ; + } + + } + +// if (MAP2::isOrbitEmbedded(EDGE)) +// { +// if (MAP2::getEmbedding(EDGE, d) != MAP2::getEmbedding(EDGE, MAP2::phi2(d))) +// { +// CGoGNout << "Check: different embeddings on edge" << CGoGNendl ; +// return false ; +// } +// } +// +// if (MAP2::isOrbitEmbedded(FACE)) +// { +// if (MAP2::getEmbedding(FACE, d) != MAP2::getEmbedding(FACE, MAP2::phi1(d))) +// { +// CGoGNout << "Check: different embeddings on face" << CGoGNendl ; +// return false ; +// } +// } + } + CGoGNout << "Check: embedding ok" << CGoGNendl ; + return true ; +} + } // namespace CGoGN diff --git a/include/Topology/map/map1.h b/include/Topology/map/map1.h index 9ca404c2e6f55a10d6f31dc0d8ce09fa43c9893b..bf9a9c08697bcd4dcc76c891d7729a546e12c2f3 100644 --- a/include/Topology/map/map1.h +++ b/include/Topology/map/map1.h @@ -145,6 +145,13 @@ public: */ void splitFace(Dart d, Dart e); + //! Link two vertices belonging to distinct faces (add an edge between the two vertices) + /*! \pre Dart d and e MUST be different and belong to distinct face + * @param d first dart in the face + * @param e second dart in the face + */ + void linkVertices(Dart d, Dart e); + //! Merge the two faces of d and e, darts d & e disappear /*! \pre Dart d and e MUST belong to distinct faces * \warning Darts d and e no longer exist after the call diff --git a/include/Topology/map/map1.hpp b/include/Topology/map/map1.hpp index 517194f1ba6a52c0b9f1e5a5f9aa8e3ef0fd31c7..d6a795768c76deff007077ace2e2500d1b401038 100644 --- a/include/Topology/map/map1.hpp +++ b/include/Topology/map/map1.hpp @@ -157,6 +157,14 @@ inline void Map1::splitFace(Dart d, Dart e) phi1sew(phi_1(d), phi_1(e)) ; // phi1sew between the 2 new inserted darts } +inline void Map1::linkVertices(Dart d, Dart e) +{ + assert(d != e && !sameOrientedFace(d, e)) ; + Map1::cutEdge(phi_1(d)); // cut the edge before d (insert a new dart before d) + Map1::cutEdge(phi_1(e)); // cut the edge before e (insert a new dart before e) + phi1sew(phi_1(d), phi_1(e)) ; // phi1sew between the 2 new inserted darts +} + inline void Map1::mergeFaces(Dart d, Dart e) { assert(!sameOrientedFace(d, e)) ; diff --git a/include/Topology/map/map2.h b/include/Topology/map/map2.h index 37eaa3a7072db95d0b650de4d9c576a134c5be84..4a02c200468953213f03593a08a02d1c0d349b5d 100644 --- a/include/Topology/map/map2.h +++ b/include/Topology/map/map2.h @@ -125,6 +125,13 @@ public: */ virtual bool deleteVertex(Dart d) ; + //! Link two vertices belonging to distinct faces (add an edge between the two vertices) + /*! \pre Dart d and e MUST be different and belong to distinct face + * @param d first dart in the face + * @param e second dart in the face + */ + virtual void linkVertices(Dart d, Dart e); + //! Cut the edge of d and its opposite edge if it exists /*! @param d a dart of the edge to cut */ @@ -163,6 +170,20 @@ public: */ virtual bool flipBackEdge(Dart d); + //! Insert an edge after a dart in the vertex orbit + /*! \pre Dart d and e MUST be different and belong to distinct face + * \pre Dart e must be phi2-linked with its phi_1 dart + * @param d dart of the vertex + * @param e dart of the edge + */ + virtual void insertEdgeInVertex(Dart d, Dart e); + + //! Remove an edge from a vertex orbit + /*! \pre Dart d must be phi2 sewn + * @param d the dart of the edge to remove from the vertex + */ + virtual void removeEdgeFromVertex(Dart d); + //! Sew two oriented faces along oriented edges /*! \pre Darts d & e MUST be fixed point of phi2 relation * @param d a dart of the first face diff --git a/include/Topology/map/map3.h b/include/Topology/map/map3.h index 758fefd27613a92c3ac81168b5077131ca11ba50..7aec20f00006c462309060d2d115079ef839a648 100644 --- a/include/Topology/map/map3.h +++ b/include/Topology/map/map3.h @@ -345,7 +345,7 @@ public: //@{ // TODO devrait disparaitre // pour les mêmes raisons que dans map2 - //bool check(); + bool check(); //@} }; diff --git a/include/Utils/cgognStream.hpp b/include/Utils/cgognStream.hpp deleted file mode 100644 index bd23f5fc2ed68c413423cbc50f17dedb9c2d08eb..0000000000000000000000000000000000000000 --- a/include/Utils/cgognStream.hpp +++ /dev/null @@ -1,318 +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 "Utils/qtSimple.h" -#include - -namespace CGoGN -{ - -namespace CGoGNStream -{ - -template -Out::Out(): - m_out_mode(STDOUT), - m_sqt_bar(NULL), - m_sqt_console(NULL), - m_qte(NULL), - m_ofs(NULL), - m_oss(NULL), - m_code(0) -{} - -template -Out::~Out() -{ - if (LEVEL <= DBG_MAX_LEVEL) - { - if (m_ofs != NULL) - { - m_ofs->close(); - delete m_ofs; - } - } -} - -template -void Out::toStd(bool yes) -{ - if (LEVEL<=DBG_MAX_LEVEL) - { - if (m_code) - { - if (yes) - this->m_out_mode |= STDERR; - else - this->m_out_mode &= ~STDERR; - } - else - { - if (yes) - m_out_mode |= STDOUT; - else - m_out_mode &= ~STDOUT; - } - } -} - -//template -//void Err::toStd(bool yes) -//{ -// if (LEVEL<=DBG_MAX_LEVEL) -// { -// if (yes) -// this->m_out_mode |= STDERR; -// else -// this->m_out_mode &= ~STDERR; -// } -//} - -template -void Out::toFile(const std::string& filename ) -{ - if (LEVEL <= DBG_MAX_LEVEL) - { - if (!filename.empty()) - m_out_mode |= FILEOUT; - else - m_out_mode &= ~FILEOUT; - - if (m_ofs != NULL) - { - m_ofs->close(); - delete m_ofs; - } - m_ofs = new std::ofstream(filename.c_str()); - } -} - -template -void Out::toStatusBar(Utils::QT::SimpleQT* sqt) -{ - if (LEVEL <= DBG_MAX_LEVEL) - { - if (sqt != NULL) - m_out_mode |= QTSTATUSBAR; - else - m_out_mode &= ~QTSTATUSBAR; - m_sqt_bar = sqt; - } -} - -template -void Out::toConsole(Utils::QT::SimpleQT* sqt) -{ - if (LEVEL <= DBG_MAX_LEVEL) - { - if (sqt) - m_out_mode |= QTCONSOLE; - else - m_out_mode &= ~QTCONSOLE; - m_sqt_console = sqt; - } -} - -template -void Out::toBuffer(std::stringstream* ss) -{ - if (LEVEL <= DBG_MAX_LEVEL) - { - if (ss != NULL) - m_out_mode |= SSBUFFER; - else - m_out_mode &= ~SSBUFFER; - - m_oss = ss; - } -} - -template -Out& Out::operator<< (Out& os) -{ - return *this; -} - -template -void Out::close() -{ - if (LEVEL <= DBG_MAX_LEVEL) - { - if (m_ofs != NULL) - { - m_ofs->close(); - } - } - -} - -template -template -Out& Out::operator<< (const T& val) -{ - if (m_out_mode & STDOUT) - std::cout << val; - if (m_out_mode & STDERR) - std::cerr << val; - - if (m_out_mode && (FILEOUT|QTSTATUSBAR|QTCONSOLE|SSBUFFER)) - m_buffer << val; - - return *this; -} - -template -Out& Out::operator<< (Special& os ) -{ - if (LEVEL <= DBG_MAX_LEVEL) - { - if (&os == &CGoGNendl) - { - char bufc[512]; - - // for cout & cerr just do the endl - if (m_out_mode & STDOUT) - std::cout << std::endl;; - if (m_out_mode & STDERR) - std::cerr << std::endl; - - if (m_out_mode & FILEOUT) - { - while (! m_buffer.eof()) - { - m_buffer.getline(bufc,512); - *m_ofs << bufc << std::endl; - } - } - - if (m_out_mode & QTSTATUSBAR) - { - while (! m_buffer.eof()) - { - m_buffer.getline(bufc,512); - m_sqt_bar->statusMsg(bufc); - } - } - - if (m_out_mode & QTCONSOLE) - { - while (! m_buffer.eof()) - { - m_buffer.getline(bufc,512); - - if (m_code >= 100) - m_sqt_console->console()->setTextColor(QColor(0, 150 - (m_code-100) * 20, 50 + (m_code-100) * 20)); - else - { - if (m_code > 0) - m_sqt_console->console()->setTextColor(QColor(150, 0, 0)); - else - m_sqt_console->console()->setTextColor(QColor(0, 0, 150)); - } - -// m_sqt_console->console()->insertPlainText(QString(bufc)); -// m_sqt_console->console()->insertPlainText(QString("\n")); - m_sqt_console->console()->append(QString(bufc)); - } - } - - if (m_out_mode & SSBUFFER) - { - while (! m_buffer.eof()) - { - m_buffer.getline(bufc, 512); - *m_oss << bufc << std::endl; - } - } - } - - if (&os == &CGoGNflush) - { - char bufc[512]; - - // for cout & cerr just do the endl - if (m_out_mode & STDOUT) - std::cout << std::flush; - if (m_out_mode & STDERR) - std::cerr << std::flush; - - if (m_out_mode & FILEOUT) - { - while (! m_buffer.eof()) - { - m_buffer.getline(bufc,512); - *m_ofs << bufc << std::flush; - } - } - - if (m_out_mode & QTSTATUSBAR) - { - while (! m_buffer.eof()) - { - m_buffer.getline(bufc,512); - m_sqt_bar->statusMsg(bufc); - } - } - - if (m_out_mode & QTCONSOLE) - { - while (! m_buffer.eof()) - { - m_buffer.getline(bufc,512); - - if (m_code >= 100) - m_sqt_console->console()->setTextColor(QColor(0, 150 - (m_code-100) * 20, 50 + (m_code-100) * 20)); - else - { - if (m_code > 0) - m_sqt_console->console()->setTextColor(QColor(150, 0, 0)); - else - m_sqt_console->console()->setTextColor(QColor(0, 0, 150)); - } - - m_sqt_console->console()->moveCursor(QTextCursor::End); - m_sqt_console->console()->insertPlainText(QString(bufc)); - } - } - - if (m_out_mode & SSBUFFER) - { - while (! m_buffer.eof()) - { - m_buffer.getline(bufc, 512); - *m_oss << bufc << std::flush; - } - } - } - - - } - - m_buffer.clear(); - return *this; -} - -} // namespace CGoGNStream - -} // namespace CGoGN diff --git a/src/Algo/ImplicitHierarchicalMesh/ihm3.cpp b/src/Algo/ImplicitHierarchicalMesh/ihm3.cpp index 725148813ac0f6439cfb9c8b3a67a18cb6c30fd5..74fe96da1a7f29cd60c48399df2b5dcbf7db9f9e 100644 --- a/src/Algo/ImplicitHierarchicalMesh/ihm3.cpp +++ b/src/Algo/ImplicitHierarchicalMesh/ihm3.cpp @@ -144,6 +144,7 @@ unsigned int ImplicitHierarchicalMap3::faceLevel(Dart d) fLevel = l < fLevel ? l : fLevel ; // of its edges } while(it != d) ; + unsigned int cur = m_curLevel ; m_curLevel = fLevel ; @@ -171,7 +172,6 @@ unsigned int ImplicitHierarchicalMap3::volumeLevel(Dart d) { assert(m_dartLevel[d] <= m_curLevel || !"Access to a dart introduced after current level") ; -//std::cout << "volumeLevel" << std::endl; if(m_curLevel == 0) return 0 ; diff --git a/src/Topology/map/map2.cpp b/src/Topology/map/map2.cpp index 2e120b8f9fe096a509d68d5964891d5cdb07ddf8..4f2408dce7b84f17d2a7e93ebd43f7da8a079994 100644 --- a/src/Topology/map/map2.cpp +++ b/src/Topology/map/map2.cpp @@ -73,6 +73,12 @@ bool Map2::deleteVertex(Dart d) return true ; } +void Map2::linkVertices(Dart d, Dart e) +{ + Map1::linkVertices(d, e); // Split the face + phi2sew(phi_1(d), phi_1(e)); // Sew the two resulting faces along the new edge +} + void Map2::cutEdge(Dart d) { Map1::cutEdge(d); // Cut the edge of d @@ -193,6 +199,20 @@ bool Map2::flipBackEdge(Dart d) return false ; // cannot flip a border edge } +void Map2::insertEdgeInVertex(Dart d, Dart e) +{ + assert(!sameVertex(d,e) && phi2(e)==phi_1(e)); + + phi1sew(phi_1(d),phi_1(e)); +} + +void Map2::removeEdgeFromVertex(Dart d) +{ + assert(phi2(d)!=d); + + phi1sew(phi_1(d),phi2(d)); +} + void Map2::sewFaces(Dart d, Dart e) { phi2sew(d, e); diff --git a/src/Topology/map/map3.cpp b/src/Topology/map/map3.cpp index 30ca1858f743debe4d14f8f5ec982784b2b6917a..83676d3dcdd9bdbada363ec8a9fa809ff5bacb3a 100644 --- a/src/Topology/map/map3.cpp +++ b/src/Topology/map/map3.cpp @@ -763,31 +763,34 @@ bool Map3::foreach_dart_of_vertex(Dart d, FunctorType& f, unsigned int thread) DartMarkerStore mv(*this,thread); // Lock a marker bool found = false; // Last functor return value - std::list darts_list; //Darts that are traversed - darts_list.push_back(d); //Start with the dart d - std::list::iterator darts; + std::vector darts_list; //Darts that are traversed + darts_list.reserve(50); + darts_list.push_back(d); //Start with the dart d mv.mark(d); - for(darts = darts_list.begin(); !found && darts != darts_list.end() ; ++darts) + for(std::vector::iterator darts = darts_list.begin(); !found && darts != darts_list.end() ; ++darts) { Dart dc = *darts; //add phi21 and phi23 successor if they are not marked yet Dart d2 = phi2(dc); - Dart d21 = phi1(d2); // turn in volume - Dart d23 = phi3(d2); // change volume - - if(!mv.isMarked(d21)) + if(d2 != dc) { - darts_list.push_back(d21); - mv.mark(d21); - } + Dart d21 = phi1(d2); // turn in volume + Dart d23 = phi3(d2); // change volume - if((d23!=d2) && !mv.isMarked(d23)) - { - darts_list.push_back(d23); - mv.mark(d23); + if(!mv.isMarked(d21)) + { + darts_list.push_back(d21); + mv.mark(d21); + } + + if((d23!=d2) && !mv.isMarked(d23)) + { + darts_list.push_back(d23); + mv.mark(d23); + } } found = f(dc); @@ -1141,66 +1144,74 @@ void Map3::closeMap(DartMarker& marker) // this->releaseMarker(DART,mf3); //} // -//bool Map3::check() -//{ -// CGoGNout << "Check: topology begin" << CGoGNendl; -// Marker m = this->getNewMarker(); -// for(Dart d = this->begin(); d != this->end(); this->next(d)) -// { -// Dart d3 = phi3(d); -// if (phi3(d3) != d) // phi3 involution ? -// { -// CGoGNout << "Check: phi3 is not an involution" << CGoGNendl; -// return false; -// } -// -// Dart d2 = phi2(d); -// if (phi2(d2) != d) // phi2 involution ? -// { -// CGoGNout << "Check: phi2 is not an involution" << CGoGNendl; -// return false; -// } -// -// Dart d1 = phi1(d); -// if (phi_1(d1) != d) // phi1 a une image correcte ? -// { -// CGoGNout << "Check: unconsistent phi_1 link" << CGoGNendl; -// return false; -// } -// -// if (isMarkedDart(d1,m)) // phi1 a un seul antécédent ? -// { -// CGoGNout << "Check: dart with two phi1 predecessors" << CGoGNendl; -// return false; -// } -// markOrbit(DART,d1,m); -// -// if (d1 == d) -// CGoGNout << "Check: (warning) face loop (one edge)" << CGoGNendl; -// -// if (phi1(d1) == d) -// CGoGNout << "Check: (warning) face with only two edges" << CGoGNendl; -// -// if (phi2(d1) == d) -// CGoGNout << "Check: (warning) dandling edge (phi2)" << CGoGNendl; -// -// if (phi3(d1) == d) -// CGoGNout << "Check: (warning) dandling edge (phi3)" << CGoGNendl; -// } -// -// for(Dart d = this->begin(); d != this->end(); this->next(d)) -// { -// if (!isMarkedDart(d,m)) // phi1 a au moins un antécédent ? -// { -// CGoGNout << "Check: dart with no phi1 predecessor" << CGoGNendl; -// return false; -// } -// } -// this->unmarkAll(DART,m); -// this->releaseMarker(DART,m); -// CGoGNout << "Check: topology ok" << CGoGNendl; -// return true; -//} +bool Map3::check() +{ + CGoGNout << "Check: topology begin" << CGoGNendl; + DartMarker m(*this); + for(Dart d = this->begin(); d != this->end(); this->next(d)) + { + Dart d3 = phi3(d); + if (phi3(d3) != d) // phi3 involution ? + { + CGoGNout << "Check: phi3 is not an involution" << CGoGNendl; + return false; + } + + if(d3 != d) + { + if(phi1(d3) != phi3(phi_1(d))) + { + CGoGNout << "Check: phi3 , faces are not entirely sewn" << CGoGNendl; + return false; + } + } + + Dart d2 = phi2(d); + if (phi2(d2) != d) // phi2 involution ? + { + CGoGNout << "Check: phi2 is not an involution" << CGoGNendl; + return false; + } + + Dart d1 = phi1(d); + if (phi_1(d1) != d) // phi1 a une image correcte ? + { + CGoGNout << "Check: unconsistent phi_1 link" << CGoGNendl; + return false; + } + + if (m.isMarked(d1)) // phi1 a un seul antécédent ? + { + CGoGNout << "Check: dart with two phi1 predecessors" << CGoGNendl; + return false; + } + m.mark(d1); + + if (d1 == d) + CGoGNout << "Check: (warning) face loop (one edge)" << CGoGNendl; + + if (phi1(d1) == d) + CGoGNout << "Check: (warning) face with only two edges" << CGoGNendl; + + if (phi2(d1) == d) + CGoGNout << "Check: (warning) dandling edge (phi2)" << CGoGNendl; + + if (phi3(d1) == d) + CGoGNout << "Check: (warning) dandling edge (phi3)" << CGoGNendl; + } + + for(Dart d = this->begin(); d != this->end(); this->next(d)) + { + if (!m.isMarked(d)) // phi1 a au moins un antécédent ? + { + CGoGNout << "Check: dart with no phi1 predecessor" << CGoGNendl; + return false; + } + } + + CGoGNout << "Check: topology ok" << CGoGNendl; + return true; +}