Coverage Report

Created: 2024-09-08 06:47

/src/draco/src/draco/point_cloud/point_cloud.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2016 The Draco Authors.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//      http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
//
15
#ifndef DRACO_POINT_CLOUD_POINT_CLOUD_H_
16
#define DRACO_POINT_CLOUD_POINT_CLOUD_H_
17
18
#include "draco/attributes/point_attribute.h"
19
#include "draco/core/bounding_box.h"
20
#include "draco/core/vector_d.h"
21
#include "draco/draco_features.h"
22
#include "draco/metadata/geometry_metadata.h"
23
24
#ifdef DRACO_TRANSCODER_SUPPORTED
25
#include "draco/compression/draco_compression_options.h"
26
#endif
27
28
namespace draco {
29
30
// PointCloud is a collection of n-dimensional points that are described by a
31
// set of PointAttributes that can represent data such as positions or colors
32
// of individual points (see point_attribute.h).
33
class PointCloud {
34
 public:
35
  PointCloud();
36
801
  virtual ~PointCloud() = default;
37
38
#ifdef DRACO_TRANSCODER_SUPPORTED
39
  // Copies all data from the |src| point cloud.
40
  void Copy(const PointCloud &src);
41
#endif
42
43
  // Returns the number of named attributes of a given type.
44
  int32_t NumNamedAttributes(GeometryAttribute::Type type) const;
45
46
  // Returns attribute id of the first named attribute with a given type or -1
47
  // when the attribute is not used by the point cloud.
48
  int32_t GetNamedAttributeId(GeometryAttribute::Type type) const;
49
50
  // Returns the id of the i-th named attribute of a given type.
51
  int32_t GetNamedAttributeId(GeometryAttribute::Type type, int i) const;
52
53
  // Returns the first named attribute of a given type or nullptr if the
54
  // attribute is not used by the point cloud.
55
  const PointAttribute *GetNamedAttribute(GeometryAttribute::Type type) const;
56
57
  // Returns the i-th named attribute of a given type.
58
  const PointAttribute *GetNamedAttribute(GeometryAttribute::Type type,
59
                                          int i) const;
60
61
  // Returns the named attribute of a given unique id.
62
  const PointAttribute *GetNamedAttributeByUniqueId(
63
      GeometryAttribute::Type type, uint32_t id) const;
64
65
  // Returns the attribute of a given unique id.
66
  const PointAttribute *GetAttributeByUniqueId(uint32_t id) const;
67
  int32_t GetAttributeIdByUniqueId(uint32_t unique_id) const;
68
69
#ifdef DRACO_TRANSCODER_SUPPORTED
70
  // Returns the named attribute with a given name.
71
  const PointAttribute *GetNamedAttributeByName(GeometryAttribute::Type type,
72
                                                const std::string &name) const;
73
#endif  // DRACO_TRANSCODER_SUPPORTED
74
75
181
  int32_t num_attributes() const {
76
181
    return static_cast<int32_t>(attributes_.size());
77
181
  }
78
624
  const PointAttribute *attribute(int32_t att_id) const {
79
624
    DRACO_DCHECK_LE(0, att_id);
80
624
    DRACO_DCHECK_LT(att_id, static_cast<int32_t>(attributes_.size()));
81
624
    return attributes_[att_id].get();
82
624
  }
83
84
  // Returned attribute can be modified, but it's caller's responsibility to
85
  // maintain the attribute's consistency with draco::PointCloud.
86
15.9k
  PointAttribute *attribute(int32_t att_id) {
87
15.9k
    DRACO_DCHECK_LE(0, att_id);
88
15.9k
    DRACO_DCHECK_LT(att_id, static_cast<int32_t>(attributes_.size()));
89
15.9k
    return attributes_[att_id].get();
90
15.9k
  }
91
92
  // Adds a new attribute to the point cloud.
93
  // Returns the attribute id.
94
  int AddAttribute(std::unique_ptr<PointAttribute> pa);
95
96
  // Creates and adds a new attribute to the point cloud. The attribute has
97
  // properties derived from the provided GeometryAttribute |att|.
98
  // If |identity_mapping| is set to true, the attribute will use identity
99
  // mapping between point indices and attribute value indices (i.e., each
100
  // point has a unique attribute value). If |identity_mapping| is false, the
101
  // mapping between point indices and attribute value indices is set to
102
  // explicit, and it needs to be initialized manually using the
103
  // PointAttribute::SetPointMapEntry() method. |num_attribute_values| can be
104
  // used to specify the number of attribute values that are going to be
105
  // stored in the newly created attribute. Returns attribute id of the newly
106
  // created attribute or -1 in case of failure.
107
  int AddAttribute(const GeometryAttribute &att, bool identity_mapping,
108
                   AttributeValueIndex::ValueType num_attribute_values);
109
110
  // Creates and returns a new attribute or nullptr in case of failure. This
111
  // method is similar to AddAttribute(), except that it returns the new
112
  // attribute instead of adding it to the point cloud.
113
  std::unique_ptr<PointAttribute> CreateAttribute(
114
      const GeometryAttribute &att, bool identity_mapping,
115
      AttributeValueIndex::ValueType num_attribute_values) const;
116
117
  // Assigns an attribute id to a given PointAttribute. If an attribute with
118
  // the same attribute id already exists, it is deleted.
119
  virtual void SetAttribute(int att_id, std::unique_ptr<PointAttribute> pa);
120
121
  // Deletes an attribute with specified attribute id. Note that this changes
122
  // attribute ids of all subsequent attributes.
123
  virtual void DeleteAttribute(int att_id);
124
125
#ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED
126
  // Deduplicates all attribute values (all attribute entries with the same
127
  // value are merged into a single entry).
128
  virtual bool DeduplicateAttributeValues();
129
#endif
130
131
#ifdef DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED
132
  // Removes duplicate point ids (two point ids are duplicate when all of their
133
  // attributes are mapped to the same entry ids).
134
  virtual void DeduplicatePointIds();
135
#endif
136
137
  // Get bounding box.
138
  BoundingBox ComputeBoundingBox() const;
139
140
  // Add metadata.
141
18
  void AddMetadata(std::unique_ptr<GeometryMetadata> metadata) {
142
18
    metadata_ = std::move(metadata);
143
18
  }
144
145
  // Add metadata for an attribute.
146
  void AddAttributeMetadata(int32_t att_id,
147
0
                            std::unique_ptr<AttributeMetadata> metadata) {
148
0
    if (!metadata_) {
149
0
      metadata_ = std::unique_ptr<GeometryMetadata>(new GeometryMetadata());
150
0
    }
151
0
    const int32_t att_unique_id = attribute(att_id)->unique_id();
152
0
    metadata->set_att_unique_id(att_unique_id);
153
0
    metadata_->AddAttributeMetadata(std::move(metadata));
154
0
  }
155
156
  const AttributeMetadata *GetAttributeMetadataByAttributeId(
157
0
      int32_t att_id) const {
158
0
    if (metadata_ == nullptr) {
159
0
      return nullptr;
160
0
    }
161
0
    const uint32_t unique_id = attribute(att_id)->unique_id();
162
0
    return metadata_->GetAttributeMetadataByUniqueId(unique_id);
163
0
  }
164
165
  // Returns the attribute metadata that has the requested metadata entry.
166
  const AttributeMetadata *GetAttributeMetadataByStringEntry(
167
0
      const std::string &name, const std::string &value) const {
168
0
    if (metadata_ == nullptr) {
169
0
      return nullptr;
170
0
    }
171
0
    return metadata_->GetAttributeMetadataByStringEntry(name, value);
172
0
  }
173
174
  // Returns the first attribute that has the requested metadata entry.
175
  int GetAttributeIdByMetadataEntry(const std::string &name,
176
0
                                    const std::string &value) const {
177
0
    if (metadata_ == nullptr) {
178
0
      return -1;
179
0
    }
180
0
    const AttributeMetadata *att_metadata =
181
0
        metadata_->GetAttributeMetadataByStringEntry(name, value);
182
0
    if (!att_metadata) {
183
0
      return -1;
184
0
    }
185
0
    return GetAttributeIdByUniqueId(att_metadata->att_unique_id());
186
0
  }
187
188
  // Get a const pointer of the metadata of the point cloud.
189
0
  const GeometryMetadata *GetMetadata() const { return metadata_.get(); }
190
191
  // Get a pointer to the metadata of the point cloud.
192
0
  GeometryMetadata *metadata() { return metadata_.get(); }
193
194
  // Returns the number of n-dimensional points stored within the point cloud.
195
7.23k
  PointIndex::ValueType num_points() const { return num_points_; }
196
197
  // Sets the number of points. It's the caller's responsibility to ensure the
198
  // new number is valid with respect to the PointAttributes stored in the point
199
  // cloud.
200
457
  void set_num_points(PointIndex::ValueType num) { num_points_ = num; }
201
202
#ifdef DRACO_TRANSCODER_SUPPORTED
203
  // Enables or disables Draco geometry compression for this mesh.
204
  void SetCompressionEnabled(bool enabled) { compression_enabled_ = enabled; }
205
  bool IsCompressionEnabled() const { return compression_enabled_; }
206
207
  // Sets |options| that configure Draco geometry compression. This does not
208
  // enable or disable compression.
209
  void SetCompressionOptions(const DracoCompressionOptions &options) {
210
    compression_options_ = options;
211
  }
212
  const DracoCompressionOptions &GetCompressionOptions() const {
213
    return compression_options_;
214
  }
215
  DracoCompressionOptions &GetCompressionOptions() {
216
    return compression_options_;
217
  }
218
#endif  // DRACO_TRANSCODER_SUPPORTED
219
220
 protected:
221
#ifdef DRACO_TRANSCODER_SUPPORTED
222
  // Copies metadata from the |src| point cloud.
223
  void CopyMetadata(const PointCloud &src);
224
#endif
225
226
#ifdef DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED
227
  // Applies id mapping of deduplicated points (called by DeduplicatePointIds).
228
  virtual void ApplyPointIdDeduplication(
229
      const IndexTypeVector<PointIndex, PointIndex> &id_map,
230
      const std::vector<PointIndex> &unique_point_ids);
231
#endif
232
233
 private:
234
  // Metadata for the point cloud.
235
  std::unique_ptr<GeometryMetadata> metadata_;
236
237
  // Attributes describing the point cloud.
238
  std::vector<std::unique_ptr<PointAttribute>> attributes_;
239
240
  // Ids of named attributes of the given type.
241
  std::vector<int32_t>
242
      named_attribute_index_[GeometryAttribute::NAMED_ATTRIBUTES_COUNT];
243
244
  // The number of n-dimensional points. All point attribute values are stored
245
  // in corresponding PointAttribute instances in the |attributes_| array.
246
  PointIndex::ValueType num_points_;
247
248
#ifdef DRACO_TRANSCODER_SUPPORTED
249
  // Compression options for this geometry.
250
  // TODO(vytyaz): Store encoded bitstream that this geometry compresses into.
251
  bool compression_enabled_ = false;
252
  DracoCompressionOptions compression_options_;
253
#endif  // DRACO_TRANSCODER_SUPPORTED
254
255
  friend struct PointCloudHasher;
256
};
257
258
// Functor for computing a hash from data stored within a point cloud.
259
// Note that this can be quite slow. Two point clouds will have the same hash
260
// only when all points have the same order and when all attribute values are
261
// exactly the same.
262
struct PointCloudHasher {
263
0
  size_t operator()(const PointCloud &pc) const {
264
0
    size_t hash = pc.num_points_;
265
0
    hash = HashCombine(pc.attributes_.size(), hash);
266
0
    for (int i = 0; i < GeometryAttribute::NAMED_ATTRIBUTES_COUNT; ++i) {
267
0
      hash = HashCombine(pc.named_attribute_index_[i].size(), hash);
268
0
      for (int j = 0; j < static_cast<int>(pc.named_attribute_index_[i].size());
269
0
           ++j) {
270
0
        hash = HashCombine(pc.named_attribute_index_[i][j], hash);
271
0
      }
272
0
    }
273
0
    // Hash attributes.
274
0
    for (int i = 0; i < static_cast<int>(pc.attributes_.size()); ++i) {
275
0
      PointAttributeHasher att_hasher;
276
0
      hash = HashCombine(att_hasher(*pc.attributes_[i]), hash);
277
0
    }
278
0
    // Hash metadata.
279
0
    GeometryMetadataHasher metadata_hasher;
280
0
    if (pc.metadata_) {
281
0
      hash = HashCombine(metadata_hasher(*pc.metadata_), hash);
282
0
    }
283
0
    return hash;
284
0
  }
285
};
286
287
}  // namespace draco
288
289
#endif  // DRACO_POINT_CLOUD_POINT_CLOUD_H_