From d7df882179c5bacb473f028ab23ff4c8cffd72b8 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Sun, 10 May 2020 15:55:29 +0100 Subject: [PATCH 1/8] Add a function to check if add_face() can be called successfully --- BGL/include/CGAL/boost/graph/test_face.h | 155 +++++++++++++++++++++++ BGL/test/BGL/CMakeLists.txt | 2 + BGL/test/BGL/test_test_face.cpp | 61 +++++++++ 3 files changed, 218 insertions(+) create mode 100644 BGL/include/CGAL/boost/graph/test_face.h create mode 100644 BGL/test/BGL/test_test_face.cpp diff --git a/BGL/include/CGAL/boost/graph/test_face.h b/BGL/include/CGAL/boost/graph/test_face.h new file mode 100644 index 00000000000..c12207e3698 --- /dev/null +++ b/BGL/include/CGAL/boost/graph/test_face.h @@ -0,0 +1,155 @@ +// Copyright (c) 2019 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); 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 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0+ +// +// +// Author(s) : Andreas Fabri + +#ifndef CGAL_BOOST_GRAPH_TEST_FACE +#define CGAL_BOOST_GRAPH_TEST_FACE + +#include + +#include +#include +#include + +namespace CGAL { + + + + template +bool test_face(const VertexRange& vrange, const PMesh& sm) +{ + typedef boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef boost::graph_traits::halfedge_descriptor halfedge_descriptor; + + std::vector::vertex_descriptor> face(vrange.begin(), vrange.end()) + + int N = face.size(); + std::vector f2(face); + std::sort(f2.begin(), f2.end()); + + std::vector::iterator it = std::unique(f2.begin(),f2.end()); + + if((N > 0) && (it != f2.end())){ + std::cerr << "twice the same vertex" << std::endl; + return false; + } + + if(N < 3){ + return false; + } + + face.push_back(face.front()); + + for(int i=0; i < N; i++){ + halfedge_descriptor hd; + bool found; + boost::tie(hd,found) = halfedge(face[i],face[i+1],sm); + if(found && (! is_border(hd,sm))){ + std::cerr << "non-manifold edge" << std::endl; + return false; + } + } + + for(int i=0; i < N; i++){ + if(halfedge(face[i],sm) == boost::graph_traits::null_halfedge()){ + continue; + } + + if(! is_border(face[i],sm)){ + std::cerr << "non-manifold vertex" << std::endl; + return false; + } + } + //Test if all halfedges of the new face + //are possibly consecutive border halfedges in the HDS. + //Possibly because it may be not directly encoded in the HDS + //(using next() function ). This situation can occur when one or + //more facets share only a vertex: For example, the new facet we try to add + //would make the vertex indices[i] a manifold but this should be forbidden + //if a facet only incident to that vertex has already been inserted. + //We check this for each vertex of the sequence. + for(int i = 0; i < N; ++i) { + std::size_t prev_index= (i-1+N)%N; + std::size_t next_index= (i+1)%N; + vertex_descriptor previous_vertex = face[ prev_index ]; + vertex_descriptor next_vertex = face[ next_index ]; + + halfedge_descriptor v = halfedge(face[i],sm); + + if ( v == boost::graph_traits::null_halfedge() || + halfedge(previous_vertex,sm) == boost::graph_traits::null_halfedge()|| + halfedge(next_vertex,sm) == boost::graph_traits::null_halfedge() + ) continue; + + halfedge_descriptor start=v; + //halfedges pointing to/running out from vertex indices[i] + //and that need to be possibly consecutive + halfedge_descriptor prev_hd= boost::graph_traits::null_halfedge(),next_hd= boost::graph_traits::null_halfedge(); + + v = opposite(next(v,sm),sm); + //look for a halfedge incident to vertex indices[i] + //and which opposite is incident to previous_vertex + do{ + if(target(opposite(v,sm),sm)==previous_vertex){ + prev_hd=v; + CGAL_precondition(is_border(prev_hd,sm)); + break; + } + v = opposite(next(v,sm),sm); + } + while (v!=start); + + if (prev_hd != boost::graph_traits::null_halfedge()){ + v = opposite(next(v,sm),sm); + //prev_hd and next are already consecutive in the HDS + if (target(opposite(v,sm),sm)==next_vertex) continue; + + //look for a border halfedge which opposite is + //incident to next_vertex: set next halfedge + do + { + if (target(opposite(v,sm),sm)==next_vertex){ + next_hd = opposite(v,sm); + break; + } + v= opposite(next(v,sm),sm); + } + while(v!=prev_hd); + if (next_hd==boost::graph_traits::null_halfedge()) continue; + + //check if no constraint prevents + //prev_hd and next_hd to be adjacent: + do{ + v= opposite(next(v,sm),sm); + if ( is_border(opposite(v,sm),sm) ) break; + } + while (v!=prev_hd); + if (v==prev_hd) return false; + start=v; + } + } + + + return true; +} + + +} // namespace CGAL + +#endif // CGAL_BOOST_GRAPH_TEST_FACE diff --git a/BGL/test/BGL/CMakeLists.txt b/BGL/test/BGL/CMakeLists.txt index 2f9e1bb404e..fc371d9ac73 100644 --- a/BGL/test/BGL/CMakeLists.txt +++ b/BGL/test/BGL/CMakeLists.txt @@ -93,6 +93,8 @@ create_single_source_cgal_program( "test_Face_filtered_graph.cpp" ) create_single_source_cgal_program( "test_Euler_operations.cpp" ) +create_single_source_cgal_program( "test_test_face.cpp" ) + create_single_source_cgal_program( "test_Collapse_edge.cpp" ) create_single_source_cgal_program( "test_graph_traits.cpp" ) diff --git a/BGL/test/BGL/test_test_face.cpp b/BGL/test/BGL/test_test_face.cpp new file mode 100644 index 00000000000..e67905b01af --- /dev/null +++ b/BGL/test/BGL/test_test_face.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +#include + +#include +#include + +typedef CGAL::Simple_cartesian K; +typedef K::Point_3 Point_3; +typedef CGAL::Surface_mesh SM; + +typedef boost::graph_traits::vertex_descriptor vertex_descriptor; +typedef boost::graph_traits::vertex_iterator vertex_iterator; +typedef std::vector V; +int main() +{ + { + SM sm; + + vertex_descriptor vp = CGAL::add_vertex(sm); + vertex_descriptor vq = CGAL::add_vertex(sm); + vertex_descriptor vr = CGAL::add_vertex(sm); + vertex_descriptor vs = CGAL::add_vertex(sm); + std::array face0; + assert( ! CGAL::test_face(face0,sm) ); + std::array face1; + assert( ! CGAL::test_face(face1,sm) ); + std::array face2; + assert( ! CGAL::test_face(face2,sm) ); + + std::array face = { vp, vq, vr }; + CGAL::Euler::add_face(face, sm); + + assert( ! CGAL::test_face(face,sm) ); + std::swap(face[0],face[1]); + assert( CGAL::test_face(face,sm) ); + + face[2] = vs; + assert( CGAL::test_face(face,sm) ); + std::swap(face[0],face[1]); + assert( ! CGAL::test_face(face,sm) ); + } + + { + SM sm; + Point_3 p(0,0,0), q(1,0,0), r(0,1,0), s(0,0,1); + CGAL::make_tetrahedron(p, q, r, s, sm); + std::array face; + vertex_iterator it = vertices(sm).first; + face[0] = *it; + ++it; + face[1] = *it; + face[2] = CGAL::add_vertex(sm); + assert( ! CGAL::test_face(face,sm) ); + std::swap(face[0],face[1]); + assert( ! CGAL::test_face(face,sm) ); + } + + return 0; +} From f76f2e8fbe0424f29d175a26fdb7ceda7818ef03 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 11 May 2020 07:29:29 +0100 Subject: [PATCH 2/8] fix license header --- BGL/include/CGAL/boost/graph/test_face.h | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/test_face.h b/BGL/include/CGAL/boost/graph/test_face.h index c12207e3698..ed6792fbaae 100644 --- a/BGL/include/CGAL/boost/graph/test_face.h +++ b/BGL/include/CGAL/boost/graph/test_face.h @@ -1,19 +1,10 @@ -// Copyright (c) 2019 GeometryFactory (France). All rights reserved. +// Copyright (c) 2020 GeometryFactory (France). All rights reserved. // -// This file is part of CGAL (www.cgal.org); 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 3 of the License, -// or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// This file is part of CGAL (www.cgal.org); // // $URL$ // $Id$ -// SPDX-License-Identifier: LGPL-3.0+ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Andreas Fabri From 6e26cf0a397e3ce8d9a54b670610cc8d190ceba7 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 15 May 2020 15:16:25 +0100 Subject: [PATCH 3/8] Change name of function and variable --- BGL/include/CGAL/boost/graph/test_face.h | 121 +++++++++++------------ BGL/test/BGL/test_test_face.cpp | 18 ++-- 2 files changed, 66 insertions(+), 73 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/test_face.h b/BGL/include/CGAL/boost/graph/test_face.h index ed6792fbaae..212cedd4ff7 100644 --- a/BGL/include/CGAL/boost/graph/test_face.h +++ b/BGL/include/CGAL/boost/graph/test_face.h @@ -15,29 +15,25 @@ #include #include -#include #include namespace CGAL { - - - template -bool test_face(const VertexRange& vrange, const PMesh& sm) +template +bool can_add_face(const VertexRange& vrange, const PMesh& sm) { - typedef boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - std::vector::vertex_descriptor> face(vrange.begin(), vrange.end()) + std::vector::vertex_descriptor> face(vrange.begin(), vrange.end()); int N = face.size(); std::vector f2(face); std::sort(f2.begin(), f2.end()); - std::vector::iterator it = std::unique(f2.begin(),f2.end()); + typename std::vector::iterator it = std::unique(f2.begin(),f2.end()); if((N > 0) && (it != f2.end())){ - std::cerr << "twice the same vertex" << std::endl; return false; } @@ -52,7 +48,6 @@ bool test_face(const VertexRange& vrange, const PMesh& sm) bool found; boost::tie(hd,found) = halfedge(face[i],face[i+1],sm); if(found && (! is_border(hd,sm))){ - std::cerr << "non-manifold edge" << std::endl; return false; } } @@ -63,79 +58,77 @@ bool test_face(const VertexRange& vrange, const PMesh& sm) } if(! is_border(face[i],sm)){ - std::cerr << "non-manifold vertex" << std::endl; return false; } } //Test if all halfedges of the new face - //are possibly consecutive border halfedges in the HDS. - //Possibly because it may be not directly encoded in the HDS - //(using next() function ). This situation can occur when one or - //more facets share only a vertex: For example, the new facet we try to add - //would make the vertex indices[i] a manifold but this should be forbidden - //if a facet only incident to that vertex has already been inserted. - //We check this for each vertex of the sequence. + //are possibly consecutive border halfedges in the HDS. + //Possibly because it may be not directly encoded in the HDS + //(using next() function ). This situation can occur when one or + //more facets share only a vertex: For example, the new facet we try to add + //would make the vertex indices[i] a manifold but this should be forbidden + //if a facet only incident to that vertex has already been inserted. + //We check this for each vertex of the sequence. for(int i = 0; i < N; ++i) { - std::size_t prev_index= (i-1+N)%N; - std::size_t next_index= (i+1)%N; - vertex_descriptor previous_vertex = face[ prev_index ]; - vertex_descriptor next_vertex = face[ next_index ]; + std::size_t prev_index= (i-1+N)%N; + std::size_t next_index= (i+1)%N; + vertex_descriptor previous_vertex = face[ prev_index ]; + vertex_descriptor next_vertex = face[ next_index ]; - halfedge_descriptor v = halfedge(face[i],sm); + halfedge_descriptor halfedge_around_vertex = halfedge(face[i],sm); - if ( v == boost::graph_traits::null_halfedge() || - halfedge(previous_vertex,sm) == boost::graph_traits::null_halfedge()|| - halfedge(next_vertex,sm) == boost::graph_traits::null_halfedge() + if ( halfedge_around_vertex == boost::graph_traits::null_halfedge() || + halfedge(previous_vertex,sm) == boost::graph_traits::null_halfedge()|| + halfedge(next_vertex,sm) == boost::graph_traits::null_halfedge() ) continue; - halfedge_descriptor start=v; - //halfedges pointing to/running out from vertex indices[i] - //and that need to be possibly consecutive - halfedge_descriptor prev_hd= boost::graph_traits::null_halfedge(),next_hd= boost::graph_traits::null_halfedge(); + halfedge_descriptor start=halfedge_around_vertex; + //halfedges pointing to/running out from vertex indices[i] + //and that need to be possibly consecutive + halfedge_descriptor prev_hd= boost::graph_traits::null_halfedge(),next_hd= boost::graph_traits::null_halfedge(); - v = opposite(next(v,sm),sm); - //look for a halfedge incident to vertex indices[i] - //and which opposite is incident to previous_vertex - do{ - if(target(opposite(v,sm),sm)==previous_vertex){ - prev_hd=v; - CGAL_precondition(is_border(prev_hd,sm)); - break; - } - v = opposite(next(v,sm),sm); + halfedge_around_vertex = opposite(next(halfedge_around_vertex,sm),sm); + //look for a halfedge incident to vertex indices[i] + //and which opposite is incident to previous_vertex + do{ + if(target(opposite(halfedge_around_vertex,sm),sm)==previous_vertex){ + prev_hd=halfedge_around_vertex; + CGAL_precondition(is_border(prev_hd,sm)); + break; } - while (v!=start); + halfedge_around_vertex = opposite(next(v,sm),sm); + } + while (halfedge_around_vertex!=start); - if (prev_hd != boost::graph_traits::null_halfedge()){ - v = opposite(next(v,sm),sm); - //prev_hd and next are already consecutive in the HDS - if (target(opposite(v,sm),sm)==next_vertex) continue; + if (prev_hd != boost::graph_traits::null_halfedge()){ + halfedge_around_vertex = opposite(next(v,sm),sm); + //prev_hd and next are already consecutive in the HDS + if (target(opposite(halfedge_around_vertex,sm),sm)==next_vertex) continue; - //look for a border halfedge which opposite is - //incident to next_vertex: set next halfedge - do + //look for a border halfedge which opposite is + //incident to next_vertex: set next halfedge + do { - if (target(opposite(v,sm),sm)==next_vertex){ - next_hd = opposite(v,sm); + if (target(opposite(halfedge_around_vertex,sm),sm)==next_vertex){ + next_hd = opposite(halfedge_around_vertex,sm); break; } - v= opposite(next(v,sm),sm); + halfedge_around_vertex = opposite(next(halfedge_around_vertex,sm),sm); } - while(v!=prev_hd); - if (next_hd==boost::graph_traits::null_halfedge()) continue; + while(halfedge_around_vertex != prev_hd); + if (next_hd==boost::graph_traits::null_halfedge()) continue; - //check if no constraint prevents - //prev_hd and next_hd to be adjacent: - do{ - v= opposite(next(v,sm),sm); - if ( is_border(opposite(v,sm),sm) ) break; - } - while (v!=prev_hd); - if (v==prev_hd) return false; - start=v; + //check if no constraint prevents + //prev_hd and next_hd to be adjacent: + do{ + halfedge_around_vertex = opposite(next(halfedge_around_vertex, sm),sm); + if ( is_border(opposite(v,sm),sm) ) break; } + while (halfedge_around_vertex != prev_hd); + if (halfedge_around_vertex == prev_hd) return false; + start = halfedge_around_vertex; } - + } return true; } diff --git a/BGL/test/BGL/test_test_face.cpp b/BGL/test/BGL/test_test_face.cpp index e67905b01af..f57bc70456d 100644 --- a/BGL/test/BGL/test_test_face.cpp +++ b/BGL/test/BGL/test_test_face.cpp @@ -23,23 +23,23 @@ int main() vertex_descriptor vr = CGAL::add_vertex(sm); vertex_descriptor vs = CGAL::add_vertex(sm); std::array face0; - assert( ! CGAL::test_face(face0,sm) ); + assert( ! CGAL::can_add_face(face0,sm) ); std::array face1; - assert( ! CGAL::test_face(face1,sm) ); + assert( ! CGAL::can_add_face(face1,sm) ); std::array face2; - assert( ! CGAL::test_face(face2,sm) ); + assert( ! CGAL::can_add_face(face2,sm) ); std::array face = { vp, vq, vr }; CGAL::Euler::add_face(face, sm); - assert( ! CGAL::test_face(face,sm) ); + assert( ! CGAL::can_add_face(face,sm) ); std::swap(face[0],face[1]); - assert( CGAL::test_face(face,sm) ); + assert( CGAL::can_add_face(face,sm) ); face[2] = vs; - assert( CGAL::test_face(face,sm) ); + assert( CGAL::can_add_face(face,sm) ); std::swap(face[0],face[1]); - assert( ! CGAL::test_face(face,sm) ); + assert( ! CGAL::can_add_face(face,sm) ); } { @@ -52,9 +52,9 @@ int main() ++it; face[1] = *it; face[2] = CGAL::add_vertex(sm); - assert( ! CGAL::test_face(face,sm) ); + assert( ! CGAL::can_add_face(face,sm) ); std::swap(face[0],face[1]); - assert( ! CGAL::test_face(face,sm) ); + assert( ! CGAL::can_add_face(face,sm) ); } return 0; From 8c68031de1b9cf1eeedf24ecb9412e051d6768c5 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 15 May 2020 15:23:52 +0100 Subject: [PATCH 4/8] Move the code into Euler_operations.h --- .../CGAL/boost/graph/Euler_operations.h | 123 ++++++++++++++++ BGL/include/CGAL/boost/graph/test_face.h | 139 ------------------ BGL/test/BGL/test_test_face.cpp | 19 ++- 3 files changed, 132 insertions(+), 149 deletions(-) delete mode 100644 BGL/include/CGAL/boost/graph/test_face.h diff --git a/BGL/include/CGAL/boost/graph/Euler_operations.h b/BGL/include/CGAL/boost/graph/Euler_operations.h index d575de0f17a..036b33bf17d 100644 --- a/BGL/include/CGAL/boost/graph/Euler_operations.h +++ b/BGL/include/CGAL/boost/graph/Euler_operations.h @@ -13,6 +13,8 @@ #define CGAL_EULER_OPERATIONS_H #include +#include +#include #include #include @@ -558,6 +560,127 @@ add_edge(typename boost::graph_traits::vertex_descriptor s, return e; } + +/** +* checks whether a new face defined by a range of vertices (identified by their descriptors, +* `boost::graph_traits::%vertex_descriptor`) can be added. +*/ +template +bool can_add_face(const VertexRange& vrange, const PMesh& sm) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + + std::vector::vertex_descriptor> face(vrange.begin(), vrange.end()); + + int N = face.size(); + std::vector f2(face); + std::sort(f2.begin(), f2.end()); + + typename std::vector::iterator it = std::unique(f2.begin(),f2.end()); + + if((N > 0) && (it != f2.end())){ + return false; + } + + if(N < 3){ + return false; + } + + face.push_back(face.front()); + + for(int i=0; i < N; i++){ + halfedge_descriptor hd; + bool found; + boost::tie(hd,found) = halfedge(face[i],face[i+1],sm); + if(found && (! is_border(hd,sm))){ + return false; + } + } + + for(int i=0; i < N; i++){ + if(halfedge(face[i],sm) == boost::graph_traits::null_halfedge()){ + continue; + } + + if(! is_border(face[i],sm)){ + return false; + } + } + //Test if all halfedges of the new face + //are possibly consecutive border halfedges in the HDS. + //Possibly because it may be not directly encoded in the HDS + //(using next() function ). This situation can occur when one or + //more facets share only a vertex: For example, the new facet we try to add + //would make the vertex indices[i] a manifold but this should be forbidden + //if a facet only incident to that vertex has already been inserted. + //We check this for each vertex of the sequence. + for(int i = 0; i < N; ++i) { + std::size_t prev_index= (i-1+N)%N; + std::size_t next_index= (i+1)%N; + vertex_descriptor previous_vertex = face[ prev_index ]; + vertex_descriptor next_vertex = face[ next_index ]; + + halfedge_descriptor halfedge_around_vertex = halfedge(face[i],sm); + + if ( halfedge_around_vertex == boost::graph_traits::null_halfedge() || + halfedge(previous_vertex,sm) == boost::graph_traits::null_halfedge()|| + halfedge(next_vertex,sm) == boost::graph_traits::null_halfedge() + ) continue; + + halfedge_descriptor start=halfedge_around_vertex; + //halfedges pointing to/running out from vertex indices[i] + //and that need to be possibly consecutive + halfedge_descriptor prev_hd= boost::graph_traits::null_halfedge(),next_hd= boost::graph_traits::null_halfedge(); + + halfedge_around_vertex = opposite(next(halfedge_around_vertex,sm),sm); + //look for a halfedge incident to vertex indices[i] + //and which opposite is incident to previous_vertex + do{ + if(target(opposite(halfedge_around_vertex,sm),sm)==previous_vertex){ + prev_hd=halfedge_around_vertex; + CGAL_precondition(is_border(prev_hd,sm)); + break; + } + halfedge_around_vertex = opposite(next(v,sm),sm); + } + while (halfedge_around_vertex!=start); + + if (prev_hd != boost::graph_traits::null_halfedge()){ + halfedge_around_vertex = opposite(next(v,sm),sm); + //prev_hd and next are already consecutive in the HDS + if (target(opposite(halfedge_around_vertex,sm),sm)==next_vertex) continue; + + //look for a border halfedge which opposite is + //incident to next_vertex: set next halfedge + do + { + if (target(opposite(halfedge_around_vertex,sm),sm)==next_vertex){ + next_hd = opposite(halfedge_around_vertex,sm); + break; + } + halfedge_around_vertex = opposite(next(halfedge_around_vertex,sm),sm); + } + while(halfedge_around_vertex != prev_hd); + if (next_hd==boost::graph_traits::null_halfedge()) continue; + + //check if no constraint prevents + //prev_hd and next_hd to be adjacent: + do{ + halfedge_around_vertex = opposite(next(halfedge_around_vertex, sm),sm); + if ( is_border(opposite(v,sm),sm) ) break; + } + while (halfedge_around_vertex != prev_hd); + if (halfedge_around_vertex == prev_hd) return false; + start = halfedge_around_vertex; + } + } + + return true; +} + + + /** * adds a new face defined by a range of vertices (identified by their descriptors, * `boost::graph_traits::%vertex_descriptor`). diff --git a/BGL/include/CGAL/boost/graph/test_face.h b/BGL/include/CGAL/boost/graph/test_face.h deleted file mode 100644 index 212cedd4ff7..00000000000 --- a/BGL/include/CGAL/boost/graph/test_face.h +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) 2020 GeometryFactory (France). All rights reserved. -// -// This file is part of CGAL (www.cgal.org); -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Andreas Fabri - -#ifndef CGAL_BOOST_GRAPH_TEST_FACE -#define CGAL_BOOST_GRAPH_TEST_FACE - -#include - -#include -#include - -namespace CGAL { - -template -bool can_add_face(const VertexRange& vrange, const PMesh& sm) -{ - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - - std::vector::vertex_descriptor> face(vrange.begin(), vrange.end()); - - int N = face.size(); - std::vector f2(face); - std::sort(f2.begin(), f2.end()); - - typename std::vector::iterator it = std::unique(f2.begin(),f2.end()); - - if((N > 0) && (it != f2.end())){ - return false; - } - - if(N < 3){ - return false; - } - - face.push_back(face.front()); - - for(int i=0; i < N; i++){ - halfedge_descriptor hd; - bool found; - boost::tie(hd,found) = halfedge(face[i],face[i+1],sm); - if(found && (! is_border(hd,sm))){ - return false; - } - } - - for(int i=0; i < N; i++){ - if(halfedge(face[i],sm) == boost::graph_traits::null_halfedge()){ - continue; - } - - if(! is_border(face[i],sm)){ - return false; - } - } - //Test if all halfedges of the new face - //are possibly consecutive border halfedges in the HDS. - //Possibly because it may be not directly encoded in the HDS - //(using next() function ). This situation can occur when one or - //more facets share only a vertex: For example, the new facet we try to add - //would make the vertex indices[i] a manifold but this should be forbidden - //if a facet only incident to that vertex has already been inserted. - //We check this for each vertex of the sequence. - for(int i = 0; i < N; ++i) { - std::size_t prev_index= (i-1+N)%N; - std::size_t next_index= (i+1)%N; - vertex_descriptor previous_vertex = face[ prev_index ]; - vertex_descriptor next_vertex = face[ next_index ]; - - halfedge_descriptor halfedge_around_vertex = halfedge(face[i],sm); - - if ( halfedge_around_vertex == boost::graph_traits::null_halfedge() || - halfedge(previous_vertex,sm) == boost::graph_traits::null_halfedge()|| - halfedge(next_vertex,sm) == boost::graph_traits::null_halfedge() - ) continue; - - halfedge_descriptor start=halfedge_around_vertex; - //halfedges pointing to/running out from vertex indices[i] - //and that need to be possibly consecutive - halfedge_descriptor prev_hd= boost::graph_traits::null_halfedge(),next_hd= boost::graph_traits::null_halfedge(); - - halfedge_around_vertex = opposite(next(halfedge_around_vertex,sm),sm); - //look for a halfedge incident to vertex indices[i] - //and which opposite is incident to previous_vertex - do{ - if(target(opposite(halfedge_around_vertex,sm),sm)==previous_vertex){ - prev_hd=halfedge_around_vertex; - CGAL_precondition(is_border(prev_hd,sm)); - break; - } - halfedge_around_vertex = opposite(next(v,sm),sm); - } - while (halfedge_around_vertex!=start); - - if (prev_hd != boost::graph_traits::null_halfedge()){ - halfedge_around_vertex = opposite(next(v,sm),sm); - //prev_hd and next are already consecutive in the HDS - if (target(opposite(halfedge_around_vertex,sm),sm)==next_vertex) continue; - - //look for a border halfedge which opposite is - //incident to next_vertex: set next halfedge - do - { - if (target(opposite(halfedge_around_vertex,sm),sm)==next_vertex){ - next_hd = opposite(halfedge_around_vertex,sm); - break; - } - halfedge_around_vertex = opposite(next(halfedge_around_vertex,sm),sm); - } - while(halfedge_around_vertex != prev_hd); - if (next_hd==boost::graph_traits::null_halfedge()) continue; - - //check if no constraint prevents - //prev_hd and next_hd to be adjacent: - do{ - halfedge_around_vertex = opposite(next(halfedge_around_vertex, sm),sm); - if ( is_border(opposite(v,sm),sm) ) break; - } - while (halfedge_around_vertex != prev_hd); - if (halfedge_around_vertex == prev_hd) return false; - start = halfedge_around_vertex; - } - } - - return true; -} - - -} // namespace CGAL - -#endif // CGAL_BOOST_GRAPH_TEST_FACE diff --git a/BGL/test/BGL/test_test_face.cpp b/BGL/test/BGL/test_test_face.cpp index f57bc70456d..e69f7e3176e 100644 --- a/BGL/test/BGL/test_test_face.cpp +++ b/BGL/test/BGL/test_test_face.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include @@ -23,23 +22,23 @@ int main() vertex_descriptor vr = CGAL::add_vertex(sm); vertex_descriptor vs = CGAL::add_vertex(sm); std::array face0; - assert( ! CGAL::can_add_face(face0,sm) ); + assert( ! CGAL::Euler::can_add_face(face0,sm) ); std::array face1; - assert( ! CGAL::can_add_face(face1,sm) ); + assert( ! CGAL::Euler::can_add_face(face1,sm) ); std::array face2; - assert( ! CGAL::can_add_face(face2,sm) ); + assert( ! CGAL::Euler::can_add_face(face2,sm) ); std::array face = { vp, vq, vr }; CGAL::Euler::add_face(face, sm); - assert( ! CGAL::can_add_face(face,sm) ); + assert( ! CGAL::Euler::can_add_face(face,sm) ); std::swap(face[0],face[1]); - assert( CGAL::can_add_face(face,sm) ); + assert( CGAL::Euler::can_add_face(face,sm) ); face[2] = vs; - assert( CGAL::can_add_face(face,sm) ); + assert( CGAL::Euler::can_add_face(face,sm) ); std::swap(face[0],face[1]); - assert( ! CGAL::can_add_face(face,sm) ); + assert( ! CGAL::Euler::can_add_face(face,sm) ); } { @@ -52,9 +51,9 @@ int main() ++it; face[1] = *it; face[2] = CGAL::add_vertex(sm); - assert( ! CGAL::can_add_face(face,sm) ); + assert( ! CGAL::Euler::can_add_face(face,sm) ); std::swap(face[0],face[1]); - assert( ! CGAL::can_add_face(face,sm) ); + assert( ! CGAL::Euler::can_add_face(face,sm) ); } return 0; From bd04336674992a15c123de93d93a6ae7e133674e Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 19 May 2020 16:42:44 +0100 Subject: [PATCH 5/8] Fix variable name. Why did this compile locally?? --- BGL/include/CGAL/boost/graph/Euler_operations.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/Euler_operations.h b/BGL/include/CGAL/boost/graph/Euler_operations.h index 036b33bf17d..59d595b4f49 100644 --- a/BGL/include/CGAL/boost/graph/Euler_operations.h +++ b/BGL/include/CGAL/boost/graph/Euler_operations.h @@ -642,12 +642,12 @@ bool can_add_face(const VertexRange& vrange, const PMesh& sm) CGAL_precondition(is_border(prev_hd,sm)); break; } - halfedge_around_vertex = opposite(next(v,sm),sm); + halfedge_around_vertex = opposite(next(halfedge_around_vertex,sm),sm); } while (halfedge_around_vertex!=start); if (prev_hd != boost::graph_traits::null_halfedge()){ - halfedge_around_vertex = opposite(next(v,sm),sm); + halfedge_around_vertex = opposite(next(halfedge_around_vertex,sm),sm); //prev_hd and next are already consecutive in the HDS if (target(opposite(halfedge_around_vertex,sm),sm)==next_vertex) continue; @@ -668,7 +668,7 @@ bool can_add_face(const VertexRange& vrange, const PMesh& sm) //prev_hd and next_hd to be adjacent: do{ halfedge_around_vertex = opposite(next(halfedge_around_vertex, sm),sm); - if ( is_border(opposite(v,sm),sm) ) break; + if ( is_border(opposite(halfedge_around_vertex,sm),sm) ) break; } while (halfedge_around_vertex != prev_hd); if (halfedge_around_vertex == prev_hd) return false; From 58f56f5a68bb848f285b7a538e2094bf18d1dbd0 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 22 May 2020 07:54:19 +0100 Subject: [PATCH 6/8] remove trailing whitespace --- Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h index 96ef666128f..ebd3d300d66 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h @@ -9,11 +9,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // - #ifndef CGAL_SURFACE_MESH_H #define CGAL_SURFACE_MESH_H - #include #include From 6358c82ef7c089742f2ead7127407ad46e36015b Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 15 Jul 2020 11:16:39 +0100 Subject: [PATCH 7/8] Add change entry --- Installation/CHANGES.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index b6cc3849288..a06ed38cfd2 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -1,6 +1,14 @@ Release History =============== +Release 5.2 +----------- + +### CGAL and the Boost Graph Library (BGL) + +- Added the function `can_add_face()`, which tests whether a new face defined by a range of vertices can be added. + + [Release 5.1](https://github.com/CGAL/cgal/releases/tag/releases%2FCGAL-5.1) ----------- From 7c7f21e2dd6277ae30129c9a983685014d43ca5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 12 Aug 2020 15:48:18 +0200 Subject: [PATCH 8/8] avoid warning --- BGL/include/CGAL/boost/graph/Euler_operations.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/Euler_operations.h b/BGL/include/CGAL/boost/graph/Euler_operations.h index 59d595b4f49..8d5268da6e0 100644 --- a/BGL/include/CGAL/boost/graph/Euler_operations.h +++ b/BGL/include/CGAL/boost/graph/Euler_operations.h @@ -573,7 +573,7 @@ bool can_add_face(const VertexRange& vrange, const PMesh& sm) std::vector::vertex_descriptor> face(vrange.begin(), vrange.end()); - int N = face.size(); + std::size_t N = face.size(); std::vector f2(face); std::sort(f2.begin(), f2.end()); @@ -589,7 +589,7 @@ bool can_add_face(const VertexRange& vrange, const PMesh& sm) face.push_back(face.front()); - for(int i=0; i < N; i++){ + for(std::size_t i=0; i < N; ++i){ halfedge_descriptor hd; bool found; boost::tie(hd,found) = halfedge(face[i],face[i+1],sm); @@ -598,7 +598,7 @@ bool can_add_face(const VertexRange& vrange, const PMesh& sm) } } - for(int i=0; i < N; i++){ + for(std::size_t i=0; i < N; ++i){ if(halfedge(face[i],sm) == boost::graph_traits::null_halfedge()){ continue; } @@ -615,7 +615,7 @@ bool can_add_face(const VertexRange& vrange, const PMesh& sm) //would make the vertex indices[i] a manifold but this should be forbidden //if a facet only incident to that vertex has already been inserted. //We check this for each vertex of the sequence. - for(int i = 0; i < N; ++i) { + for(std::size_t i = 0; i < N; ++i) { std::size_t prev_index= (i-1+N)%N; std::size_t next_index= (i+1)%N; vertex_descriptor previous_vertex = face[ prev_index ];