Apollo 10.0
自动驾驶开放平台
i_struct_s.h
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2018 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
17#pragma once
18
19#include <vector>
20
21#if defined(__x86_64__)
22#include <smmintrin.h>
23#elif defined(__aarch64__) && defined(__ARM_NEON)
24#include "sse2neon.h" // NOLINT
25#else
26#error "Processor architecture not supported!"
27#endif
28
32
33namespace apollo {
34namespace perception {
35namespace algorithm {
36template <typename T, unsigned int d>
37class PtCluster {
38 public:
39 typedef T *iterator;
40 typedef const T *const_iterator;
41 typedef T &reference;
42 typedef const T &const_reference;
43
44 static unsigned int NrPointElement() { return (d); }
45
46 static unsigned int PointsizeInByte() { return (d * sizeof(T)); }
47
48 unsigned int ClustersizeInByte() const {
49 return (d * sizeof(T) * nr_points_);
50 }
51
52 unsigned int NrPoints() const { return (nr_points_); }
53
54 bool Initialized() const { return (nr_points_ > 0); }
55
56 const T *ConstData() const { return (data_); }
57
58 T *Data() { return (data_); }
59
60 void CleanUp();
61
62 PtCluster();
63 explicit PtCluster(unsigned int n);
64 PtCluster(const T *data, unsigned int n);
65 PtCluster(const PtCluster<T, d> &c) : data_(nullptr), nr_points_(0) {
66 if (c.NrPoints()) {
67 nr_points_ = c.NrPoints();
68 data_ = IAllocAligned<T>(nr_points_ * d, 4);
69 assert(data_ != nullptr && IVerifyAlignment(data_, 4));
71 }
72 }
73
75 if (this != &c) {
76 if (this->nr_points_ != c.NrPoints()) {
78 data_ = IAllocAligned<T>(this->nr_points_ * d, 4);
79 assert(data_ != nullptr && IVerifyAlignment(data_, 4));
80 this->nr_points_ = c.NrPoints();
81 }
82 ICopy(c.ConstData(), data_, this->nr_points_ * d);
83 }
84 return (*this);
85 }
86
87 virtual ~PtCluster() { CleanUp(); }
88
89 T *operator[](unsigned int i) {
90 assert(i < nr_points_);
91 assert(data_ != nullptr);
92 return (data_ + i * d);
93 }
94
95 const T *operator[](unsigned int i) const {
96 assert(i < nr_points_);
97 assert(data_ != nullptr);
98 return (data_ + i * d);
99 }
100
101 reference operator()(unsigned int i, unsigned int j) {
102 assert(i < nr_points_ && j < d);
103 return data_[i * d + j];
104 }
105
106 const_reference operator()(unsigned int i, unsigned int j) const {
107 assert(i < nr_points_ && j < d);
108 return data_[i * d + j];
109 }
110
111 iterator Begin() { return data_; }
112
113 iterator End() { return data_ + (nr_points_ * d); }
114
115 const_iterator Begin() const { return data_; }
116
117 const_iterator End() const { return data_ + (nr_points_ * d); }
118
119 protected:
120 // continuous 16-byte aligned memory
122 unsigned int nr_points_;
123};
124
125template <typename T, unsigned int d>
126PtCluster<T, d>::PtCluster() : data_(nullptr), nr_points_(0) {}
127
128template <typename T, unsigned int d>
129PtCluster<T, d>::PtCluster(unsigned int n) : data_(nullptr), nr_points_(n) {
130 if (n != 0) {
131 data_ = IAllocAligned<T>(n * d, 4);
132 if (!data_ || !IVerifyAlignment(data_, 4)) {
133 nr_points_ = 0;
135 }
136 }
137}
138
139template <typename T, unsigned int d>
140PtCluster<T, d>::PtCluster(const T *data, unsigned int n)
141 : data_(nullptr), nr_points_(n) {
142 if (data && n) {
143 data_ = IAllocAligned<T>(n * d, 4);
144 if (data_ && IVerifyAlignment(data_, 4)) {
145 ICopy(data, data_, n * d);
146 } else {
147 nr_points_ = 0;
149 }
150 }
151}
152
153template <typename T, unsigned int d>
155 IFreeAligned(&data_);
156 nr_points_ = 0;
157}
158
159template <typename T>
160inline int IAssignPointToVoxel(const T *data, T bound_x_min, T bound_x_max,
161 T bound_y_min, T bound_y_max, T bound_z_min,
162 T bound_z_max, T voxel_width_x_rec,
163 T voxel_width_y_rec, int nr_voxel_x,
164 int nr_voxel_y) {
165 int i, j, k;
166 T x = data[0];
167 T y = data[1];
168 T z = data[2];
169
170 // points that are outside the defined BBOX are ignored
171 if (x < bound_x_min || x > bound_x_max || y < bound_y_min ||
172 y > bound_y_max || z < bound_z_min || z > bound_z_max) {
173 return (-1);
174 }
175
176 // compute the x, y voxel indices
177 k = IMin(nr_voxel_x - 1,
178 static_cast<int>((x - bound_x_min) * voxel_width_x_rec));
179 j = IMin(nr_voxel_y - 1,
180 static_cast<int>((y - bound_y_min) * voxel_width_y_rec));
181 i = (nr_voxel_x * j) + k;
182 return (i);
183}
184
185template <typename T>
186inline int AssignPointToVoxel(T xx, T yy, T zz, T bound_x_min, T bound_x_max,
187 T bound_y_min, T bound_y_max, T bound_z_min,
188 T bound_z_max, T voxel_width_x_rec,
189 T voxel_width_y_rec, int nr_voxel_x,
190 int nr_voxel_y) {
191 int i, j, k;
192 T x = xx;
193 T y = yy;
194 T z = zz;
195
196 // points that are outside the defined BBOX are ignored
197 if (x < bound_x_min || x > bound_x_max || y < bound_y_min ||
198 y > bound_y_max || z < bound_z_min || z > bound_z_max) {
199 return (-1);
200 }
201
202 // compute the x, y voxel indices
203 k = IMin(nr_voxel_x - 1,
204 static_cast<int>((x - bound_x_min) * voxel_width_x_rec));
205 j = IMin(nr_voxel_y - 1,
206 static_cast<int>((y - bound_y_min) * voxel_width_y_rec));
207 i = (nr_voxel_x * j) + k;
208 return (i);
209}
210
211template <typename T>
212class Voxel {
213 public:
214 Voxel() {}
216 Voxel(const Voxel<T> &voxel) {
217 dim_x_ = voxel.dim_x_;
218 dim_y_ = voxel.dim_y_;
219 dim_z_ = voxel.dim_z_;
220 ix_ = voxel.ix_;
221 iy_ = voxel.iy_;
222 iz_ = voxel.iz_;
223 ICopy3(voxel.v_, v_);
224 indices_.assign(voxel.indices_.begin(), voxel.indices_.end());
225 }
226
227 Voxel &operator=(const Voxel<T> &voxel) {
228 if (this != &voxel) {
229 this->dim_x_ = voxel.dim_x_;
230 this->dim_y_ = voxel.dim_y_;
231 this->dim_z_ = voxel.dim_z_;
232 this->ix_ = voxel.ix_;
233 this->iy_ = voxel.iy_;
234 this->iz_ = voxel.iz_;
235 ICopy3(voxel.v_, this->v_);
236 this->indices_.assign(voxel.indices_.begin(), voxel.indices_.end());
237 }
238 return (*this);
239 }
240
241 void Init(const T *v, T dim_x, T dim_y, T dim_z, int ix, int iy, int iz) {
242 ICopy3(v, v_);
243 dim_x_ = dim_x;
244 dim_y_ = dim_y;
245 dim_z_ = dim_z;
246 ix_ = ix;
247 iy_ = iy;
248 iz_ = iz;
249 indices_.clear();
250 }
251
252 void Init(T v_x, T v_y, T v_z, T dim_x, T dim_y, T dim_z, int ix, int iy,
253 int iz) {
254 v_[0] = v_x;
255 v_[1] = v_y;
256 v_[2] = v_z;
257 dim_x_ = dim_x;
258 dim_y_ = dim_y;
259 dim_z_ = dim_z;
260 ix_ = ix;
261 iy_ = iy;
262 iz_ = iz;
263 indices_.clear();
264 }
265
266 void Reset() {
267 IZero3(v_);
268 dim_x_ = dim_y_ = dim_z_ = 0;
269 ix_ = iy_ = iz_ = 0;
270 indices_.clear();
271 }
272
273 void Reserve(unsigned int size) { indices_.reserve(size); }
274
275 void PushBack(int id) { indices_.push_back(id); }
276
277 unsigned int Capacity() const { return (unsigned int)indices_.capacity(); }
278
279 unsigned int NrPoints() const { return (unsigned int)indices_.size(); }
280
281 bool Empty() const { return indices_.empty(); }
282
284
285 // voxel indices in the X, Y, Z dimensions - meaningful for voxel grid
286 int ix_, iy_, iz_;
287
288 // point indices
289 std::vector<int> indices_;
290};
291
292// -----Voxel Grid XY-----
293template <typename T>
295 // assuming at most 320000 points
296 static const unsigned int s_nr_max_reserved_points_ = 320000;
297
298 public:
300 VoxelGridXY(unsigned int nr_voxel_x, unsigned int nr_voxel_y,
301 T spatial_bound_x_min, T spatial_bound_x_max,
302 T spatial_bound_y_min, T spatial_bound_y_max,
303 T spatial_bound_z_min, T spatial_bound_z_max);
304
306 if (this != &vg) {
307 this->initialized_ = vg.Initialized();
308 this->nr_points_ = vg.NrPoints();
309 this->nr_point_element_ = vg.NrPointElement();
310 this->nr_voxel_x_ = vg.NrVoxelX();
311 this->nr_voxel_y_ = vg.NrVoxelY();
312 this->nr_voxel_z_ = vg.NrVoxelZ();
313 this->data_ = vg.const_data();
314 vg.GetGridDimension(&this->dim_x_[0], &this->dim_x_[1], &this->dim_y_[0],
315 &this->dim_y_[1], &this->dim_z_[0], &this->dim_z_[1]);
316 this->voxels_.resize(vg.NrVoxel());
317 for (unsigned int i = 0; i < vg.NrVoxel(); ++i) {
318 this->voxels_[i] = vg[i];
319 }
320
321 this->AllocAlignedMemory();
322 }
323 return (*this);
324 }
325
326 void CleanUp();
327
329 IFreeAligned<float>(&mem_aligned16_f32_);
330 IFreeAligned<int>(&mem_aligned16_i32_);
331 CleanUp();
332 }
333
334 bool Alloc(unsigned int nr_voxel_x, unsigned int nr_voxel_y,
335 T spatial_bound_x_min, T spatial_bound_x_max,
336 T spatial_bound_y_min, T spatial_bound_y_max,
337 T spatial_bound_z_min, T spatial_bound_z_max);
338
339 bool Set(const T *data, unsigned int nr_points,
340 unsigned int nr_point_element);
341
342 // sse2 version: only for float type input Data
343 bool SetS(const float *data, unsigned int nr_points,
344 unsigned int nr_point_element);
345
346 bool Set(const T *data, unsigned int nr_points, unsigned int nr_point_element,
347 unsigned int nr_voxel_x, unsigned int nr_voxel_y,
348 T spatial_bound_x_min, T spatial_bound_x_max, T spatial_bound_y_min,
349 T spatial_bound_y_max, T spatial_bound_z_min, T spatial_bound_z_max,
350 bool force_bound = true);
351
352 bool Initialized() const { return initialized_; }
353
354 unsigned int NrVoxel() const { return (unsigned int)voxels_.size(); }
355
356 unsigned int NrVoxelX() const { return nr_voxel_x_; }
357
358 unsigned int NrVoxelY() const { return nr_voxel_y_; }
359
360 unsigned int NrVoxelZ() const { return (1); }
361
362 unsigned int NrPoints() const { return nr_points_; }
363
364 unsigned int NrPointElement() const { return nr_point_element_; }
365
366 unsigned int NrIndexedPoints() const;
367
368 std::vector<Voxel<T>> &GetVoxels() { return voxels_; }
369
370 const std::vector<Voxel<T>> &GetConstVoxels() const { return voxels_; }
371
372 void SetVoxels(const std::vector<Voxel<T>> &voxels) {
373 voxels_.assign(voxels.begin(), voxels.end());
374 }
375
376 bool GetGridDimension(T *dim_min_x, T *dim_max_x, T *dim_min_y, T *dim_max_y,
377 T *dim_min_z, T *dim_max_z) const {
378 if (!initialized_) {
379 dim_min_x = dim_max_x = dim_min_y = dim_max_y = dim_min_z = dim_max_z =
380 static_cast<T>(0);
381 return (false);
382 }
383 *dim_min_x = dim_x_[0];
384 *dim_max_x = dim_x_[1];
385 *dim_min_y = dim_y_[0];
386 *dim_max_y = dim_y_[1];
387 *dim_min_z = dim_z_[0];
388 *dim_max_z = dim_z_[1];
389 return (true);
390 }
391
392 void SetGridDimension(T dim_min_x, T dim_max_x, T dim_min_y, T dim_max_y,
393 T dim_min_z, T dim_max_z) {
394 dim_x_[0] = dim_min_x;
395 dim_x_[1] = dim_max_x;
396 dim_y_[0] = dim_min_y;
397 dim_y_[1] = dim_max_y;
398 dim_z_[0] = dim_min_z;
399 dim_z_[1] = dim_max_z;
400 }
401
402 bool GetVoxelDimension(T *voxel_width_x, T *voxel_width_y,
403 T *voxel_width_z) const {
404 if (!initialized_) {
405 *voxel_width_x = *voxel_width_y = *voxel_width_z = static_cast<T>(0);
406 return (false);
407 }
408 *voxel_width_x = voxel_dim_[0];
409 *voxel_width_y = voxel_dim_[1];
410 *voxel_width_z = voxel_dim_[2];
411 return (true);
412 }
413
414 void SetVoxelDimension(T voxel_width_x, T voxel_width_y, T voxel_width_z) {
415 voxel_dim_[0] = voxel_width_x;
416 voxel_dim_[1] = voxel_width_y;
417 voxel_dim_[2] = voxel_width_z;
418 }
419
420 void SetNrPoints(unsigned int nr_points) { nr_points_ = nr_points; }
421
422 void SetNrPointElement(unsigned int nr_point_element) {
423 nr_point_element_ = nr_point_element;
424 }
425
426 void SetNrVoxel(unsigned int nr_voxel_x, unsigned int nr_voxel_y,
427 unsigned int nr_voxel_z) {
428 nr_voxel_x_ = nr_voxel_x;
429 nr_voxel_y_ = nr_voxel_y;
430 nr_voxel_z_ = nr_voxel_z;
431 }
432
433 void SetPointCloudsData(const T *data) { data_ = data; }
434
435 void SetInitialized(bool initialized) { initialized_ = initialized; }
436
437 // int GetAllIndices(std::vector<int> &indices) const;
438
439 int WhichVoxel(T x, T y, T z) const;
440
441 // add by Fangzhen Li on 03/27/17
442 bool GetVoxelCoordinateXY(T x, T y, int *row, int *col) const;
443
444 Voxel<T> &operator[](unsigned int i) {
445 assert(i >= 0 && i < voxels_.size());
446 return (voxels_[i]);
447 }
448
449 const Voxel<T> &operator[](unsigned int i) const {
450 assert(i >= 0 && i < voxels_.size());
451 return (voxels_[i]);
452 }
453
455 assert(i >= 0 && i < static_cast<int>(voxels_.size()));
456 return (voxels_[i]);
457 }
458 const Voxel<T> &operator[](int i) const {
459 assert(i >= 0 && i < static_cast<int>(voxels_.size()));
460 return (voxels_[i]);
461 }
462
463 Voxel<T> &operator()(unsigned int iy, unsigned int ix) {
464 assert(iy < nr_voxel_y_ && ix < nr_voxel_x_);
465 unsigned int i = nr_voxel_x_ * iy + ix;
466 assert(i < voxels_.size());
467 return (voxels_[i]);
468 }
469
470 const Voxel<T> &operator()(unsigned int iy, unsigned int ix) const {
471 assert(iy < nr_voxel_y_ && ix < nr_voxel_x_);
472 unsigned int i = nr_voxel_x_ * iy + ix;
473 assert(i < voxels_.size());
474 return (voxels_[i]);
475 }
476
477 T *Data() { return (data_); }
478
479 const T *const_data() const { return (data_); }
480
481 private:
482 void Reserve();
483 bool AllocAlignedMemory();
484
485 private:
486 unsigned int nr_points_ = 0;
487 unsigned int nr_point_element_ = 0;
488 unsigned int nr_voxel_x_ = 0;
489 unsigned int nr_voxel_y_ = 0;
490 unsigned int nr_voxel_z_ = 0;
491 const T *data_ = nullptr; // point clouds memory
492 bool initialized_ = false;
493 T dim_x_[2], dim_y_[2], dim_z_[2], voxel_dim_[3];
494 float *mem_aligned16_f32_ = nullptr;
495 int *mem_aligned16_i32_ = nullptr;
496 std::vector<Voxel<T>> voxels_;
497};
498
499template <typename T>
501 : nr_points_(0),
502 nr_point_element_(0),
503 nr_voxel_x_(0),
504 nr_voxel_y_(0),
505 nr_voxel_z_(1),
506 data_(nullptr),
507 initialized_(false),
508 mem_aligned16_f32_(nullptr),
509 mem_aligned16_i32_(nullptr) {
510 IZero2(dim_x_);
511 IZero2(dim_y_);
512 IZero2(dim_z_);
513 IZero3(voxel_dim_);
514 AllocAlignedMemory();
515}
516
517template <typename T>
519 initialized_ = false;
520 data_ = nullptr;
521 nr_points_ = nr_point_element_ = nr_voxel_x_ = nr_voxel_y_ = 0;
522 nr_voxel_z_ = 1;
523 IZero2(dim_x_);
524 IZero2(dim_y_);
525 IZero2(dim_z_);
526 IZero3(voxel_dim_);
527 voxels_.clear();
528}
529
530template <typename T>
531VoxelGridXY<T>::VoxelGridXY(unsigned int nr_voxel_x, unsigned int nr_voxel_y,
532 T spatial_bound_x_min, T spatial_bound_x_max,
533 T spatial_bound_y_min, T spatial_bound_y_max,
534 T spatial_bound_z_min, T spatial_bound_z_max) {
535 Alloc(nr_voxel_x, nr_voxel_y, spatial_bound_x_min, spatial_bound_x_max,
536 spatial_bound_y_min, spatial_bound_y_max, spatial_bound_z_min,
537 spatial_bound_z_max);
538 AllocAlignedMemory();
539 initialized_ = false;
540}
541
542template <typename T>
544 int r, c, i = 0, m = 0;
545 unsigned int n = (nr_voxel_x_ * nr_voxel_y_);
546
547 if (n == 0 || voxels_.size() != n) {
548 return;
549 }
550
551 double cen_x = (static_cast<double>(nr_voxel_x_ - 1)) * 0.5;
552 double cen_y = (static_cast<double>(nr_voxel_y_ - 1)) * 0.5;
553
554 // normalization factor = 1/(2sigma*sigma)
555 // hardcode sigma 10.0
556 double sigma = static_cast<double>(IAverage(nr_voxel_x_, nr_voxel_y_) / 10.0);
557 double nf = IDiv(0.5, (sigma * sigma));
558 double dr, drsqr, dc, dcsqr, v, ksum = 0.0;
559 std::vector<double> kernel(n, 0.0);
560
561 // pre-compute kernel
562 for (r = 0; r < static_cast<int>(nr_voxel_y_); ++r) {
563 dr = static_cast<double>(r) - cen_y;
564 drsqr = ISqr(dr);
565 for (c = 0; c < static_cast<int>(nr_voxel_x_); ++c) {
566 dc = static_cast<double>(c) - cen_x;
567 dcsqr = ISqr(dc);
568 v = IExp(-(drsqr + dcsqr) * nf);
569 ksum += v;
570 kernel[i++] = v;
571 }
572 }
573
574 // normalize the kernel, sum to 1.0
575 v = IRec(ksum);
576 for (i = 0; i < static_cast<int>(n); ++i) {
577 kernel[i] *= v;
578 }
579
580 // Alloc at least 8 positions
581 for (i = 0; i < static_cast<int>(n); ++i) {
582 m = IMax(8, static_cast<int>(s_nr_max_reserved_points_ * kernel[i]));
583 voxels_[i].Reserve(m);
584 }
585}
586
587template <typename T>
588bool VoxelGridXY<T>::AllocAlignedMemory() {
589 if (!mem_aligned16_f32_) {
590 mem_aligned16_f32_ = IAllocAligned<float>(4, 4);
591 }
592 if (!mem_aligned16_i32_) {
593 mem_aligned16_i32_ = IAllocAligned<int>(4, 4);
594 }
595 return (mem_aligned16_f32_ != nullptr && mem_aligned16_i32_ != nullptr &&
596 IVerifyAlignment(mem_aligned16_f32_, 4) &&
597 IVerifyAlignment(mem_aligned16_i32_, 4));
598}
599
600template <typename T>
601int VoxelGridXY<T>::WhichVoxel(T x, T y, T z) const {
602 int j, k;
603 if (!initialized_) {
604 return (-1);
605 }
606
607 if (x < dim_x_[0] || x > dim_x_[1] || y < dim_y_[0] || y > dim_y_[1] ||
608 z < dim_z_[0] || z > dim_z_[1]) {
609 return (-1); // points that are outside the defined BBOX are ignored
610 }
611
612 k = static_cast<int>(IMax(
613 (unsigned int)0,
614 IMin(nr_voxel_x_ - 1, (unsigned int)((x - dim_x_[0]) / voxel_dim_[0]))));
615 j = static_cast<int>(IMax(
616 (unsigned int)0,
617 IMin(nr_voxel_y_ - 1, (unsigned int)((y - dim_y_[0]) / voxel_dim_[1]))));
618 return (nr_voxel_x_ * j + k);
619}
620
621// add by Fangzhen Li on 03/27/17
622template <typename T>
623bool VoxelGridXY<T>::GetVoxelCoordinateXY(T x, T y, int *row, int *col) const {
624 if (x < dim_x_[0] || x > dim_x_[1] || y < dim_y_[0] || y > dim_y_[1]) {
625 return false; // points that are outside the defined BBOX are ignored
626 }
627
628 *col = static_cast<int>((x - dim_x_[0]) / voxel_dim_[0]);
629 *row = static_cast<int>((y - dim_y_[0]) / voxel_dim_[1]);
630 return true;
631}
632
633template <typename T>
634bool VoxelGridXY<T>::Alloc(unsigned int nr_voxel_x, unsigned int nr_voxel_y,
635 T spatial_bound_x_min, T spatial_bound_x_max,
636 T spatial_bound_y_min, T spatial_bound_y_max,
637 T spatial_bound_z_min, T spatial_bound_z_max) {
638 if (!nr_voxel_x || !nr_voxel_y) {
639 initialized_ = false;
640 return initialized_;
641 }
642 nr_voxel_x_ = nr_voxel_x;
643 nr_voxel_y_ = nr_voxel_y;
644
645 unsigned int i, j, k, n = 0;
646 unsigned int nr_voxel_xy = (nr_voxel_x_ * nr_voxel_y_);
647 unsigned int nr_voxel = nr_voxel_xy;
648
649 T vx, vy, vz, voxel_width_x, voxel_width_y, voxel_width_z;
650
651 voxels_.clear();
652 voxels_.resize(nr_voxel);
653
654 // voxel grid dimesion is forced to be the manual input
655 dim_x_[0] = spatial_bound_x_min;
656 dim_x_[1] = spatial_bound_x_max;
657
658 dim_y_[0] = spatial_bound_y_min;
659 dim_y_[1] = spatial_bound_y_max;
660
661 dim_z_[0] = spatial_bound_z_min;
662 dim_z_[1] = spatial_bound_z_max;
663
664 T span_x = (dim_x_[1] - dim_x_[0]);
665 T span_y = (dim_y_[1] - dim_y_[0]);
666 T span_z = (dim_z_[1] - dim_z_[0]);
667
668 assert(span_x > 0 && span_y > 0 && span_z > 0);
669
670 voxel_dim_[0] = voxel_width_x = IDiv(span_x, static_cast<int>(nr_voxel_x_));
671 voxel_dim_[1] = voxel_width_y = IDiv(span_y, static_cast<int>(nr_voxel_y_));
672 voxel_dim_[2] = voxel_width_z = span_z;
673
674 std::vector<T> vxs(nr_voxel_x_);
675
676 vxs[0] = dim_x_[0];
677 for (i = 1; i < nr_voxel_x_; i++) {
678 vxs[i] = vxs[i - 1] + voxel_width_x;
679 }
680
681 vy = dim_y_[0];
682 vz = dim_z_[0];
683
684 for (j = 0; j < nr_voxel_y_; j++) {
685 for (k = 0; k < nr_voxel_x_; k++) {
686 vx = vxs[k];
687 voxels_[n++].Init(vx, vy, vz, voxel_width_x, voxel_width_y, voxel_width_z,
688 static_cast<int>(k), static_cast<int>(j), 0);
689 }
690 vy += voxel_width_y;
691 }
692
693 // pre-Alloc capacaity for indices_ vector - speed-up the code slightly
694 Reserve();
695 return (true);
696}
697
698template <typename T>
699bool VoxelGridXY<T>::Set(const T *data, unsigned int nr_points,
700 unsigned int nr_point_element) {
701 if (!data || !nr_points || !nr_point_element || !nr_voxel_x_ ||
702 !nr_voxel_y_ || nr_voxel_z_ != 1) {
703 initialized_ = false;
704 return initialized_;
705 }
706
707 data_ = data;
708 nr_points_ = nr_points;
709 nr_point_element_ = nr_point_element;
710
711 unsigned int nr_voxel = (nr_voxel_x_ * nr_voxel_y_);
712 unsigned int i, nd = 0;
713 int id, n = 0;
714
715 T voxel_width_x_rec = IRec(voxel_dim_[0]);
716 T voxel_width_y_rec = IRec(voxel_dim_[1]);
717
718 T bound_x_min = dim_x_[0];
719 T bound_x_max = dim_x_[1];
720 T bound_y_min = dim_y_[0];
721 T bound_y_max = dim_y_[1];
722 T bound_z_min = dim_z_[0];
723 T bound_z_max = dim_z_[1];
724
725 // clear the old index buffer
726 for (i = 0; i < nr_voxel; ++i) {
727 voxels_[i].indices_.clear();
728 }
729
730 // Assign point indices
731 for (; n < static_cast<int>(nr_points_); n++, nd += nr_point_element_) {
733 data_ + nd, bound_x_min, bound_x_max, bound_y_min, bound_y_max,
734 bound_z_min, bound_z_max, voxel_width_x_rec, voxel_width_y_rec,
735 static_cast<int>(nr_voxel_x_), static_cast<int>(nr_voxel_y_));
736
737 if (id >= 0) {
738 voxels_[id].indices_.push_back(n);
739 }
740 }
741
742 initialized_ = true;
743 return (initialized_);
744}
745
746template <typename T>
747bool VoxelGridXY<T>::SetS(const float *data, unsigned int nr_points,
748 unsigned int nr_point_element) {
749 if (!data || !nr_points || !nr_point_element || !nr_voxel_x_ ||
750 !nr_voxel_y_ || nr_voxel_z_ != 1) {
751 initialized_ = false;
752 return initialized_;
753 }
754
755 data_ = data;
756 nr_points_ = nr_points;
757 nr_point_element_ = nr_point_element;
758
759 unsigned int nr_voxel = (nr_voxel_x_ * nr_voxel_y_);
760 unsigned int i, n = 0;
761 int id;
762
763 float voxel_width_x_rec = IRec(static_cast<float>(voxel_dim_[0]));
764 float voxel_width_y_rec = IRec(static_cast<float>(voxel_dim_[1]));
765
766 __m128i iv_nr_voxel_x = _mm_setr_epi32(static_cast<int>(nr_voxel_x_), 0,
767 static_cast<int>(nr_voxel_x_), 0);
768 __m128i iv_nr_voxel_x_m1 = _mm_set1_epi32(static_cast<int>(nr_voxel_x_ - 1));
769 __m128i iv_nr_voxel_y_m1 = _mm_set1_epi32(static_cast<int>(nr_voxel_y_ - 1));
770
771 __m128 v_width_x_rec = _mm_set_ps1(voxel_width_x_rec);
772 __m128 v_width_y_rec = _mm_set_ps1(voxel_width_y_rec);
773
774 __m128 v_x_min = _mm_set_ps1(dim_x_[0]);
775 __m128 v_x_max = _mm_set_ps1(dim_x_[1]);
776 __m128 v_y_min = _mm_set_ps1(dim_y_[0]);
777 __m128 v_y_max = _mm_set_ps1(dim_y_[1]);
778 __m128 v_z_min = _mm_set_ps1(dim_z_[0]);
779 __m128 v_z_max = _mm_set_ps1(dim_z_[1]);
780
781 __m128 v_cmp_x, v_cmp_y, v_cmp_z, v_in_roi;
782 v_in_roi = _mm_setr_ps(1.0, 1.0, 1.0, 1.0);
783
784 __m128 v_xs, v_ys, v_zs;
785 __m128i iv_indices, iv_x_indices, iv_y_indices, iv_v_indices_02,
786 iv_v_indices_13;
787
788 for (i = 0; i < nr_voxel; ++i) {
789 voxels_[i].indices_.clear();
790 }
791
792 unsigned int nr_loops = (nr_points >> 2);
793 unsigned int nr_fast_processed = (nr_loops << 2);
794 unsigned int remainder = nr_points - nr_fast_processed;
795
796 unsigned int d1 = nr_point_element;
797 unsigned int d2 = (nr_point_element << 1);
798 unsigned int d3 = d1 + d2;
799 unsigned int d4 = (nr_point_element << 2);
800
801 // xyz are required to be stored in continuous memory
802 const float *cptr_x = data;
803 const float *cptr_y = data + 1;
804 const float *cptr_z = data + 2;
805 const float *cptr_remainder = data + (nr_fast_processed * nr_point_element);
806
807 for (i = 0; i < nr_loops; ++i, n += 4) {
808 // Set memory
809 v_xs = _mm_setr_ps(cptr_x[0], cptr_x[d1], cptr_x[d2], cptr_x[d3]);
810 v_ys = _mm_setr_ps(cptr_y[0], cptr_y[d1], cptr_y[d2], cptr_y[d3]);
811 v_zs = _mm_setr_ps(cptr_z[0], cptr_z[d1], cptr_z[d2], cptr_z[d3]);
812
813 // compare range:
814 v_cmp_x =
815 _mm_and_ps(_mm_cmpge_ps(v_xs, v_x_min), _mm_cmple_ps(v_xs, v_x_max));
816 v_cmp_y =
817 _mm_and_ps(_mm_cmpge_ps(v_ys, v_y_min), _mm_cmple_ps(v_ys, v_y_max));
818 v_cmp_z =
819 _mm_and_ps(_mm_cmpge_ps(v_zs, v_z_min), _mm_cmple_ps(v_zs, v_z_max));
820 v_in_roi = _mm_and_ps(_mm_and_ps(v_cmp_x, v_cmp_y), v_cmp_z);
821
822 // vector operations, cast into signed integers
823 v_xs = _mm_sub_ps(v_xs, v_x_min);
824 v_xs = _mm_mul_ps(v_xs, v_width_x_rec);
825 iv_x_indices = _mm_cvttps_epi32(v_xs); // truncate towards zero
826 iv_x_indices = _mm_min_epi32(iv_nr_voxel_x_m1, iv_x_indices);
827
828 // vector operations, cast into signed integers
829 v_ys = _mm_sub_ps(v_ys, v_y_min);
830 v_ys = _mm_mul_ps(v_ys, v_width_y_rec);
831 iv_y_indices = _mm_cvttps_epi32(v_ys); // truncate towards zero
832 iv_y_indices = _mm_min_epi32(iv_nr_voxel_y_m1, iv_y_indices);
833
834 iv_v_indices_02 = _mm_mullo_epi32(iv_y_indices, iv_nr_voxel_x);
835 iv_y_indices = _mm_shuffle_epi32(iv_y_indices, _MM_SHUFFLE(2, 3, 0, 1));
836
837 iv_v_indices_13 = _mm_mullo_epi32(iv_y_indices, iv_nr_voxel_x);
838 iv_v_indices_13 =
839 _mm_shuffle_epi32(iv_v_indices_13, _MM_SHUFFLE(2, 3, 0, 1));
840
841 iv_indices = _mm_add_epi32(iv_v_indices_02, iv_v_indices_13);
842 iv_indices = _mm_add_epi32(iv_indices, iv_x_indices);
843
844 // store values from registers to memory
845 // address 16byte-aligned
846 _mm_store_ps(mem_aligned16_f32_, v_in_roi);
847 // address 16byte-aligned
848 _mm_store_si128(reinterpret_cast<__m128i *>(mem_aligned16_i32_),
849 iv_indices);
850
851 if (mem_aligned16_f32_[0] != 0) {
852 voxels_[mem_aligned16_i32_[0]].indices_.push_back(n);
853 }
854 if (mem_aligned16_f32_[1] != 0) {
855 voxels_[mem_aligned16_i32_[1]].indices_.push_back(n + 1);
856 }
857 if (mem_aligned16_f32_[2] != 0) {
858 voxels_[mem_aligned16_i32_[2]].indices_.push_back(n + 2);
859 }
860 if (mem_aligned16_f32_[3] != 0) {
861 voxels_[mem_aligned16_i32_[3]].indices_.push_back(n + 3);
862 }
863 cptr_x += d4;
864 cptr_y += d4;
865 cptr_z += d4;
866 }
867
868 // handling remaining points
869 for (i = 0; i < remainder; i++, n++) {
870 id = IAssignPointToVoxel(cptr_remainder, dim_x_[0], dim_x_[1], dim_y_[0],
871 dim_y_[1], dim_z_[0], dim_z_[1], voxel_width_x_rec,
872 voxel_width_y_rec, static_cast<int>(nr_voxel_x_),
873 static_cast<int>(nr_voxel_y_));
874
875 if (id >= 0) {
876 voxels_[id].indices_.push_back(n);
877 }
878
879 cptr_remainder += nr_point_element;
880 }
881
882 // for (i = 0; i < nr_voxel; ++i) {
883 // voxels_[i].indices_.clear();
884 // }
885 // for (i = 0; i < nr_points; i++, n++) {
886 // float x = data_[nr_point_element_ * i];
887 // float y = data_[nr_point_element_ * i + 1];
888 // float z = data_[nr_point_element_ * i + 2];
889 // id = AssignPointToVoxel(x, y, z, dim_x_[0], dim_x_[1], dim_y_[0], dim_y_[1], dim_z_[0], dim_z_[1],
890 // voxel_width_x_rec, voxel_width_y_rec, static_cast<int>(nr_voxel_x_), static_cast<int>(nr_voxel_y_));
891
892 // if (id >= 0) {
893 // voxels_[id].indices_.push_back(i);
894 // }
895 // }
896
897 initialized_ = true;
898 return (initialized_);
899}
900
901template <typename T>
902bool VoxelGridXY<T>::Set(const T *data, unsigned int nr_points,
903 unsigned int nr_point_element, unsigned int nr_voxel_x,
904 unsigned int nr_voxel_y, T spatial_bound_x_min,
905 T spatial_bound_x_max, T spatial_bound_y_min,
906 T spatial_bound_y_max, T spatial_bound_z_min,
907 T spatial_bound_z_max, bool force_bound) {
908 if (!data || !nr_points || !nr_point_element || !nr_voxel_x || !nr_voxel_y) {
909 initialized_ = false;
910 return initialized_;
911 }
912
913 data_ = data;
914 nr_points_ = nr_points;
915 nr_point_element_ = nr_point_element;
916 nr_voxel_x_ = nr_voxel_x;
917 nr_voxel_y_ = nr_voxel_y;
918 nr_voxel_z_ = 1;
919
920 unsigned int i, j, k, n = 0, nd = 0;
921 unsigned int nr_voxel_xy = (nr_voxel_x_ * nr_voxel_y_);
922 unsigned int nr_voxel = nr_voxel_xy;
923 unsigned int nr_voxel_xm1 = nr_voxel_x - 1;
924 unsigned int nr_voxel_ym1 = nr_voxel_y - 1;
925 T vx, vy, vz, x, y, z;
926 T voxel_width_x, voxel_width_y, voxel_width_z;
927
928 voxels_.clear();
929 voxels_.resize(nr_voxel);
930
931 // if force_bound then the voxel grid dimesion is forced to be the manual
932 // * input
933 if (force_bound) {
934 dim_x_[0] = spatial_bound_x_min;
935 dim_x_[1] = spatial_bound_x_max;
936
937 dim_y_[0] = spatial_bound_y_min;
938 dim_y_[1] = spatial_bound_y_max;
939
940 dim_z_[0] = spatial_bound_z_min;
941 dim_z_[1] = spatial_bound_z_max;
942 } else {
944 data_, nr_points_, 0, nr_point_element_, &dim_x_[0], &dim_x_[1],
945 &dim_y_[0], &dim_y_[1], &dim_z_[0], &dim_z_[1], spatial_bound_x_min,
946 spatial_bound_x_max, spatial_bound_y_min, spatial_bound_y_max,
947 spatial_bound_z_min, spatial_bound_z_max);
948 }
949
950 T dim_x_min = dim_x_[0];
951 T dim_x_max = dim_x_[1];
952
953 T dim_y_min = dim_y_[0];
954 T dim_y_max = dim_y_[1];
955
956 T dim_z_min = dim_z_[0];
957 T dim_z_max = dim_z_[1];
958
959 T span_x = (dim_x_max - dim_x_min);
960 T span_y = (dim_y_max - dim_y_min);
961 T span_z = (dim_z_max - dim_z_min);
962
963 assert(span_x > 0 && span_y > 0 && span_z > 0);
964
965 voxel_dim_[0] = voxel_width_x = IDiv(span_x, static_cast<int>(nr_voxel_x_));
966 voxel_dim_[1] = voxel_width_y = IDiv(span_y, static_cast<int>(nr_voxel_y_));
967 voxel_dim_[2] = voxel_width_z = span_z;
968
969 T voxel_width_x_rec = IRec(voxel_dim_[0]);
970 T voxel_width_y_rec = IRec(voxel_dim_[1]);
971
972 std::vector<T> vxs(nr_voxel_x_);
973 vxs[0] = dim_x_[0];
974
975 for (i = 1; i < nr_voxel_x_; i++) {
976 vxs[i] = vxs[i - 1] + voxel_width_x;
977 }
978
979 vy = dim_y_[0];
980 vz = dim_z_[0];
981
982 for (j = 0; j < nr_voxel_y_; j++) {
983 for (k = 0; k < nr_voxel_x_; k++) {
984 vx = vxs[k];
985 voxels_[n++].init(vx, vy, vz, voxel_width_x, voxel_width_y, voxel_width_z,
986 static_cast<int>(k), static_cast<int>(j), 0);
987 }
988 vy += voxel_width_y;
989 }
990
991 // Assign point indices
992 for (; n < nr_points_; n++, nd += nr_point_element_) {
993 x = data_[nd];
994 y = data_[nd + 1];
995 z = data_[nd + 2];
996
997 if (x < dim_x_min || x > dim_x_max || y < dim_y_min || y > dim_y_max ||
998 z < dim_z_min || z > dim_z_max) {
999 // points that are outside the defined BBOX are ignored
1000 continue;
1001 }
1002
1003 k = IMax((unsigned int)0,
1004 IMin(nr_voxel_xm1,
1005 (unsigned int)((x - dim_x_min) * voxel_width_x_rec)));
1006 j = IMax((unsigned int)0,
1007 IMin(nr_voxel_ym1,
1008 (unsigned int)((y - dim_y_min) * voxel_width_y_rec)));
1009 i = nr_voxel_x * j + k;
1010
1011 assert(i < nr_voxel);
1012 voxels_[i].indices_.push_back(n);
1013 }
1014 initialized_ = true;
1015 return initialized_;
1016}
1017
1018// template <typename T>
1019// int VoxelGridXY<T>::GetAllIndices(std::vector<int> &indices) const {
1020// unsigned int i, j;
1021// indices.clear();
1022
1023// if (!initialized_) {
1024// return -1;
1025// }
1026// for (i = 0; i < voxels_.size(); ++i) {
1027// for (j = 0; j < voxels_[i].indices_.size(); ++j) {
1028// indices.push_back(voxels_[i].indices_.at(j));
1029// }
1030// }
1031
1032// return static_cast<int> (indices.size());
1033// }
1034
1035template <typename T>
1037 if (!initialized_) {
1038 return 0;
1039 }
1040 unsigned int i, n = 0;
1041 for (i = 0; i < voxels_.size(); ++i) {
1042 n += voxels_[i].indices_.size();
1043 }
1044 return n;
1045}
1046
1047template <typename T>
1048static void IPushBackVectors(const std::vector<T> &src, std::vector<T> *dst) {
1049 unsigned int i = src.size();
1050 unsigned int j = dst->size();
1051
1052 if (i == 0) {
1053 return;
1054 } else if (j == 0) {
1055 dst->assign(src.begin(), src.end());
1056 } else {
1057 dst->resize(i + j);
1058 ICopy(src.data(), dst->data() + j, static_cast<int>(i));
1059 }
1060}
1061
1062// VoxelgridXY downsample functions
1063template <typename T>
1065 unsigned int dsf_dim_x, unsigned int dsf_dim_y) {
1066 if (!src.Initialized()) {
1067 return (false);
1068 } else if (dsf_dim_x == 0 && dsf_dim_y == 0) {
1069 *dst = src;
1070 return (true);
1071 } else {
1072 if (&src == dst) {
1073 return (false); // not allowed to downsample a voxel grid from itself
1074 }
1075 }
1076
1077 dst->CleanUp(); // perform CleanUp first
1078
1079 // # of voxels of the src voxel grid
1080 unsigned int nr_voxel_x_src = src.NrVoxelX();
1081 unsigned int nr_voxel_y_src = src.NrVoxelY();
1082 unsigned int nr_voxel_z_src = src.NrVoxelZ();
1083
1084 assert(nr_voxel_z_src == 1);
1085
1086 // scale factors
1087 unsigned int sf_x = (unsigned int)IPow((unsigned int)2, dsf_dim_x);
1088 unsigned int sf_y = (unsigned int)IPow((unsigned int)2, dsf_dim_y);
1089
1090 // compute the # of voxels for the new scale
1091 unsigned int nr_voxel_x_dst = nr_voxel_x_src / sf_x;
1092 unsigned int nr_voxel_y_dst = nr_voxel_y_src / sf_y;
1093 unsigned int nr_voxel_z_dst = nr_voxel_z_src;
1094
1095 if (!nr_voxel_x_dst || !nr_voxel_y_dst || !nr_voxel_z_dst) {
1096 return (false); // do not continue
1097 }
1098
1099 unsigned int nr_res_voxel_x_dst = (nr_voxel_x_src % sf_x);
1100 unsigned int nr_res_voxel_y_dst = (nr_voxel_y_src % sf_y);
1101
1102 T voxel_width_x_src = 0;
1103 T voxel_width_y_src = 0;
1104 T voxel_width_z_src = 0;
1105 T dim_min_x_src = 0;
1106 T dim_max_x_src = 0;
1107 T dim_min_y_src = 0;
1108 T dim_max_y_src = 0;
1109 T dim_min_z_src = 0;
1110 T dim_max_z_src = 0;
1111
1112 // the dimension of the voxels in the src voxel grid
1113 src.GetVoxelDimension(&voxel_width_x_src, &voxel_width_y_src,
1114 &voxel_width_z_src);
1115
1116 src.GetGridDimension(&dim_min_x_src, &dim_max_x_src, &dim_min_y_src,
1117 &dim_max_y_src, &dim_min_z_src, &dim_max_z_src);
1118
1119 // new voxel dimensions after downsampling the 3D grid
1120 T voxel_width_x_dst = (sf_x * voxel_width_x_src);
1121 T voxel_width_y_dst = (sf_y * voxel_width_y_src);
1122 T voxel_width_z_dst = voxel_width_z_src;
1123
1124 // new grid dimensions after downsampling the 3D grid
1125 T dim_x_dst[2], dim_y_dst[2], dim_z_dst[2];
1126
1127 dim_x_dst[0] = dim_min_x_src;
1128 dim_y_dst[0] = dim_min_y_src;
1129 dim_z_dst[0] = dim_min_z_src;
1130
1131 dim_x_dst[1] = (0 == nr_res_voxel_x_dst)
1132 ? dim_max_x_src
1133 : (voxel_width_x_dst * nr_voxel_x_dst + dim_x_dst[0]);
1134 dim_y_dst[1] = (0 == nr_res_voxel_y_dst)
1135 ? dim_max_y_src
1136 : (voxel_width_y_dst * nr_voxel_y_dst + dim_y_dst[0]);
1137 dim_z_dst[1] = dim_max_z_src;
1138
1139 // Set dst
1140 dst->SetNrPoints(src.NrPoints());
1142 dst->SetVoxelDimension(voxel_width_x_dst, voxel_width_y_dst,
1143 voxel_width_z_dst);
1144 dst->SetGridDimension(dim_x_dst[0], dim_x_dst[1], dim_y_dst[0], dim_y_dst[1],
1145 dim_z_dst[0], dim_z_dst[1]);
1146 dst->SetNrVoxel(nr_voxel_x_dst, nr_voxel_y_dst, nr_voxel_z_dst);
1147 dst->SetPointCloudsData(src.const_data());
1148
1149 unsigned int i, j, r, c, rs, cs, rspi, n = 0;
1150
1151 T vy, vz = dim_z_dst[0];
1152 std::vector<T> vxs(nr_voxel_x_dst);
1153
1154 vxs[0] = dim_x_dst[0];
1155
1156 for (i = 1; i < nr_voxel_x_dst; i++) {
1157 vxs[i] = vxs[i - 1] + voxel_width_x_dst;
1158 }
1159
1160 std::vector<Voxel<T>> voxels(nr_voxel_y_dst * nr_voxel_x_dst);
1161
1162 for (r = 0; r < nr_voxel_y_dst; r++) {
1163 rs = (r * sf_y);
1164 vy = dim_y_dst[0] + (r * voxel_width_y_dst);
1165
1166 for (c = 0; c < nr_voxel_x_dst; c++) {
1167 cs = (c * sf_x);
1168 voxels[n].init(vxs[c], vy, vz, voxel_width_x_dst, voxel_width_y_dst,
1169 voxel_width_z_dst, static_cast<int>(c),
1170 static_cast<int>(r), static_cast<int>(0));
1171 // collect samples from its lower scale:
1172 for (i = 0; i < sf_y; ++i) {
1173 rspi = rs + i;
1174 for (j = 0; j < sf_x; ++j) {
1175 IPushBackVectors(src(rspi, cs + j).indices_, &voxels[n].indices_);
1176 }
1177 }
1178 // increase voxel index by 1
1179 n++;
1180 }
1181 }
1182 dst->SetVoxels(voxels);
1183 dst->SetInitialized(true);
1184 return (true);
1185}
1186
1187// -----Multiscale Voxel Grid Pyramid-----
1188template <typename DATA_TYPE>
1190 public:
1192 VoxelGridXYPyramid(unsigned int nr_scale, unsigned int nr_voxel_x_base,
1193 unsigned int nr_voxel_y_base, unsigned int dsf_x,
1194 unsigned int dsf_y, DATA_TYPE spatial_bound_x_min,
1195 DATA_TYPE spatial_bound_x_max,
1196 DATA_TYPE spatial_bound_y_min,
1197 DATA_TYPE spatial_bound_y_max,
1198 DATA_TYPE spatial_bound_z_min,
1199 DATA_TYPE spatial_bound_z_max) {
1200 Alloc(nr_scale, nr_voxel_x_base, nr_voxel_y_base, dsf_x, dsf_y,
1201 spatial_bound_x_min, spatial_bound_x_max, spatial_bound_y_min,
1202 spatial_bound_y_max, spatial_bound_z_min, spatial_bound_z_max);
1203 }
1204
1205 void CleanUp();
1206
1208
1209 bool Alloc(unsigned int nr_scale, unsigned int nr_voxel_x_base,
1210 unsigned int nr_voxel_y_base, unsigned int dsf_x,
1211 unsigned int dsf_y, DATA_TYPE spatial_bound_x_min,
1212 DATA_TYPE spatial_bound_x_max, DATA_TYPE spatial_bound_y_min,
1213 DATA_TYPE spatial_bound_y_max, DATA_TYPE spatial_bound_z_min,
1214 DATA_TYPE spatial_bound_z_max);
1215
1216 // non-sse2 version
1217 bool Set(const DATA_TYPE *pc, unsigned int nr_points,
1218 unsigned int nr_point_element);
1219
1220 // the sse2 version - speed up the voxel grid construction, for float type
1221 // * points only
1222 bool SetS(const float *pc, unsigned int nr_points,
1223 unsigned int nr_point_element);
1224
1225 bool Set(const DATA_TYPE *pc, unsigned int nr_scale, unsigned int nr_points,
1226 unsigned int nr_point_element, unsigned int nr_voxel_x_base,
1227 unsigned int nr_voxel_y_base, unsigned int dsf_x, unsigned int dsf_y,
1228 DATA_TYPE spatial_bound_x_min, DATA_TYPE spatial_bound_x_max,
1229 DATA_TYPE spatial_bound_y_min, DATA_TYPE spatial_bound_y_max,
1230 DATA_TYPE spatial_bound_z_min, DATA_TYPE spatial_bound_z_max);
1231
1232 unsigned int NrScale() const { return (unsigned int)vgrids_.size(); }
1233
1234 unsigned int NrVoxel(unsigned int i = 0) const {
1235 return (i < vgrids_.size()) ? vgrids_[i].nr_voxel() : 0;
1236 }
1237
1238 unsigned int NrVoxelX(unsigned int i = 0) const {
1239 return (i < vgrids_.size()) ? vgrids_[i].nr_voxel_x() : 0;
1240 }
1241
1242 unsigned int NrVoxelY(unsigned int i = 0) const {
1243 return (i < vgrids_.size()) ? vgrids_[i].nr_voxel_y() : 0;
1244 }
1245
1246 unsigned int NrVoxelZ(unsigned int i = 0) const {
1247 return (i < vgrids_.size()) ? vgrids_[i].nr_voxel_z() : 0;
1248 }
1249
1250 unsigned int NrPoints(unsigned int scale) const {
1251 return (scale < vgrids_.size()) ? vgrids_[scale].nr_points() : 0;
1252 }
1253
1254 unsigned int NrPoints() const { return nr_points_; }
1255
1256 unsigned int NrPointElement() const { return nr_point_element_; }
1257
1258 bool Initialized() const;
1259
1260 unsigned int GetDsfX() const { return dsf_x_; }
1261 unsigned int GetDsfY() const { return dsf_y_; }
1262 unsigned int GetDsfZ() const { return (0); }
1263
1265 assert(i >= 0 && i < vgrids_.size());
1266 return vgrids_[i];
1267 }
1268
1269 const VoxelGridXY<DATA_TYPE> &operator[](unsigned int i) const {
1270 assert(i >= 0 && i < vgrids_.size());
1271 return vgrids_[i];
1272 }
1273
1275 assert(i >= 0 && i < static_cast<int>(vgrids_.size()));
1276 return vgrids_[i];
1277 }
1278
1280 assert(i >= 0 && i < static_cast<int>(vgrids_.size()));
1281 return vgrids_[i];
1282 }
1283
1284 const DATA_TYPE *ConstData() const { return pc_; }
1285
1286 DATA_TYPE *Data() { return pc_; }
1287
1288 private:
1289 unsigned int nr_points_, nr_point_element_;
1290 unsigned int dsf_x_, dsf_y_, dsf_z_;
1291 const DATA_TYPE *pc_;
1292 std::vector<VoxelGridXY<DATA_TYPE>> vgrids_;
1293};
1294
1295template <typename DATA_TYPE>
1297 : pc_(nullptr),
1298 nr_points_(0),
1299 nr_point_element_(0),
1300 dsf_x_(0),
1301 dsf_y_(0),
1302 dsf_z_(0) {}
1303
1304template <typename DATA_TYPE>
1306 unsigned int nr_scale, unsigned int nr_voxel_x_base,
1307 unsigned int nr_voxel_y_base, unsigned int dsf_x, unsigned int dsf_y,
1308 DATA_TYPE spatial_bound_x_min, DATA_TYPE spatial_bound_x_max,
1309 DATA_TYPE spatial_bound_y_min, DATA_TYPE spatial_bound_y_max,
1310 DATA_TYPE spatial_bound_z_min, DATA_TYPE spatial_bound_z_max) {
1311 if (!nr_scale || !nr_voxel_x_base || !nr_voxel_y_base) {
1312 return false;
1313 }
1314
1315 unsigned int scale;
1316 unsigned int nr_voxel_x = nr_voxel_x_base;
1317 unsigned int nr_voxel_y = nr_voxel_y_base;
1318 unsigned int sf_x = (unsigned int)IPow((unsigned int)2, dsf_x);
1319 unsigned int sf_y = (unsigned int)IPow((unsigned int)2, dsf_y);
1320
1321 dsf_x_ = dsf_x;
1322 dsf_y_ = dsf_y;
1323 dsf_z_ = 0;
1324
1325 vgrids_.clear();
1326 vgrids_.resize(nr_scale);
1327
1328 for (scale = 0; scale < nr_scale; ++scale) {
1329 if (!vgrids_[scale].alloc(nr_voxel_x, nr_voxel_y, spatial_bound_x_min,
1330 spatial_bound_x_max, spatial_bound_y_min,
1331 spatial_bound_y_max, spatial_bound_z_min,
1332 spatial_bound_z_max)) {
1333 break;
1334 }
1335 nr_voxel_x /= sf_x;
1336 nr_voxel_y /= sf_y;
1337 }
1338
1339 if (scale == 0) {
1340 vgrids_.clear();
1341 return false;
1342 } else {
1343 if (scale != nr_scale) {
1344 vgrids_.resize(scale);
1345 }
1346 }
1347
1348 return (true);
1349}
1350
1351template <typename DATA_TYPE>
1352bool VoxelGridXYPyramid<DATA_TYPE>::Set(const DATA_TYPE *pc,
1353 unsigned int nr_points,
1354 unsigned int nr_point_element) {
1355 if (!pc || !nr_points || !nr_point_element || vgrids_.empty()) {
1356 return false;
1357 }
1358
1359 unsigned int scale, nr_scale = (unsigned int)vgrids_.size();
1360
1361 pc_ = pc;
1362 nr_points_ = nr_points;
1363 nr_point_element_ = nr_point_element;
1364
1365 for (scale = 0; scale < nr_scale; ++scale) {
1366 if (!vgrids_[scale].set(pc, nr_points, nr_point_element)) {
1367 break;
1368 }
1369 }
1370
1371 // break in the middle - last (NrScale - s) grids are invalid
1372 if (scale < nr_scale) {
1373 vgrids_.resize(scale);
1374 }
1375
1376 return (vgrids_.size() == nr_scale);
1377}
1378
1379template <typename DATA_TYPE>
1381 unsigned int nr_points,
1382 unsigned int nr_point_element) {
1383 if (!pc || !nr_points || !nr_point_element || vgrids_.empty()) {
1384 return false;
1385 }
1386
1387 unsigned int scale, nr_scale = (unsigned int)vgrids_.size();
1388
1389 pc_ = pc;
1390 nr_points_ = nr_points;
1391 nr_point_element_ = nr_point_element;
1392
1393 for (scale = 0; scale < nr_scale; ++scale) {
1394 if (!vgrids_[scale].set_s(pc, nr_points, nr_point_element)) {
1395 break;
1396 }
1397 }
1398
1399 // break in the middle - last (NrScale - s) grids are invalid
1400 if (scale < nr_scale) {
1401 vgrids_.resize(scale);
1402 }
1403
1404 return (vgrids_.size() == nr_scale);
1405}
1406
1407template <typename DATA_TYPE>
1409 const DATA_TYPE *pc, unsigned int nr_scale, unsigned int nr_points,
1410 unsigned int nr_point_element, unsigned int nr_voxel_x_base,
1411 unsigned int nr_voxel_y_base, unsigned int dsf_x, unsigned int dsf_y,
1412 DATA_TYPE spatial_bound_x_min, DATA_TYPE spatial_bound_x_max,
1413 DATA_TYPE spatial_bound_y_min, DATA_TYPE spatial_bound_y_max,
1414 DATA_TYPE spatial_bound_z_min, DATA_TYPE spatial_bound_z_max) {
1415 if (!pc || !nr_scale || !nr_points || !nr_point_element || !nr_voxel_x_base ||
1416 !nr_voxel_y_base) {
1417 return false;
1418 }
1419
1420 unsigned int i, s;
1421 pc_ = pc;
1422 nr_points_ = nr_points;
1423 nr_point_element_ = nr_point_element;
1424
1425 dsf_x_ = dsf_x;
1426 dsf_y_ = dsf_y;
1427 dsf_z_ = 0;
1428
1429 vgrids_.clear();
1430 vgrids_.resize(nr_scale);
1431
1432 // Set the base level pyramid
1433 if (!vgrids_[0].set(pc_, nr_points, nr_point_element, nr_voxel_x_base,
1434 nr_voxel_y_base, spatial_bound_x_min, spatial_bound_x_max,
1435 spatial_bound_y_min, spatial_bound_y_max,
1436 spatial_bound_z_min, spatial_bound_z_max)) {
1437 vgrids_.clear();
1438 return false;
1439 }
1440
1441 for (s = 1; s < nr_scale; ++s) {
1442 if (!IDownsampleVoxelGridXY(vgrids_[s - 1], &vgrids_[s], dsf_x_, dsf_y_)) {
1443 break;
1444 }
1445 }
1446
1447 if (s < nr_scale) {
1448 for (i = 0; i < (nr_scale - s); ++i) {
1449 vgrids_.pop_back();
1450 }
1451 }
1452
1453 return (vgrids_.size() == nr_scale); // check if all scales are valid
1454}
1455
1456template <typename DATA_TYPE>
1458 pc_ = nullptr;
1459 vgrids_.clear();
1460 nr_points_ = nr_point_element_ = dsf_x_ = dsf_y_ = dsf_z_ = 0;
1461}
1462
1463template <typename DATA_TYPE>
1465 unsigned int i;
1466 if (vgrids_.empty()) {
1467 return false;
1468 }
1469 for (i = 0; i < vgrids_.size(); ++i) {
1470 if (!vgrids_[i].initialized()) {
1471 break;
1472 }
1473 }
1474 return (i == vgrids_.size());
1475}
1476
1477} // namespace algorithm
1478} // namespace perception
1479} // namespace apollo
const T * operator[](unsigned int i) const
Definition i_struct_s.h:95
PtCluster & operator=(const PtCluster< T, d > &c)
Definition i_struct_s.h:74
reference operator()(unsigned int i, unsigned int j)
Definition i_struct_s.h:101
const_reference operator()(unsigned int i, unsigned int j) const
Definition i_struct_s.h:106
static unsigned int PointsizeInByte()
Definition i_struct_s.h:46
PtCluster(const PtCluster< T, d > &c)
Definition i_struct_s.h:65
bool Alloc(unsigned int nr_scale, unsigned int nr_voxel_x_base, unsigned int nr_voxel_y_base, unsigned int dsf_x, unsigned int dsf_y, DATA_TYPE spatial_bound_x_min, DATA_TYPE spatial_bound_x_max, DATA_TYPE spatial_bound_y_min, DATA_TYPE spatial_bound_y_max, DATA_TYPE spatial_bound_z_min, DATA_TYPE spatial_bound_z_max)
unsigned int NrVoxel(unsigned int i=0) const
bool SetS(const float *pc, unsigned int nr_points, unsigned int nr_point_element)
unsigned int NrVoxelZ(unsigned int i=0) const
const VoxelGridXY< DATA_TYPE > & operator[](unsigned int i) const
unsigned int NrPoints(unsigned int scale) const
unsigned int NrVoxelX(unsigned int i=0) const
unsigned int NrVoxelY(unsigned int i=0) const
bool Set(const DATA_TYPE *pc, unsigned int nr_points, unsigned int nr_point_element)
VoxelGridXY< DATA_TYPE > & operator[](unsigned int i)
VoxelGridXY< DATA_TYPE > & operator[](int i)
const VoxelGridXY< DATA_TYPE > & operator[](int i) const
VoxelGridXYPyramid(unsigned int nr_scale, unsigned int nr_voxel_x_base, unsigned int nr_voxel_y_base, unsigned int dsf_x, unsigned int dsf_y, DATA_TYPE spatial_bound_x_min, DATA_TYPE spatial_bound_x_max, DATA_TYPE spatial_bound_y_min, DATA_TYPE spatial_bound_y_max, DATA_TYPE spatial_bound_z_min, DATA_TYPE spatial_bound_z_max)
Voxel< T > & operator()(unsigned int iy, unsigned int ix)
Definition i_struct_s.h:463
bool Set(const T *data, unsigned int nr_points, unsigned int nr_point_element, unsigned int nr_voxel_x, unsigned int nr_voxel_y, T spatial_bound_x_min, T spatial_bound_x_max, T spatial_bound_y_min, T spatial_bound_y_max, T spatial_bound_z_min, T spatial_bound_z_max, bool force_bound=true)
Definition i_struct_s.h:902
const Voxel< T > & operator[](unsigned int i) const
Definition i_struct_s.h:449
void SetGridDimension(T dim_min_x, T dim_max_x, T dim_min_y, T dim_max_y, T dim_min_z, T dim_max_z)
Definition i_struct_s.h:392
const Voxel< T > & operator()(unsigned int iy, unsigned int ix) const
Definition i_struct_s.h:470
VoxelGridXY & operator=(const VoxelGridXY< T > &vg)
Definition i_struct_s.h:305
const Voxel< T > & operator[](int i) const
Definition i_struct_s.h:458
bool GetVoxelDimension(T *voxel_width_x, T *voxel_width_y, T *voxel_width_z) const
Definition i_struct_s.h:402
void SetVoxelDimension(T voxel_width_x, T voxel_width_y, T voxel_width_z)
Definition i_struct_s.h:414
void SetNrPointElement(unsigned int nr_point_element)
Definition i_struct_s.h:422
void SetNrPoints(unsigned int nr_points)
Definition i_struct_s.h:420
bool SetS(const float *data, unsigned int nr_points, unsigned int nr_point_element)
Definition i_struct_s.h:747
bool GetGridDimension(T *dim_min_x, T *dim_max_x, T *dim_min_y, T *dim_max_y, T *dim_min_z, T *dim_max_z) const
Definition i_struct_s.h:376
bool Set(const T *data, unsigned int nr_points, unsigned int nr_point_element)
Definition i_struct_s.h:699
VoxelGridXY(unsigned int nr_voxel_x, unsigned int nr_voxel_y, T spatial_bound_x_min, T spatial_bound_x_max, T spatial_bound_y_min, T spatial_bound_y_max, T spatial_bound_z_min, T spatial_bound_z_max)
Definition i_struct_s.h:531
Voxel< T > & operator[](unsigned int i)
Definition i_struct_s.h:444
const std::vector< Voxel< T > > & GetConstVoxels() const
Definition i_struct_s.h:370
void SetVoxels(const std::vector< Voxel< T > > &voxels)
Definition i_struct_s.h:372
bool GetVoxelCoordinateXY(T x, T y, int *row, int *col) const
Definition i_struct_s.h:623
bool Alloc(unsigned int nr_voxel_x, unsigned int nr_voxel_y, T spatial_bound_x_min, T spatial_bound_x_max, T spatial_bound_y_min, T spatial_bound_y_max, T spatial_bound_z_min, T spatial_bound_z_max)
Definition i_struct_s.h:634
std::vector< Voxel< T > > & GetVoxels()
Definition i_struct_s.h:368
void SetNrVoxel(unsigned int nr_voxel_x, unsigned int nr_voxel_y, unsigned int nr_voxel_z)
Definition i_struct_s.h:426
Voxel & operator=(const Voxel< T > &voxel)
Definition i_struct_s.h:227
void Init(T v_x, T v_y, T v_z, T dim_x, T dim_y, T dim_z, int ix, int iy, int iz)
Definition i_struct_s.h:252
void Init(const T *v, T dim_x, T dim_y, T dim_z, int ix, int iy, int iz)
Definition i_struct_s.h:241
Voxel(const Voxel< T > &voxel)
Definition i_struct_s.h:216
void Reserve(unsigned int size)
Definition i_struct_s.h:273
int AssignPointToVoxel(T xx, T yy, T zz, T bound_x_min, T bound_x_max, T bound_y_min, T bound_y_max, T bound_z_min, T bound_z_max, T voxel_width_x_rec, T voxel_width_y_rec, int nr_voxel_x, int nr_voxel_y)
Definition i_struct_s.h:186
void ICopy(const T *src, T *dst, int n)
Definition i_blas.h:27
int IAssignPointToVoxel(const T *data, T bound_x_min, T bound_x_max, T bound_y_min, T bound_y_max, T bound_z_min, T bound_z_max, T voxel_width_x_rec, T voxel_width_y_rec, int nr_voxel_x, int nr_voxel_y)
Definition i_struct_s.h:160
void ICopy3(const T src[3], T dst[3])
Definition i_blas.h:40
int IVerifyAlignment(const T *mem, int alignment_power=4)
Definition i_alloc.h:150
float IDiv(float a, float b)
Definition i_basic.h:35
float IPow(float a, float b)
Definition i_basic.h:142
void IGetPointcloudsDimWBound(const T *threeds, int n, int start_offset, int element_size, T *dim_min_x, T *dim_max_x, T *dim_min_y, T *dim_max_y, T *dim_min_z, T *dim_max_z, T bound_min_x, T bound_max_x, T bound_min_y, T bound_max_y, T bound_min_z, T bound_max_z)
Definition i_util.h:27
bool IDownsampleVoxelGridXY(const VoxelGridXY< T > &src, VoxelGridXY< T > *dst, unsigned int dsf_dim_x, unsigned int dsf_dim_y)
class register implement
Definition arena_queue.h:37
FORCE_INLINE __m128 _mm_sub_ps(__m128 a, __m128 b)
Definition sse2neon.h:2963
FORCE_INLINE void _mm_store_si128(__m128i *p, __m128i a)
Definition sse2neon.h:6110
float32x4_t __m128
Definition sse2neon.h:307
FORCE_INLINE __m128i _mm_add_epi32(__m128i a, __m128i b)
Definition sse2neon.h:3113
FORCE_INLINE __m128 _mm_setr_ps(float w, float z, float y, float x)
Definition sse2neon.h:2629
FORCE_INLINE __m128 _mm_cmpge_ps(__m128 a, __m128 b)
Definition sse2neon.h:1252
FORCE_INLINE __m128i _mm_set1_epi32(int)
Definition sse2neon.h:5378
FORCE_INLINE __m128i _mm_setr_epi32(int i3, int i2, int i1, int i0)
Definition sse2neon.h:5444
FORCE_INLINE __m128 _mm_mul_ps(__m128 a, __m128 b)
Definition sse2neon.h:2299
FORCE_INLINE __m128i _mm_cvttps_epi32(__m128 a)
Definition sse2neon.h:4479
FORCE_INLINE __m128 _mm_cmple_ps(__m128 a, __m128 b)
Definition sse2neon.h:1294
FORCE_INLINE __m128 _mm_set_ps1(float)
Definition sse2neon.h:2544
FORCE_INLINE __m128i _mm_min_epi32(__m128i a, __m128i b)
Definition sse2neon.h:8102
FORCE_INLINE __m128 _mm_and_ps(__m128 a, __m128 b)
Definition sse2neon.h:1183
FORCE_INLINE __m128i _mm_mullo_epi32(__m128i a, __m128i b)
Definition sse2neon.h:8295
#define _MM_SHUFFLE(fp3, fp2, fp1, fp0)
MACRO for shuffle parameter for _mm_shuffle_ps().
Definition sse2neon.h:247
int64x2_t __m128i
Definition sse2neon.h:316
FORCE_INLINE void _mm_store_ps(float *p, __m128 a)
Definition sse2neon.h:2833
#define _mm_shuffle_epi32(a, imm)
Definition sse2neon.h:5524