diff --git a/Shape_detection/examples/Shape_detection/region_growing_circles_on_point_set_2.cpp b/Shape_detection/examples/Shape_detection/region_growing_circles_on_point_set_2.cpp index 5ae41407200..65dd4721378 100644 --- a/Shape_detection/examples/Shape_detection/region_growing_circles_on_point_set_2.cpp +++ b/Shape_detection/examples/Shape_detection/region_growing_circles_on_point_set_2.cpp @@ -80,7 +80,7 @@ int main(int argc, char** argv) { // Create an instance of the region growing class. Region_growing region_growing( - point_set_2, neighbor_query, region_type, sorting.ordered()); + point_set_2, sorting.ordered(), neighbor_query, region_type); // Add maps to get a colored output. Point_set_2::Property_map diff --git a/Shape_detection/examples/Shape_detection/region_growing_lines_on_segment_set.cpp b/Shape_detection/examples/Shape_detection/region_growing_lines_on_segment_set.cpp index d3a5cb6acf4..c283a4652fe 100644 --- a/Shape_detection/examples/Shape_detection/region_growing_lines_on_segment_set.cpp +++ b/Shape_detection/examples/Shape_detection/region_growing_lines_on_segment_set.cpp @@ -69,7 +69,7 @@ int main(int argc, char *argv[]) { line_sorting.sort(); RG_lines rg_lines( - segment_range, pgraph, line_region, line_sorting.ordered()); + segment_range, line_sorting.ordered(), pgraph, line_region); std::vector subregions; rg_lines.detect(std::back_inserter(subregions)); diff --git a/Shape_detection/examples/Shape_detection/region_growing_planes_on_point_set_3.cpp b/Shape_detection/examples/Shape_detection/region_growing_planes_on_point_set_3.cpp index d7c48366742..794d1edd5b3 100644 --- a/Shape_detection/examples/Shape_detection/region_growing_planes_on_point_set_3.cpp +++ b/Shape_detection/examples/Shape_detection/region_growing_planes_on_point_set_3.cpp @@ -63,7 +63,7 @@ int main(int argc, char *argv[]) { // Create an instance of the region growing class. Region_growing region_growing( - point_set, neighbor_query, region_type, sorting.ordered()); + point_set, sorting.ordered(), neighbor_query, region_type); // Run the algorithm. Output_range output_range; diff --git a/Shape_detection/examples/Shape_detection/region_growing_planes_on_polygon_mesh.cpp b/Shape_detection/examples/Shape_detection/region_growing_planes_on_polygon_mesh.cpp index 49f37af4040..0e22b724761 100644 --- a/Shape_detection/examples/Shape_detection/region_growing_planes_on_polygon_mesh.cpp +++ b/Shape_detection/examples/Shape_detection/region_growing_planes_on_polygon_mesh.cpp @@ -70,7 +70,7 @@ int main(int argc, char *argv[]) { // Create an instance of the region growing class. Region_growing region_growing( - face_range, neighbor_query, region_type, sorting.ordered()); + face_range, sorting.ordered(), neighbor_query, region_type); // Run the algorithm. std::vector regions; diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/K_neighbor_query.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/K_neighbor_query.h index 2ffc18ed644..5d9e1196a02 100644 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/K_neighbor_query.h +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/K_neighbor_query.h @@ -122,7 +122,7 @@ namespace Point_set { \cgalNamedParamsBegin \cgalParamNBegin{item_map} \cgalParamDescription{an instance of a model of `ReadablePropertyMap` with `InputRange::const_iterator` - as key type and `Item` as value type.`} + as key type and `Item` as value type.} \cgalParamDefault{A default is provided when `Item` is `InputRange::const_iterator` or its value type.} \cgalParamNEnd \cgalParamNBegin{k_neighbors} diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_circle_fit_sorting.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_circle_fit_sorting.h index 25a30da225b..daca30a0be9 100644 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_circle_fit_sorting.h +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_circle_fit_sorting.h @@ -100,7 +100,7 @@ namespace Point_set { \cgalNamedParamsBegin \cgalParamNBegin{item_map} \cgalParamDescription{an instance of a model of `ReadablePropertyMap` with `InputRange::const_iterator` - as key type and `Item` as value type.`} + as key type and `Item` as value type.} \cgalParamDefault{A default is provided when `Item` is `InputRange::const_iterator` or its value type.} \cgalParamNEnd \cgalParamNBegin{point_map} diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_cylinder_fit_sorting.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_cylinder_fit_sorting.h index 93d43d6e9d7..03eca304957 100644 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_cylinder_fit_sorting.h +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_cylinder_fit_sorting.h @@ -104,7 +104,7 @@ namespace Point_set { \cgalNamedParamsBegin \cgalParamNBegin{item_map} \cgalParamDescription{an instance of a model of `ReadablePropertyMap` with `InputRange::const_iterator` - as key type and `Item` as value type.`} + as key type and `Item` as value type.} \cgalParamDefault{A default is provided when `Item` is `InputRange::const_iterator` or its value type.} \cgalParamNEnd \cgalParamNBegin{point_map} diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_line_fit_sorting.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_line_fit_sorting.h index b4cc1f4d1d9..379cc76b460 100644 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_line_fit_sorting.h +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_line_fit_sorting.h @@ -100,7 +100,7 @@ namespace Point_set { \cgalNamedParamsBegin \cgalParamNBegin{item_map} \cgalParamDescription{an instance of a model of `ReadablePropertyMap` with `InputRange::const_iterator` - as key type and `Item` as value type.`} + as key type and `Item` as value type.} \cgalParamDefault{A default is provided when `Item` is `InputRange::const_iterator` or its value type.} \cgalParamNEnd \cgalParamNBegin{point_map} diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_plane_fit_sorting.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_plane_fit_sorting.h index 4914699d520..2b3953904d4 100644 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_plane_fit_sorting.h +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_plane_fit_sorting.h @@ -100,7 +100,7 @@ namespace Point_set { \cgalNamedParamsBegin \cgalParamNBegin{item_map} \cgalParamDescription{an instance of a model of `ReadablePropertyMap` with `InputRange::const_iterator` - as key type and `Item` as value type.`} + as key type and `Item` as value type.} \cgalParamDefault{A default is provided when `Item` is `InputRange::const_iterator` or its value type.} \cgalParamNEnd \cgalParamNBegin{point_map} diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_sphere_fit_sorting.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_sphere_fit_sorting.h index ee506a9b363..d11f8feae25 100644 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_sphere_fit_sorting.h +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_sphere_fit_sorting.h @@ -100,7 +100,7 @@ namespace Point_set { \cgalNamedParamsBegin \cgalParamNBegin{item_map} \cgalParamDescription{an instance of a model of `ReadablePropertyMap` with `InputRange::const_iterator` - as key type and `Item` as value type.`} + as key type and `Item` as value type.} \cgalParamDefault{A default is provided when `Item` is `InputRange::const_iterator` or its value type.} \cgalParamNEnd \cgalParamNBegin{point_map} diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Sphere_neighbor_query.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Sphere_neighbor_query.h index a09fa6a80d1..5000e954d7c 100644 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Sphere_neighbor_query.h +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Sphere_neighbor_query.h @@ -115,7 +115,7 @@ public: \cgalNamedParamsBegin \cgalParamNBegin{item_map} \cgalParamDescription{an instance of a model of `ReadablePropertyMap` with `InputRange::const_iterator` - as key type and `Item` as value type.`} + as key type and `Item` as value type.} \cgalParamDefault{A default is provided when `Item` is `InputRange::const_iterator` or its value type.} \cgalParamNEnd \cgalParamNBegin{sphere_radius} diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing.h index 8e0a226baa1..417136fa2b4 100644 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing.h +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing.h @@ -29,6 +29,7 @@ #include #include #include +#include namespace CGAL { namespace Shape_detection { @@ -85,6 +86,11 @@ namespace Shape_detection { \tparam InputRange a model of `ConstRange` + \tparam ItemMap + a model of `ReadablePropertyMap` with `InputRange::const_iterator` as key type and `Item` as value type. + A default can be deduced using the value type of `InputRange` and `Item` to be + either `CGAL::Dereference_property_map` or `CGAL::Identity_property_map`. + \param input_range a range of input items for region growing @@ -96,33 +102,49 @@ namespace Shape_detection { an instance of `RegionType` that is used internally to control if items form a valid region type + \param item_map + an instance of the property map to retrieve items from input values + \pre `input_range.size() > 0` */ - template + template Region_growing( const InputRange& input_range, NeighborQuery& neighbor_query, - RegionType& region_type) : + RegionType& region_type, + ItemMap item_map = ItemMap()) : m_neighbor_query(neighbor_query), m_region_type(region_type), m_region_map(region_type.region_index_map()), - m_visited(m_visited_map) { - + m_visited(m_visited_map) + { CGAL_precondition(input_range.size() > 0); m_seed_range.resize(input_range.size()); + using Item_helper = internal::Item_map_helper; + using Item_map = typename Item_helper::type; + Item_map item_map_ = Item_helper::get(item_map); + std::size_t idx = 0; for (auto it = input_range.begin(); it != input_range.end(); it++) - m_seed_range[idx++] = internal::conditional_deref()(it); + m_seed_range[idx++] = get(item_map_, it); - clear(input_range); + clear(input_range, item_map_); } /*! \brief initializes the region growing algorithm. \tparam InputRange - a model of `ConstRange + a model of `ConstRange` + + \tparam SeedRange + a model of `ConstRange` with `Item` as value type + + \tparam ItemMap + a model of `ReadablePropertyMap` with `InputRange::const_iterator` as key type and `Item` as value type. + A default can be deduced using the value type of `InputRange` and `Item` to be + either `CGAL::Dereference_property_map` or `CGAL::Identity_property_map`. \param input_range a range of input items for region growing @@ -139,14 +161,18 @@ namespace Shape_detection { a vector of `Item` that is used as seeds for the region growing. Defaults to the full input_range. + \param item_map + an instance of the property map to retrieve items from input values + \pre `input_range.size() > 0` */ - template + template Region_growing( const InputRange& input_range, + SeedRange& seed_range, NeighborQuery& neighbor_query, RegionType& region_type, - SeedRange& seed_range) : + ItemMap item_map = ItemMap()) : m_neighbor_query(neighbor_query), m_region_type(region_type), m_region_map(region_type.region_index_map()), @@ -154,14 +180,17 @@ namespace Shape_detection { CGAL_precondition(input_range.size() > 0); CGAL_precondition(seed_range.size() > 0); - m_seed_range.resize(seed_range.size()); + using Item_helper = internal::Item_map_helper; + using Item_map = typename Item_helper::type; + Item_map item_map_ = Item_helper::get(item_map); + std::size_t idx = 0; for (auto it = seed_range.begin(); it != seed_range.end(); it++) - m_seed_range[idx++] = internal::conditional_deref()(it); + m_seed_range[idx++] = *it; - clear(input_range); + clear(input_range, item_map_); } /// @} @@ -235,18 +264,31 @@ namespace Shape_detection { \tparam InputRange a model of `ConstRange + \tparam ItemMap + a model of `ReadablePropertyMap` with `InputRange::const_iterator` as key type and `Item` as value type. + A default can be deduced using the value type of `InputRange` and `Item` to be + either `CGAL::Dereference_property_map` or `CGAL::Identity_property_map`. + \param input_range a range of input items for region growing \param output an iterator of type `PrimitiveAndRegionOutputIterator`. + \param item_map + an instance of the property map to retrieve items from input values + \return past-the-end position in the output sequence */ - template - ItemOutputIterator unassigned_items(const InputRange& input_range, ItemOutputIterator output) const { + template + ItemOutputIterator unassigned_items(const InputRange& input_range, ItemOutputIterator output, ItemMap item_map = ItemMap()) const + { + using Item_helper = internal::Item_map_helper; + using Item_map = typename Item_helper::type; + Item_map item_map_ = Item_helper::get(item_map); + for (auto it = input_range.begin(); it != input_range.end(); it++) { - Item i = internal::conditional_deref()(it); + Item i = get(item_map_,it); if (!get(m_visited, i)) *(output++) = i; } @@ -256,10 +298,10 @@ namespace Shape_detection { /// @} /// \cond SKIP_IN_MANUAL - template - void clear(const InputRange& input_range) { + template + void clear(const InputRange& input_range, ItemMap item_map) { for (auto it = input_range.begin(); it != input_range.end(); it++) { - Item item = internal::conditional_deref()(it); + Item item = get(item_map, it); put(m_region_map, item, std::size_t(-1)); } // TODO if we want to allow subranges while NeighborQuery operates on the full range diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/property_map.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/property_map.h index 65e18074821..856ad5db9a5 100644 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/property_map.h +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/property_map.h @@ -56,6 +56,26 @@ struct Default_property_map_helper } }; +template +struct Item_map_helper +{ + using type = ItemMap; + static const ItemMap& get(const ItemMap& m) + { + return m; + } +}; + +template +struct Item_map_helper +{ + using type = typename Default_property_map_helper::type; + static type get(Default) + { + return type(); + } +}; + } // namespace internal } // namespace Shape_detection } // namespace CGAL diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/utils.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/utils.h index 9d70c22c61a..3afd5b1a7f5 100644 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/utils.h +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/utils.h @@ -61,24 +61,6 @@ namespace internal { mutable T it; }; - template::value > - struct conditional_deref; - - template - struct conditional_deref { - const Result& operator()(const Input& it) { - return it; - } - }; - - template - struct conditional_deref { - typename std::iterator_traits::reference - operator()(Input it) { - return *it; - } - }; - // TODO: this should be customisable in named function parameters template::value> struct hash_item {}; diff --git a/Shape_detection/test/Shape_detection/test_region_growing_on_cube.cpp b/Shape_detection/test/Shape_detection/test_region_growing_on_cube.cpp index 6ab6671fe14..e948c52c803 100644 --- a/Shape_detection/test/Shape_detection/test_region_growing_on_cube.cpp +++ b/Shape_detection/test/Shape_detection/test_region_growing_on_cube.cpp @@ -79,7 +79,7 @@ bool test_region_growing_on_cube(int argc, char *argv[]) { // Run region growing. Region_growing region_growing( - face_range, neighbor_query, region_type, sorting.ordered()); + face_range, sorting.ordered(), neighbor_query, region_type); std::vector regions; region_growing.detect(std::back_inserter(regions)); diff --git a/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_2_with_sorting.cpp b/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_2_with_sorting.cpp index 543c5e3977f..48ea50f7969 100644 --- a/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_2_with_sorting.cpp +++ b/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_2_with_sorting.cpp @@ -81,7 +81,7 @@ bool test(int argc, char** argv, const std::string name, const std::size_t minr, // Run region growing. Region_growing region_growing( - input_range, neighbor_query, region_type, sorting.ordered()); + input_range, sorting.ordered(), neighbor_query, region_type); std::vector regions; region_growing.detect(std::back_inserter(regions)); diff --git a/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_3_with_sorting.cpp b/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_3_with_sorting.cpp index c47ee3c6dea..a110f376a22 100644 --- a/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_3_with_sorting.cpp +++ b/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_3_with_sorting.cpp @@ -74,7 +74,7 @@ bool test( // Run region growing. Region_type region_type = lambda_region(input_range); Region_growing region_growing( - input_range, neighbor_query, region_type, sorting.ordered()); + input_range, sorting.ordered(), neighbor_query, region_type); std::vector regions; region_growing.detect(std::back_inserter(regions)); diff --git a/Shape_detection/test/Shape_detection/test_region_growing_on_polygon_mesh_with_sorting.cpp b/Shape_detection/test/Shape_detection/test_region_growing_on_polygon_mesh_with_sorting.cpp index fb481c8fcd3..3251f14b220 100644 --- a/Shape_detection/test/Shape_detection/test_region_growing_on_polygon_mesh_with_sorting.cpp +++ b/Shape_detection/test/Shape_detection/test_region_growing_on_polygon_mesh_with_sorting.cpp @@ -71,7 +71,7 @@ int main(int argc, char *argv[]) { // Run region growing. Region_growing region_growing( - face_range, neighbor_query, region_type, sorting.ordered()); + face_range, sorting.ordered(), neighbor_query, region_type); std::vector regions; region_growing.detect(std::back_inserter(regions)); diff --git a/Shape_detection/test/Shape_detection/test_region_growing_strict.cpp b/Shape_detection/test/Shape_detection/test_region_growing_strict.cpp index fc11fe5ff7c..2ae8972fa0d 100644 --- a/Shape_detection/test/Shape_detection/test_region_growing_strict.cpp +++ b/Shape_detection/test/Shape_detection/test_region_growing_strict.cpp @@ -170,7 +170,7 @@ bool test_lines_segment_set_2_sorting() { std::vector regions; Region_growing region_growing( - segments, neighbor_query, region_type, sorting.ordered()); + segments, sorting.ordered(), neighbor_query, region_type); region_growing.detect(std::back_inserter(regions)); assert(regions.size() == 2); assert(regions[0].second.size() == 2); @@ -227,7 +227,7 @@ bool test_lines_segment_set_3() { // Create an instance of the region growing class. RG_planes rg_planes( - face_range, one_ring_query, plane_type, plane_sorting.ordered()); + face_range, plane_sorting.ordered(), one_ring_query, plane_type); assert(surface_mesh.number_of_faces() == 7320); std::vector regions; @@ -246,7 +246,7 @@ bool test_lines_segment_set_3() { std::vector regions2; RG_lines region_growing( - segment_range, pgraph, region_type, sorting.ordered()); + segment_range, sorting.ordered(), pgraph, region_type); region_growing.detect(std::back_inserter(regions2)); assert(regions2.size() == 21); return true;