#ifndef CGAL_SURFACE_MESH_SEGMENTATION_MESH_SEGMENTATION_H #define CGAL_SURFACE_MESH_SEGMENTATION_MESH_SEGMENTATION_H /** * @file mesh_segmentation.h * @brief The API which contains free template functions for SDF computation and mesh segmentation. */ #include #include namespace CGAL { /// @cond SKIP_IN_MANUAL template std::pair compute_sdf_values(const Polyhedron& polyhedron, SDFPropertyMap sdf_values, double cone_angle = 2.0 / 3.0 * CGAL_PI, int number_of_rays = 25, bool postprocess = true, GeomTraits traits = GeomTraits()) { internal::Surface_mesh_segmentation algorithm(polyhedron, traits); return algorithm.calculate_sdf_values(cone_angle, number_of_rays, sdf_values, postprocess); } /// @endcond /*! * \ingroup PkgSurfaceSegmentation * @brief Function computing the Shape Diameter Function over a surface mesh. * * This function implements the Shape Diameter Function (SDF) as described in \cgalCite{shapira2008consistent}. * It is possible to compute raw SDF values (see \ref Surface_mesh_segmentationRawSDF) and apply post-processing steps (see \ref Surface_mesh_segmentationPostprocessing). * For raw SDF values, -1.0 is used to indicate that no SDF value could be computed for a facet. * * @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 GeomTraits a model of SegmentationGeomTraits * @param polyhedron surface mesh on which SDF values are computed * @param[out] sdf_values the SDF value of each facet * @param cone_angle opening angle for cone, expressed in radians * @param number_of_rays number of rays picked from cone for each facet. In general, increasing the number of rays beyond the default value has little influence upon the resulting segmentation. * @param postprocess if true apply post-processing steps in `CGAL::postprocess_sdf_values`, otherwise return raw SDF values. * @param traits traits object * @return minimum and maximum SDF values if @a postprocess is true, otherwise minimum and maximum SDF values before linear normalization */ template std::pair compute_sdf_values(const Polyhedron& polyhedron, SDFPropertyMap sdf_values, double cone_angle = 2.0 / 3.0 * CGAL_PI, int number_of_rays = 25, bool postprocess = true, GeomTraits traits = GeomTraits()) { return compute_sdf_values (polyhedron, sdf_values, cone_angle, number_of_rays, postprocess, traits); } /*! * \ingroup PkgSurfaceSegmentation * @brief Function post-processing raw SDF values computed per facet. * * Post-processing steps applied are: * - Facets with -1.0 SDF values are assigned the average SDF value of their edge-adjacent neighbors. * If there is still a facet having -1.0 SDF value, the minimum valid SDF value assigned to it. Note that this step is not inherited from the paper. * The main reason for not assigning 0 to facets with no SDF values (i.e. -1.0) is that it can obstruct log-normalization process which takes place at the beginning of `CGAL::segment_from_sdf_values`. * - SDF values are smoothed with bilateral filtering. * - SDF values are linearly normalized between [0,1]. * * See the section \ref Surface_mesh_segmentationPostprocessing for more details. * * @pre @a polyhedron.is_pure_triangle() * @pre Raw values should be either equal to -1.0 or, greater or equal than 0.0 * @tparam Polyhedron a %CGAL polyhedron * @tparam SDFPropertyMap a `ReadWritePropertyMap` with `Polyhedron::Facet_const_handle` as key and `double` as value type * * @param polyhedron surface mesh on which SDF values are computed * @param[in, out] sdf_values the SDF value of each facet * * @return minimum and maximum SDF values before linear normalization */ template std::pair postprocess_sdf_values(const Polyhedron& polyhedron, SDFPropertyMap sdf_values) { CGAL_precondition(polyhedron.is_pure_triangle()); return internal::Postprocess_sdf_values().postprocess(polyhedron, sdf_values); } /*! * \ingroup PkgSurfaceSegmentation * @brief Function computing the segmentation of a surface mesh given an SDF value per facet. * * This function fills a property map which associates a segment-id (between [0, number of segments -1]) * or a cluster-id (between [0, @a number_of_levels -1]) to each facet. * A segment is a set of connected facets which are placed under the same cluster \cgalFigureRef{Cluster_vs_segment}. * * \note Log-normalization is applied on @a sdf_values before segmentation. * \note There is no direct relation between the parameter @a number_of_levels * and the final number of segments after segmentation. However, large number of clusters likely to result in detailed segmentation of the mesh with a large number of segments. * * @pre @a polyhedron.is_pure_triangle() * @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 `int` as value type * @tparam GeomTraits a model of SegmentationGeomTraits * @param polyhedron surface mesh on which SDF values are computed * @param sdf_values the SDF value of each facet between [0-1] * @param[out] segment_ids the segment id of each facet * @param number_of_levels number of clusters for soft clustering * @param smoothing_lambda factor which indicates the importance of the surface features for the energy minimization. It is recommended to choose a value in the interval [0,1]. See the section \ref Surface_mesh_segmentationGraphCut for more details. * @param extract_segments if true fill @a segment_ids with segment-ids, otherwise fill with cluster-ids \cgalFigureRef{Cluster_vs_segment} * @param traits traits object * @return number of segments if @a extract_segments true, @a number_of_levels otherwise */ template int segment_from_sdf_values(const Polyhedron& polyhedron, SDFPropertyMap sdf_values, SegmentPropertyMap segment_ids, int number_of_levels = 5, double smoothing_lambda = 0.26, bool extract_segments = true, GeomTraits traits = GeomTraits()) { internal::Surface_mesh_segmentation algorithm( polyhedron, traits); return algorithm.partition(number_of_levels, smoothing_lambda, sdf_values, segment_ids, extract_segments); } ///\cond SKIP_IN_MANUAL template < bool Fast_sdf_calculation_mode, class Polyhedron, class SegmentPropertyMap, class GeomTraits #ifndef BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS = typename Polyhedron::Traits #endif > int compute_sdf_values_and_segment(const Polyhedron& polyhedron, SegmentPropertyMap segment_ids, double cone_angle = 2.0 / 3.0 * CGAL_PI, int number_of_rays = 25, int number_of_levels = 5, double smoothing_lambda = 0.26, bool extract_segments = true, GeomTraits traits = GeomTraits()) { typedef std::map< typename Polyhedron::Facet_const_handle, double> Facet_double_map; Facet_double_map internal_sdf_map; boost::associative_property_map sdf_property_map( internal_sdf_map); compute_sdf_values, GeomTraits> (polyhedron, sdf_property_map, cone_angle, number_of_rays, true, traits); return segment_from_sdf_values, SegmentPropertyMap, GeomTraits> (polyhedron, sdf_property_map, segment_ids, number_of_levels, smoothing_lambda, extract_segments, traits); } /// \endcond /*! * \ingroup PkgSurfaceSegmentation * @brief Function computing the segmentation of a surface mesh. * * This function combines `CGAL::compute_sdf_values` and * `CGAL::segment_from_sdf_values` functions by computing SDF values and segmenting the mesh in one go. * * \note For computing segmentations of the mesh with different parameters (i.e. number of levels, and smoothing lambda), * it is more efficient to first compute the SDF values using `CGAL::compute_sdf_values` and use them for each call to * `CGAL::segment_from_sdf_values`. * * @pre @a polyhedron.is_pure_triangle() * @tparam Polyhedron a %CGAL polyhedron * @tparam SegmentPropertyMap a `ReadWritePropertyMap` with `Polyhedron::Facet_const_handle` as key and `int` as value type * @tparam GeomTraits a model of SegmentationGeomTraits * @param polyhedron surface mesh on which SDF values are computed * @param[out] segment_ids the segment id of each facet * @param cone_angle opening angle for cone, expressed in radians * @param number_of_rays number of rays picked from cone for each facet. In general, increasing the number of rays has a little effect on the quality of the result * @param number_of_levels number of clusters for soft clustering * @param smoothing_lambda factor which indicates the importance of the surface features for the energy minimization. It is recommended to choose a value in the interval [0,1]. See the section \ref Surface_mesh_segmentationGraphCut for more details. * @param extract_segments if true fill @a segment_ids with segment-ids, otherwise fill with cluster-ids \cgalFigureRef{Cluster_vs_segment} * @param traits traits object * @return number of segments if @a extract_segments true, @a number_of_levels otherwise */ template < class Polyhedron, class SegmentPropertyMap, class GeomTraits #ifndef BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS = typename Polyhedron::Traits #endif > int compute_sdf_values_and_segment(const Polyhedron& polyhedron, SegmentPropertyMap segment_ids, double cone_angle = 2.0 / 3.0 * CGAL_PI, int number_of_rays = 25, int number_of_levels = 5, double smoothing_lambda = 0.26, bool extract_segments = true, GeomTraits traits = GeomTraits()) { return compute_sdf_values_and_segment (polyhedron, segment_ids, cone_angle, number_of_rays, number_of_levels, smoothing_lambda, extract_segments, traits); } #ifdef BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS template std::pair compute_sdf_values(const Polyhedron& polyhedron, SDFPropertyMap sdf_values, double cone_angle = 2.0 / 3.0 * CGAL_PI, int number_of_rays = 25, bool postprocess = true, typename Polyhedron::Traits traits = typename Polyhedron::Traits()) { return compute_sdf_values (polyhedron, sdf_values, cone_angle, number_of_rays, postprocess, traits); } template < class Polyhedron, class SDFPropertyMap> std::pair compute_sdf_values(const Polyhedron& polyhedron, SDFPropertyMap sdf_values, double cone_angle = 2.0 / 3.0 * CGAL_PI, int number_of_rays = 25, bool postprocess = true, typename Polyhedron::Traits traits = typename Polyhedron::Traits()) { return compute_sdf_values (polyhedron, sdf_values, cone_angle, number_of_rays, postprocess, traits); } template int segment_from_sdf_values(const Polyhedron& polyhedron, SDFPropertyMap sdf_values, SegmentPropertyMap segment_ids, int number_of_levels = 5, double smoothing_lambda = 0.26, bool extract_segments = true, typename Polyhedron::Traits traits = typename Polyhedron::Traits()) { return segment_from_sdf_values (polyhedron, sdf_values, segment_ids, number_of_levels, smoothing_lambda, extract_segments, traits); } template int compute_sdf_values_and_segment(const Polyhedron& polyhedron, SegmentPropertyMap segment_ids, double cone_angle = 2.0 / 3.0 * CGAL_PI, int number_of_rays = 25, int number_of_levels = 5, double smoothing_lambda = 0.26, bool extract_segments = true, typename Polyhedron::Traits traits = typename Polyhedron::Traits()) { return compute_sdf_values_and_segment< Fast_sdf_calculation_mode, Polyhedron, SegmentPropertyMap, typename Polyhedron::Traits> (polyhedron, segment_ids, cone_angle, number_of_rays, number_of_levels, smoothing_lambda, extract_segments, traits); } template int compute_sdf_values_and_segment(const Polyhedron& polyhedron, SegmentPropertyMap segment_ids, double cone_angle = 2.0 / 3.0 * CGAL_PI, int number_of_rays = 25, int number_of_levels = 5, double smoothing_lambda = 0.26, bool extract_segments = true, typename Polyhedron::Traits traits = typename Polyhedron::Traits()) { return compute_sdf_values_and_segment (polyhedron, segment_ids, cone_angle, number_of_rays, number_of_levels, smoothing_lambda, extract_segments, traits); } #endif }//namespace CGAL #endif // CGAL_SURFACE_MESH_SEGMENTATION_MESH_SEGMENTATION_H //