diff --git a/include/Algo/Export/exportPov.h b/include/Algo/Export/exportPov.h index 0b97ad352cc8e66acf72e1ac1dc846d6c52a56a7..0120d51f546edc8f0c95c4ee106dfdc25d66b3fc 100644 --- a/include/Algo/Export/exportPov.h +++ b/include/Algo/Export/exportPov.h @@ -3,6 +3,7 @@ #include "Topology/generic/attributeHandler.h" #include "Utils/cgognStream.h" +#include "Algo/Geometry/normal.h" namespace CGoGN { @@ -45,7 +46,7 @@ void exportMeshPlain(std::ofstream& out, typename PFP::MAP& map, typename PFP::T unsigned int nb=0; Dart dd=d; do { - traite.markOrbit(DART,dd); + traite.mark(dd); dd = map.phi1(dd); nb++; } while(dd!=d); @@ -69,6 +70,104 @@ void exportMeshPlain(std::ofstream& out, typename PFP::MAP& map, typename PFP::T out << "}" << std::endl; } +template +void export3MeshPlainSmooth(std::ofstream& out, typename PFP::MAP& map, typename PFP::TVEC3& position, const std::string& meshName, const FunctorSelect& good = SelectorTrue()) +{ + typedef typename PFP::VEC3 VEC3; + + out << "#declare " << meshName << "= mesh2 {" << std::endl; + + unsigned int nbDarts = map.getNbDarts() ; + + //vector containing the degree of faces + std::vector facesSize ; + //vector containing the list of index of vertices + std::vector > facesIdx ; + facesSize.reserve(nbDarts/3) ; + facesIdx.reserve(nbDarts/3) ; + + //map : attribute place / index in declaration (for vertices and normals) + std::map vIndex ; + //index : start from 0 and increase (used to ignore the gaps potentially present in the container) + unsigned int vCpt = 0 ; + + //remember the attribute lines + std::vector vertices ; + + std::vector normals ; + vertices.reserve(nbDarts/6) ; + normals.reserve(nbDarts/6) ; + + CellMarker markV(map, VERTEX) ; + DartMarker markF(map) ; + for(Dart d = map.begin(); d != map.end(); map.next(d)) + { + + if(good(d) && !markF.isMarked(d) && map.phi3(d)==d) + { + markF.markOrbit(FACE, d) ; + std::vector fidx ; + fidx.reserve(4) ; + Dart dd = d ; + do + { + unsigned int vNum = map.getEmbedding(VERTEX, dd) ; + if(!markV.isMarked(dd)) + { + markV.mark(dd) ; + VEC3 norm = Algo::Geometry::vertexBorderNormal(map,dd,position); + + vIndex[vNum] = vCpt++ ; + vertices.push_back(vNum) ; + + normals.push_back(norm) ; + } + + fidx.push_back(vIndex[vNum]) ; + + dd = map.phi1(dd) ; + } while(dd != d) ; + + facesSize.push_back(map.faceDegree(d)) ; + facesIdx.push_back(fidx) ; + } + } + + //export all vertices + out << "vertex_vectors {" << std::endl; + out << vertices.size() << "," << std::endl; + for(unsigned int i = 0; i < vertices.size(); ++i) + { + const VEC3& v = position[vertices[i]] ; + out << "<" << v[0] << ", " << v[1] << ", " << v[2] << ">"<< std::endl ; + } + out << "}" << std::endl; + + //export all normals + out << "normal_vectors {" << std::endl; + out << normals.size() << "," << std::endl; + for(unsigned int i = 0; i < normals.size(); ++i) + { + const VEC3& v = normals[i]; + out << "<" << v[0] << ", " << v[1] << ", " << v[2] << ">"<< std::endl ; + } + out << "}" << std::endl; + + //export all faces + out << "face_indices {" << std::endl; + out << facesSize.size() << "," << std::endl; + for(unsigned int i = 0; i < facesSize.size(); ++i) + { + out << "<" << facesIdx[i][0]; + for(unsigned int j = 1; j < facesIdx[i].size(); ++j) + out << ", " << facesIdx[i][j] ; + out << ">" << std::endl ; + } + out << "}" << std::endl; + + out << "}" << std::endl; +} + template void exportMeshWire(std::ofstream& out, typename PFP::MAP& map, typename PFP::TVEC3& position, const std::string& meshName, const FunctorSelect& good = SelectorTrue()) { @@ -134,7 +233,8 @@ bool exportScenePov(typename PFP::MAP& map, typename PFP::TVEC3& position, const out << "global_settings {" << std::endl; out << "radiosity {" << std::endl; out << "pretrace_start 0.08 pretrace_end 0.04" << std::endl; - out << "count 100 nearest_count 10 error_bound 0.15 recursion_limit 1 low_error_factor 0.2 gray_threshold 0.0 minimum_reuse 0.015 brightness 1 adc_bailout 0.01/2 normal off media off} max_trace_level 255}" << std::endl; + out << "count 100 nearest_count 10 error_bound 0.15 recursion_limit 1 low_error_factor 0.2 gray_threshold 0.0 minimum_reuse 0.015 brightness 1 adc_bailout 0.01/2 normal off media off}" << std::endl; + out << "max_trace_level 255}" << std::endl; Algo::ExportPov::exportMeshPlain(out,map,position,"myMesh",good); @@ -147,6 +247,51 @@ bool exportScenePov(typename PFP::MAP& map, typename PFP::TVEC3& position, const return true; } +template +bool exportScenePovSmooth(typename PFP::MAP& map, typename PFP::TVEC3& position, const std::string& filename, typename PFP::VEC3 cameraPos, typename PFP::VEC3 cameraLook, typename PFP::VEC3 translate, float angle_X, float angle_Y, float angle_Z,const FunctorSelect& good = SelectorTrue()) +{ + std::ofstream out(filename.c_str(), std::ios::out); + if (!out.good()) { + CGoGNerr << "(export) Unable to open file " << filename << CGoGNendl; + return false; + } + + float angleX = angle_X; + float angleY = angle_Y; + float angleZ = angle_Z; + + //define the camera position + out << "camera { location <" << cameraPos[0] << "," << cameraPos[1] << "," << cameraPos[2] << "> look_at <" << cameraLook[0] << "," << cameraLook[1] << "," << cameraLook[2] <<">}" << std::endl; + + //set a "infinite" plane +// out << "plane { y, -1 pigment { color rgb 1 } }" << std::endl; + + //set a sky sphere + out << "sphere { <0, 0, 0>, 5000"; + out << "texture{ pigment { color rgb <1, 1, 1>} finish { ambient 1 diffuse 0 } } }" << std::endl; + + //put some lights + out << "light_source { <" << cameraPos[0] << "," << cameraPos[1] << "," << cameraPos[2] << "> color rgb 0.45}" << std::endl; + + //set a high quality rendering + out << "global_settings {" << std::endl; +// out << "radiosity {" << std::endl; +// out << "pretrace_start 0.08 pretrace_end 0.04" << std::endl; +// out << "count 300 nearest_count 10 error_bound 0.15 recursion_limit 1 low_error_factor 0.2 gray_threshold 0.0 minimum_reuse 0.015 brightness 1 adc_bailout 0.01/2 normal off media off}" << std::endl; + out << "max_trace_level 60}" << std::endl; + + Algo::ExportPov::export3MeshPlainSmooth(out,map,position,"myMesh",good); + + out << "object {myMesh" << std::endl; + out << "translate <" << translate[0] << "," << translate[1] << "," << translate[2] << ">" << std::endl; + out << "rotate <" << angleX << "," << angleY << "," << angleZ << "> " << std::endl; + out << "double_illuminate" << std::endl; + out << "texture{ pigment{ color rgb <0.5,1.0,0.5>} finish { ambient 0.5 roughness 0.2 } } }" << std::endl; + + out.close(); + return true; +} + } } diff --git a/include/Algo/Geometry/normal.h b/include/Algo/Geometry/normal.h index d17f60f87b19c19be14c330882d02ceb8af69af6..34b1ad2b0aa5f13949382522c0e9cf7894bd88c2 100644 --- a/include/Algo/Geometry/normal.h +++ b/include/Algo/Geometry/normal.h @@ -39,12 +39,18 @@ namespace Geometry template typename PFP::VEC3 triangleNormal(typename PFP::MAP& map, Dart d, const typename PFP::TVEC3& position) ; +template +typename PFP::VEC3 newellNormal(typename PFP::MAP& map, Dart d, const typename PFP::TVEC3& position); + template typename PFP::VEC3 faceNormal(typename PFP::MAP& map, Dart d, const typename PFP::TVEC3& position) ; template typename PFP::VEC3 vertexNormal(typename PFP::MAP& map, Dart d, const typename PFP::TVEC3& position) ; +template +typename PFP::VEC3 vertexBorderNormal(typename PFP::MAP& map, Dart d, const typename PFP::TVEC3& position) ; + template void computeNormalFaces(typename PFP::MAP& map, const typename PFP::TVEC3& position, typename PFP::TVEC3& face_normal, const FunctorSelect& select = SelectorTrue(), unsigned int thread = 0) ; diff --git a/include/Algo/Geometry/normal.hpp b/include/Algo/Geometry/normal.hpp index e6bc5855af2d8d78c8e45b598e1947ac929919f1..d33ff29f20a978c197421f16e8a401a3a28ca78d 100644 --- a/include/Algo/Geometry/normal.hpp +++ b/include/Algo/Geometry/normal.hpp @@ -116,6 +116,40 @@ typename PFP::VEC3 vertexNormal(typename PFP::MAP& map, Dart d, const typename P return N ; } +template +typename PFP::VEC3 vertexBorderNormal(typename PFP::MAP& map, Dart d, const typename PFP::TVEC3& position) +{ + assert(map.dimension() == 3); + + typedef typename PFP::VEC3 VEC3 ; + + VEC3 N(0) ; + std::vector faces; + CellMarker f(map,FACE); + + FunctorStore fs(faces); + map.foreach_dart_of_oriented_vertex(d,fs); + + for(std::vector::iterator it = faces.begin() ; it != faces.end() ; ++it) + { + if(!f.isMarked(*it) && map.phi3(*it)==*it) + { + f.mark(*it); + VEC3 n = faceNormal(map, *it, position); + if(!n.hasNan()) + { + VEC3 v1 = vectorOutOfDart(map, *it, position); + VEC3 v2 = vectorOutOfDart(map, map.phi_1(*it), position); + n *= convexFaceArea(map, *it, position) / (v1.norm2() * v2.norm2()); + N += n ; + } + } + } + + N.normalize() ; + return N ; +} + template void computeNormalFaces(typename PFP::MAP& map, const typename PFP::TVEC3& position, typename PFP::TVEC3& face_normal, const FunctorSelect& select, unsigned int thread) { diff --git a/include/Topology/gmap/gmap1.hpp b/include/Topology/gmap/gmap1.hpp index 9e1de3f14b7377041cf63bb0f0ff4607de9933ac..8e365accead745a3ee908a34cceda1b37969da9c 100644 --- a/include/Topology/gmap/gmap1.hpp +++ b/include/Topology/gmap/gmap1.hpp @@ -213,6 +213,10 @@ inline void GMap1::collapseEdge(Dart d) inline void GMap1::splitFace(Dart d, Dart e) { assert(d != e && sameFace(d, e)) ; + + if(!sameOrientedFace(d,e)) + e = beta1(e); + Dart d1 = beta1(d) ; Dart e1 = beta1(e) ; Dart dd = newEdge() ; diff --git a/include/Topology/gmap/gmap2.h b/include/Topology/gmap/gmap2.h index 229e6ab17d9e2383af90d89fadaddd56af05138e..f4f64e2724659a61bcb8e5fdc854251e7148a899 100644 --- a/include/Topology/gmap/gmap2.h +++ b/include/Topology/gmap/gmap2.h @@ -336,14 +336,6 @@ public: * @param fonct functor obj ref */ bool foreach_dart_of_cc(Dart d, FunctorType& fonct, unsigned int thread=0); - - //! - /*! TODO Ajout a valider - * restreint aux complexes simpliciaux - * Apply a functor on the all darts in the set of the link from orbit - */ - bool foreach_dart_of_link(Dart d, unsigned int orbit, FunctorType& f, unsigned int thread=0); - //@} }; } // namespace CGoGN diff --git a/include/Topology/gmap/gmap3.h b/include/Topology/gmap/gmap3.h index 26d49c3c852fcc46382c79c587c7218aa0188e03..545c9cecec3e70d2bf485a7ae92664085d840bf6 100644 --- a/include/Topology/gmap/gmap3.h +++ b/include/Topology/gmap/gmap3.h @@ -200,7 +200,14 @@ public: //@{ /** - * Apply a functor on each dart of a face + * Apply a functor on each dart of a vertex + * @param d a dart of the face + * @param fonct functor obj ref + */ + bool foreach_dart_of_oriented_vertex(Dart d, FunctorType& fonct, unsigned int thread=0); + + /** + * Apply a functor on each dart of a vertex * @param d a dart of the face * @param fonct functor obj ref */ diff --git a/include/Topology/map/map2.h b/include/Topology/map/map2.h index 14cd0f513fdcc8d5068d944d3d9a82c994ac4d78..733e4e3fd676e301fd94048c3c4999a26bf07a5b 100644 --- a/include/Topology/map/map2.h +++ b/include/Topology/map/map2.h @@ -286,33 +286,53 @@ public: */ bool sameOrientedVertex(Dart d, Dart e) ; + //! Test if dart d and e belong to the same vertex + /*! @param d a dart + * @param e a dart + */ + bool sameVertex(Dart d, Dart e) ; + + //! Compute the number of edges of the vertex of d + /*! @param d a dart + */ + unsigned int vertexDegree(Dart d) ; + + //! Tell if the vertex of d is on the boundary of the map + /*! @param d a dart + */ + bool isBoundaryVertex(Dart d) ; + //!Test if dart d and e belong to the same oriented face /*! @param d a dart * @param e a dart */ bool sameOrientedFace(Dart d, Dart e); - //! Test if dart d and e belong to the same vertex + // TODO a mettre en algo + /** + * check if the mesh is triangular or not + * @return a boolean indicating if the mesh is triangular + */ + bool isTriangular() ; + + //@{ + //! Test if dart d and e belong to the same oriented volume /*! @param d a dart * @param e a dart */ - bool sameVertex(Dart d, Dart e) ; + bool sameOrientedVolume(Dart d, Dart e) ; - //! Compute the number of edges of the vertex of d + //! Test if dart d and e belong to the same volume /*! @param d a dart + * @param e a dart */ - unsigned int vertexDegree(Dart d) ; + bool sameVolume(Dart d, Dart e) ; //! Compute the number of faces in the volume of d /*! @param d a dart */ unsigned int volumeDegree(Dart d); - //! Tell if the vertex of d is on the boundary of the map - /*! @param d a dart - */ - bool isBoundaryVertex(Dart d) ; - //! 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. @@ -320,12 +340,6 @@ public: */ Dart nextOnBoundary(Dart d); - // TODO a mettre en algo - /** - * check if the mesh is triangular or not - * @return a boolean indicating if the mesh is triangular - */ - bool isTriangular() ; // TODO a mettre en algo /** @@ -339,7 +353,6 @@ public: * Apply functors to all darts of a cell *************************************************************************/ - //@{ //! Apply a functor on every dart of a vertex /*! @param d a dart of the vertex * @param f the functor to apply diff --git a/include/Topology/map/map2.hpp b/include/Topology/map/map2.hpp index 6ec61a88122cdde0ec45f94eba897541a4359371..04d4afb6bbc9f4d127294d36bbb8d6bc56c0ebc1 100644 --- a/include/Topology/map/map2.hpp +++ b/include/Topology/map/map2.hpp @@ -181,6 +181,11 @@ inline bool Map2::sameVertex(Dart d, Dart e) return sameOrientedVertex(d, e) ; } +inline bool Map2::sameVolume(Dart d, Dart e) +{ + return sameOrientedVolume(d, e) ; +} + /*! @name Cell Functors * Apply functors to all darts of a cell *************************************************************************/ diff --git a/include/Topology/map/map3.h b/include/Topology/map/map3.h index 23db8a4ae1bb36b1c47a1dc645fb465921b6ce67..2f95252acf9cbfb7dfd13cc22cbb65f451af51ed 100644 --- a/include/Topology/map/map3.h +++ b/include/Topology/map/map3.h @@ -236,6 +236,12 @@ public: *************************************************************************/ //@{ + //! Apply a functor on each dart of a vertex + /*! @param d a dart of the vertex + * @param fonct the functor + */ + bool foreach_dart_of_oriented_vertex(Dart d, FunctorType& f, unsigned int thread=0); + //! Apply a functor on each dart of a vertex /*! @param d a dart of the vertex * @param fonct the functor diff --git a/include/Topology/map/map3.hpp b/include/Topology/map/map3.hpp index 12169f7c3fd215a10e4f4b029496a534d6b8016e..9c0fd0b074ddd92d7dca1767022b50cde174ad1a 100644 --- a/include/Topology/map/map3.hpp +++ b/include/Topology/map/map3.hpp @@ -178,6 +178,11 @@ inline void Map3::phi3unsew(Dart d) (*m_phi3)[e.index] = e ; } +inline bool Map3::foreach_dart_of_vertex(Dart d, FunctorType& f, unsigned int thread) +{ + return foreach_dart_of_oriented_vertex(d, f, thread); +} + //template //bool Map3::foreach_dart_of_parent_cell(int dim, Dart d, FunctorType& f) //{ diff --git a/src/Topology/gmap/gmap2.cpp b/src/Topology/gmap/gmap2.cpp index 772c65da936bd7ac823d23513828f8abe98dda9e..d6a7693e2062db47ed9231e139eeeb1e86d26c70 100644 --- a/src/Topology/gmap/gmap2.cpp +++ b/src/Topology/gmap/gmap2.cpp @@ -664,33 +664,4 @@ bool GMap2::foreach_dart_of_cc(Dart d, FunctorType& f, unsigned int thread) return found; } -bool GMap2::foreach_dart_of_link(Dart d, unsigned int orbit, FunctorType& f, unsigned int thread) -{ - if(orbit == VERTEX) - { - Dart dNext = d; - do - { - if(GMap2::foreach_dart_of_edge(phi1(dNext),f,thread)) - return true; - - dNext = alpha1(dNext); - } while (dNext != d); - - return false; - } - else if(orbit == FACE) - { - if(GMap2::foreach_dart_of_vertex(phi_1(d),f,thread)) - return true; - - if(GMap2::foreach_dart_of_vertex(phi_1(phi2(d)),f,thread)) - return true; - - return false; - } - - return false; -} - } // namespace CGoGN diff --git a/src/Topology/gmap/gmap3.cpp b/src/Topology/gmap/gmap3.cpp index 40db040d6ad2e6634a34d8fd42a8832459ca82b6..16e7d22ce94d94b5e4c2d627ad34ef4a483d8d19 100644 --- a/src/Topology/gmap/gmap3.cpp +++ b/src/Topology/gmap/gmap3.cpp @@ -500,6 +500,46 @@ bool GMap3::check() * Apply functors to all darts of a cell *************************************************************************/ +bool GMap3::foreach_dart_of_oriented_vertex(Dart d, FunctorType& f, unsigned int thread) +{ + DartMarkerStore mv(*this,thread); // Lock a marker + bool found = false; // Last functor return value + + std::vector darts_list; //Darts that are traversed + darts_list.reserve(512); + darts_list.push_back(d); //Start with the dart d + mv.mark(d); + + 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); + if(d2 != dc) + { + Dart d21 = phi1(d2); // turn in volume + Dart d23 = phi3(d2); // change volume + + 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); + } + + return found; +} + bool GMap3::foreach_dart_of_vertex(Dart d, FunctorType& f, unsigned int thread) { DartMarkerStore mv(*this,thread); // Lock a marker diff --git a/src/Topology/map/map2.cpp b/src/Topology/map/map2.cpp index 1ca6ba4ab70d8506aeafd9a927f3ac7bd242bcc6..728cb513d4d6d32dd2d1808da080fb4b837ea40a 100644 --- a/src/Topology/map/map2.cpp +++ b/src/Topology/map/map2.cpp @@ -427,6 +427,32 @@ bool Map2::sameOrientedVertex(Dart d, Dart e) return false; // None is equal to e => vertices are distinct } +unsigned int Map2::vertexDegree(Dart d) +{ + unsigned int count = 0 ; + Dart dNext = d ; + do + { + ++count ; + if(phi2(dNext) == dNext) + ++count ; + dNext = alpha1(dNext) ; + } while (dNext != d) ; + return count ; +} + +bool Map2::isBoundaryVertex(Dart d) +{ + Dart dNext = d ; + do + { + if(phi2(dNext) == dNext) + return true ; + dNext = alpha1(dNext) ; + } while (dNext != d) ; + return false ; +} + bool Map2::sameOrientedFace(Dart d, Dart e) { Dart dNext = d; @@ -439,18 +465,35 @@ bool Map2::sameOrientedFace(Dart d, Dart e) return false; // None is equal to e => faces are distinct } -unsigned int Map2::vertexDegree(Dart d) +bool Map2::sameOrientedVolume(Dart d, Dart e) { - unsigned int count = 0 ; - Dart dNext = d ; - do + DartMarkerStore mark(*this); // Lock a marker + bool found = false; // Last functor return value + + std::list visitedFaces; // Faces that are traversed + visitedFaces.push_back(d); // Start with the face of d + std::list::iterator face; + + // For every face added to the list + for (face = visitedFaces.begin(); !found && face != visitedFaces.end(); ++face) { - ++count ; - if(phi2(dNext) == dNext) - ++count ; - dNext = alpha1(dNext) ; - } while (dNext != d) ; - return count ; + if (!mark.isMarked(*face)) // Face has not been visited yet + { + Dart dNext = *face ; + do + { + if(dNext==e) + return true; + + 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 false; } unsigned int Map2::volumeDegree(Dart d) @@ -485,18 +528,6 @@ unsigned int Map2::volumeDegree(Dart d) return count; } -bool Map2::isBoundaryVertex(Dart d) -{ - Dart dNext = d ; - do - { - if(phi2(dNext) == dNext) - return true ; - dNext = alpha1(dNext) ; - } while (dNext != d) ; - return false ; -} - Dart Map2::nextOnBoundary(Dart d) { assert(phi2(d) == d); // Only work on boundary dart diff --git a/src/Topology/map/map3.cpp b/src/Topology/map/map3.cpp index 06b31e901ee6fe52e79418d2e94bc654f9fecb99..af2c8a446dbb61412a664af14f22b3f7d5972e5b 100644 --- a/src/Topology/map/map3.cpp +++ b/src/Topology/map/map3.cpp @@ -535,7 +535,7 @@ bool Map3::check() * Apply functors to all darts of a cell *************************************************************************/ -bool Map3::foreach_dart_of_vertex(Dart d, FunctorType& f, unsigned int thread) +bool Map3::foreach_dart_of_oriented_vertex(Dart d, FunctorType& f, unsigned int thread) { DartMarkerStore mv(*this,thread); // Lock a marker bool found = false; // Last functor return value