OPAL (Object Oriented Parallel Accelerator Library)  2024.1
OPAL
BoundingBox.cpp
Go to the documentation of this file.
1 //
2 // Class BoundingBox
3 //
4 // This class provides functionality to compute bounding boxes, to compute if a position
5 // is inside the box and to compute the intersection point between a ray and the bounding box.
6 //
7 // Copyright (c) 201x - 2021, Paul Scherrer Institut, Villigen PSI, Switzerland
8 //
9 // All rights reserved
10 //
11 // This file is part of OPAL.
12 //
13 // OPAL is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation, either version 3 of the License, or
16 // (at your option) any later version.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
20 //
21 #include "BoundingBox.h"
22 
23 #include <iomanip>
24 #include <limits>
25 
27  lowerLeftCorner_m(std::numeric_limits<double>::max()),
28  upperRightCorner_m(std::numeric_limits<double>::lowest())
29 {}
30 
31 BoundingBox BoundingBox::getBoundingBox(const std::vector<Vector_t>& positions)
32 {
33  BoundingBox boundingBox;
34  for (const Vector_t& position : positions) {
35  boundingBox.enlargeToContainPosition(position);
36  }
37 
38  return boundingBox;
39 }
40 
42 {
43  for (unsigned int d = 0; d < 3; ++ d) {
44  lowerLeftCorner_m[d] = std::min(lowerLeftCorner_m[d], position[d]);
45  upperRightCorner_m[d] = std::max(upperRightCorner_m[d], position[d]);
46  }
47 }
48 
50 {
51  for (unsigned int d = 0; d < 3; ++ d) {
54  }
55 }
56 
57 boost::optional<Vector_t> BoundingBox::getIntersectionPoint(const Vector_t& position,
58  const Vector_t& direction) const
59 {
60  boost::optional<Vector_t> result = boost::none;
61  double minDistance = std::numeric_limits<double>::max();
62  const Vector_t dimensions = upperRightCorner_m - lowerLeftCorner_m;
63  Vector_t normal(1, 0, 0);
64  for (unsigned int d = 0; d < 3; ++ d) {
65  double sign = -1;
66  Vector_t upperCorner = lowerLeftCorner_m + dot(normal, upperRightCorner_m) * normal;
67  for (const Vector_t& p0 : {lowerLeftCorner_m, upperCorner}) {
68  double tau = dot(p0 - position, sign * normal) / dot(direction, sign * normal);
69  if (tau < 0.0) {
70  continue;
71  }
72  Vector_t pointOnPlane = position + tau * direction;
73  Vector_t relativeP = pointOnPlane - p0;
74  bool isOnFace = true;
75  for (unsigned int i = 1; i < 3; ++ i) {
76  unsigned int idx = (d + i) % 3;
77  if (relativeP[idx] < 0 ||
78  relativeP[idx] > dimensions[idx]) {
79  isOnFace = false;
80  break;
81  }
82  }
83  if (isOnFace) {
84  double distance = euclidean_norm(pointOnPlane - position);
85  if (distance < minDistance) {
86  minDistance = distance;
87  result = pointOnPlane;
88  }
89  }
90  sign *= -1;
91  }
92 
93  normal = Vector_t(normal[2], normal[0], normal[1]);
94  }
95 
96  return result;
97 }
98 
99 bool BoundingBox::isInside(const Vector_t& position) const
100 {
101  Vector_t relPosition = position - lowerLeftCorner_m;
103  for (unsigned int d = 0; d < 3; ++ d) {
104  if (relPosition[d] < 0 || relPosition[d] > dimensions[d]) return false;
105  }
106  return true;
107 }
108 
109 void BoundingBox::print(std::ostream& output) const
110 {
111  int prePrecision = output.precision();
112  output << std::setprecision(8);
113  output << "Bounding box\n"
114  << "lower left corner: " << lowerLeftCorner_m << "\n"
115  << "upper right corner: " << upperRightCorner_m << std::endl;
116  output.precision(prePrecision);
117 }
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6
void enlargeToContainPosition(const Vector_t &position)
Definition: BoundingBox.cpp:41
int precision() const
Definition: Inform.h:112
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:76
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:84
T euclidean_norm(const Vector< T > &)
Euclidean norm.
Definition: Vector.h:243
FnArg FnReal sign(a))
void enlargeToContainBoundingBox(const BoundingBox &boundingBox)
Definition: BoundingBox.cpp:49
static BoundingBox getBoundingBox(const std::vector< Vector_t > &positions)
Definition: BoundingBox.cpp:31
bool isInside(const Vector_t &position) const
Definition: BoundingBox.cpp:99
Vector_t lowerLeftCorner_m
Definition: BoundingBox.h:52
boost::optional< Vector_t > getIntersectionPoint(const Vector_t &position, const Vector_t &direction) const
Definition: BoundingBox.cpp:57
float result
Definition: test.py:2
void print(std::ostream &output) const
Vector_t upperRightCorner_m
Definition: BoundingBox.h:53
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition: Vector3D.cpp:118