1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
|
// Copyright (c) 2018 GeometryFactory Sarl (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL: https://github.com/CGAL/cgal/blob/v6.1/Classification/include/CGAL/Classification/Cluster.h $
// $Id: include/CGAL/Classification/Cluster.h b26b07a1242 $
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Simon Giraudot
#ifndef CGAL_CLASSIFICATION_CLUSTER_H
#define CGAL_CLASSIFICATION_CLUSTER_H
#include <CGAL/license/Classification.h>
#include <CGAL/Bbox_3.h>
#include <CGAL/property_map.h>
#include <boost/iterator/transform_iterator.hpp>
namespace CGAL {
namespace Classification {
/*!
\ingroup PkgClassificationCluster
\brief Class that represent a cluster of items to be classified as
a single atomic object.
A cluster is a set of indices of items inside an input range with
random access.
\tparam ItemRange model of `ConstRange`. Its iterator type is
`RandomAccessIterator`. Its value type depends on the data that is
classified (for example, `CGAL::Point_3` or `CGAL::Triangle_3`).
\tparam ItemMap model of `ReadablePropertyMap` whose key
type is the value type of the iterator of `ItemRange` and value type
is the type of item to classify (for example, `CGAL::Point_3`).
*/
template <typename ItemRange, typename ItemMap>
class Cluster
{
public:
using Item = typename boost::property_traits<ItemMap>::value_type;
/// \cond SKIP_IN_MANUAL
struct Neighbor_query
{
template <typename OutputIterator>
OutputIterator operator() (const Cluster& cluster, OutputIterator output) const
{
return std::copy (cluster.neighbors->begin(), cluster.neighbors->end(), output);
}
};
std::shared_ptr<std::vector<std::size_t> > neighbors;
/// \endcond
/// \cond SKIP_IN_MANUAL
class Point_idx_to_point_unary_function
{
public:
using argument_type = std::size_t;
using result_type = typename boost::property_traits<ItemMap>::reference;
const ItemRange* m_range;
ItemMap m_item_map;
Point_idx_to_point_unary_function (const ItemRange* range, ItemMap item_map)
: m_range (range), m_item_map (item_map)
{ }
result_type operator() (const argument_type& arg) const
{
return get (m_item_map, *(m_range->begin() + arg));
}
};
/// \endcond
private:
const ItemRange* m_range;
ItemMap m_item_map;
std::shared_ptr<std::vector<std::size_t> > m_inliers;
mutable CGAL::Bbox_3 m_bounding_box;
int m_training;
int m_label;
public:
/// \name Constructor
/// @{
/*!
\brief Constructs an empty cluster of items.
Items in the clusters will be subsets of `range`.
\param range input range.
\param item_map property map to access the input items.
*/
Cluster (const ItemRange& range, ItemMap item_map)
: neighbors (std::make_shared<std::vector<std::size_t> >())
, m_range (&range), m_item_map (item_map)
, m_inliers (std::make_shared<std::vector<std::size_t> >())
, m_training(-1), m_label(-1)
{ }
/// @}
/// \name Modifications
/// @{
/*!
\brief Clears the cluster.
*/
void clear () { m_inliers->clear(); }
/*!
\brief inserts element of index `idx` in the cluster.
*/
void insert (std::size_t idx) { m_inliers->push_back (idx); }
/// @}
/// \name Access
/// @{
/*!
\brief returns the number of items in the cluster.
*/
std::size_t size() const { return m_inliers->size(); }
/*!
\brief returns the index (in the input range) of the i^{th} element of the cluster.
*/
std::size_t index (std::size_t i) const { return (*m_inliers)[i]; }
/*!
\brief returns the i^{th} item of the cluster.
*/
const Item& operator[] (std::size_t i) const
{ return get (m_item_map, *(m_range->begin() + (*m_inliers)[i])); }
/*!
\brief returns the bounding box of the cluster.
*/
const CGAL::Bbox_3& bbox() const
{
if (m_bounding_box == CGAL::Bbox_3())
{
Point_idx_to_point_unary_function transform (m_range, m_item_map);
m_bounding_box = CGAL::bbox_3 (boost::make_transform_iterator (m_inliers->begin(), transform),
boost::make_transform_iterator (m_inliers->end(), transform));
}
return m_bounding_box;
}
/// @}
/// \name Classification
/// @{
/*!
\brief returns the input classification value used for training.
*/
int training() const { return m_training; }
/*!
\brief returns a reference to the input classification value used for training.
*/
int& training() { return m_training; }
/*!
\brief returns the output classification value.
*/
int label() const { return m_label; }
/*!
\brief returns a reference to the output classification value.
*/
int& label() { return m_label; }
// @}
};
/*!
\ingroup PkgClassificationCluster
\brief Given a set of cluster indices, segments the input `range`
into `Cluster` objects.
All items whose index value `idx` (accessed through `index_map`)
is the same are stored in the same cluster at position `idx` in
the `clusters` vector.
\tparam ItemRange model of `ConstRange`. Its iterator type is
`RandomAccessIterator`. Its value type depends on the data that is
classified (for example, `CGAL::Point_3` or `CGAL::Triangle_3`).
\tparam ItemMap model of `ReadablePropertyMap` whose key
type is the value type of the iterator of `ItemRange` and value type
is the type of item to classify (for example, `CGAL::Point_3`).
\tparam IndexMap is a model of `ReadablePropertyMap` with value type `int`.
\param range input range.
\param item_map property map to access the input items.
\param index_map property map that associates the index of an item
in the input range to the index of a cluster (-1 if item is not
assigned to a cluster).
\param clusters container where generated `Cluster` objects are stored.
*/
template <typename ItemRange, typename ItemMap, typename IndexMap>
std::size_t create_clusters_from_indices (const ItemRange& range,
ItemMap item_map,
IndexMap index_map,
std::vector<Cluster<ItemRange, ItemMap> >& clusters)
{
std::size_t idx = 0;
for (typename ItemRange::const_iterator it = range.begin(); it != range.end(); ++ it, ++ idx)
{
int c = int(get (index_map, idx));
if (c == -1)
continue;
if (std::size_t(c) >= clusters.size())
{
clusters.reserve (c + 1);
for (std::size_t i = clusters.size(); i <= std::size_t(c); ++ i)
clusters.push_back (Cluster<ItemRange, ItemMap>(range, item_map));
}
clusters[std::size_t(c)].insert (idx);
}
return clusters.size();
}
} // namespace Classification
} // namespace CGAL
#endif // CGAL_CLASSIFICATION_CLUSTER_H
|