From e17cabba9094ff5f02988539fbd7959006bdc7a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 18 Nov 2016 07:52:40 +0100 Subject: [PATCH 1/2] use BGL helper free function is_triangle_mesh instead of a member one --- .../include/CGAL/mesh_segmentation.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Surface_mesh_segmentation/include/CGAL/mesh_segmentation.h b/Surface_mesh_segmentation/include/CGAL/mesh_segmentation.h index 987bdcfa87c..19f29f6145c 100644 --- a/Surface_mesh_segmentation/include/CGAL/mesh_segmentation.h +++ b/Surface_mesh_segmentation/include/CGAL/mesh_segmentation.h @@ -21,6 +21,7 @@ * @brief The API which contains free template functions for SDF computation and mesh segmentation. */ #include +#include #include namespace CGAL @@ -64,7 +65,7 @@ sdf_values( const TriangleMesh& triangle_mesh, * It is possible to compute raw SDF values (without post-processing). In such a case, * -1 is used to indicate when no SDF value could be computed for a facet. * - * @pre @a triangle_mesh.is_pure_triangle() + * @pre `is_triangle_mesh(triangle_mesh)` * * @tparam TriangleMesh a model of `FaceListGraph` * @tparam SDFPropertyMap a `ReadWritePropertyMap` with `boost::graph_traits::%face_descriptor` as key and `double` as value type @@ -79,7 +80,7 @@ sdf_values( const TriangleMesh& triangle_mesh, * @param traits traits class * @param ppmap point property map. An overload is provided with `get(boost::vertex_point,triangle_mesh)` as default. * - * @return minimum and maximum raw SDF values if @a postprocess is `true`, otherwise minimum and maximum SDF values (before linear normalization) + * @return minimum and maximum raw SDF values if `postprocess` is `true`, otherwise minimum and maximum SDF values (before linear normalization) */ template sdf_values_postprocessing(const TriangleMesh& triangle_mesh, SDFPropertyMap sdf_values_map) { - CGAL_precondition(triangle_mesh.is_pure_triangle()); + CGAL_precondition(is_triangle_mesh(triangle_mesh)); return internal::Postprocess_sdf_values().postprocess(triangle_mesh, sdf_values_map); } @@ -155,8 +156,8 @@ sdf_values_postprocessing(const TriangleMesh& triangle_mesh, * \note There is no direct relation between the parameter `number_of_clusters` * and the final number of segments after segmentation. However, setting a large number of clusters will result in a detailed segmentation of the mesh with a large number of segments. * - * @pre @a triangle_mesh.is_pure_triangle() - * @pre @a number_of_clusters > 0 + * @pre `is_triangle_mesh(triangle_mesh)` + * @pre `number_of_clusters > 0` * * @tparam TriangleMesh a model of `FaceListGraph` * @tparam SDFPropertyMap a `ReadablePropertyMap` with `boost::graph_traits::%face_descriptor` as key and `double` as value type @@ -252,8 +253,8 @@ segmentation_via_sdf_values(const TriangleMesh& triangle_mesh, * it is more efficient to first compute the SDF values using `CGAL::sdf_values()` and use them in different calls to * `CGAL::segmentation_from_sdf_values()`. * - * @pre @a triangle_mesh.is_pure_triangle() - * @pre @a number_of_clusters > 0 + * @pre `is_triangle_mesh(triangle_mesh)` + * @pre `number_of_clusters > 0` * * @tparam TriangleMesh a model of `FaceListGraph` * @tparam SegmentPropertyMap a `ReadWritePropertyMap` with `boost::graph_traits::%face_descriptor` as key and `std::size_t` as value type From a619107eebd138eed29b854480a3105ebe1394df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 18 Nov 2016 07:54:57 +0100 Subject: [PATCH 2/2] property maps are readable property maps not lvalue --- .../Surface_mesh_segmentation/Filters.h | 11 +++--- .../SDF_calculation.h | 4 +-- .../Surface_mesh_segmentation.h | 34 +++++++++---------- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Filters.h b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Filters.h index 1006efdd080..f6bdf364cd3 100644 --- a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Filters.h +++ b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Filters.h @@ -84,7 +84,8 @@ public: std::map neighbors; NeighborSelector()(mesh,*facet_it, window_size, neighbors); // gather neighbors in the window - double current_sdf_value = values[*facet_it]; + + double current_sdf_value = get(values, *facet_it); double range_parameter_actual; if(!range_parameter) { @@ -92,7 +93,7 @@ public: double deviation = 0.0; for(typename std::map::iterator it = neighbors.begin(); it != neighbors.end(); ++it) { - deviation += std::pow(values[it->first] - current_sdf_value, 2); + deviation += std::pow(get(values, it->first) - current_sdf_value, 2); } deviation = std::sqrt(deviation / neighbors.size()); if(deviation == 0.0) { @@ -112,12 +113,12 @@ public: neighbors.begin(); it != neighbors.end(); ++it) { double spatial_weight = gaussian_function(static_cast(it->second), spatial_parameter_actual); - double range_weight = gaussian_function(values[it->first] - current_sdf_value, + double range_weight = gaussian_function(get(values, it->first) - current_sdf_value, range_parameter_actual); // we can use just spatial_weight for Gaussian filtering double weight = spatial_weight * range_weight; - total_sdf_value += values[it->first] * weight; + total_sdf_value += get(values, it->first) * weight; total_weight += weight; } smoothed_values.push_back(total_sdf_value / total_weight); @@ -127,7 +128,7 @@ public: for(boost::tie(facet_it,fend) = faces(mesh); facet_it != fend; ++facet_it, ++smoothed_value_it) { - values[*facet_it] = *smoothed_value_it; + put(values, *facet_it, *smoothed_value_it); } } private: diff --git a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/SDF_calculation.h b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/SDF_calculation.h index 9ff239f9d3d..6861bed16dd 100644 --- a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/SDF_calculation.h +++ b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/SDF_calculation.h @@ -204,9 +204,9 @@ public: cone_angle, true, disk_samples); if(sdf_value) { - sdf_values[*facet_begin] = *sdf_value; + put(sdf_values, *facet_begin, *sdf_value); } else { - sdf_values[*facet_begin] = -1.0; + put(sdf_values, *facet_begin, -1.0); } } } diff --git a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Surface_mesh_segmentation.h b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Surface_mesh_segmentation.h index b6273d49922..5bce1aa2ae0 100644 --- a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Surface_mesh_segmentation.h +++ b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Surface_mesh_segmentation.h @@ -82,7 +82,7 @@ public: 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]; + double sdf_value = get(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); @@ -95,7 +95,7 @@ public: std::size_t nb_valid_neighbors = 0; do { if(!(face(opposite(*facet_circulator,mesh),mesh) == boost::graph_traits::null_face())) { - double neighbor_sdf = sdf_values[face(opposite(*facet_circulator,mesh),mesh)]; + double neighbor_sdf = get(sdf_values, face(opposite(*facet_circulator,mesh),mesh)); if(neighbor_sdf != -1) { total_neighbor_sdf += neighbor_sdf; ++nb_valid_neighbors; @@ -107,7 +107,7 @@ public: still_missing_facets.push_back(*facet_it); } else { sdf_value = total_neighbor_sdf / nb_valid_neighbors; - sdf_values[*facet_it] = sdf_value; + put(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 } } @@ -116,7 +116,7 @@ public: for(typename std::vector::iterator it = still_missing_facets.begin(); it != still_missing_facets.end(); ++it) { - sdf_values[*it] = min_sdf; + put(sdf_values, *it, min_sdf); } } @@ -128,7 +128,7 @@ public: 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]; + double sdf_value = get(sdf_values, *facet_it); max_sdf = (std::max)(sdf_value, max_sdf); min_sdf = (std::min)(sdf_value, min_sdf); } @@ -154,7 +154,7 @@ public: 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; + put(sdf_values, *facet_it, (get(sdf_values, *facet_it) - min_sdf) / max_min_dif); } return std::make_pair(min_sdf, max_sdf); } @@ -295,7 +295,7 @@ public: 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 + put(segment_pmap, *facet_it, *label_it); // fill with cluster-ids } if(clusters_to_segments) { // assign a segment id for each facet @@ -351,7 +351,7 @@ private: 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 + + double log_normalized = log(get(sdf_values, *facet_it) * CGAL_NORMALIZATION_ALPHA + 1) / log(CGAL_NORMALIZATION_ALPHA + 1); normalized_sdf_values.push_back(log_normalized); } @@ -458,7 +458,7 @@ private: face_iterator facet_it, fend; for(boost::tie(facet_it,fend) = faces(mesh); facet_it != fend; ++facet_it) { - if(segments[*facet_it] < + if(get(segments, *facet_it) < number_of_clusters) { // not visited by depth_first_traversal double average_sdf_value = breadth_first_traversal(*facet_it, segment_id, sdf_values, segments); @@ -485,8 +485,8 @@ private: // . Then place its sorted index to pmap 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]; + std::size_t segment_id = get(segments, *facet_it) - number_of_clusters; + put(segments, *facet_it, segment_id_to_sorted_id_map[segment_id]); } return segment_id - number_of_clusters; } @@ -507,10 +507,10 @@ private: std::queue facet_queue; facet_queue.push(root); - std::size_t prev_segment_id = segments[root]; - segments[root] = segment_id; + std::size_t prev_segment_id = get(segments, root); + put(segments, root, segment_id); - double total_sdf_value = sdf_values[root]; + double total_sdf_value = get(sdf_values, root); std::size_t visited_facet_count = 1; while(!facet_queue.empty()) { @@ -522,11 +522,11 @@ private: continue; // no facet to traversal } face_descriptor neighbor = face(opposite(*facet_circulator,mesh),mesh); - if(prev_segment_id == segments[neighbor]) { - segments[neighbor] = segment_id; + if(prev_segment_id == get(segments, neighbor)) { + put(segments, neighbor, segment_id); facet_queue.push(neighbor); - total_sdf_value += sdf_values[neighbor]; + total_sdf_value += get(sdf_values, neighbor); ++visited_facet_count; } } while( ++facet_circulator != done);