mirror of https://github.com/CGAL/cgal
Changes after Surface_reconstruction_points_3/Point_set_processing_3 submission review by AF (12):
Moved keep_largest_connected_components() to HalfedgeDS_decorator and Polyhedron_3 classes.
This commit is contained in:
parent
4a71c24908
commit
94690fd34f
|
|
@ -141,6 +141,12 @@ incidence relations except if mentioned otherwise.
|
|||
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
||||
\ccc{CGAL::Tag_true}.}
|
||||
|
||||
\ccMethod{unsigned int keep_largest_connected_components(unsigned int nb_components_to_keep);}
|
||||
{Erases the small connected components and the isolated vertices.
|
||||
Keep \ccc{nb_components_to_keep} largest connected components.
|
||||
Returns the number of connected components erased (ignoring isolated vertices).
|
||||
\ccCommentHeading{Requirement} supports vertices, halfedges, and removal operation.}
|
||||
|
||||
% -----------------------------------------
|
||||
\ccHeading{Modifying Functions (For Border Halfedges)}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,9 +26,13 @@
|
|||
|
||||
#include <CGAL/HalfedgeDS_items_decorator.h>
|
||||
#include <CGAL/HalfedgeDS_const_decorator.h>
|
||||
#include <vector>
|
||||
#include <CGAL/HalfedgeDS_iterator.h>
|
||||
#include <CGAL/IO/Verbose_ostream.h>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
CGAL_BEGIN_NAMESPACE
|
||||
|
||||
template < class p_HDS >
|
||||
|
|
@ -761,6 +765,53 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/// Erases the small connected components and the isolated vertices.
|
||||
///
|
||||
/// @commentheading Preconditions:
|
||||
/// supports vertices, halfedges, and removal operation.
|
||||
///
|
||||
/// @commentheading Template Parameters:
|
||||
/// @param nb_components_to_keep the number of large connected components to keep.
|
||||
///
|
||||
/// @return the number of connected components erased (ignoring isolated vertices).
|
||||
unsigned int keep_largest_connected_components(unsigned int nb_components_to_keep)
|
||||
{
|
||||
Assert_compile_time_tag(Supports_removal(), Tag_true());
|
||||
Assert_compile_time_tag(Supports_vertex_halfedge(), Tag_true());
|
||||
|
||||
unsigned int nb_erased_components = 0,
|
||||
nb_isolated_vertices = 0;
|
||||
|
||||
// Gets list of connected components, ordered by size (i.e. number of vertices)
|
||||
std::vector<Vertex_handle> components;
|
||||
get_connected_components(std::back_inserter(components));
|
||||
|
||||
// Erases all connected components but the largest
|
||||
while (components.size() > nb_components_to_keep)
|
||||
{
|
||||
Vertex_handle vertex = *(components.begin());
|
||||
|
||||
// Removes component from list
|
||||
components.erase(components.begin());
|
||||
|
||||
if (vertex->halfedge() != NULL) // if not isolated vertex
|
||||
{
|
||||
erase_connected_component(vertex->halfedge());
|
||||
nb_erased_components++;
|
||||
}
|
||||
else // if isolated vertex
|
||||
{
|
||||
vertices_erase(vertex);
|
||||
nb_isolated_vertices++;
|
||||
}
|
||||
}
|
||||
|
||||
// if (nb_isolated_vertices > 0)
|
||||
// std::cerr << " Erased " << nb_isolated_vertices << " isolated vertices\n";
|
||||
|
||||
return nb_erased_components;
|
||||
}
|
||||
|
||||
// Implementing These Functions.
|
||||
// ====================================================
|
||||
// Creation of New Elements
|
||||
|
|
@ -829,6 +880,123 @@ private:
|
|||
hds->faces_pop_back();
|
||||
}
|
||||
|
||||
/// Helper type for keep_largest_connected_components():
|
||||
///
|
||||
/// Possible values of a vertex tag.
|
||||
enum { tag_free, tag_done };
|
||||
|
||||
/// Helper method for keep_largest_connected_components():
|
||||
///
|
||||
/// Gets any vertex with tag == tag_free.
|
||||
///
|
||||
/// @return a list of pairs (component's size (number of vertices), a vertex of the component),
|
||||
/// ordered by size.
|
||||
Vertex_handle get_any_free_vertex(
|
||||
/*const*/ std::map<Vertex*, int>& tags) ///< container holding the tag of all vertices
|
||||
{
|
||||
for (Vertex_iterator it = hds->vertices_begin(); it != hds->vertices_end(); it++)
|
||||
{
|
||||
if (tags[&*it] == tag_free)
|
||||
return it;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// Helper method for keep_largest_connected_components():
|
||||
///
|
||||
/// Tag a "free" connected component as "done".
|
||||
///
|
||||
/// @return the size (number of vertices) of the component.
|
||||
unsigned int tag_component(
|
||||
Vertex_handle pSeedVertex, ///< one vertex of the connected component
|
||||
std::map<Vertex*, int>& tags) ///< container holding the tag of all vertices
|
||||
{
|
||||
// Circulator category.
|
||||
typedef typename Halfedge::Supports_halfedge_prev Supports_prev;
|
||||
typedef HalfedgeDS_circulator_traits<Supports_prev> Ctr;
|
||||
typedef typename Ctr::iterator_category circulator_category;
|
||||
|
||||
// Circulator around a vertex
|
||||
typedef I_HalfedgeDS_vertex_circ< Halfedge_handle, circulator_category>
|
||||
Halfedge_around_vertex_circulator;
|
||||
|
||||
unsigned int number_of_vertices = 0; // size (number of vertices) of the component
|
||||
|
||||
std::list<Vertex_handle> vertices;
|
||||
vertices.push_front(pSeedVertex);
|
||||
while (!vertices.empty())
|
||||
{
|
||||
Vertex_handle pVertex = vertices.front();
|
||||
vertices.pop_front();
|
||||
|
||||
// Skip vertex if already done
|
||||
if (tags[&*pVertex] == tag_done)
|
||||
continue;
|
||||
|
||||
// Mark vertex done
|
||||
tags[&*pVertex] = tag_done;
|
||||
number_of_vertices++;
|
||||
|
||||
// Add vertex's "free" neighbors to the list
|
||||
Halfedge_around_vertex_circulator neighbor_cir, neighbor_end;
|
||||
neighbor_cir = pVertex->vertex_begin();
|
||||
neighbor_end = neighbor_cir;
|
||||
CGAL_For_all(neighbor_cir,neighbor_end)
|
||||
{
|
||||
Vertex_handle neighbor = neighbor_cir->opposite()->vertex();
|
||||
if (tags[&*neighbor] == tag_free)
|
||||
vertices.push_front(neighbor);
|
||||
}
|
||||
}
|
||||
|
||||
return number_of_vertices;
|
||||
}
|
||||
|
||||
/// Helper method for keep_largest_connected_components():
|
||||
///
|
||||
/// Computes the list of all connected components of the polyhedron.
|
||||
/// Returns it as a list of components ordered by size.
|
||||
///
|
||||
/// @commentheading Template Parameters:
|
||||
/// @param OutputIterator value_type must be Vertex_handle.
|
||||
template<typename OutputIterator>
|
||||
void get_connected_components(
|
||||
OutputIterator output) ///< output iterator over vertex handles
|
||||
{
|
||||
// Implementation note:
|
||||
// We tag vertices instead of halfedges to save a factor 6.
|
||||
// The drawback is that we require the Polyhedron_3<Traits> to support vertices.
|
||||
// TODO: replace std::map by a property map to tag vertices.
|
||||
Assert_compile_time_tag(Supports_halfedge_vertex(), Tag_true());
|
||||
std::map<Vertex*, int> tags;
|
||||
|
||||
// list of all connected components of a polyhedron, ordered by size.
|
||||
std::multimap<unsigned int, Vertex_handle> components;
|
||||
|
||||
// Tag all mesh vertices as "free".
|
||||
for (Vertex_iterator it = hds->vertices_begin(); it != hds->vertices_end(); it++)
|
||||
{
|
||||
tags[&*it] = tag_free;
|
||||
}
|
||||
|
||||
// Record each component
|
||||
Vertex_handle seed_vertex = NULL;
|
||||
while((seed_vertex = get_any_free_vertex(tags)) != NULL)
|
||||
{
|
||||
// Tag it as "done" and compute its size (number of vertices)
|
||||
unsigned int number_of_vertices = tag_component(seed_vertex, tags);
|
||||
|
||||
// Add component to ordered list
|
||||
components.insert(std::make_pair(number_of_vertices, seed_vertex));
|
||||
}
|
||||
|
||||
// Copy ordered list to output iterator
|
||||
typename std::multimap<unsigned int, Vertex_handle>::iterator src;
|
||||
for (src = components.begin(); src != components.end(); ++src)
|
||||
*output++ = src->second;
|
||||
}
|
||||
|
||||
// Others
|
||||
// ----------------------------------
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -650,6 +650,12 @@ unchanged.
|
|||
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
||||
\ccc{CGAL::Tag_true}.}
|
||||
|
||||
\ccMethod{unsigned int keep_largest_connected_components(unsigned int nb_components_to_keep);}
|
||||
{Erases the small connected components and the isolated vertices.
|
||||
Keep \ccc{nb_components_to_keep} largest connected components.
|
||||
Returns the number of connected components erased (ignoring isolated vertices).
|
||||
\ccCommentHeading{Requirement} supports vertices, halfedges, and removal operation.}
|
||||
|
||||
\ccMethod{void clear();}
|
||||
{removes all vertices, halfedges, and facets.}
|
||||
|
||||
|
|
|
|||
|
|
@ -1376,6 +1376,21 @@ public:
|
|||
D.erase_connected_component(h);
|
||||
}
|
||||
|
||||
/// Erases the small connected components and the isolated vertices.
|
||||
///
|
||||
/// @commentheading Preconditions:
|
||||
/// supports vertices, halfedges, and removal operation.
|
||||
///
|
||||
/// @commentheading Template Parameters:
|
||||
/// @param nb_components_to_keep the number of large connected components to keep.
|
||||
///
|
||||
/// @return the number of connected components erased (ignoring isolated vertices).
|
||||
unsigned int keep_largest_connected_components(unsigned int nb_components_to_keep)
|
||||
{
|
||||
HalfedgeDS_decorator<HDS> D(hds);
|
||||
return D.keep_largest_connected_components(nb_components_to_keep);
|
||||
}
|
||||
|
||||
void clear() { hds.clear(); }
|
||||
// removes all vertices, halfedges, and facets.
|
||||
|
||||
|
|
|
|||
|
|
@ -633,6 +633,14 @@ void test_Polyhedron() {
|
|||
CGAL_assertion( P.size_of_vertices() == 4);
|
||||
CGAL_assertion( P.size_of_halfedges() == 12);
|
||||
CGAL_assertion( P.size_of_facets() == 4);
|
||||
P.make_triangle();
|
||||
unsigned int nb_erased_components = P.keep_largest_connected_components(1);
|
||||
CGAL_assertion( nb_erased_components == 1 );
|
||||
CGAL_assertion( P.is_valid());
|
||||
CGAL_assertion( P.is_tetrahedron( g));
|
||||
CGAL_assertion( P.size_of_vertices() == 4);
|
||||
CGAL_assertion( P.size_of_halfedges() == 12);
|
||||
CGAL_assertion( P.size_of_facets() == 4);
|
||||
P.erase_facet( g);
|
||||
CGAL_assertion( P.is_valid());
|
||||
CGAL_assertion( P.size_of_vertices() == 4);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ endforeach()
|
|||
# Require packages new or improved since CGAL 3.4
|
||||
include_directories (BEFORE ../../../../AABB_tree/include)
|
||||
include_directories (BEFORE ../../../../Surface_mesher/include)
|
||||
include_directories (BEFORE ../../../../Polyhedron/include/)
|
||||
include_directories (BEFORE ../../../../HalfedgeDS/include/)
|
||||
include_directories (BEFORE ../../../../Point_set_processing_3/include)
|
||||
|
||||
# Include this package's headers first
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
// This package
|
||||
#include <CGAL/APSS_reconstruction_function.h>
|
||||
#include <CGAL/IO/output_surface_facets_to_polyhedron.h>
|
||||
#include <CGAL/keep_largest_connected_components.h>
|
||||
|
||||
|
||||
// APSS implicit function
|
||||
|
|
@ -127,11 +126,11 @@ Polyhedron* APSS_reconstruct(const Point_set& points,
|
|||
std::cerr << "Erases small connected components...\n";
|
||||
|
||||
unsigned int nb_erased_components =
|
||||
CGAL::keep_largest_connected_components(*output_mesh, 1/* keep largest component only*/);
|
||||
output_mesh->keep_largest_connected_components( 1 /* keep largest component only*/ );
|
||||
|
||||
// Prints status
|
||||
std::cerr << "Erases small connected components: " << task_timer.time() << " seconds, "
|
||||
<< nb_erased_components << " components erased"
|
||||
<< nb_erased_components << " component(s) erased"
|
||||
<< std::endl;
|
||||
task_timer.reset();
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ endif(COMMAND cmake_policy)
|
|||
# Require packages new or improved since CGAL 3.4
|
||||
include_directories (BEFORE ../../../../AABB_tree/include)
|
||||
include_directories (BEFORE ../../../../Surface_mesher/include)
|
||||
include_directories (BEFORE ../../../../Polyhedron/include/)
|
||||
include_directories (BEFORE ../../../../HalfedgeDS/include/)
|
||||
include_directories (BEFORE ../../../../Point_set_processing_3/include)
|
||||
|
||||
# Include this package's headers first
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ The quality of the reconstruction highly depends on both the quality of input no
|
|||
|
||||
The radius property should correspond to the local point spacing which can be intuitively defined as the average distance to its {\em natural} one ring neighbors. It defines the {\em surface definition domain} as the union of these balls. Outside this union of balls, the surface is not defined. Therefore, if the balls do not overlap enough, then some holes might appear. If no radius is provided, then they are automatically computed from a basic estimate of the local density based on the 16 nearest neighbors.
|
||||
|
||||
APSS reconstruction may create small {\em ghost} connected components close to the reconstructed surface that you should delete with e.g. \ccc{keep_largest_connected_components}().
|
||||
APSS reconstruction may create small {\em ghost} connected components close to the reconstructed surface that you should delete with e.g. \ccc{Polyhedron_3::keep_largest_connected_components}().
|
||||
|
||||
%END-AUTO(\ccDefinition)
|
||||
|
||||
|
|
@ -164,7 +164,6 @@ Returns a point located inside the inferred surface.
|
|||
\ccSeeAlso
|
||||
|
||||
\ccRefIdfierPage{CGAL::Poisson_reconstruction_function<GeomTraits, ReconstructionTriangulation_3>} \\
|
||||
\ccRefIdfierPage{CGAL::keep_largest_connected_components<Polyhedron>} \\
|
||||
|
||||
\ccExample
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
% +------------------------------------------------------------------------+
|
||||
% | Reference manual page: Surface_reconstruction_points_3/intro.tex
|
||||
% +------------------------------------------------------------------------+
|
||||
% | 06.01.2009 Pierre Alliez, Laurent Saboret, Gael Guennebaud, Mariette Yvinec
|
||||
% | 06.01.2009 Pierre Alliez, Laurent Saboret
|
||||
% | Package: Surface_reconstruction_points_3
|
||||
% |
|
||||
% |
|
||||
|
|
@ -23,9 +23,3 @@ Note that since reconstruction methods often require pre-processing a point set
|
|||
\ccRefIdfierPage{CGAL::Poisson_reconstruction_function<GeomTraits, ReconstructionTriangulation_3>} \\
|
||||
\ccRefIdfierPage{CGAL::APSS_reconstruction_function<GeomTraits>} \\
|
||||
|
||||
|
||||
\subsection{Functions}
|
||||
|
||||
\ccRefIdfierPage{CGAL::output_surface_facets_to_polyhedron} \\
|
||||
\ccRefIdfierPage{CGAL::keep_largest_connected_components<Polyhedron>} \\
|
||||
|
||||
|
|
|
|||
|
|
@ -1,58 +0,0 @@
|
|||
% +------------------------------------------------------------------------+
|
||||
% | Reference manual page: keep_largest_connected_components.tex
|
||||
% +------------------------------------------------------------------------+
|
||||
% | 16.04.2009 Pierre Alliez, Laurent Saboret, Gael Guennebaud
|
||||
% | Package: Surface_reconstruction_points_3
|
||||
% |
|
||||
\RCSdef{\RCSerasesmallpolyhedronconnectedcomponentsRev}{$Id$}
|
||||
\RCSdefDate{\RCSerasesmallpolyhedronconnectedcomponentsDate}{$Date$}
|
||||
% |
|
||||
\ccRefPageBegin
|
||||
%%RefPage: end of header, begin of main body
|
||||
% +------------------------------------------------------------------------+
|
||||
|
||||
|
||||
\begin{ccRefFunction}{keep_largest_connected_components<Polyhedron>}
|
||||
|
||||
%% \ccHtmlCrossLink{} %% add further rules for cross referencing links
|
||||
%% \ccHtmlIndexC[function]{} %% add further index entries
|
||||
|
||||
\ccDefinition
|
||||
|
||||
\ccc{keep_largest_connected_components<Polyhedron>} erases the small connected components of a polyhedron.
|
||||
|
||||
% The section below is automatically generated. Do not edit!
|
||||
%START-AUTO(\ccDefinition)
|
||||
|
||||
% Reduce left margin
|
||||
\ccThree{123456789012345}{6789012}{}
|
||||
|
||||
\ccFunction{template<class Polyhedron> unsigned int keep_largest_connected_components(Polyhedron& polyhedron, unsigned int nb_components_to_keep);}
|
||||
{
|
||||
Erases small connected components of a polyhedron.
|
||||
\ccCommentHeading{Template Parameters} \\
|
||||
\ccc{Polyhedron}: an instance of \ccc{Polyhedron_3<Traits>} that supports vertices and removal operation. \ccc{nb_components_to_keep}: the number of large connected components to keep.
|
||||
\ccCommentHeading{Returns} the number of connected components erased.
|
||||
}
|
||||
\ccGlue
|
||||
|
||||
%END-AUTO(\ccDefinition)
|
||||
|
||||
\ccInclude{CGAL/keep_largest_connected_components.h}
|
||||
|
||||
\ccSeeAlso
|
||||
|
||||
\ccRefIdfierPage{CGAL::Polyhedron_3<Traits>} \\
|
||||
|
||||
\ccExample
|
||||
|
||||
See \ccc{APSS_reconstruction.cpp} example.
|
||||
|
||||
\end{ccRefFunction}
|
||||
|
||||
% +------------------------------------------------------------------------+
|
||||
%%RefPage: end of main body, begin of footer
|
||||
\ccRefPageEnd
|
||||
% EOF
|
||||
% +------------------------------------------------------------------------+
|
||||
|
||||
|
|
@ -8,8 +8,6 @@
|
|||
\input{Surface_reconstruction_points_3_ref/intro.tex}
|
||||
|
||||
\input{Surface_reconstruction_points_3_ref/APSS_reconstruction_function.tex}
|
||||
\input{Surface_reconstruction_points_3_ref/keep_largest_connected_components.tex}
|
||||
\input{Surface_reconstruction_points_3_ref/output_surface_facets_to_polyhedron.tex}
|
||||
\input{Surface_reconstruction_points_3_ref/Poisson_reconstruction_function.tex}
|
||||
|
||||
%% EOF
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
#include <CGAL/point_set_property_map.h>
|
||||
#include <CGAL/IO/read_xyz_points.h>
|
||||
#include <CGAL/IO/output_surface_facets_to_polyhedron.h>
|
||||
#include <CGAL/keep_largest_connected_components.h>
|
||||
|
||||
#include "compute_normal.h"
|
||||
|
||||
|
|
@ -273,11 +272,11 @@ int main(int argc, char * argv[])
|
|||
std::cerr << "Erases small connected components...\n";
|
||||
|
||||
unsigned int nb_erased_components =
|
||||
CGAL::keep_largest_connected_components(output_mesh, 1/* keep largest component only*/);
|
||||
output_mesh.keep_largest_connected_components( 1 /* keep largest component only*/ );
|
||||
|
||||
// Prints status
|
||||
std::cerr << "Erases small connected components: " << task_timer.time() << " seconds, "
|
||||
<< nb_erased_components << " components erased"
|
||||
<< nb_erased_components << " component(s) erased"
|
||||
<< std::endl;
|
||||
task_timer.reset();
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ endif(COMMAND cmake_policy)
|
|||
|
||||
# Require packages new or improved since CGAL 3.4
|
||||
include_directories (BEFORE ../../../Surface_mesher/include/)
|
||||
include_directories (BEFORE ../../../Polyhedron/include/)
|
||||
include_directories (BEFORE ../../../HalfedgeDS/include/)
|
||||
include_directories (BEFORE ../../../Point_set_processing_3/include/)
|
||||
|
||||
# Include this package's headers first
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ CGAL_BEGIN_NAMESPACE
|
|||
///
|
||||
/// APSS reconstruction may create small "ghost" connected components
|
||||
/// close to the reconstructed surface that you should delete with e.g.
|
||||
/// keep_largest_connected_components().
|
||||
/// Polyhedron_3::keep_largest_connected_components().
|
||||
///
|
||||
/// @heading Is Model for the Concepts:
|
||||
/// Model of the ImplicitFunction concept.
|
||||
|
|
|
|||
|
|
@ -1,233 +0,0 @@
|
|||
// Copyright (c) 2005-2009 INRIA (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org); you may redistribute it under
|
||||
// the terms of the Q Public License version 1.0.
|
||||
// See the file LICENSE.QPL distributed with CGAL.
|
||||
//
|
||||
// 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$
|
||||
//
|
||||
//
|
||||
// Author(s) : Laurent Saboret, Pierre Alliez
|
||||
|
||||
#ifndef CGAL_POLYHEDRON_CONNECTED_COMPONENTS_H
|
||||
#define CGAL_POLYHEDRON_CONNECTED_COMPONENTS_H
|
||||
|
||||
#include <CGAL/Polyhedron_3.h>
|
||||
#include <CGAL/point_set_processing_assertions.h>
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
CGAL_BEGIN_NAMESPACE
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Private section
|
||||
// ----------------------------------------------------------------------------
|
||||
namespace CGALi {
|
||||
|
||||
|
||||
/// Possible values of a vertex tag.
|
||||
enum { tag_free, tag_done };
|
||||
|
||||
|
||||
/// Gets any vertex with tag == tag_free.
|
||||
///
|
||||
/// @commentheading Template Parameters:
|
||||
/// @param Polyhedron an instance of CGAL::Polyhedron_3<Traits>.
|
||||
///
|
||||
/// @return a list of pairs (component's size (number of vertices), a vertex of the component),
|
||||
/// ordered by size.
|
||||
|
||||
template<class Polyhedron>
|
||||
typename Polyhedron::Vertex_handle
|
||||
get_any_free_vertex(Polyhedron& polyhedron,
|
||||
std::map<typename Polyhedron::Vertex*, int>& tags)
|
||||
{
|
||||
typedef typename Polyhedron::Vertex_handle Vertex_handle;
|
||||
typedef typename Polyhedron::Vertex_iterator Vertex_iterator;
|
||||
|
||||
for (Vertex_iterator it = polyhedron.vertices_begin();
|
||||
it != polyhedron.vertices_end();
|
||||
it++)
|
||||
{
|
||||
if (tags[&*it] == tag_free)
|
||||
return it;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// Tag a "free" connected component as "done".
|
||||
///
|
||||
/// @commentheading Template Parameters:
|
||||
/// @param Polyhedron an instance of CGAL::Polyhedron_3<Traits>.
|
||||
///
|
||||
/// @return the size (number of vertices) of the component.
|
||||
template<class Polyhedron>
|
||||
unsigned int tag_component(Polyhedron& polyhedron,
|
||||
typename Polyhedron::Vertex_handle pSeedVertex,
|
||||
std::map<typename Polyhedron::Vertex*, int>& tags)
|
||||
{
|
||||
typedef typename Polyhedron::Vertex_handle Vertex_handle;
|
||||
typedef typename Polyhedron::Vertex_iterator Vertex_iterator;
|
||||
typedef typename Polyhedron::Halfedge_around_vertex_circulator
|
||||
Halfedge_around_vertex_circulator;
|
||||
|
||||
unsigned int number_of_vertices = 0; // size (number of vertices) of the component
|
||||
|
||||
std::list<Vertex_handle> vertices;
|
||||
vertices.push_front(pSeedVertex);
|
||||
while (!vertices.empty())
|
||||
{
|
||||
Vertex_handle pVertex = vertices.front();
|
||||
vertices.pop_front();
|
||||
|
||||
// Skip vertex if already done
|
||||
if (tags[&*pVertex] == tag_done)
|
||||
continue;
|
||||
|
||||
// Mark vertex done
|
||||
tags[&*pVertex] = tag_done;
|
||||
number_of_vertices++;
|
||||
|
||||
// Add vertex's "free" neighbors to the list
|
||||
Halfedge_around_vertex_circulator neighbor_cir, neighbor_end;
|
||||
neighbor_cir = pVertex->vertex_begin();
|
||||
neighbor_end = neighbor_cir;
|
||||
CGAL_For_all(neighbor_cir,neighbor_end)
|
||||
{
|
||||
Vertex_handle neighbor = neighbor_cir->opposite()->vertex();
|
||||
if (tags[&*neighbor] == tag_free)
|
||||
vertices.push_front(neighbor);
|
||||
}
|
||||
}
|
||||
|
||||
return number_of_vertices;
|
||||
}
|
||||
|
||||
|
||||
} /* namespace CGALi */
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Public section
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/// Computes the list of all connected components of a polyhedron.
|
||||
/// Returns it as a list of components ordered by size.
|
||||
///
|
||||
/// @commentheading Template Parameters:
|
||||
/// @param Polyhedron an instance of CGAL::Polyhedron_3<Traits> that supports vertices.
|
||||
/// @param OutputIterator value_type must be Polyhedron::Vertex_handle.
|
||||
template<class Polyhedron,
|
||||
typename OutputIterator>
|
||||
void
|
||||
get_polyhedron_connected_components(
|
||||
Polyhedron& polyhedron, ///< input polyhedron
|
||||
OutputIterator output) ///< output iterator over vertex handles
|
||||
{
|
||||
// Implementation note:
|
||||
// We tag vertices instead of halfedges to save a factor 6.
|
||||
// The drawback is that we require the Polyhedron_3<Traits> to support vertices.
|
||||
// TODO: replace std::map by a property map to tag vertices.
|
||||
Assert_compile_time_tag(typename Polyhedron::Supports_halfedge_vertex(), Tag_true());
|
||||
std::map<typename Polyhedron::Vertex*, int> tags;
|
||||
|
||||
typedef typename Polyhedron::Vertex_handle Vertex_handle;
|
||||
typedef typename Polyhedron::Vertex_iterator Vertex_iterator;
|
||||
|
||||
// list of all connected components of a polyhedron, ordered by size.
|
||||
std::multimap<unsigned int, Vertex_handle> components;
|
||||
|
||||
// Tag all mesh vertices as "free".
|
||||
for (Vertex_iterator it = polyhedron.vertices_begin();
|
||||
it != polyhedron.vertices_end();
|
||||
it++)
|
||||
{
|
||||
tags[&*it] = CGALi::tag_free;
|
||||
}
|
||||
|
||||
// Record each component
|
||||
Vertex_handle seed_vertex = NULL;
|
||||
while((seed_vertex = CGALi::get_any_free_vertex(polyhedron, tags)) != NULL)
|
||||
{
|
||||
// Tag it as "done" and compute its size (number of vertices)
|
||||
unsigned int number_of_vertices = CGALi::tag_component(polyhedron, seed_vertex, tags);
|
||||
|
||||
// Add component to ordered list
|
||||
components.insert(std::make_pair(number_of_vertices, seed_vertex));
|
||||
}
|
||||
|
||||
// Copy ordered list to output iterator
|
||||
typename std::multimap<unsigned int, Vertex_handle>::iterator src;
|
||||
for (src = components.begin(); src != components.end(); ++src)
|
||||
*output++ = src->second;
|
||||
}
|
||||
|
||||
|
||||
/// Erases small connected components of a polyhedron.
|
||||
///
|
||||
/// @commentheading Template Parameters:
|
||||
/// @param Polyhedron an instance of CGAL::Polyhedron_3<Traits> that supports
|
||||
/// vertices and removal operation.
|
||||
/// @param nb_components_to_keep the number of large connected components to keep.
|
||||
///
|
||||
/// @return the number of connected components erased.
|
||||
template<class Polyhedron>
|
||||
unsigned int
|
||||
keep_largest_connected_components(Polyhedron& polyhedron, unsigned int nb_components_to_keep)
|
||||
{
|
||||
Assert_compile_time_tag(typename Polyhedron::Supports_removal(), Tag_true());
|
||||
|
||||
typedef typename Polyhedron::Vertex_handle Vertex_handle;
|
||||
|
||||
unsigned int nb_erased_components = 0,
|
||||
nb_isolated_vertices = 0;
|
||||
|
||||
// Gets list of connected components, ordered by size (number of vertices)
|
||||
std::vector<Vertex_handle> components;
|
||||
CGAL::get_polyhedron_connected_components(polyhedron, std::back_inserter(components));
|
||||
|
||||
// Erases all connected components but the largest
|
||||
while (components.size() > nb_components_to_keep)
|
||||
{
|
||||
Vertex_handle vertex = *(components.begin());
|
||||
|
||||
// Removes component from list
|
||||
components.erase(components.begin());
|
||||
|
||||
if (vertex->halfedge() != NULL) // if not isolated vertex
|
||||
{
|
||||
CGAL_TRACE_STREAM << " Erases connected component\n";
|
||||
polyhedron.erase_connected_component(vertex->halfedge());
|
||||
nb_erased_components++;
|
||||
}
|
||||
else // if isolated vertex
|
||||
{
|
||||
// TODO: erase isolated vertices?
|
||||
// Note: Polyhedron_3 does not export HalfedgeDS::vertices_erase(Vertex_handle v)
|
||||
|
||||
nb_isolated_vertices++;
|
||||
}
|
||||
}
|
||||
|
||||
if (nb_isolated_vertices > 0)
|
||||
CGAL_TRACE_STREAM << " Skipped " << nb_isolated_vertices << " isolated vertices\n";
|
||||
|
||||
return nb_erased_components;
|
||||
}
|
||||
|
||||
|
||||
CGAL_END_NAMESPACE
|
||||
|
||||
#endif // CGAL_POLYHEDRON_CONNECTED_COMPONENTS_H
|
||||
|
|
@ -23,7 +23,6 @@
|
|||
#include <CGAL/point_set_property_map.h>
|
||||
#include <CGAL/IO/read_xyz_points.h>
|
||||
#include <CGAL/IO/output_surface_facets_to_polyhedron.h>
|
||||
#include <CGAL/keep_largest_connected_components.h>
|
||||
|
||||
#include "compute_normal.h"
|
||||
|
||||
|
|
@ -285,12 +284,12 @@ int main(int argc, char * argv[])
|
|||
std::cerr << "Erases small connected components...\n";
|
||||
|
||||
unsigned int nb_erased_components =
|
||||
CGAL::keep_largest_connected_components(output_mesh, 1/* keep largest component only*/);
|
||||
output_mesh.keep_largest_connected_components( 1 /* keep largest component only*/ );
|
||||
|
||||
// Prints status
|
||||
/*long*/ memory = CGAL::Memory_sizer().virtual_size();
|
||||
std::cerr << "Erases small connected components: " << task_timer.time() << " seconds, "
|
||||
<< nb_erased_components << " components erased, "
|
||||
<< nb_erased_components << " component(s) erased, "
|
||||
<< (memory>>20) << " Mb allocated"
|
||||
<< std::endl;
|
||||
task_timer.reset();
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ endif(COMMAND cmake_policy)
|
|||
|
||||
# Require packages new or improved since CGAL 3.4
|
||||
include_directories (BEFORE ../../../Surface_mesher/include/)
|
||||
include_directories (BEFORE ../../../Polyhedron/include/)
|
||||
include_directories (BEFORE ../../../HalfedgeDS/include/)
|
||||
include_directories (BEFORE ../../../Point_set_processing_3/include/)
|
||||
|
||||
# Include this package's headers first
|
||||
|
|
|
|||
Loading…
Reference in New Issue