finally get rid of conditional_deref

This commit is contained in:
Sébastien Loriot 2022-07-22 16:07:06 +02:00
parent 2541f7c22c
commit f693471647
19 changed files with 98 additions and 54 deletions

View File

@ -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<unsigned char>

View File

@ -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<typename RG_lines::Primitive_and_region> subregions;
rg_lines.detect(std::back_inserter(subregions));

View File

@ -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;

View File

@ -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<typename Region_growing::Primitive_and_region> regions;

View File

@ -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}

View File

@ -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}

View File

@ -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}

View File

@ -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}

View File

@ -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}

View File

@ -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}

View File

@ -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}

View File

@ -29,6 +29,7 @@
#include <CGAL/property_map.h>
#include <CGAL/boost/graph/properties.h>
#include <CGAL/Shape_detection/Region_growing/internal/utils.h>
#include <CGAL/Shape_detection/Region_growing/internal/property_map.h>
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<typename InputRange>
template<typename InputRange, typename ItemMap = Default>
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<ItemMap, Item, typename InputRange::const_iterator>;
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<typename InputRange::const_iterator, Item>()(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<typename InputRange, typename SeedRange>
template<typename InputRange, typename SeedRange, typename ItemMap = Default>
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<ItemMap, Item, typename InputRange::const_iterator>;
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<typename SeedRange::const_iterator, Item>()(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<typename InputRange, typename ItemOutputIterator>
ItemOutputIterator unassigned_items(const InputRange& input_range, ItemOutputIterator output) const {
template<typename InputRange, typename ItemOutputIterator, typename ItemMap = Default>
ItemOutputIterator unassigned_items(const InputRange& input_range, ItemOutputIterator output, ItemMap item_map = ItemMap()) const
{
using Item_helper = internal::Item_map_helper<ItemMap, Item, typename InputRange::const_iterator>;
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<typename InputRange::const_iterator, Item>()(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 <class InputRange>
void clear(const InputRange& input_range) {
template <class InputRange, class ItemMap>
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<typename InputRange::const_iterator, typename Region_map::key_type>()(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

View File

@ -56,6 +56,26 @@ struct Default_property_map_helper<NP, Item, Iterator, Tag, false>
}
};
template <class ItemMap, class Item, class Iterator>
struct Item_map_helper
{
using type = ItemMap;
static const ItemMap& get(const ItemMap& m)
{
return m;
}
};
template <class Item, class Iterator>
struct Item_map_helper<Default, Item, Iterator>
{
using type = typename Default_property_map_helper<Default, Item, Iterator, int, false>::type;
static type get(Default)
{
return type();
}
};
} // namespace internal
} // namespace Shape_detection
} // namespace CGAL

View File

@ -61,24 +61,6 @@ namespace internal {
mutable T it;
};
template<typename Input, typename Result, bool = std::is_same<Input, Result>::value >
struct conditional_deref;
template<typename Input, typename Result>
struct conditional_deref<Input, Result, true> {
const Result& operator()(const Input& it) {
return it;
}
};
template<typename Input, typename Result>
struct conditional_deref<Input, Result, false> {
typename std::iterator_traits<Input>::reference
operator()(Input it) {
return *it;
}
};
// TODO: this should be customisable in named function parameters
template<class T, bool = CGAL::is_iterator<T>::value>
struct hash_item {};

View File

@ -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<typename Region_growing::Primitive_and_region> regions;
region_growing.detect(std::back_inserter(regions));

View File

@ -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<typename Region_growing::Primitive_and_region> regions;
region_growing.detect(std::back_inserter(regions));

View File

@ -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<typename Region_growing::Primitive_and_region> regions;
region_growing.detect(std::back_inserter(regions));

View File

@ -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<Region_growing::Primitive_and_region> regions;
region_growing.detect(std::back_inserter(regions));

View File

@ -170,7 +170,7 @@ bool test_lines_segment_set_2_sorting() {
std::vector<typename Region_growing::Primitive_and_region> 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<typename RG_planes::Primitive_and_region> regions;
@ -246,7 +246,7 @@ bool test_lines_segment_set_3() {
std::vector<typename RG_lines::Primitive_and_region> 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;