OPALX (Object Oriented Parallel Accelerator Library for Exascal) MINIorX
OPALX
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#include "Ippl.h"
23
24#include <iomanip>
25#include <limits>
26
28 : lowerLeftCorner_m(std::numeric_limits<double>::max()),
29 upperRightCorner_m(std::numeric_limits<double>::lowest()) {
30}
31
33 BoundingBox boundingBox;
34 for (const Vector_t<double, 3>& position : positions) {
35 boundingBox.enlargeToContainPosition(position);
36 }
37
38 return boundingBox;
39}
40
42 for (unsigned int d = 0; d < 3; ++d) {
43 lowerLeftCorner_m[d] = std::min(lowerLeftCorner_m[d], position[d]);
44 upperRightCorner_m[d] = std::max(upperRightCorner_m[d], position[d]);
45 }
46}
47
49 for (unsigned int d = 0; d < 3; ++d) {
50 lowerLeftCorner_m[d] = std::min(lowerLeftCorner_m[d], boundingBox.lowerLeftCorner_m[d]);
51 upperRightCorner_m[d] = std::max(upperRightCorner_m[d], boundingBox.upperRightCorner_m[d]);
52 }
53}
54
55boost::optional<Vector_t<double, 3>> BoundingBox::getIntersectionPoint(
56
57 const Vector_t<double, 3>& position, const Vector_t<double, 3>& direction) const {
58 boost::optional<Vector_t<double, 3>> result = boost::none;
59 double minDistance = std::numeric_limits<double>::max();
61 Vector_t<double, 3> normal(1, 0, 0);
62 for (unsigned int d = 0; d < 3; ++d) {
63 double sign = -1;
64 Vector_t<double, 3> upperCorner =
65 lowerLeftCorner_m + dot(normal, upperRightCorner_m) * normal;
66 for (const Vector_t<double, 3>& p0 : {lowerLeftCorner_m, upperCorner}) {
67 normal *= sign;
68 const Vector_t<double, 3> dp = p0 - position;
69 double tau = dot(dp, Vector_t<double, 3>(sign)) / dot(direction, normal);
70 if (tau < 0.0) {
71 continue;
72 }
73 Vector_t<double, 3> pointOnPlane = position + tau * direction;
74 Vector_t<double, 3> relativeP = pointOnPlane - p0;
75 bool isOnFace = true;
76 for (unsigned int i = 1; i < 3; ++i) {
77 unsigned int idx = (d + i) % 3;
78 if (relativeP[idx] < 0 || relativeP[idx] > dimensions[idx]) {
79 isOnFace = false;
80 break;
81 }
82 }
83 if (isOnFace) {
84 Vector<double, 3> d = pointOnPlane - position;
85 double distance = euclidean_norm(d);
86 if (distance < minDistance) {
87 minDistance = distance;
88 result = pointOnPlane;
89 }
90 }
91 sign *= -1;
92 }
93
94 normal = Vector_t<double, 3>(normal[2], normal[0], normal[1]);
95 }
96
97 return result;
98}
99
100bool BoundingBox::isInside(const Vector_t<double, 3>& position) const {
101 Vector_t<double, 3> relPosition = position - lowerLeftCorner_m;
103 for (unsigned int d = 0; d < 3; ++d) {
104 if (relPosition[d] < 0 || relPosition[d] > dimensions[d])
105 return false;
106 }
107 return true;
108}
109
110void BoundingBox::print(std::ostream& output) const {
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}
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition Vector3D.cpp:118
ippl::Vector< T, Dim > Vector_t
KOKKOS_INLINE_FUNCTION double euclidean_norm(const Vector_t< T, D > &v)
Definition OPALTypes.h:35
STL namespace.
void print(std::ostream &output) const
Vector_t< double, 3 > lowerLeftCorner_m
Definition BoundingBox.h:52
boost::optional< Vector_t< double, 3 > > getIntersectionPoint(const Vector_t< double, 3 > &position, const Vector_t< double, 3 > &direction) const
Vector_t< double, 3 > upperRightCorner_m
Definition BoundingBox.h:53
bool isInside(const Vector_t< double, 3 > &position) const
void enlargeToContainPosition(const Vector_t< double, 3 > &position)
static BoundingBox getBoundingBox(const std::vector< Vector_t< double, 3 > > &positions)
void enlargeToContainBoundingBox(const BoundingBox &boundingBox)