OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
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
32 BoundingBox boundingBox;
33 for (const Vector_t<double, 3>& position : positions) {
34 boundingBox.enlargeToContainPosition(position);
35 }
36
37 return boundingBox;
38}
39
41 for (unsigned int d = 0; d < 3; ++d) {
42 lowerLeftCorner_m[d] = std::min(lowerLeftCorner_m[d], position[d]);
43 upperRightCorner_m[d] = std::max(upperRightCorner_m[d], position[d]);
44 }
45}
46
48 for (unsigned int d = 0; d < 3; ++d) {
49 lowerLeftCorner_m[d] = std::min(lowerLeftCorner_m[d], boundingBox.lowerLeftCorner_m[d]);
50 upperRightCorner_m[d] = std::max(upperRightCorner_m[d], boundingBox.upperRightCorner_m[d]);
51 }
52}
53
54std::optional<Vector_t<double, 3>> BoundingBox::getIntersectionPoint(
55 const Vector_t<double, 3>& position, const Vector_t<double, 3>& direction) const {
56 std::optional<Vector_t<double, 3>> result = std::nullopt;
57 double minDistance = std::numeric_limits<double>::max();
59 Vector_t<double, 3> normal(1, 0, 0);
60
61 for (unsigned int d = 0; d < 3; ++d) {
62 double sign = -1;
63
64 Vector_t<double, 3> upperCorner =
65 lowerLeftCorner_m + dot(normal, upperRightCorner_m) * normal;
66
67 for (const Vector_t<double, 3>& p0 : {lowerLeftCorner_m, upperCorner}) {
68 normal *= sign;
69
70 const Vector_t<double, 3> dp = p0 - position;
71 double tau = dot(dp, Vector_t<double, 3>(sign)) / dot(direction, normal);
72 if (tau < 0.0) continue;
73
74 Vector_t<double, 3> pointOnPlane = position + tau * direction;
75 Vector_t<double, 3> relativeP = pointOnPlane - p0;
76
77 bool isOnFace = true;
78 for (unsigned int i = 1; i < 3; ++i) {
79 unsigned int idx = (d + i) % 3;
80 if (relativeP[idx] < 0 || relativeP[idx] > dimensions[idx]) {
81 isOnFace = false;
82 break;
83 }
84 }
85
86 if (isOnFace) {
87 Vector_t<double, 3> delta = pointOnPlane - position;
88 double distance = euclidean_norm(delta);
89 if (distance < minDistance) {
90 minDistance = distance;
91 result = pointOnPlane;
92 }
93 }
94
95 sign *= -1;
96 }
97
98 normal = Vector_t<double, 3>(normal[2], normal[0], normal[1]);
99 }
100 return result;
101}
102
103bool BoundingBox::isInside(const Vector_t<double, 3>& position) const {
104 Vector_t<double, 3> relPosition = position - lowerLeftCorner_m;
106 for (unsigned int d = 0; d < 3; ++d) {
107 if (relPosition[d] < 0 || relPosition[d] > dimensions[d]) return false;
108 }
109 return true;
110}
111
112void BoundingBox::print(std::ostream& output) const {
113 int prePrecision = output.precision();
114 output << std::setprecision(8);
115 output << "Bounding box\n"
116 << "lower left corner: " << lowerLeftCorner_m << "\n"
117 << "upper right corner: " << upperRightCorner_m << std::endl;
118 output.precision(prePrecision);
119}
ippl::Vector< T, Dim > Vector_t
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition Vector3D.cpp:95
KOKKOS_INLINE_FUNCTION double euclidean_norm(const Vector_t< T, D > &v)
Definition VectorMath.h:15
void print(std::ostream &output) const
Vector_t< double, 3 > lowerLeftCorner_m
Definition BoundingBox.h:51
Vector_t< double, 3 > upperRightCorner_m
Definition BoundingBox.h:52
bool isInside(const Vector_t< double, 3 > &position) const
void enlargeToContainPosition(const Vector_t< double, 3 > &position)
std::optional< Vector_t< double, 3 > > getIntersectionPoint(const Vector_t< double, 3 > &position, const Vector_t< double, 3 > &direction) const
static BoundingBox getBoundingBox(const std::vector< Vector_t< double, 3 > > &positions)
void enlargeToContainBoundingBox(const BoundingBox &boundingBox)
STL namespace.