/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_ |