ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
VoxelGridFactory.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include <Helper.h>
9 #include <IntersectionTest.h>
10 #include <Logging.h>
11 
12 #include <numeric>
13 #include <unordered_map>
14 
15 #include "VoxelGrid.h"
16 #include "ecvMesh.h"
17 #include "ecvPointCloud.h"
18 
19 namespace cloudViewer {
20 namespace geometry {
21 using namespace cloudViewer;
22 
23 std::shared_ptr<VoxelGrid> VoxelGrid::CreateDense(const Eigen::Vector3d &origin,
24  const Eigen::Vector3d &color,
25  double voxel_size,
26  double width,
27  double height,
28  double depth) {
29  auto output = std::make_shared<VoxelGrid>();
30  int num_w = int(std::round(width / voxel_size));
31  int num_h = int(std::round(height / voxel_size));
32  int num_d = int(std::round(depth / voxel_size));
33  output->origin_ = origin;
34  output->voxel_size_ = voxel_size;
35  for (int widx = 0; widx < num_w; widx++) {
36  for (int hidx = 0; hidx < num_h; hidx++) {
37  for (int didx = 0; didx < num_d; didx++) {
38  Eigen::Vector3i grid_index(widx, hidx, didx);
39  output->AddVoxel(geometry::Voxel(grid_index, color));
40  }
41  }
42  }
43  return output;
44 }
45 
47  const ccPointCloud &input,
48  double voxel_size,
49  const Eigen::Vector3d &min_bound,
50  const Eigen::Vector3d &max_bound,
51  VoxelGrid::VoxelPoolingMode pooling_mode) {
52  auto output = std::make_shared<VoxelGrid>();
53  if (voxel_size <= 0.0) {
54  utility::LogError("[VoxelGridFromPointCloud] voxel_size <= 0.");
55  }
56 
57  if (voxel_size * std::numeric_limits<int>::max() <
58  (max_bound - min_bound).maxCoeff()) {
59  utility::LogError("[VoxelGridFromPointCloud] voxel_size is too small.");
60  }
61  output->voxel_size_ = voxel_size;
62  output->origin_ = min_bound;
63  std::unordered_map<Eigen::Vector3i, AvgColorVoxel,
65  voxelindex_to_accpoint;
66  Eigen::Vector3d ref_coord;
68  bool has_colors = input.hasColors();
69  for (size_t i = 0; i < input.size(); i++) {
70  Eigen::Vector3d p =
71  input.getEigenPoint(i); // must reserve a temp variable
72  ref_coord = (p - min_bound) / voxel_size;
73  voxel_index << int(floor(ref_coord(0))), int(floor(ref_coord(1))),
74  int(floor(ref_coord(2)));
75  if (has_colors) {
76  voxelindex_to_accpoint[voxel_index].Add(voxel_index,
77  input.getEigenColor(i));
78  } else {
79  voxelindex_to_accpoint[voxel_index].Add(voxel_index);
80  }
81  }
82  for (auto accpoint : voxelindex_to_accpoint) {
83  const Eigen::Vector3i &grid_index = accpoint.second.GetVoxelIndex();
84  const Eigen::Vector3d &color =
85  has_colors ? (pooling_mode == VoxelPoolingMode::AVG
86  ? accpoint.second.GetAverageColor()
87  : pooling_mode == VoxelPoolingMode::MIN
88  ? accpoint.second.GetMinColor()
89  : pooling_mode == VoxelPoolingMode::MAX
90  ? accpoint.second.GetMaxColor()
91  : pooling_mode == VoxelPoolingMode::SUM
92  ? accpoint.second.GetSumColor()
93  : Eigen::Vector3d::Zero())
94  : Eigen::Vector3d::Zero();
95  output->AddVoxel(geometry::Voxel(grid_index, color));
96  }
98  "Pointcloud is voxelized from {:d} points to {:d} voxels.",
99  (int)input.size(), (int)output->voxels_.size());
100  return output;
101 }
102 
103 std::shared_ptr<VoxelGrid> VoxelGrid::CreateFromPointCloud(
104  const ccPointCloud &input,
105  double voxel_size,
106  VoxelGrid::VoxelPoolingMode pooling_mode) {
107  Eigen::Vector3d voxel_size3(voxel_size, voxel_size, voxel_size);
108  Eigen::Vector3d min_bound = input.GetMinBound() - voxel_size3 * 0.5;
109  Eigen::Vector3d max_bound = input.GetMaxBound() + voxel_size3 * 0.5;
110  return CreateFromPointCloudWithinBounds(input, voxel_size, min_bound,
111  max_bound, pooling_mode);
112 }
113 
115  const ccMesh &input,
116  double voxel_size,
117  const Eigen::Vector3d &min_bound,
118  const Eigen::Vector3d &max_bound) {
119  auto output = std::make_shared<VoxelGrid>();
120  if (voxel_size <= 0.0) {
121  utility::LogError("voxel_size <= 0.");
122  }
123 
124  if (voxel_size * std::numeric_limits<int>::max() <
125  (max_bound - min_bound).maxCoeff()) {
126  utility::LogError("voxel_size is too small.");
127  }
128  output->voxel_size_ = voxel_size;
129  output->origin_ = min_bound;
130 
131  const Eigen::Vector3d box_half_size(voxel_size / 2, voxel_size / 2,
132  voxel_size / 2);
133  unsigned int triNum = input.size();
134  for (unsigned int i = 0; i < triNum; ++i) {
135  Eigen::Vector3d v0, v1, v2;
136  input.getTriangleVertices(i, v0.data(), v1.data(), v2.data());
137  double minx, miny, minz, maxx, maxy, maxz;
138  int num_w, num_h, num_d, inix, iniy, iniz;
139  minx = std::min(v0[0], std::min(v1[0], v2[0]));
140  miny = std::min(v0[1], std::min(v1[1], v2[1]));
141  minz = std::min(v0[2], std::min(v1[2], v2[2]));
142  maxx = std::max(v0[0], std::max(v1[0], v2[0]));
143  maxy = std::max(v0[1], std::max(v1[1], v2[1]));
144  maxz = std::max(v0[2], std::max(v1[2], v2[2]));
145  inix = static_cast<int>(std::floor((minx - min_bound[0]) / voxel_size));
146  iniy = static_cast<int>(std::floor((miny - min_bound[1]) / voxel_size));
147  iniz = static_cast<int>(std::floor((minz - min_bound[2]) / voxel_size));
148  num_w = static_cast<int>((std::round((maxx - minx) / voxel_size))) + 2;
149  num_h = static_cast<int>((std::round((maxy - miny) / voxel_size))) + 2;
150  num_d = static_cast<int>((std::round((maxz - minz) / voxel_size))) + 2;
151  for (int widx = inix; widx < inix + num_w; widx++) {
152  for (int hidx = iniy; hidx < iniy + num_h; hidx++) {
153  for (int didx = iniz; didx < iniz + num_d; didx++) {
154  const Eigen::Vector3d box_center =
155  min_bound + box_half_size +
156  Eigen::Vector3d(widx, hidx, didx) * voxel_size;
158  box_center, box_half_size, v0, v1, v2)) {
159  Eigen::Vector3i grid_index(widx, hidx, didx);
160  output->AddVoxel(geometry::Voxel(grid_index));
161  // Don't `break` here, since a triangle can span
162  // across multiple voxels.
163  }
164  }
165  }
166  }
167  }
168 
169  return output;
170 }
171 
172 std::shared_ptr<VoxelGrid> VoxelGrid::CreateFromTriangleMesh(
173  const ccMesh &input, double voxel_size) {
174  Eigen::Vector3d voxel_size3(voxel_size, voxel_size, voxel_size);
175  Eigen::Vector3d min_bound = input.GetMinBound() - voxel_size3 * 0.5;
176  Eigen::Vector3d max_bound = input.GetMaxBound() + voxel_size3 * 0.5;
177  return CreateFromTriangleMeshWithinBounds(input, voxel_size, min_bound,
178  max_bound);
179 }
180 
181 } // namespace geometry
182 } // namespace cloudViewer
int width
bool has_colors
int height
math::float4 color
long voxel_index
Definition: VoxelGridIO.cpp:29
double voxel_size
Definition: VoxelGridIO.cpp:28
Eigen::Vector3d origin
Definition: VoxelGridIO.cpp:26
Triangular mesh.
Definition: ecvMesh.h:35
virtual Eigen::Vector3d GetMaxBound() const override
Returns max bounds for geometry coordinates.
Definition: ecvMesh.cpp:828
virtual unsigned size() const override
Returns the number of triangles.
Definition: ecvMesh.cpp:2143
virtual void getTriangleVertices(unsigned triangleIndex, CCVector3 &A, CCVector3 &B, CCVector3 &C) const override
Returns the vertices of a given triangle.
Definition: ecvMesh.cpp:2187
virtual Eigen::Vector3d GetMinBound() const override
Returns min bounds for geometry coordinates.
Definition: ecvMesh.cpp:820
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
virtual Eigen::Vector3d GetMinBound() const override
Returns min bounds for geometry coordinates.
bool hasColors() const override
Returns whether colors are enabled or not.
Eigen::Vector3d getEigenColor(size_t index) const
virtual Eigen::Vector3d GetMaxBound() const override
Returns max bounds for geometry coordinates.
unsigned size() const override
Definition: PointCloudTpl.h:38
Eigen::Vector3d getEigenPoint(size_t index) const
Class to aggregate color values from different votes in one voxel Computes the average color value in...
Definition: VoxelGrid.h:281
static std::shared_ptr< VoxelGrid > CreateFromTriangleMesh(const ccMesh &input, double voxel_size)
static std::shared_ptr< VoxelGrid > CreateFromPointCloudWithinBounds(const ccPointCloud &input, double voxel_size, const Eigen::Vector3d &min_bound, const Eigen::Vector3d &max_bound, VoxelPoolingMode color_mode=VoxelPoolingMode::AVG)
static std::shared_ptr< VoxelGrid > CreateFromTriangleMeshWithinBounds(const ccMesh &input, double voxel_size, const Eigen::Vector3d &min_bound, const Eigen::Vector3d &max_bound)
static std::shared_ptr< VoxelGrid > CreateDense(const Eigen::Vector3d &origin, const Eigen::Vector3d &color, double voxel_size, double width, double height, double depth)
VoxelPoolingMode
Possible ways of determining voxel color from PointCloud.
Definition: VoxelGrid.h:200
static std::shared_ptr< VoxelGrid > CreateFromPointCloud(const ccPointCloud &input, double voxel_size, VoxelPoolingMode color_mode=VoxelPoolingMode::AVG)
Base Voxel class, containing grid id and color.
Definition: VoxelGrid.h:38
static bool TriangleAABB(const Eigen::Vector3d &box_center, const Eigen::Vector3d &box_half_size, const Eigen::Vector3d &vert0, const Eigen::Vector3d &vert1, const Eigen::Vector3d &vert2)
#define LogError(...)
Definition: Logging.h:60
#define LogDebug(...)
Definition: Logging.h:90
MiniVec< float, N > floor(const MiniVec< float, N > &a)
Definition: MiniVec.h:75
Generic file read and write utility for python interface.
Eigen::Matrix< Index, 3, 1 > Vector3i
Definition: knncpp.h:30