mirror of https://github.com/CGAL/cgal
switch internally to BGL API in mesh segmentation. We still have to deal with the point property maps
This commit is contained in:
parent
4a37f74122
commit
2c4c38809d
|
|
@ -137,7 +137,7 @@ public:
|
|||
Triangle_property_map(&graph),
|
||||
Point_property_map(&graph) )
|
||||
{}
|
||||
#if 1
|
||||
#if 0
|
||||
// for backward compatibility with Polyhedron::facets_begin()
|
||||
AABB_face_graph_triangle_primitive(typename boost::graph_traits<FaceGraph>::face_descriptor fd, FaceGraph& graph)
|
||||
: Base( Id_(fd),
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include <CGAL/IO/Verbose_ostream.h>
|
||||
#include <CGAL/Polyhedron_traits_3.h>
|
||||
|
||||
// at the end of this file: #include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
|
||||
namespace CGAL {
|
||||
|
||||
template <class VertexBase>
|
||||
|
|
@ -1533,4 +1534,6 @@ public:
|
|||
|
||||
} //namespace CGAL
|
||||
|
||||
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
|
||||
|
||||
#endif // CGAL_POLYHEDRON_3_H //
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
#include <cmath>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <CGAL/boost/graph/iterator.h>
|
||||
namespace CGAL
|
||||
{
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ public:
|
|||
* - domain : over value distances
|
||||
* @param mesh `CGAL Polyhedron` on which @a values are defined
|
||||
* @param window_size range of effective neighbors
|
||||
* @param[in, out] values `ReadWritePropertyMap` with `Polyhedron::Facet_const_handle` as key and `double` as value type
|
||||
* @param[in, out] values `ReadWritePropertyMap` with `boost::graph_traits<Polyhedron>::face_handle` as key and `double` as value type
|
||||
*/
|
||||
template<class ValuePropertyMap>
|
||||
void operator()(const Polyhedron& mesh,
|
||||
|
|
@ -65,8 +65,8 @@ public:
|
|||
boost::optional<double> spatial_parameter = boost::optional<double>(),
|
||||
boost::optional<double> range_parameter = boost::optional<double>()
|
||||
) const {
|
||||
typedef typename Polyhedron::Facet_const_handle Facet_const_handle;
|
||||
typedef typename Polyhedron::Facet_const_iterator Facet_const_iterator;
|
||||
typedef typename boost::graph_traits<Polyhedron>::face_descriptor face_descriptor;
|
||||
typedef typename boost::graph_traits<Polyhedron>::face_iterator face_iterator;
|
||||
|
||||
double spatial_parameter_actual;
|
||||
if(!spatial_parameter) {
|
||||
|
|
@ -78,18 +78,19 @@ public:
|
|||
std::vector<double> smoothed_values; // holds smoothed values
|
||||
smoothed_values.reserve(mesh.size_of_facets());
|
||||
|
||||
for(Facet_const_iterator facet_it = mesh.facets_begin();
|
||||
facet_it != mesh.facets_end(); ++facet_it) {
|
||||
std::map<Facet_const_handle, std::size_t> neighbors;
|
||||
NeighborSelector()(facet_it, window_size,
|
||||
face_iterator facet_it, fend;
|
||||
for(boost::tie(facet_it,fend) = faces(mesh);
|
||||
facet_it != fend; ++facet_it) {
|
||||
std::map<face_descriptor, std::size_t> neighbors;
|
||||
NeighborSelector()(mesh,*facet_it, window_size,
|
||||
neighbors); // gather neighbors in the window
|
||||
double current_sdf_value = values[facet_it];
|
||||
double current_sdf_value = values[*facet_it];
|
||||
|
||||
double range_parameter_actual;
|
||||
if(!range_parameter) {
|
||||
// calculate deviation for range weighting.
|
||||
double deviation = 0.0;
|
||||
for(typename std::map<Facet_const_handle, std::size_t>::iterator it =
|
||||
for(typename std::map<face_descriptor, std::size_t>::iterator it =
|
||||
neighbors.begin(); it != neighbors.end(); ++it) {
|
||||
deviation += std::pow(values[it->first] - current_sdf_value, 2);
|
||||
}
|
||||
|
|
@ -107,7 +108,7 @@ public:
|
|||
|
||||
// smooth
|
||||
double total_sdf_value = 0.0, total_weight = 0.0;
|
||||
for(typename std::map<Facet_const_handle, std::size_t>::iterator it =
|
||||
for(typename std::map<face_descriptor, std::size_t>::iterator it =
|
||||
neighbors.begin(); it != neighbors.end(); ++it) {
|
||||
double spatial_weight = gaussian_function(static_cast<double>(it->second),
|
||||
spatial_parameter_actual);
|
||||
|
|
@ -123,10 +124,10 @@ public:
|
|||
}
|
||||
// put smoothed values back again to values pmap.
|
||||
std::vector<double>::iterator smoothed_value_it = smoothed_values.begin();
|
||||
for(Facet_const_iterator facet_it = mesh.facets_begin();
|
||||
facet_it != mesh.facets_end();
|
||||
for(boost::tie(facet_it,fend) = faces(mesh);
|
||||
facet_it != fend;
|
||||
++facet_it, ++smoothed_value_it) {
|
||||
values[facet_it] = *smoothed_value_it;
|
||||
values[*facet_it] = *smoothed_value_it;
|
||||
}
|
||||
}
|
||||
private:
|
||||
|
|
@ -147,26 +148,27 @@ public:
|
|||
*
|
||||
* @param mesh `CGAL Polyhedron` on which @a values are defined
|
||||
* @param window_size range of effective neighbors
|
||||
* @param[in, out] values `ReadWritePropertyMap` with `Polyhedron::Facet_const_handle` as key and `double` as value type
|
||||
* @param[in, out] values `ReadWritePropertyMap` with `boost::graph_traits<Polyhedron>::face_handle` as key and `double` as value type
|
||||
*/
|
||||
template<class ValuePropertyMap>
|
||||
void operator()(const Polyhedron& mesh,
|
||||
std::size_t window_size,
|
||||
ValuePropertyMap values) const {
|
||||
typedef typename Polyhedron::Facet_const_handle Facet_const_handle;
|
||||
typedef typename Polyhedron::Facet_const_iterator Facet_const_iterator;
|
||||
typedef typename boost::graph_traits<Polyhedron>::face_descriptor face_descriptor;
|
||||
typedef typename boost::graph_traits<Polyhedron>::face_iterator face_iterator;
|
||||
|
||||
std::vector<double> smoothed_values;
|
||||
smoothed_values.reserve(mesh.size_of_facets());
|
||||
for(Facet_const_iterator facet_it = mesh.facets_begin();
|
||||
facet_it != mesh.facets_end(); ++facet_it) {
|
||||
std::map<Facet_const_handle, std::size_t> neighbors;
|
||||
NeighborSelector()(facet_it, window_size,
|
||||
face_iterator facet_it, fend;
|
||||
for(boost::tie(facet_it,fend) = faces(mesh);
|
||||
facet_it != fend; ++facet_it) {
|
||||
std::map<face_descriptor, std::size_t> neighbors;
|
||||
NeighborSelector()(*facet_it, window_size,
|
||||
neighbors); // gather neighbors in the window
|
||||
|
||||
std::vector<double> neighbor_values;
|
||||
neighbor_values.reserve(neighbors.size());
|
||||
for(typename std::map<Facet_const_handle, std::size_t>::iterator it =
|
||||
for(typename std::map<face_descriptor, std::size_t>::iterator it =
|
||||
neighbors.begin(); it != neighbors.end(); ++it) {
|
||||
neighbor_values.push_back(values[it->first]);
|
||||
}
|
||||
|
|
@ -184,9 +186,8 @@ public:
|
|||
}
|
||||
// put smoothed values back again to values pmap.
|
||||
std::vector<double>::iterator smoothed_value_it = smoothed_values.begin();
|
||||
for(Facet_const_iterator facet_it = mesh.facets_begin();
|
||||
facet_it != mesh.facets_end();
|
||||
++facet_it) {
|
||||
for(boost::tie(facet_it,fend) = faces(mesh);
|
||||
facet_it != fend; ++facet_it) {
|
||||
values[facet_it] = *smoothed_value_it;
|
||||
}
|
||||
}
|
||||
|
|
@ -224,20 +225,20 @@ template<class Polyhedron>
|
|||
class Neighbor_selector_by_edge
|
||||
{
|
||||
private:
|
||||
typedef typename Polyhedron::Facet::Halfedge_around_facet_const_circulator
|
||||
Halfedge_around_facet_const_circulator;
|
||||
typedef Halfedge_around_face_circulator<Polyhedron> Halfedge_around_face_circulator;
|
||||
public:
|
||||
typedef typename Polyhedron::Facet_const_handle Facet_const_handle;
|
||||
typedef typename boost::graph_traits<Polyhedron>::face_descriptor face_descriptor;
|
||||
/**
|
||||
* Breadth-first traversal on facets by treating facets, which share a common edge, are 1-level neighbors.
|
||||
* @param facet root facet
|
||||
* @param max_level maximum allowed distance (number of levels) between root facet and visited facet
|
||||
* @param[out] neighbors visited facets and their distances to root facet
|
||||
*/
|
||||
void operator()(Facet_const_handle facet,
|
||||
void operator()(const Polyhedron& polyhedron,
|
||||
face_descriptor facet,
|
||||
std::size_t max_level,
|
||||
std::map<Facet_const_handle, std::size_t>& neighbors) const {
|
||||
typedef std::pair<Facet_const_handle, std::size_t> Facet_level_pair;
|
||||
std::map<face_descriptor, std::size_t>& neighbors) const {
|
||||
typedef std::pair<face_descriptor, std::size_t> Facet_level_pair;
|
||||
|
||||
std::queue<Facet_level_pair> facet_queue;
|
||||
facet_queue.push(Facet_level_pair(facet, 0));
|
||||
|
|
@ -250,11 +251,10 @@ public:
|
|||
while(!facet_queue.empty()) {
|
||||
const Facet_level_pair& pair = facet_queue.front();
|
||||
|
||||
Halfedge_around_facet_const_circulator facet_circulator =
|
||||
pair.first->facet_begin();
|
||||
Halfedge_around_face_circulator facet_circulator(halfedge(pair.first,polyhedron),polyhedron), done(facet_circulator);
|
||||
do {
|
||||
if(!facet_circulator->opposite()->is_border()) {
|
||||
Facet_level_pair new_pair(facet_circulator->opposite()->facet(),
|
||||
if(!(face(opposite(*facet_circulator,polyhedron),polyhedron) == boost::graph_traits<Polyhedron>::null_face())) {
|
||||
Facet_level_pair new_pair(face(opposite(*facet_circulator,polyhedron),polyhedron),
|
||||
pair.second + 1);
|
||||
if(neighbors.insert(new_pair).second
|
||||
&& new_pair.second < max_level) { // first insert new_pair to map
|
||||
|
|
@ -263,7 +263,7 @@ public:
|
|||
new_pair); // if its level is equal to max_level do not put it in
|
||||
} // queue since we do not want to traverse its neighbors
|
||||
}
|
||||
} while(++facet_circulator != pair.first->facet_begin());
|
||||
} while(++facet_circulator != done);
|
||||
|
||||
facet_queue.pop();
|
||||
}
|
||||
|
|
@ -275,22 +275,22 @@ template<class Polyhedron>
|
|||
class Neighbor_selector_by_vertex
|
||||
{
|
||||
private:
|
||||
typedef typename Polyhedron::Facet::Halfedge_around_vertex_const_circulator
|
||||
Halfedge_around_vertex_const_circulator;
|
||||
typedef typename Polyhedron::Halfedge_const_iterator Halfedge_const_iterator;
|
||||
typedef typename Polyhedron::Vertex_const_iterator Vertex_const_iterator;
|
||||
typedef Halfedge_around_target_circulator<Polyhedron> Halfedge_around_target_circulator;
|
||||
typedef typename boost::graph_traits<Polyhedron>::halfedge_iterator halfedge_iterator;
|
||||
typedef typename boost::graph_traits<Polyhedron>::vertex_iterator vertex_iterator;
|
||||
public:
|
||||
typedef typename Polyhedron::Facet_const_handle Facet_const_handle;
|
||||
typedef typename boost::graph_traits<Polyhedron>::face_descriptor face_descriptor;
|
||||
/**
|
||||
* Breadth-first traversal on facets by treating facets, which share a common vertex, are 1-level neighbors.
|
||||
* @param facet root facet
|
||||
* @param max_level maximum allowed distance (number of levels) between root facet and visited facet
|
||||
* @param[out] neighbors visited facets and their distances to root facet
|
||||
*/
|
||||
void operator()(Facet_const_handle facet,
|
||||
void operator()(const Polyhedron& polyhedron,
|
||||
face_descriptor facet,
|
||||
std::size_t max_level,
|
||||
std::map<Facet_const_handle, std::size_t>& neighbors) const {
|
||||
typedef std::pair<Facet_const_handle, std::size_t> Facet_level_pair;
|
||||
std::map<face_descriptor, std::size_t>& neighbors) const {
|
||||
typedef std::pair<face_descriptor, std::size_t> Facet_level_pair;
|
||||
|
||||
std::queue<Facet_level_pair> facet_queue;
|
||||
facet_queue.push(Facet_level_pair(facet, 0));
|
||||
|
|
@ -303,15 +303,14 @@ public:
|
|||
while(!facet_queue.empty()) {
|
||||
const Facet_level_pair& pair = facet_queue.front();
|
||||
|
||||
Facet_const_handle facet_front = pair.first;
|
||||
Halfedge_const_iterator edge = facet_front->halfedge();
|
||||
face_descriptor facet_front = pair.first;
|
||||
halfedge_iterator edge = halfedge(facet_front,polyhedron)
|
||||
do { // loop on three vertices of the facet
|
||||
Vertex_const_iterator vertex = edge->vertex();
|
||||
Halfedge_around_vertex_const_circulator vertex_circulator =
|
||||
vertex->vertex_begin();
|
||||
Halfedge_around_target_circulator vertex_circulator(*edge,polyhedron), done(vertex_circulator);
|
||||
|
||||
do { // for each vertex loop on incoming edges (through those edges loop on neighbor facets which includes the vertex)
|
||||
if(!vertex_circulator->is_border()) {
|
||||
Facet_level_pair new_pair(vertex_circulator->opposite()->facet(),
|
||||
if(!(face(*vertex_circulator,polyhedron) == graph_traits<Polyhedron::null_face())) {
|
||||
Facet_level_pair new_pair(face(opposite(*vertex_circulator),polyhedron,polyhedron),
|
||||
pair.second + 1);
|
||||
if(neighbors.insert(new_pair).second
|
||||
&& new_pair.second < max_level) { // first insert new_pair to map
|
||||
|
|
@ -320,8 +319,8 @@ public:
|
|||
new_pair); // if its level is equal to max_level do not put it in
|
||||
} // queue since we do not want to traverse its childs
|
||||
}
|
||||
} while(++vertex_circulator != vertex->vertex_begin());
|
||||
} while((edge = edge->next()) != facet_front->halfedge());
|
||||
} while(++vertex_circulator != done);
|
||||
} while((edge = next(edge,polyhedron)) != halfedge(facet_front,polyhedron));
|
||||
|
||||
facet_queue.pop();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,10 +78,8 @@ private:
|
|||
typedef typename GeomTraits::Segment_3 Segment;
|
||||
typedef typename GeomTraits::FT FT;
|
||||
|
||||
typedef typename Polyhedron::Facet Facet;
|
||||
|
||||
typedef typename boost::graph_traits<Polyhedron>::face_iterator Facet_const_iterator;
|
||||
typedef typename boost::graph_traits<Polyhedron>::face_descriptor Facet_const_handle;
|
||||
typedef typename boost::graph_traits<Polyhedron>::face_iterator face_iterator;
|
||||
typedef typename boost::graph_traits<Polyhedron>::face_descriptor face_handle;
|
||||
|
||||
typedef AABB_face_graph_triangle_primitive<Polyhedron> Primitive;
|
||||
typedef AABB_traits_SDF<GeomTraits, Primitive, fast_bbox_intersection>
|
||||
|
|
@ -184,7 +182,7 @@ public:
|
|||
|
||||
/**
|
||||
* Calculates SDF values for each facet in a range, and stores them in @a sdf_values. Note that sdf values are neither smoothed nor normalized.
|
||||
* @tparam FacetValueMap `WritablePropertyMap` with `Polyhedron::Facet_const_handle` as key and `double` as value type
|
||||
* @tparam FacetValueMap `WritablePropertyMap` with `boost::graph_traits<Polyhedron>::face_handle` as key and `double` as value type
|
||||
* @tparam InputIterator Iterator over polyhedrons. Its value type is `pointer to polyhedron`.
|
||||
* @param facet_begin range begin
|
||||
* @param facet_end range past-the-end
|
||||
|
|
@ -374,7 +372,7 @@ private:
|
|||
* @return calculated SDF value
|
||||
*/
|
||||
boost::optional<double> calculate_sdf_value_of_facet(
|
||||
Facet_const_handle facet,
|
||||
face_handle facet,
|
||||
double cone_angle,
|
||||
bool accept_if_acute,
|
||||
const Disk_samples_list& disk_samples) const {
|
||||
|
|
@ -386,9 +384,9 @@ private:
|
|||
normal=scale_functor(normal,
|
||||
FT(1.0/std::sqrt(to_double(normal.squared_length()))));
|
||||
|
||||
CGAL::internal::SkipPrimitiveFunctor<Facet_const_handle>
|
||||
CGAL::internal::SkipPrimitiveFunctor<face_handle>
|
||||
skip(facet);
|
||||
CGAL::internal::FirstIntersectionVisitor<Facet_const_handle>
|
||||
CGAL::internal::FirstIntersectionVisitor<face_handle>
|
||||
visitor;
|
||||
|
||||
return calculate_sdf_value_of_point(center, normal, skip, visitor, cone_angle,
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@ class Postprocess_sdf_values
|
|||
{
|
||||
|
||||
typedef typename Polyhedron::Facet Facet;
|
||||
typedef typename Polyhedron::Facet_const_handle Facet_const_handle;
|
||||
typedef typename Polyhedron::Facet_const_iterator Facet_const_iterator;
|
||||
typedef typename boost::graph_traits<Polyhedron>::face_descriptor face_descriptor;
|
||||
typedef typename boost::graph_traits<Polyhedron>::face_iterator face_iterator;
|
||||
|
||||
typedef Bilateral_filtering<Polyhedron> Default_filter;
|
||||
|
||||
|
|
@ -73,48 +73,49 @@ public:
|
|||
* Sdf values on these facets are assigned to average sdf value of its neighbors.
|
||||
* If still there is any facet which has no sdf value, assigns minimum sdf value to it.
|
||||
* This is meaningful since (being an outlier) zero sdf values might effect normalization & log extremely.
|
||||
* @param[in, out] sdf_values `ReadWritePropertyMap` with `Polyhedron::Facet_const_handle` as key and `double` as value type
|
||||
* @param[in, out] sdf_values `ReadWritePropertyMap` with `Polyhedron::face_descriptor` as key and `double` as value type
|
||||
*/
|
||||
template<class SDFPropertyMap>
|
||||
void check_missing_sdf_values(const Polyhedron& mesh,
|
||||
SDFPropertyMap sdf_values) {
|
||||
std::vector<Facet_const_handle> still_missing_facets;
|
||||
std::vector<face_descriptor> still_missing_facets;
|
||||
double min_sdf = (std::numeric_limits<double>::max)();
|
||||
// If there is any facet which has no sdf value, assign average sdf value of its neighbors
|
||||
for(Facet_const_iterator facet_it = mesh.facets_begin();
|
||||
facet_it != mesh.facets_end(); ++facet_it) {
|
||||
double sdf_value = sdf_values[facet_it];
|
||||
face_iterator facet_it, fend;
|
||||
for(boost::tie(facet_it,fend) = faces(mesh);
|
||||
facet_it != fend; ++facet_it) {
|
||||
double sdf_value = sdf_values[*facet_it];
|
||||
CGAL_assertion(sdf_value == -1 || sdf_value >= 0); // validity check
|
||||
if(sdf_value != -1.0) {
|
||||
min_sdf = (std::min)(sdf_value, min_sdf);
|
||||
continue;
|
||||
}
|
||||
|
||||
typename Facet::Halfedge_around_facet_const_circulator facet_circulator =
|
||||
facet_it->facet_begin();
|
||||
typename Halfedge_around_face_circulator<Polyhedron> facet_circulator(halfedge(*facet_it,mesh),mesh), done(facet_circulator);
|
||||
|
||||
double total_neighbor_sdf = 0.0;
|
||||
std::size_t nb_valid_neighbors = 0;
|
||||
do {
|
||||
if(!facet_circulator->opposite()->is_border()) {
|
||||
double neighbor_sdf = sdf_values[facet_circulator->opposite()->facet()];
|
||||
if(!(*facet_circulator)->opposite()->is_border()) {
|
||||
double neighbor_sdf = sdf_values[(*facet_circulator)->opposite()->facet()];
|
||||
if(neighbor_sdf != -1) {
|
||||
total_neighbor_sdf += neighbor_sdf;
|
||||
++nb_valid_neighbors;
|
||||
}
|
||||
}
|
||||
} while( ++facet_circulator != facet_it->facet_begin());
|
||||
} while( ++facet_circulator != done);
|
||||
|
||||
if(nb_valid_neighbors == 0) {
|
||||
still_missing_facets.push_back(facet_it);
|
||||
still_missing_facets.push_back(*facet_it);
|
||||
} else {
|
||||
sdf_value = total_neighbor_sdf / nb_valid_neighbors;
|
||||
sdf_values[facet_it] = sdf_value;
|
||||
sdf_values[*facet_it] = sdf_value;
|
||||
// trying to update min_sdf is pointless, since it is interpolated one of the neighbors sdf will be smaller than it
|
||||
}
|
||||
}
|
||||
// If still there is any facet which has no sdf value, assign minimum sdf value.
|
||||
// This is meaningful since (being an outlier) 0 sdf values might effect normalization & log extremely.
|
||||
for(typename std::vector<Facet_const_handle>::iterator it =
|
||||
for(typename std::vector<face_descriptor>::iterator it =
|
||||
still_missing_facets.begin();
|
||||
it != still_missing_facets.end(); ++it) {
|
||||
sdf_values[*it] = min_sdf;
|
||||
|
|
@ -126,9 +127,10 @@ public:
|
|||
SDFPropertyMap sdf_values) {
|
||||
double min_sdf = (std::numeric_limits<double>::max)();
|
||||
double max_sdf = -min_sdf;
|
||||
for(Facet_const_iterator facet_it = mesh.facets_begin();
|
||||
facet_it != mesh.facets_end(); ++facet_it) {
|
||||
double sdf_value = sdf_values[facet_it];
|
||||
face_iterator facet_it, fend;
|
||||
for(boost::tie(facet_it,fend) = faces(mesh);
|
||||
facet_it != fend; ++facet_it) {
|
||||
double sdf_value = sdf_values[*facet_it];
|
||||
max_sdf = (std::max)(sdf_value, max_sdf);
|
||||
min_sdf = (std::min)(sdf_value, min_sdf);
|
||||
}
|
||||
|
|
@ -136,7 +138,7 @@ public:
|
|||
}
|
||||
/**
|
||||
* Normalize sdf values between [0-1].
|
||||
* @param sdf_values `ReadWritePropertyMap` with `Polyhedron::Facet_const_handle` as key and `double` as value type
|
||||
* @param sdf_values `ReadWritePropertyMap` with `Polyhedron::face_descriptor` as key and `double` as value type
|
||||
* @return minimum and maximum SDF values before normalization
|
||||
*/
|
||||
template<class SDFPropertyMap>
|
||||
|
|
@ -151,9 +153,10 @@ public:
|
|||
}
|
||||
|
||||
const double max_min_dif = max_sdf - min_sdf;
|
||||
for(Facet_const_iterator facet_it = mesh.facets_begin();
|
||||
facet_it != mesh.facets_end(); ++facet_it) {
|
||||
sdf_values[facet_it] = (sdf_values[facet_it] - min_sdf) / max_min_dif;
|
||||
face_iterator facet_it, fend;
|
||||
for(boost::tie(facet_it,fend) = faces(mesh);
|
||||
facet_it != fend; ++facet_it) {
|
||||
sdf_values[*facet_it] = (sdf_values[*facet_it] - min_sdf) / max_min_dif;
|
||||
}
|
||||
return std::make_pair(min_sdf, max_sdf);
|
||||
}
|
||||
|
|
@ -207,19 +210,17 @@ class Surface_mesh_segmentation
|
|||
{
|
||||
//type definitions
|
||||
public:
|
||||
typedef typename Polyhedron::Facet_const_handle Facet_const_handle;
|
||||
typedef typename boost::graph_traits<Polyhedron>::face_descriptor face_descriptor;
|
||||
|
||||
private:
|
||||
//typedef typename Polyhedron::Traits Kernel;
|
||||
typedef typename GeomTraits::Point_3 Point;
|
||||
|
||||
typedef typename Polyhedron::Facet Facet;
|
||||
|
||||
typedef typename Polyhedron::Edge_const_iterator Edge_const_iterator;
|
||||
typedef typename Polyhedron::Halfedge_const_handle Halfedge_const_handle;
|
||||
typedef typename Polyhedron::Halfedge_const_iterator Halfedge_const_iterator;
|
||||
typedef typename Polyhedron::Facet_const_iterator Facet_const_iterator;
|
||||
typedef typename Polyhedron::Vertex_const_iterator Vertex_const_iterator;
|
||||
typedef typename boost::graph_traits<Polyhedron>::edge_iterator edge_iterator;
|
||||
typedef typename boost::graph_traits<Polyhedron>::halfedge_descriptor halfedge_descriptor;
|
||||
typedef typename boost::graph_traits<Polyhedron>::halfedge_iterator halfedge_iterator;
|
||||
typedef typename boost::graph_traits<Polyhedron>::face_iterator face_iterator;
|
||||
typedef typename boost::graph_traits<Polyhedron>::vertex_iterator vertex_iterator;
|
||||
|
||||
typedef SDF_calculation<Polyhedron, GeomTraits, fast_bbox_intersection>
|
||||
SDF_calculation_class;
|
||||
|
|
@ -287,10 +288,11 @@ public:
|
|||
// apply graph cut
|
||||
GraphCut()(edges, edge_weights, probability_matrix, labels);
|
||||
std::vector<std::size_t>::iterator label_it = labels.begin();
|
||||
for(Facet_const_iterator facet_it = mesh.facets_begin();
|
||||
facet_it != mesh.facets_end();
|
||||
face_iterator facet_it, fend;
|
||||
for(boost::tie(facet_it,fend) = faces(mesh);
|
||||
facet_it != fend;
|
||||
++facet_it, ++label_it) {
|
||||
segment_pmap[facet_it] = *label_it; // fill with cluster-ids
|
||||
segment_pmap[*facet_it] = *label_it; // fill with cluster-ids
|
||||
}
|
||||
if(clusters_to_segments) {
|
||||
// assign a segment id for each facet
|
||||
|
|
@ -310,7 +312,7 @@ private:
|
|||
* @param edge whose dihedral angle is computed using incident facets
|
||||
* @return computed dihedral angle
|
||||
*/
|
||||
double calculate_dihedral_angle_of_edge(Halfedge_const_handle edge) const {
|
||||
double calculate_dihedral_angle_of_edge(halfedge_descriptor edge) const {
|
||||
CGAL_precondition(!edge->is_border_edge());
|
||||
const Point& a = edge->vertex()->point();
|
||||
const Point& b = edge->prev()->vertex()->point();
|
||||
|
|
@ -333,7 +335,7 @@ private:
|
|||
/**
|
||||
* Normalize sdf values using function:
|
||||
* normalized_sdf = log( alpha * ( current_sdf - min_sdf ) / ( max_sdf - min_sdf ) + 1 ) / log( alpha + 1 )
|
||||
* @param sdf_values `ReadablePropertyMap` with `Polyhedron::Facet_const_handle` as key and `double` as value type
|
||||
* @param sdf_values `ReadablePropertyMap` with `Polyhedron::face_descriptor` as key and `double` as value type
|
||||
* @param[out] normalized_sdf_values normalized values stored in facet iteration order
|
||||
* Important note: @a sdf_values parameter should contain linearly normalized values between [0-1]
|
||||
*/
|
||||
|
|
@ -341,9 +343,10 @@ private:
|
|||
void log_normalize_sdf_values(SDFPropertyMap sdf_values,
|
||||
std::vector<double>& normalized_sdf_values) {
|
||||
normalized_sdf_values.reserve(mesh.size_of_facets());
|
||||
for(Facet_const_iterator facet_it = mesh.facets_begin();
|
||||
facet_it != mesh.facets_end(); ++facet_it) {
|
||||
double log_normalized = log(sdf_values[facet_it] * CGAL_NORMALIZATION_ALPHA +
|
||||
face_iterator facet_it, fend;
|
||||
for(boost::tie(facet_it,fend) = faces(mesh);
|
||||
facet_it != fend; ++facet_it) {
|
||||
double log_normalized = log(sdf_values[*facet_it] * CGAL_NORMALIZATION_ALPHA +
|
||||
1) / log(CGAL_NORMALIZATION_ALPHA + 1);
|
||||
normalized_sdf_values.push_back(log_normalized);
|
||||
}
|
||||
|
|
@ -382,26 +385,31 @@ private:
|
|||
// important note: ids should be compatible with iteration order of facets:
|
||||
// [0 <- facet_begin(),...., size_of_facets() -1 <- facet_end()]
|
||||
// Why ? it is send to graph cut algorithm where other data associated with facets are also sorted according to iteration order.
|
||||
std::map<Facet_const_handle, std::size_t> facet_index_map;
|
||||
std::map<face_descriptor, std::size_t> facet_index_map;
|
||||
std::size_t facet_index = 0;
|
||||
for(Facet_const_iterator facet_it = mesh.facets_begin();
|
||||
facet_it != mesh.facets_end();
|
||||
face_iterator facet_it, fend;
|
||||
for(boost::tie(facet_it,fend) = faces(mesh);
|
||||
facet_it != fend;
|
||||
++facet_it, ++facet_index) {
|
||||
facet_index_map[facet_it] = facet_index;
|
||||
facet_index_map[*facet_it] = facet_index;
|
||||
}
|
||||
|
||||
const double epsilon = 5e-6;
|
||||
// edges and their weights. pair<std::size_t, std::size_t> stores facet-id pairs (see above) (may be using boost::tuple can be more suitable)
|
||||
for(Edge_const_iterator edge_it = mesh.edges_begin();
|
||||
edge_it != mesh.edges_end(); ++edge_it) {
|
||||
if(edge_it->is_border_edge()) {
|
||||
edge_iterator edge_it, eend;
|
||||
for(boost::tie(edge_it,eend) = CGAL::edges(mesh); // AF: get rid of CGAL::
|
||||
edge_it != eend; ++edge_it) {
|
||||
halfedge_descriptor hd = halfedge(*edge_it,mesh);
|
||||
halfedge_descriptor ohd = opposite(hd,mesh);
|
||||
if((face(hd,mesh)==boost::graph_traits<Polyhedron>::null_face())
|
||||
|| (face(ohd,mesh)==boost::graph_traits<Polyhedron>::null_face())) {
|
||||
continue; // if edge does not contain two neighbor facets then do not include it in graph-cut
|
||||
}
|
||||
const std::size_t index_f1 = facet_index_map[edge_it->facet()];
|
||||
const std::size_t index_f2 = facet_index_map[edge_it->opposite()->facet()];
|
||||
const std::size_t index_f1 = facet_index_map[hd->facet()];
|
||||
const std::size_t index_f2 = facet_index_map[ohd->facet()];
|
||||
edges.push_back(std::make_pair(index_f1, index_f2));
|
||||
|
||||
double angle = calculate_dihedral_angle_of_edge(edge_it);
|
||||
double angle = calculate_dihedral_angle_of_edge(hd);
|
||||
|
||||
angle = (std::max)(angle, epsilon);
|
||||
angle = -log(angle);
|
||||
|
|
@ -432,8 +440,8 @@ private:
|
|||
* set of connected facets which are placed under same cluster. Note that returned segment-ids are ordered by average sdf value of segment ascen.
|
||||
*
|
||||
* @param number_of_clusters cluster-ids in @a segments should be between [0, number_of_clusters -1]
|
||||
* @param sdf_values `ReadablePropertyMap` with `Polyhedron::Facet_const_handle` as key and `double` as value type
|
||||
* @param[in, out] segments `ReadWritePropertyMap` with `Polyhedron::Facet_const_handle` as key and `std::size_t` as value type.
|
||||
* @param sdf_values `ReadablePropertyMap` with `Polyhedron::face_descriptor` as key and `double` as value type
|
||||
* @param[in, out] segments `ReadWritePropertyMap` with `Polyhedron::face_descriptor` as key and `std::size_t` as value type.
|
||||
* @return number of segments
|
||||
*/
|
||||
template<class SegmentPropertyMap, class SDFProperyMap>
|
||||
|
|
@ -442,12 +450,12 @@ private:
|
|||
// assign a segment-id to each facet
|
||||
std::size_t segment_id = number_of_clusters;
|
||||
std::vector<std::pair<std::size_t, double> > segments_with_average_sdf_values;
|
||||
|
||||
for(Facet_const_iterator facet_it = mesh.facets_begin();
|
||||
facet_it != mesh.facets_end(); ++facet_it) {
|
||||
if(segments[facet_it] <
|
||||
face_iterator facet_it, fend;
|
||||
for(boost::tie(facet_it,fend) = faces(mesh);
|
||||
facet_it != fend; ++facet_it) {
|
||||
if(segments[*facet_it] <
|
||||
number_of_clusters) { // not visited by depth_first_traversal
|
||||
double average_sdf_value = breadth_first_traversal(facet_it, segment_id,
|
||||
double average_sdf_value = breadth_first_traversal(*facet_it, segment_id,
|
||||
sdf_values, segments);
|
||||
|
||||
segments_with_average_sdf_values.push_back(std::make_pair(segment_id,
|
||||
|
|
@ -470,10 +478,10 @@ private:
|
|||
}
|
||||
// make one-pass on facets. First make segment-id zero based by subtracting number_of_clusters
|
||||
// . Then place its sorted index to pmap
|
||||
for(Facet_const_iterator facet_it = mesh.facets_begin();
|
||||
facet_it != mesh.facets_end(); ++facet_it) {
|
||||
std::size_t segment_id = segments[facet_it] - number_of_clusters;
|
||||
segments[facet_it] = segment_id_to_sorted_id_map[segment_id];
|
||||
for(boost::tie(facet_it,fend) = faces(mesh);
|
||||
facet_it != fend; ++facet_it) {
|
||||
std::size_t segment_id = segments[*facet_it] - number_of_clusters;
|
||||
segments[*facet_it] = segment_id_to_sorted_id_map[segment_id];
|
||||
}
|
||||
return segment_id - number_of_clusters;
|
||||
}
|
||||
|
|
@ -483,15 +491,15 @@ private:
|
|||
* Each visited facet assigned to @a segment_id.
|
||||
* @param facet root facet
|
||||
* @param segment_id segment-id of root facet
|
||||
* @param sdf_values `ReadablePropertyMap` with `Polyhedron::Facet_const_handle` as key and `double` as value type
|
||||
* @param[in, out] segments `ReadWritePropertyMap` with `Polyhedron::Facet_const_handle` as key and `std::size_t` as value type.
|
||||
* @param sdf_values `ReadablePropertyMap` with `Polyhedron::face_descriptor` as key and `double` as value type
|
||||
* @param[in, out] segments `ReadWritePropertyMap` with `Polyhedron::face_descriptor` as key and `std::size_t` as value type.
|
||||
* @return average sdf value for segment
|
||||
*/
|
||||
template<class SegmentPropertyMap, class SDFProperyMap>
|
||||
double
|
||||
breadth_first_traversal(Facet_const_handle root, std::size_t segment_id,
|
||||
breadth_first_traversal(face_descriptor root, std::size_t segment_id,
|
||||
SDFProperyMap sdf_values, SegmentPropertyMap segments) {
|
||||
std::queue<Facet_const_handle> facet_queue;
|
||||
std::queue<face_descriptor> facet_queue;
|
||||
facet_queue.push(root);
|
||||
|
||||
std::size_t prev_segment_id = segments[root];
|
||||
|
|
@ -501,15 +509,14 @@ private:
|
|||
std::size_t visited_facet_count = 1;
|
||||
|
||||
while(!facet_queue.empty()) {
|
||||
Facet_const_handle facet = facet_queue.front();
|
||||
face_descriptor facet = facet_queue.front();
|
||||
|
||||
typename Facet::Halfedge_around_facet_const_circulator facet_circulator =
|
||||
facet->facet_begin();
|
||||
typename Halfedge_around_face_circulator<Polyhedron> facet_circulator(halfedge(facet,mesh),mesh), done(facet_circulator);
|
||||
do {
|
||||
if(facet_circulator->opposite()->is_border()) {
|
||||
if((*facet_circulator)->opposite()->is_border()) {
|
||||
continue; // no facet to traversal
|
||||
}
|
||||
Facet_const_handle neighbor = facet_circulator->opposite()->facet();
|
||||
face_descriptor neighbor = (*facet_circulator)->opposite()->facet();
|
||||
if(prev_segment_id == segments[neighbor]) {
|
||||
segments[neighbor] = segment_id;
|
||||
facet_queue.push(neighbor);
|
||||
|
|
@ -517,7 +524,7 @@ private:
|
|||
total_sdf_value += sdf_values[neighbor];
|
||||
++visited_facet_count;
|
||||
}
|
||||
} while( ++facet_circulator != facet->facet_begin());
|
||||
} while( ++facet_circulator != done);
|
||||
|
||||
facet_queue.pop();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ sdf_values( const Polyhedron& polyhedron,
|
|||
* @pre @a polyhedron.is_pure_triangle()
|
||||
*
|
||||
* @tparam Polyhedron a %CGAL polyhedron
|
||||
* @tparam SDFPropertyMap a `ReadWritePropertyMap` with `Polyhedron::Facet_const_handle` as key and `double` as value type
|
||||
* @tparam SDFPropertyMap a `ReadWritePropertyMap` with `boost::graph_traits<Polyhedron>::face_handle` as key and `double` as value type
|
||||
* @tparam GeomTraits a model of SegmentationGeomTraits
|
||||
*
|
||||
* @param polyhedron surface mesh on which SDF values are computed
|
||||
|
|
@ -107,7 +107,7 @@ sdf_values( const Polyhedron& polyhedron,
|
|||
* @pre Raw values should be greater or equal to 0. -1 indicates when no value could be computed
|
||||
*
|
||||
* @tparam Polyhedron a %CGAL polyhedron
|
||||
* @tparam SDFPropertyMap a `ReadWritePropertyMap` with `Polyhedron::Facet_const_handle` as key and `double` as value type
|
||||
* @tparam SDFPropertyMap a `ReadWritePropertyMap` with `boost::graph_traits<Polyhedron>::face_handle` as key and `double` as value type
|
||||
*
|
||||
* @param polyhedron surface mesh on which SDF values are computed
|
||||
* @param[in, out] sdf_values_map the SDF value of each facet
|
||||
|
|
@ -145,8 +145,8 @@ sdf_values_postprocessing(const Polyhedron& polyhedron,
|
|||
* @pre @a number_of_clusters > 0
|
||||
*
|
||||
* @tparam Polyhedron a %CGAL polyhedron
|
||||
* @tparam SDFPropertyMap a `ReadablePropertyMap` with `Polyhedron::Facet_const_handle` as key and `double` as value type
|
||||
* @tparam SegmentPropertyMap a `ReadWritePropertyMap` with `Polyhedron::Facet_const_handle` as key and `std::size_t` as value type
|
||||
* @tparam SDFPropertyMap a `ReadablePropertyMap` with `boost::graph_traits<Polyhedron>::face_handle` as key and `double` as value type
|
||||
* @tparam SegmentPropertyMap a `ReadWritePropertyMap` with `boost::graph_traits<Polyhedron>::face_handle` as key and `std::size_t` as value type
|
||||
* @tparam GeomTraits a model of SegmentationGeomTraits
|
||||
*
|
||||
* @param polyhedron surface mesh corresponding to the SDF values
|
||||
|
|
@ -197,7 +197,8 @@ segmentation_via_sdf_values(const Polyhedron& polyhedron,
|
|||
bool output_cluster_ids = false,
|
||||
GeomTraits traits = GeomTraits())
|
||||
{
|
||||
typedef std::map< typename Polyhedron::Facet_const_handle, double>
|
||||
typedef boost::graph_traits<Polyhedron>::face_descriptor face_descriptor;
|
||||
typedef std::map<face_descriptor, double>
|
||||
Facet_double_map;
|
||||
Facet_double_map internal_sdf_map;
|
||||
boost::associative_property_map<Facet_double_map> sdf_property_map(
|
||||
|
|
@ -229,7 +230,7 @@ segmentation_via_sdf_values(const Polyhedron& polyhedron,
|
|||
* @pre @a number_of_clusters > 0
|
||||
*
|
||||
* @tparam Polyhedron a %CGAL polyhedron
|
||||
* @tparam SegmentPropertyMap a `ReadWritePropertyMap` with `Polyhedron::Facet_const_handle` as key and `std::size_t` as value type
|
||||
* @tparam SegmentPropertyMap a `ReadWritePropertyMap` with `boost::graph_traits<Polyhedron>::face_handle` as key and `std::size_t` as value type
|
||||
* @tparam GeomTraits a model of SegmentationGeomTraits
|
||||
*
|
||||
* @param polyhedron surface mesh on which SDF values are computed
|
||||
|
|
|
|||
Loading…
Reference in New Issue