1 // Copyright 2018 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 #include "draco/compression/attributes/point_d_vector.h"
16 
17 #include "draco/compression/point_cloud/algorithms/point_cloud_types.h"
18 #include "draco/core/draco_test_base.h"
19 
20 namespace draco {
21 
22 class PointDVectorTest : public ::testing::Test {
23  protected:
24   template <typename PT>
TestIntegrity()25   void TestIntegrity() {}
26   template <typename PT>
TestSize()27   void TestSize() {
28     for (uint32_t n_items = 0; n_items <= 10; ++n_items) {
29       for (uint32_t dimensionality = 1; dimensionality <= 10;
30            ++dimensionality) {
31         draco::PointDVector<PT> var(n_items, dimensionality);
32         ASSERT_EQ(n_items, var.size());
33         ASSERT_EQ(n_items * dimensionality, var.GetBufferSize());
34       }
35     }
36   }
37   template <typename PT>
TestContentsContiguous()38   void TestContentsContiguous() {
39     for (uint32_t n_items = 1; n_items <= 1000; n_items *= 10) {
40       for (uint32_t dimensionality = 1; dimensionality < 10;
41            dimensionality += 2) {
42         for (uint32_t att_dimensionality = 1;
43              att_dimensionality <= dimensionality; att_dimensionality += 2) {
44           for (uint32_t offset_dimensionality = 0;
45                offset_dimensionality < dimensionality - att_dimensionality;
46                ++offset_dimensionality) {
47             PointDVector<PT> var(n_items, dimensionality);
48 
49             std::vector<PT> att(n_items * att_dimensionality);
50             for (PT val = 0; val < n_items; val += 1) {
51               for (PT att_dim = 0; att_dim < att_dimensionality; att_dim += 1) {
52                 att[val * att_dimensionality + att_dim] = val;
53               }
54             }
55             const PT *const attribute_data = att.data();
56 
57             var.CopyAttribute(att_dimensionality, offset_dimensionality,
58                               attribute_data);
59 
60             for (PT val = 0; val < n_items; val += 1) {
61               for (PT att_dim = 0; att_dim < att_dimensionality; att_dim += 1) {
62                 ASSERT_EQ(var[val][offset_dimensionality + att_dim], val);
63               }
64             }
65           }
66         }
67       }
68     }
69   }
70   template <typename PT>
TestContentsDiscrete()71   void TestContentsDiscrete() {
72     for (uint32_t n_items = 1; n_items <= 1000; n_items *= 10) {
73       for (uint32_t dimensionality = 1; dimensionality < 10;
74            dimensionality += 2) {
75         for (uint32_t att_dimensionality = 1;
76              att_dimensionality <= dimensionality; att_dimensionality += 2) {
77           for (uint32_t offset_dimensionality = 0;
78                offset_dimensionality < dimensionality - att_dimensionality;
79                ++offset_dimensionality) {
80             PointDVector<PT> var(n_items, dimensionality);
81 
82             std::vector<PT> att(n_items * att_dimensionality);
83             for (PT val = 0; val < n_items; val += 1) {
84               for (PT att_dim = 0; att_dim < att_dimensionality; att_dim += 1) {
85                 att[val * att_dimensionality + att_dim] = val;
86               }
87             }
88             const PT *const attribute_data = att.data();
89 
90             for (PT item = 0; item < n_items; item += 1) {
91               var.CopyAttribute(att_dimensionality, offset_dimensionality, item,
92                                 attribute_data + item * att_dimensionality);
93             }
94 
95             for (PT val = 0; val < n_items; val += 1) {
96               for (PT att_dim = 0; att_dim < att_dimensionality; att_dim += 1) {
97                 ASSERT_EQ(var[val][offset_dimensionality + att_dim], val);
98               }
99             }
100           }
101         }
102       }
103     }
104   }
105 
106   template <typename PT>
TestContentsCopy()107   void TestContentsCopy() {
108     for (uint32_t n_items = 1; n_items <= 1000; n_items *= 10) {
109       for (uint32_t dimensionality = 1; dimensionality < 10;
110            dimensionality += 2) {
111         for (uint32_t att_dimensionality = 1;
112              att_dimensionality <= dimensionality; att_dimensionality += 2) {
113           for (uint32_t offset_dimensionality = 0;
114                offset_dimensionality < dimensionality - att_dimensionality;
115                ++offset_dimensionality) {
116             PointDVector<PT> var(n_items, dimensionality);
117             PointDVector<PT> dest(n_items, dimensionality);
118 
119             std::vector<PT> att(n_items * att_dimensionality);
120             for (PT val = 0; val < n_items; val += 1) {
121               for (PT att_dim = 0; att_dim < att_dimensionality; att_dim += 1) {
122                 att[val * att_dimensionality + att_dim] = val;
123               }
124             }
125             const PT *const attribute_data = att.data();
126 
127             var.CopyAttribute(att_dimensionality, offset_dimensionality,
128                               attribute_data);
129 
130             for (PT item = 0; item < n_items; item += 1) {
131               dest.CopyItem(var, item, item);
132             }
133 
134             for (PT val = 0; val < n_items; val += 1) {
135               for (PT att_dim = 0; att_dim < att_dimensionality; att_dim += 1) {
136                 ASSERT_EQ(var[val][offset_dimensionality + att_dim], val);
137                 ASSERT_EQ(dest[val][offset_dimensionality + att_dim], val);
138               }
139             }
140           }
141         }
142       }
143     }
144   }
145   template <typename PT>
TestIterator()146   void TestIterator() {
147     for (uint32_t n_items = 1; n_items <= 1000; n_items *= 10) {
148       for (uint32_t dimensionality = 1; dimensionality < 10;
149            dimensionality += 2) {
150         for (uint32_t att_dimensionality = 1;
151              att_dimensionality <= dimensionality; att_dimensionality += 2) {
152           for (uint32_t offset_dimensionality = 0;
153                offset_dimensionality < dimensionality - att_dimensionality;
154                ++offset_dimensionality) {
155             PointDVector<PT> var(n_items, dimensionality);
156             PointDVector<PT> dest(n_items, dimensionality);
157 
158             std::vector<PT> att(n_items * att_dimensionality);
159             for (PT val = 0; val < n_items; val += 1) {
160               for (PT att_dim = 0; att_dim < att_dimensionality; att_dim += 1) {
161                 att[val * att_dimensionality + att_dim] = val;
162               }
163             }
164             const PT *const attribute_data = att.data();
165 
166             var.CopyAttribute(att_dimensionality, offset_dimensionality,
167                               attribute_data);
168 
169             for (PT item = 0; item < n_items; item += 1) {
170               dest.CopyItem(var, item, item);
171             }
172 
173             auto V0 = var.begin();
174             auto VE = var.end();
175             auto D0 = dest.begin();
176             auto DE = dest.end();
177 
178             while (V0 != VE && D0 != DE) {
179               ASSERT_EQ(*D0, *V0);  // compare PseudoPointD
180               // verify elemental values
181               for (auto index = 0; index < dimensionality; index += 1) {
182                 ASSERT_EQ((*D0)[index], (*V0)[index]);
183               }
184               ++V0;
185               ++D0;
186             }
187 
188             for (PT val = 0; val < n_items; val += 1) {
189               for (PT att_dim = 0; att_dim < att_dimensionality; att_dim += 1) {
190                 ASSERT_EQ(var[val][offset_dimensionality + att_dim], val);
191                 ASSERT_EQ(dest[val][offset_dimensionality + att_dim], val);
192               }
193             }
194           }
195         }
196       }
197     }
198   }
199   template <typename PT>
TestPoint3Iterator()200   void TestPoint3Iterator() {
201     for (uint32_t n_items = 1; n_items <= 1000; n_items *= 10) {
202       const uint32_t dimensionality = 3;
203       // for (uint32_t dimensionality = 1; dimensionality < 10;
204       //      dimensionality += 2) {
205       const uint32_t att_dimensionality = 3;
206       // for (uint32_t att_dimensionality = 1;
207       //      att_dimensionality <= dimensionality; att_dimensionality += 2) {
208       for (uint32_t offset_dimensionality = 0;
209            offset_dimensionality < dimensionality - att_dimensionality;
210            ++offset_dimensionality) {
211         PointDVector<PT> var(n_items, dimensionality);
212         PointDVector<PT> dest(n_items, dimensionality);
213 
214         std::vector<PT> att(n_items * att_dimensionality);
215         std::vector<draco::Point3ui> att3(n_items);
216         for (PT val = 0; val < n_items; val += 1) {
217           att3[val][0] = val;
218           att3[val][1] = val;
219           att3[val][2] = val;
220           for (PT att_dim = 0; att_dim < att_dimensionality; att_dim += 1) {
221             att[val * att_dimensionality + att_dim] = val;
222           }
223         }
224         const PT *const attribute_data = att.data();
225 
226         var.CopyAttribute(att_dimensionality, offset_dimensionality,
227                           attribute_data);
228 
229         for (PT item = 0; item < n_items; item += 1) {
230           dest.CopyItem(var, item, item);
231         }
232 
233         auto aV0 = att3.begin();
234         auto aVE = att3.end();
235         auto V0 = var.begin();
236         auto VE = var.end();
237         auto D0 = dest.begin();
238         auto DE = dest.end();
239 
240         while (aV0 != aVE && V0 != VE && D0 != DE) {
241           ASSERT_EQ(*D0, *V0);  // compare PseudoPointD
242           // verify elemental values
243           for (auto index = 0; index < dimensionality; index += 1) {
244             ASSERT_EQ((*D0)[index], (*V0)[index]);
245             ASSERT_EQ((*D0)[index], (*aV0)[index]);
246             ASSERT_EQ((*aV0)[index], (*V0)[index]);
247           }
248           ++aV0;
249           ++V0;
250           ++D0;
251         }
252 
253         for (PT val = 0; val < n_items; val += 1) {
254           for (PT att_dim = 0; att_dim < att_dimensionality; att_dim += 1) {
255             ASSERT_EQ(var[val][offset_dimensionality + att_dim], val);
256             ASSERT_EQ(dest[val][offset_dimensionality + att_dim], val);
257           }
258         }
259       }
260     }
261   }
262 
TestPseudoPointDSwap()263   void TestPseudoPointDSwap() {
264     draco::Point3ui val = {0, 1, 2};
265     draco::Point3ui dest = {10, 11, 12};
266     draco::PseudoPointD<uint32_t> val_src1(&val[0], 3);
267     draco::PseudoPointD<uint32_t> dest_src1(&dest[0], 3);
268 
269     ASSERT_EQ(val_src1[0], 0);
270     ASSERT_EQ(val_src1[1], 1);
271     ASSERT_EQ(val_src1[2], 2);
272     ASSERT_EQ(dest_src1[0], 10);
273     ASSERT_EQ(dest_src1[1], 11);
274     ASSERT_EQ(dest_src1[2], 12);
275 
276     ASSERT_NE(val_src1, dest_src1);
277 
278     swap(val_src1, dest_src1);
279 
280     ASSERT_EQ(dest_src1[0], 0);
281     ASSERT_EQ(dest_src1[1], 1);
282     ASSERT_EQ(dest_src1[2], 2);
283     ASSERT_EQ(val_src1[0], 10);
284     ASSERT_EQ(val_src1[1], 11);
285     ASSERT_EQ(val_src1[2], 12);
286 
287     ASSERT_NE(val_src1, dest_src1);
288   }
TestPseudoPointDEquality()289   void TestPseudoPointDEquality() {
290     draco::Point3ui val = {0, 1, 2};
291     draco::Point3ui dest = {0, 1, 2};
292     draco::PseudoPointD<uint32_t> val_src1(&val[0], 3);
293     draco::PseudoPointD<uint32_t> val_src2(&val[0], 3);
294     draco::PseudoPointD<uint32_t> dest_src1(&dest[0], 3);
295     draco::PseudoPointD<uint32_t> dest_src2(&dest[0], 3);
296 
297     ASSERT_EQ(val_src1, val_src1);
298     ASSERT_EQ(val_src1, val_src2);
299     ASSERT_EQ(dest_src1, val_src1);
300     ASSERT_EQ(dest_src1, val_src2);
301     ASSERT_EQ(val_src2, val_src1);
302     ASSERT_EQ(val_src2, val_src2);
303     ASSERT_EQ(dest_src2, val_src1);
304     ASSERT_EQ(dest_src2, val_src2);
305 
306     for (auto i = 0; i < 3; i++) {
307       ASSERT_EQ(val_src1[i], val_src1[i]);
308       ASSERT_EQ(val_src1[i], val_src2[i]);
309       ASSERT_EQ(dest_src1[i], val_src1[i]);
310       ASSERT_EQ(dest_src1[i], val_src2[i]);
311       ASSERT_EQ(val_src2[i], val_src1[i]);
312       ASSERT_EQ(val_src2[i], val_src2[i]);
313       ASSERT_EQ(dest_src2[i], val_src1[i]);
314       ASSERT_EQ(dest_src2[i], val_src2[i]);
315     }
316   }
TestPseudoPointDInequality()317   void TestPseudoPointDInequality() {
318     draco::Point3ui val = {0, 1, 2};
319     draco::Point3ui dest = {1, 2, 3};
320     draco::PseudoPointD<uint32_t> val_src1(&val[0], 3);
321     draco::PseudoPointD<uint32_t> val_src2(&val[0], 3);
322     draco::PseudoPointD<uint32_t> dest_src1(&dest[0], 3);
323     draco::PseudoPointD<uint32_t> dest_src2(&dest[0], 3);
324 
325     ASSERT_EQ(val_src1, val_src1);
326     ASSERT_EQ(val_src1, val_src2);
327     ASSERT_NE(dest_src1, val_src1);
328     ASSERT_NE(dest_src1, val_src2);
329     ASSERT_EQ(val_src2, val_src1);
330     ASSERT_EQ(val_src2, val_src2);
331     ASSERT_NE(dest_src2, val_src1);
332     ASSERT_NE(dest_src2, val_src2);
333 
334     for (auto i = 0; i < 3; i++) {
335       ASSERT_EQ(val_src1[i], val_src1[i]);
336       ASSERT_EQ(val_src1[i], val_src2[i]);
337       ASSERT_NE(dest_src1[i], val_src1[i]);
338       ASSERT_NE(dest_src1[i], val_src2[i]);
339       ASSERT_EQ(val_src2[i], val_src1[i]);
340       ASSERT_EQ(val_src2[i], val_src2[i]);
341       ASSERT_NE(dest_src2[i], val_src1[i]);
342       ASSERT_NE(dest_src2[i], val_src2[i]);
343     }
344   }
345 };
346 
TEST_F(PointDVectorTest,VectorTest)347 TEST_F(PointDVectorTest, VectorTest) {
348   TestSize<uint32_t>();
349   TestContentsDiscrete<uint32_t>();
350   TestContentsContiguous<uint32_t>();
351   TestContentsCopy<uint32_t>();
352   TestIterator<uint32_t>();
353   TestPoint3Iterator<uint32_t>();
354 }
TEST_F(PointDVectorTest,PseudoPointDTest)355 TEST_F(PointDVectorTest, PseudoPointDTest) {
356   TestPseudoPointDSwap();
357   TestPseudoPointDEquality();
358   TestPseudoPointDInequality();
359 }
360 }  // namespace draco
361