File: Cluster.h

package info (click to toggle)
cgal 6.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 144,912 kB
  • sloc: cpp: 810,858; ansic: 208,477; sh: 493; python: 411; makefile: 286; javascript: 174
file content (248 lines) | stat: -rw-r--r-- 6,935 bytes parent folder | download
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