mirror of https://github.com/CGAL/cgal
Merge pull request #604 from bo0ts/BGL-add_clear-pmoeller
Add BGL helper CGAL::clear
This commit is contained in:
commit
4c4b191209
|
|
@ -150,6 +150,8 @@ user might encounter.
|
||||||
- `CGAL::make_quad()`
|
- `CGAL::make_quad()`
|
||||||
- `CGAL::make_hexahedron()`
|
- `CGAL::make_hexahedron()`
|
||||||
|
|
||||||
|
- `CGAL::clear()`
|
||||||
|
|
||||||
## Iterators ##
|
## Iterators ##
|
||||||
- `CGAL::Halfedge_around_source_iterator`
|
- `CGAL::Halfedge_around_source_iterator`
|
||||||
- `CGAL::Halfedge_around_target_iterator`
|
- `CGAL::Halfedge_around_target_iterator`
|
||||||
|
|
|
||||||
|
|
@ -654,6 +654,25 @@ bool is_valid(OpenMesh::PolyMesh_ArrayKernelT<K>& sm, bool /* verbose */ = false
|
||||||
|
|
||||||
} // namespace OpenMesh
|
} // namespace OpenMesh
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
|
||||||
|
// Overload CGAL::clear function. PolyMesh_ArrayKernel behaves
|
||||||
|
// differently from other meshes. Calling clear does not affect the
|
||||||
|
// number of vertices, edges, or faces in the mesh. To get actual
|
||||||
|
// numbers it is necessary to first collect garbage. We add an
|
||||||
|
// overlaod to get consistent behavior.
|
||||||
|
template<typename K>
|
||||||
|
void clear(OpenMesh::PolyMesh_ArrayKernelT<K>& sm)
|
||||||
|
{
|
||||||
|
sm.clear();
|
||||||
|
sm.garbage_collection(true, true, true);
|
||||||
|
CGAL_postcondition(num_edges(sm) == 0);
|
||||||
|
CGAL_postcondition(num_vertices(sm) == 0);
|
||||||
|
CGAL_postcondition(num_faces(sm) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef CGAL_NO_DEPRECATED_CODE
|
#ifndef CGAL_NO_DEPRECATED_CODE
|
||||||
#include <CGAL/boost/graph/backward_compatibility_functions.h>
|
#include <CGAL/boost/graph/backward_compatibility_functions.h>
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <CGAL/boost/graph/iterator.h>
|
#include <CGAL/boost/graph/iterator.h>
|
||||||
#include <CGAL/boost/graph/properties.h>
|
#include <CGAL/boost/graph/properties.h>
|
||||||
|
#include <CGAL/boost/graph/internal/Has_member_clear.h>
|
||||||
|
|
||||||
namespace CGAL {
|
namespace CGAL {
|
||||||
|
|
||||||
|
|
@ -663,6 +663,60 @@ make_tetrahedron(const P& p0, const P& p1, const P& p2, const P& p3, Graph& g)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
template<typename FaceGraph>
|
||||||
|
inline
|
||||||
|
typename boost::enable_if<Has_member_clear<FaceGraph>, void>::type
|
||||||
|
clear_impl(FaceGraph& g)
|
||||||
|
{ g.clear(); }
|
||||||
|
|
||||||
|
template<typename FaceGraph>
|
||||||
|
inline
|
||||||
|
typename boost::disable_if<Has_member_clear<FaceGraph>, void>::type
|
||||||
|
clear_impl(FaceGraph& g)
|
||||||
|
{
|
||||||
|
typedef typename boost::graph_traits<FaceGraph>::edge_descriptor edge_descriptor;
|
||||||
|
typedef typename boost::graph_traits<FaceGraph>::vertex_descriptor vertex_descriptor;
|
||||||
|
typedef typename boost::graph_traits<FaceGraph>::face_descriptor face_descriptor;
|
||||||
|
BOOST_FOREACH(edge_descriptor ed, edges(g)) {
|
||||||
|
remove_edge(ed, g);
|
||||||
|
}
|
||||||
|
BOOST_FOREACH(vertex_descriptor vd, vertices(g)) {
|
||||||
|
remove_vertex(vd, g);
|
||||||
|
}
|
||||||
|
BOOST_FOREACH(face_descriptor fd, faces(g)) {
|
||||||
|
remove_face(fd, g);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \ingroup PkgBGLHelperFct
|
||||||
|
*
|
||||||
|
* removes all vertices, faces and halfedges from a graph. Calls
|
||||||
|
* `remove_edge()`, `remove_vertex()`, and `remove_face()` for each
|
||||||
|
* edge, vertex or face.
|
||||||
|
*
|
||||||
|
* If the graph has a member function `clear`, it will be called
|
||||||
|
* instead.
|
||||||
|
*
|
||||||
|
* @tparam FaceGraph model of `MutableHalfedgeGraph` and `MutableFaceGraph`
|
||||||
|
*
|
||||||
|
* @param g the graph to clear
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
template<typename FaceGraph>
|
||||||
|
void clear(FaceGraph& g)
|
||||||
|
{
|
||||||
|
internal::clear_impl(g);
|
||||||
|
CGAL_postcondition(num_edges(g) == 0);
|
||||||
|
CGAL_postcondition(num_vertices(g) == 0);
|
||||||
|
CGAL_postcondition(num_faces(g) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace CGAL
|
} // namespace CGAL
|
||||||
|
|
||||||
#endif // CGAL_BOOST_GRAPH_HELPERS_H
|
#endif // CGAL_BOOST_GRAPH_HELPERS_H
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef CGAL_HAS_MEMBER_CLEAR_H
|
||||||
|
#define CGAL_HAS_MEMBER_CLEAR_H
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class Has_member_clear
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
template<class U, U>
|
||||||
|
class check {};
|
||||||
|
|
||||||
|
template<class C>
|
||||||
|
static char f(check<void(C::*)(void), &C::clear>*);
|
||||||
|
|
||||||
|
template<class C>
|
||||||
|
static int f(...);
|
||||||
|
public:
|
||||||
|
static const bool value = (sizeof(f<T>(0)) == sizeof(char));
|
||||||
|
};
|
||||||
|
|
||||||
|
} // internal
|
||||||
|
} // cgal
|
||||||
|
|
||||||
|
#endif /* CGAL_HAS_MEMBER_CLEAR_H */
|
||||||
|
|
@ -67,16 +67,24 @@ create_single_source_cgal_program( "graph_concept_Polyhedron_3.cpp" )
|
||||||
|
|
||||||
create_single_source_cgal_program( "graph_concept_Triangulation_2.cpp" )
|
create_single_source_cgal_program( "graph_concept_Triangulation_2.cpp" )
|
||||||
|
|
||||||
|
create_single_source_cgal_program( "test_clear.cpp" )
|
||||||
|
|
||||||
create_single_source_cgal_program( "test_graph_geometry.cpp" )
|
create_single_source_cgal_program( "test_graph_geometry.cpp" )
|
||||||
|
|
||||||
create_single_source_cgal_program( "test_helpers.cpp" )
|
create_single_source_cgal_program( "test_helpers.cpp" )
|
||||||
|
|
||||||
|
create_single_source_cgal_program( "test_Has_member_clear.cpp" )
|
||||||
|
|
||||||
create_single_source_cgal_program( "test_cgal_bgl_named_params.cpp" )
|
create_single_source_cgal_program( "test_cgal_bgl_named_params.cpp" )
|
||||||
|
|
||||||
if(OpenMesh_FOUND)
|
if(OpenMesh_FOUND)
|
||||||
target_link_libraries( test_graph_geometry ${OPENMESH_LIBRARIES})
|
target_link_libraries( test_graph_geometry ${OPENMESH_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(OpenMesh_FOUND)
|
||||||
|
target_link_libraries( test_clear ${OPENMESH_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
create_single_source_cgal_program( "test_Euler_operations.cpp" )
|
create_single_source_cgal_program( "test_Euler_operations.cpp" )
|
||||||
if(OpenMesh_FOUND)
|
if(OpenMesh_FOUND)
|
||||||
target_link_libraries( test_Euler_operations ${OPENMESH_LIBRARIES})
|
target_link_libraries( test_Euler_operations ${OPENMESH_LIBRARIES})
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include <CGAL/assertions.h>
|
||||||
|
#include <CGAL/boost/graph/internal/Has_member_clear.h>
|
||||||
|
|
||||||
|
struct with_clear {
|
||||||
|
void clear() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wo_clear { };
|
||||||
|
|
||||||
|
struct with_clear_but_args {
|
||||||
|
void clear(int) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct with_clear_but_const {
|
||||||
|
void clear() const {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using namespace CGAL::internal;
|
||||||
|
CGAL_static_assertion(Has_member_clear<with_clear>::value);
|
||||||
|
CGAL_static_assertion(!Has_member_clear<wo_clear>::value);
|
||||||
|
CGAL_static_assertion(!Has_member_clear<with_clear_but_args>::value);
|
||||||
|
CGAL_static_assertion(!Has_member_clear<with_clear_but_const>::value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
#include "test_Prefix.h"
|
||||||
|
|
||||||
|
#include <CGAL/boost/graph/helpers.h>
|
||||||
|
|
||||||
|
template<typename Mesh>
|
||||||
|
void test() {
|
||||||
|
const std::string fname = "data/7_faces_triangle.off";
|
||||||
|
Mesh m;
|
||||||
|
if(!read_a_mesh(m, fname)) {
|
||||||
|
std::cout << "Error reading file: " << fname << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGAL::clear(m);
|
||||||
|
assert(num_vertices(m) == 0);
|
||||||
|
assert(num_faces(m) == 0);
|
||||||
|
assert(num_edges(m) == 0);
|
||||||
|
assert(is_valid(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test<SM>();
|
||||||
|
test<Polyhedron>();
|
||||||
|
#if defined(CGAL_USE_OPENMESH)
|
||||||
|
test<OMesh>();
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -289,6 +289,10 @@ and <code>src/</code> directories).
|
||||||
<code>CGAL::expand_vertex_selection()</code>, <code>CGAL::reduce_vertex_selection()</code>
|
<code>CGAL::expand_vertex_selection()</code>, <code>CGAL::reduce_vertex_selection()</code>
|
||||||
and <code>CGAL::select_incident_faces()</code>.
|
and <code>CGAL::select_incident_faces()</code>.
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
Add a helper function <code>CGAL::clear</code> which clears a
|
||||||
|
MutableFaceGraph efficiently and generically.
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<!-- Visualization -->
|
<!-- Visualization -->
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -607,6 +607,14 @@ std::size_t keep_largest_connected_components(PolygonMesh& pmesh
|
||||||
boost::vector_property_map<std::size_t, FaceIndexMap> face_cc(fim);
|
boost::vector_property_map<std::size_t, FaceIndexMap> face_cc(fim);
|
||||||
std::size_t num = connected_components(pmesh, face_cc, np);
|
std::size_t num = connected_components(pmesh, face_cc, np);
|
||||||
|
|
||||||
|
// Even even we do not want to keep anything we need to first
|
||||||
|
// calculate the number of existing connected_components to get the
|
||||||
|
// correct return value.
|
||||||
|
if(nb_components_to_keep == 0) {
|
||||||
|
CGAL::clear(pmesh);
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
if((num == 1)|| (nb_components_to_keep > num) )
|
if((num == 1)|| (nb_components_to_keep > num) )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -150,11 +150,38 @@ void test_border_cases()
|
||||||
assert(num_vertices(copy)==0);
|
assert(num_vertices(copy)==0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void keep_nothing(const char* argv1)
|
||||||
|
{
|
||||||
|
typedef boost::graph_traits<Mesh_with_id>::vertex_descriptor vertex_descriptor;
|
||||||
|
typedef boost::graph_traits<Mesh_with_id>::face_descriptor face_descriptor;
|
||||||
|
|
||||||
|
Mesh_with_id sm;
|
||||||
|
std::ifstream in(argv1);
|
||||||
|
if(!(in >> sm)) {
|
||||||
|
std::cerr << "ERROR reading file: " << argv1 << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int i=0;
|
||||||
|
BOOST_FOREACH(face_descriptor f, faces(sm)){
|
||||||
|
f->id() = i++;
|
||||||
|
}
|
||||||
|
i=0;
|
||||||
|
BOOST_FOREACH(vertex_descriptor v, vertices(sm)){
|
||||||
|
v->id() = i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
PMP::keep_largest_connected_components(sm, 0);
|
||||||
|
assert(num_vertices(sm) == 0);
|
||||||
|
assert(num_edges(sm) == 0);
|
||||||
|
assert(num_faces(sm) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
const char* filename = (argc > 1) ? argv[1] : "data/blobby_3cc.off";
|
const char* filename = (argc > 1) ? argv[1] : "data/blobby_3cc.off";
|
||||||
mesh_with_id(filename);
|
mesh_with_id(filename);
|
||||||
mesh_no_id(filename);
|
mesh_no_id(filename);
|
||||||
test_border_cases();
|
test_border_cases();
|
||||||
|
keep_nothing(filename);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue