ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
BoundingVolume.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 
9 
14 
15 namespace cloudViewer {
16 namespace t {
17 namespace geometry {
18 
21  device_(device),
22  dtype_(core::Float32),
23  min_bound_(core::Tensor::Zeros({3}, dtype_, device)),
24  max_bound_(core::Tensor::Zeros({3}, dtype_, device)),
25  color_(core::Tensor::Ones({3}, dtype_, device)) {}
26 
28  const core::Tensor &max_bound)
29  : AxisAlignedBoundingBox([&]() {
30  core::AssertTensorDevice(max_bound, min_bound.GetDevice());
31  core::AssertTensorDtype(max_bound, min_bound.GetDtype());
33  core::AssertTensorShape(min_bound, {3});
34  core::AssertTensorShape(max_bound, {3});
35  return min_bound.GetDevice();
36  }()) {
37  device_ = min_bound.GetDevice();
38  dtype_ = min_bound.GetDtype();
39 
40  min_bound_ = min_bound;
41  max_bound_ = max_bound;
43 
44  // Check if the bounding box is valid.
45  if (Volume() < 0) {
47  "max_bound {} of bounding box is smaller than min_bound {} in "
48  "one or more axes. Fix input values to remove this warning.",
49  max_bound_.ToString(false), min_bound_.ToString(false));
50  max_bound_ = cloudViewer::core::Maximum(min_bound, max_bound);
51  min_bound_ = cloudViewer::core::Minimum(min_bound, max_bound);
52  }
53 }
54 
56  bool copy) const {
57  if (!copy && GetDevice() == device) {
58  return *this;
59  }
60  AxisAlignedBoundingBox box(device);
61  box.SetMaxBound(max_bound_.To(device, true));
62  box.SetMinBound(min_bound_.To(device, true));
63  box.SetColor(color_.To(device, true));
64  return box;
65 }
66 
71  return *this;
72 }
73 
75  core::AssertTensorDevice(min_bound, GetDevice());
76  core::AssertTensorShape(min_bound, {3});
78 
79  const core::Tensor tmp = min_bound_.Clone();
80  min_bound_ = min_bound.To(GetDtype());
81 
82  // If the volume is invalid, the min_bound_ will be set to the
83  // original value.
84  if (Volume() < 0) {
86  "Invalid axis-aligned bounding box. Please make sure all "
87  "the elements in min bound are smaller than max bound.");
88  min_bound_ = tmp;
89  }
90 }
91 
93  core::AssertTensorDevice(max_bound, GetDevice());
94  core::AssertTensorShape(max_bound, {3});
96 
97  const core::Tensor tmp = max_bound_.Clone();
98  max_bound_ = max_bound.To(GetDtype());
99 
100  // If the volume is invalid, the max_bound_ will be set to the
101  // original value.
102  if (Volume() < 0) {
104  "Invalid axis-aligned bounding box. Please make sure all "
105  "the elements in max bound are larger than min bound.");
106  max_bound_ = tmp;
107  }
108 }
109 
113 
114  if (color.Max({0}).To(core::Float64).Item<double>() > 1.0 ||
115  color.Min({0}).To(core::Float64).Item<double>() < 0.0) {
117  "The color must be in the range [0, 1], but found in range "
118  "[{}, {}].",
119  color.Min({0}).To(core::Float64).Item<double>(),
120  color.Max({0}).To(core::Float64).Item<double>());
121  }
122 
123  color_ = color.To(GetDtype());
124 }
125 
127  const core::Tensor &translation, bool relative) {
128  core::AssertTensorDevice(translation, GetDevice());
129  core::AssertTensorShape(translation, {3});
131 
132  const core::Tensor translation_d = translation.To(GetDtype());
133  if (relative) {
134  min_bound_ += translation_d;
135  max_bound_ += translation_d;
136  } else {
137  const core::Tensor half_extent = GetHalfExtent();
138  min_bound_ = translation_d - half_extent;
139  max_bound_ = translation_d + half_extent;
140  }
141  return *this;
142 }
143 
145  double scale, const utility::optional<core::Tensor> &center) {
146  core::Tensor center_d;
147  if (!center.has_value()) {
148  center_d = GetCenter();
149  } else {
150  center_d = center.value();
151  core::AssertTensorDevice(center_d, GetDevice());
152  core::AssertTensorShape(center_d, {3});
154  center_d = center_d.To(GetDtype());
155  }
156  min_bound_ = center_d + scale * (min_bound_ - center_d);
157  max_bound_ = center_d + scale * (max_bound_ - center_d);
158 
159  return *this;
160 }
161 
163  const AxisAlignedBoundingBox &other) {
164  if (other.GetDtype() != GetDtype()) {
166  "The data-type of the other bounding box is {}, but the "
167  "data-type of this bounding box is {}.",
168  other.GetDtype().ToString(), GetDtype().ToString());
169  }
170 
171  if (IsEmpty()) {
172  min_bound_ = other.GetMinBound();
173  max_bound_ = other.GetMaxBound();
174  } else if (!other.IsEmpty()) {
177  }
178  return *this;
179 }
180 
182  const double x_min = min_bound_[0].To(core::Float64).Item<double>();
183  const double x_max = max_bound_[0].To(core::Float64).Item<double>();
184  return (x - x_min) / (x_max - x_min);
185 }
186 
188  const double y_min = min_bound_[1].To(core::Float64).Item<double>();
189  const double y_max = max_bound_[1].To(core::Float64).Item<double>();
190  return (y - y_min) / (y_max - y_min);
191 }
192 
194  const double z_min = min_bound_[2].To(core::Float64).Item<double>();
195  const double z_max = max_bound_[2].To(core::Float64).Item<double>();
196  return (z - z_min) / (z_max - z_min);
197 }
198 
200  const core::Tensor extent_3x3 =
202  .Mul(GetExtent().Reshape({3, 1}));
203 
204  return core::Concatenate({min_bound_.Reshape({1, 3}),
205  min_bound_.Reshape({1, 3}) + extent_3x3,
206  max_bound_.Reshape({1, 3}),
207  max_bound_.Reshape({1, 3}) - extent_3x3});
208 }
209 
211  const core::Tensor &points) const {
215 
216  core::Tensor mask =
217  core::Tensor::Zeros({points.GetLength()}, core::Bool, GetDevice());
218  // Convert min_bound and max_bound to the same dtype as points.
220  points, min_bound_.To(points.GetDtype()),
221  max_bound_.To(points.GetDtype()), mask);
222 
223  return mask.NonZero().Flatten();
224 }
225 
226 std::string AxisAlignedBoundingBox::ToString() const {
227  return fmt::format("AxisAlignedBoundingBox[{} - {}, {}, {}]",
228  GetMinBound().ToString(false),
229  GetMaxBound().ToString(false), GetDtype().ToString(),
230  GetDevice().ToString());
231 }
232 
234  const core::Tensor &points) {
237  if (points.GetLength() <= 0) {
239  "The number of points is 0 when creating axis-aligned bounding "
240  "box.");
241  return AxisAlignedBoundingBox(points.GetDevice());
242  } else {
243  const core::Tensor min_bound = points.Min({0});
244  const core::Tensor max_bound = points.Max({0});
245  return AxisAlignedBoundingBox(min_bound, max_bound);
246  }
247 }
248 
250  const {
252  {
254  GetMinBound().Reshape({1, 3}))[0];
255  auto &minc = legacy_box.minCorner();
257  minc.x = static_cast<PointCoordinateType>(e(0));
258  minc.y = static_cast<PointCoordinateType>(e(1));
259  minc.z = static_cast<PointCoordinateType>(e(2));
260  }
261  {
263  GetMaxBound().Reshape({1, 3}))[0];
264  auto &maxc = legacy_box.maxCorner();
266  maxc.x = static_cast<PointCoordinateType>(e(0));
267  maxc.y = static_cast<PointCoordinateType>(e(1));
268  maxc.z = static_cast<PointCoordinateType>(e(2));
269  }
271  GetColor().Reshape({1, 3}))[0]);
272  return legacy_box;
273 }
274 
277 }
278 
281  const core::Dtype &dtype,
282  const core::Device &device) {
283  if (dtype != core::Float32 && dtype != core::Float64) {
285  "Got data-type {}, but the supported data-type of the bounding "
286  "box are Float32 and Float64.",
287  dtype.ToString());
288  }
289 
290  Eigen::Vector3d min_b(box.minCorner().x, box.minCorner().y,
291  box.minCorner().z);
292  Eigen::Vector3d max_b(box.maxCorner().x, box.maxCorner().y,
293  box.maxCorner().z);
296  device, dtype),
298  device, dtype));
299 
301  .Flatten()
302  .To(device, dtype));
303  return t_box;
304 }
305 
308  device_(device),
309  dtype_(core::Float32),
310  center_(core::Tensor::Zeros({3}, dtype_, device)),
311  rotation_(core::Tensor::Eye(3, dtype_, device)),
312  extent_(core::Tensor::Zeros({3}, dtype_, device)),
313  color_(core::Tensor::Ones({3}, dtype_, device)) {}
314 
316  const core::Tensor &rotation,
317  const core::Tensor &extent)
318  : OrientedBoundingBox([&]() {
319  core::AssertTensorDevice(center, extent.GetDevice());
320  core::AssertTensorDevice(rotation, extent.GetDevice());
321  core::AssertTensorDtype(center, extent.GetDtype());
322  core::AssertTensorDtype(rotation, extent.GetDtype());
324  core::AssertTensorShape(center, {3});
325  core::AssertTensorShape(extent, {3});
326  core::AssertTensorShape(rotation, {3, 3});
327  return center.GetDevice();
328  }()) {
329  device_ = center.GetDevice();
330  dtype_ = center.GetDtype();
331 
332  center_ = center;
333  extent_ = extent;
334  rotation_ = rotation;
336 
337  // Check if the bounding box is valid by checking the volume and the
338  // orthogonality of rotation.
339  if (Volume() < 0 ||
340  !rotation_.T().AllClose(rotation.Inverse(), 1e-5, 1e-5)) {
342  "Invalid oriented bounding box. Please make sure the values of "
343  "extent are all positive and the rotation matrix is "
344  "orthogonal.");
345  }
346 }
347 
349  bool copy) const {
350  if (!copy && GetDevice() == device) {
351  return *this;
352  }
353  OrientedBoundingBox box(device);
354  box.SetCenter(center_.To(device, true));
355  box.SetRotation(rotation_.To(device, true));
356  box.SetExtent(extent_.To(device, true));
357  box.SetColor(color_.To(device, true));
358  return box;
359 }
360 
366  return *this;
367 }
368 
371  core::AssertTensorShape(center, {3});
373 
374  center_ = center.To(GetDtype());
375 }
376 
379  core::AssertTensorShape(extent, {3});
381 
382  if (extent.Min({0}).To(core::Float64).Item<double>() <= 0) {
384  "Invalid oriented bounding box. Please make sure the values of "
385  "extent are all positive.");
386  }
387 
388  extent_ = extent.To(GetDtype());
389 }
390 
392  core::AssertTensorDevice(rotation, GetDevice());
393  core::AssertTensorShape(rotation, {3, 3});
395 
396  if (!rotation.T().AllClose(rotation.Inverse(), 1e-5, 1e-5)) {
398  "Invalid oriented bounding box. Please make sure the rotation "
399  "matrix is orthogonal.");
400  } else {
401  rotation_ = rotation.To(GetDtype());
402  }
403 }
404 
408  if (color.Max({0}).To(core::Float64).Item<double>() > 1.0 ||
409  color.Min({0}).To(core::Float64).Item<double>() < 0.0) {
411  "The color must be in the range [0, 1], but found in range "
412  "[{}, {}].",
413  color.Min({0}).To(core::Float64).Item<double>(),
414  color.Max({0}).To(core::Float64).Item<double>());
415  }
416 
417  color_ = color.To(GetDtype());
418 }
419 
421  return GetBoxPoints().Min({0});
422 }
423 
425  return GetBoxPoints().Max({0});
426 }
427 
430  GetExtent() * 0.5);
431  return aabb.GetBoxPoints().Matmul(GetRotation().T()).Add(GetCenter());
432 }
433 
435  const core::Tensor &translation, bool relative) {
436  core::AssertTensorDevice(translation, GetDevice());
437  core::AssertTensorShape(translation, {3});
439 
440  const core::Tensor translation_d = translation.To(GetDtype());
441  if (relative) {
442  center_ += translation_d;
443  } else {
444  center_ = translation_d;
445  }
446  return *this;
447 }
448 
450  const core::Tensor &rotation,
451  const utility::optional<core::Tensor> &center) {
452  core::AssertTensorDevice(rotation, GetDevice());
453  core::AssertTensorShape(rotation, {3, 3});
455 
456  if (!rotation.T().AllClose(rotation.Inverse(), 1e-5, 1e-5)) {
458  "Invalid rotation matrix. Please make sure the rotation "
459  "matrix is orthogonal.");
460  return *this;
461  }
462 
463  const core::Tensor rotation_d = rotation.To(GetDtype());
464  rotation_ = rotation_d.Matmul(rotation_);
465  if (center.has_value()) {
467  core::AssertTensorShape(center.value(), {3});
469  {core::Float32, core::Float64});
470 
471  core::Tensor center_d = center.value().To(GetDtype());
472  center_ = rotation_d.Matmul(center_ - center_d).Flatten() + center_d;
473  }
474 
475  return *this;
476 }
477 
479  const core::Tensor &transformation) {
480  core::AssertTensorDevice(transformation, GetDevice());
481  core::AssertTensorShape(transformation, {4, 4});
483 
484  const core::Tensor transformation_d = transformation.To(GetDtype());
485  Rotate(transformation_d.GetItem({core::TensorKey::Slice(0, 3, 1),
486  core::TensorKey::Slice(0, 3, 1)}));
487  Translate(transformation_d
488  .GetItem({core::TensorKey::Slice(0, 3, 1),
490  .Flatten());
491  return *this;
492 }
493 
495  const double scale, const utility::optional<core::Tensor> &center) {
496  extent_ *= scale;
497  if (center.has_value()) {
498  core::Tensor center_d = center.value();
499  core::AssertTensorDevice(center_d, GetDevice());
500  core::AssertTensorShape(center_d, {3});
502 
503  center_d = center_d.To(GetDtype());
504  center_ = scale * (center_ - center_d) + center_d;
505  }
506  return *this;
507 }
508 
510  const core::Tensor &points) const {
514 
515  core::Tensor mask =
516  core::Tensor::Zeros({points.GetLength()}, core::Bool, GetDevice());
517  // Convert center, rotation and same to the same dtype as points.
519  points, center_.To(points.GetDtype()),
520  rotation_.To(points.GetDtype()), extent_.To(points.GetDtype()),
521  mask);
522 
523  return mask.NonZero().Flatten();
524 }
525 
526 std::string OrientedBoundingBox::ToString() const {
527  return fmt::format("OrientedBoundingBox[{}, {}]", GetDtype().ToString(),
528  GetDevice().ToString());
529 }
530 
532  const {
535  GetCenter().Reshape({1, 3}))[0],
538  GetExtent().Reshape({1, 3}))[0]);
540  GetColor().Reshape({1, 3}))[0]);
541  return legacy_box;
542 }
543 
546 }
547 
549  const AxisAlignedBoundingBox &aabb) {
551  aabb.GetCenter(),
552  core::Tensor::Eye(3, aabb.GetDtype(), aabb.GetDevice()),
553  aabb.GetExtent());
554  return box;
555 }
556 
559  const core::Dtype &dtype,
560  const core::Device &device) {
561  if (dtype != core::Float32 && dtype != core::Float64) {
563  "Got data-type {}, but the supported data-type of the bounding "
564  "box are Float32 and Float64.",
565  dtype.ToString());
566  }
567 
568  OrientedBoundingBox t_box(
570  .Flatten()
571  .To(device, dtype),
573  .To(device, dtype),
575  .Flatten()
576  .To(device, dtype));
577 
579  .Flatten()
580  .To(device, dtype));
581  return t_box;
582 }
583 
585  const core::Tensor &points, bool robust, MethodOBBCreate method) {
588  switch (method) {
590  if (points.GetShape(0) < 4) {
591  utility::LogError("Input point set has less than 4 points.");
592  }
596  points)),
597  points.GetDtype(), points.GetDevice());
602  robust);
603  default:
605  "Invalid method for computing oriented bounding "
606  "box. Supported methods are PCA, MINIMAL_APPROX, "
607  "and MINIMAL_JYLANKI.");
608  return OrientedBoundingBox();
609  }
610 }
611 
612 } // namespace geometry
613 } // namespace t
614 } // namespace cloudViewer
float PointCoordinateType
Type of the coordinates of a (N-D) point.
Definition: CVTypes.h:16
filament::Texture::InternalFormat format
int points
const core::Dtype dtype_
Definition: FilePLY.cpp:349
math::float4 color
Eigen::Vector3d center_
Definition: MinimumOBB.cpp:51
Eigen::Vector3d extent_
Definition: MinimumOBB.cpp:50
#define AssertTensorDevice(tensor,...)
Definition: TensorCheck.h:45
#define AssertTensorDtype(tensor,...)
Definition: TensorCheck.h:21
#define AssertTensorDtypes(tensor,...)
Definition: TensorCheck.h:33
#define AssertTensorShape(tensor,...)
Definition: TensorCheck.h:61
bool copy
Definition: VtkUtils.cpp:74
Type y
Definition: CVGeom.h:137
Type x
Definition: CVGeom.h:137
Type z
Definition: CVGeom.h:137
Bounding box structure.
Definition: ecvBBox.h:25
Eigen::Vector3d GetColor() const
Gets the bounding box color.
Definition: BoundingBox.h:267
const Vector3Tpl< T > & maxCorner() const
Returns max corner (const)
Definition: BoundingBox.h:156
const Vector3Tpl< T > & minCorner() const
Returns min corner (const)
Definition: BoundingBox.h:154
void SetColor(const Eigen::Vector3d &color)
Sets the bounding box color.
Definition: BoundingBox.h:265
const Eigen::Vector3d & GetExtent() const
const Eigen::Vector3d & GetPosition() const
const Eigen::Matrix3d & GetRotation() const
const Eigen::Vector3d & GetColor() const
Gets the bounding box color.
void SetColor(const Eigen::Vector3d &color)
Sets the bounding box color.
std::string ToString() const
Definition: Dtype.h:65
static TensorKey Index(int64_t index)
Definition: TensorKey.cpp:134
static TensorKey Slice(utility::optional< int64_t > start, utility::optional< int64_t > stop, utility::optional< int64_t > step)
Definition: TensorKey.cpp:138
bool AllClose(const Tensor &other, double rtol=1e-5, double atol=1e-8) const
Definition: Tensor.cpp:1895
Tensor Matmul(const Tensor &rhs) const
Definition: Tensor.cpp:1919
Dtype GetDtype() const
Definition: Tensor.h:1164
Tensor Inverse() const
Definition: Tensor.cpp:1982
static Tensor Eye(int64_t n, Dtype dtype, const Device &device)
Create an identity matrix of size n x n.
Definition: Tensor.cpp:418
Tensor Max(const SizeVector &dims, bool keepdim=false) const
Definition: Tensor.cpp:1275
Tensor Flatten(int64_t start_dim=0, int64_t end_dim=-1) const
Definition: Tensor.cpp:685
static Tensor Zeros(const SizeVector &shape, Dtype dtype, const Device &device=Device("CPU:0"))
Create a tensor fill with zeros.
Definition: Tensor.cpp:406
Tensor Add(const Tensor &value) const
Adds a tensor and returns the resulting tensor.
Definition: Tensor.cpp:1097
Device GetDevice() const override
Definition: Tensor.cpp:1435
Tensor Min(const SizeVector &dims, bool keepdim=false) const
Definition: Tensor.cpp:1268
Tensor Reshape(const SizeVector &dst_shape) const
Definition: Tensor.cpp:671
Tensor Clone() const
Copy Tensor to the same device.
Definition: Tensor.h:502
std::string ToString(bool with_suffix=true, const std::string &indent="") const
Definition: Tensor.cpp:780
static Tensor Ones(const SizeVector &shape, Dtype dtype, const Device &device=Device("CPU:0"))
Create a tensor fill with ones.
Definition: Tensor.cpp:412
Tensor T() const
Expects input to be <= 2-D Tensor by swapping dimension 0 and 1.
Definition: Tensor.cpp:1079
Tensor Mul(const Tensor &value) const
Multiplies a tensor and returns the resulting tensor.
Definition: Tensor.cpp:1169
Tensor To(Dtype dtype, bool copy=false) const
Definition: Tensor.cpp:739
A bounding box that is aligned along the coordinate axes and defined by the min_bound and max_bound.
core::Tensor color_
The color of the bounding box in RGB. The default is white.
cloudViewer::geometry::AxisAlignedBoundingBox ToLegacy() const
Convert to a legacy CloudViewer axis-aligned box.
core::Tensor max_bound_
The upper x, y, z bounds of the bounding box.
core::Tensor GetExtent() const
Get the extent/length of the bounding box in x, y, and z dimension.
core::Tensor GetPointIndicesWithinBoundingBox(const core::Tensor &points) const
Indices to points that are within the bounding box.
static AxisAlignedBoundingBox FromLegacy(const cloudViewer::geometry::AxisAlignedBoundingBox &box, const core::Dtype &dtype=core::Float32, const core::Device &device=core::Device("CPU:0"))
void SetColor(const core::Tensor &color)
Set the color of the box. If the data type of the given tensor differs from the data type of the box,...
static AxisAlignedBoundingBox CreateFromPoints(const core::Tensor &points)
core::Tensor min_bound_
The lower x, y, z bounds of the bounding box.
core::Device device_
The device to use for the bounding box. The default is CPU:0.
core::Device GetDevice() const override
Returns the device attribute of this AxisAlignedBoundingBox.
void SetMinBound(const core::Tensor &min_bound)
Set the min bound of the box. If the data type of the given tensor differs from the data type of the ...
AxisAlignedBoundingBox To(const core::Device &device, bool copy=false) const
Transfer the AxisAlignedBoundingBox to a specified device.
AxisAlignedBoundingBox & operator+=(const AxisAlignedBoundingBox &other)
Add operation for axis-aligned bounding box. The device of other box must be the same as the device o...
AxisAlignedBoundingBox(const core::Device &device=core::Device("CPU:0"))
Construct an empty AxisAlignedBoundingBox on the provided device.
bool IsEmpty() const override
Returns true iff the geometry is empty.
AxisAlignedBoundingBox & Clear() override
Clear all elements in the geometry.
core::Dtype dtype_
The data type of the bounding box.
OrientedBoundingBox GetOrientedBoundingBox() const
Convert to an oriented box.
core::Tensor GetHalfExtent() const
Returns the half extent of the bounding box.
void SetMaxBound(const core::Tensor &max_bound)
Set the max bound of the box. If the data type of the given tensor differs from the data type of the ...
AxisAlignedBoundingBox & Scale(double scale, const utility::optional< core::Tensor > &center=utility::nullopt)
Scale the axis-aligned box. If is the min_bound and is the max_bound of the axis aligned bounding b...
core::Tensor GetBoxPoints() const
Returns the eight points that define the bounding box.
std::string ToString() const
Text description.
AxisAlignedBoundingBox & Translate(const core::Tensor &translation, bool relative=true)
Translate the axis-aligned box by the given translation.
core::Dtype GetDtype() const
Returns the data type attribute of this AxisAlignedBoundingBox.
double Volume() const
Returns the volume of the bounding box.
The base geometry class.
Definition: Geometry.h:23
GeometryType
Specifies possible geometry types.
Definition: Geometry.h:28
A bounding box oriented along an arbitrary frame of reference.
OrientedBoundingBox(const core::Device &device=core::Device("CPU:0"))
Construct an empty OrientedBoundingBox on the provided device.
OrientedBoundingBox & Rotate(const core::Tensor &rotation, const utility::optional< core::Tensor > &center=utility::nullopt)
Rotate the oriented box by the given rotation matrix. If the rotation matrix is not orthogonal,...
AxisAlignedBoundingBox GetAxisAlignedBoundingBox() const
Convert to an axis-aligned box.
OrientedBoundingBox To(const core::Device &device, bool copy=false) const
void SetExtent(const core::Tensor &extent)
Set the extent of the box. If the data type of the given tensor differs from the data type of the box...
cloudViewer::geometry::OrientedBoundingBox ToLegacy() const
Convert to a legacy CloudViewer oriented box.
core::Dtype GetDtype() const
Returns the data type attribute of this OrientedBoundingBox.
OrientedBoundingBox & Scale(double scale, const utility::optional< core::Tensor > &center=utility::nullopt)
Scale the axis-aligned box. If is the min_bound and is the max_bound of the axis aligned bounding b...
OrientedBoundingBox & Clear() override
Clear all elements in the geometry.
static OrientedBoundingBox CreateFromPoints(const core::Tensor &points, bool robust=false, MethodOBBCreate method=MethodOBBCreate::MINIMAL_APPROX)
OrientedBoundingBox & Transform(const core::Tensor &transformation)
Transform the oriented box by the given transformation matrix.
OrientedBoundingBox & Translate(const core::Tensor &translation, bool relative=true)
Translate the oriented box by the given translation. If relative is true, the translation is added to...
static OrientedBoundingBox CreateFromAxisAlignedBoundingBox(const AxisAlignedBoundingBox &aabb)
void SetCenter(const core::Tensor &center)
Set the center of the box. If the data type of the given tensor differs from the data type of the box...
core::Tensor GetBoxPoints() const
Returns the eight points that define the bounding box.
core::Device GetDevice() const override
Returns the device attribute of this OrientedBoundingBox.
static OrientedBoundingBox FromLegacy(const cloudViewer::geometry::OrientedBoundingBox &box, const core::Dtype &dtype=core::Float32, const core::Device &device=core::Device("CPU:0"))
core::Tensor GetPointIndicesWithinBoundingBox(const core::Tensor &points) const
Indices to points that are within the bounding box.
std::string ToString() const
Text description.
void SetRotation(const core::Tensor &rotation)
Set the rotation matrix of the box. If the data type of the given tensor differs from the data type o...
double Volume() const
Returns the volume of the bounding box.
void SetColor(const core::Tensor &color)
Set the color of the box.
constexpr bool has_value() const noexcept
Definition: Optional.h:440
constexpr T const & value() const &
Definition: Optional.h:465
static ecvOrientedBBox CreateFromPoints(const std::vector< Eigen::Vector3d > &points)
#define LogWarning(...)
Definition: Logging.h:72
#define LogError(...)
Definition: Logging.h:60
core::Tensor EigenMatrixToTensor(const Eigen::MatrixBase< Derived > &matrix)
Converts a eigen matrix of shape (M, N) with alignment A and type T to a tensor.
std::vector< Eigen::Vector3d > TensorToEigenVector3dVector(const core::Tensor &tensor)
Converts a tensor of shape (N, 3) to std::vector<Eigen::Vector3d>. An exception will be thrown if the...
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > TensorToEigenMatrixXd(const core::Tensor &tensor)
Converts a 2D tensor to Eigen::MatrixXd of same shape. Regardless of the tensor dtype,...
Tensor Concatenate(const std::vector< Tensor > &tensors, const utility::optional< int64_t > &axis)
Concatenates the list of tensors in their order, along the given axis into a new tensor....
const Dtype Bool
Definition: Dtype.cpp:52
void Zeros(benchmark::State &state, const Device &device)
Definition: Zeros.cpp:16
const Dtype Float64
Definition: Dtype.cpp:43
Tensor Minimum(const Tensor &input, const Tensor &other)
Computes the element-wise minimum of input and other. The tensors must have same data type and device...
Tensor Maximum(const Tensor &input, const Tensor &other)
Computes the element-wise maximum of input and other. The tensors must have same data type and device...
const Dtype Float32
Definition: Dtype.cpp:42
OrientedBoundingBox ComputeMinimumOBBApprox(const core::Tensor &points, bool robust)
OrientedBoundingBox ComputeMinimumOBBJylanki(const core::Tensor &points_, bool robust)
Definition: MinimumOBB.cpp:55
void GetPointMaskWithinAABB(const core::Tensor &points, const core::Tensor &min_bound, const core::Tensor &max_bound, core::Tensor &mask)
Definition: PointCloud.cpp:101
void GetPointMaskWithinOBB(const core::Tensor &points, const core::Tensor &center, const core::Tensor &rotation, const core::Tensor &extent, core::Tensor &mask)
Definition: PointCloud.cpp:126
@ MINIMAL_APPROX
Minimal OBB approximation.
@ PCA
Principal Component Analysis.
@ MINIMAL_JYLANKI
Minimal OBB by Jylanki.
constexpr nullopt_t nullopt
Definition: Optional.h:136
Generic file read and write utility for python interface.