Antkeeper  0.0.1
intersection.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Christopher J. Howard
3  *
4  * This file is part of Antkeeper source code.
5  *
6  * Antkeeper source code is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Antkeeper source code is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef ANTKEEPER_GEOM_INTERSECTION_HPP
21 #define ANTKEEPER_GEOM_INTERSECTION_HPP
22 
27 #include <algorithm>
28 #include <optional>
29 
30 namespace geom {
31 
41 template <class T, std::size_t N>
42 [[nodiscard]] constexpr std::optional<T> intersection(const ray<T, N>& ray, const hyperplane<T, N>& hyperplane) noexcept
43 {
44  const T cos_theta = math::dot(ray.direction, hyperplane.normal);
45  if (cos_theta != T{0})
46  {
47  const T t = -hyperplane.distance(ray.origin) / cos_theta;
48  if (t >= T{0})
49  {
50  return t;
51  }
52  }
53 
54  return std::nullopt;
55 }
56 
57 template <class T, std::size_t N>
58 [[nodiscard]] inline constexpr std::optional<T> intersection(const hyperplane<T, N>& hyperplane, const ray<T, N>& ray) noexcept
59 {
60  return intersection<T, N>(ray, hyperplane);
61 }
63 
73 template <class T, std::size_t N>
74 [[nodiscard]] constexpr std::optional<std::tuple<T, T>> intersection(const ray<T, N>& ray, const hyperrectangle<T, N>& hyperrectangle) noexcept
75 {
76  T t0 = -std::numeric_limits<T>::infinity();
77  T t1 = std::numeric_limits<T>::infinity();
78 
79  for (std::size_t i = 0; i < N; ++i)
80  {
81  if (!ray.direction[i])
82  {
83  if (ray.origin[i] < hyperrectangle.min[i] || ray.origin[i] > hyperrectangle.max[i])
84  {
85  return std::nullopt;
86  }
87  }
88  else
89  {
90  T min = (hyperrectangle.min[i] - ray.origin[i]) / ray.direction[i];
91  T max = (hyperrectangle.max[i] - ray.origin[i]) / ray.direction[i];
92  t0 = std::max(t0, std::min(min, max));
93  t1 = std::min(t1, std::max(min, max));
94  }
95  }
96 
97  if (t0 > t1 || t1 < T{0})
98  {
99  return std::nullopt;
100  }
101 
102  return std::tuple<T, T>{t0, t1};
103 }
104 
105 template <class T, std::size_t N>
106 [[nodiscard]] inline constexpr std::optional<std::tuple<T, T>> intersection(const hyperrectangle<T, N>& hyperrectangle, const ray<T, N>& ray) noexcept
107 {
108  return intersection<T, N>(ray, hyperrectangle);
109 }
111 
122 template <class T, std::size_t N>
123 [[nodiscard]] std::optional<std::tuple<T, T>> intersection(const ray<T, N>& ray, const hypersphere<T, N>& hypersphere) noexcept
124 {
126  const T b = math::dot(d, ray.direction);
127  const math::vector<T, N> qc = d - ray.direction * b;
128  const T h = hypersphere.radius * hypersphere.radius - math::dot(qc, qc);
129 
130  if (h < T{0})
131  {
132  return std::nullopt;
133  }
134 
135  const T sqrt_h = std::sqrt(h);
136  return std::tuple<T, T>{-b - sqrt_h, -b + sqrt_h};
137 }
138 
148 template <class T>
149 [[nodiscard]] constexpr std::optional<std::tuple<T, T, T>> intersection(const ray<T, 3>& ray, const math::vec3<T>& a, const math::vec3<T>& b, const math::vec3<T>& c) noexcept
150 {
151  // Find edges
152  const math::vec3<T> edge_ab = b - a;
153  const math::vec3<T> edge_ac = c - a;
154 
155  // Calculate determinant
156  const math::vec3<T> pv = math::cross(ray.direction, edge_ac);
157  const T det = math::dot(edge_ab, pv);
158  if (!det)
159  {
160  return std::nullopt;
161  }
162 
163  const T inverse_det = T{1} / det;
164 
165  // Calculate u
166  const math::vec3<T> tv = ray.origin - a;
167  const T u = math::dot(tv, pv) * inverse_det;
168  if (u < T{0} || u > T{1})
169  {
170  return std::nullopt;
171  }
172 
173  // Calculate v
174  const math::vec3<T> qv = math::cross(tv, edge_ab);
175  const T v = math::dot(ray.direction, qv) * inverse_det;
176  if (v < T{0} || u + v > T{1})
177  {
178  return std::nullopt;
179  }
180 
181  // Calculate t
182  const T t = math::dot(edge_ac, qv) * inverse_det;
183  if (t < T{0})
184  {
185  return std::nullopt;
186  }
187 
188  return std::tuple<T, T, T>{t, u, v};
189 }
190 template <class T>
191 [[nodiscard]] inline constexpr std::optional<std::tuple<T, T, T>> intersection(const math::vec3<T>& a, const math::vec3<T>& b, const math::vec3<T>& c, const ray<T, 3>& ray) noexcept
192 {
193  return intersection(ray, a, b, c);
194 }
196 
205 template <class T, std::size_t N>
206 [[nodiscard]] inline constexpr bool intersection(const hyperrectangle<T, N>& a, const hyperrectangle<T, N>& b) noexcept
207 {
208  return a.intersects(b);
209 }
210 
220 template <class T, std::size_t N>
221 [[nodiscard]] constexpr bool intersection(const hyperrectangle<T, N>& hyperrectangle, const hypersphere<T, N>& hypersphere) noexcept
222 {
223  T sqr_distance{0};
224  for (std::size_t i = 0; i < N; ++i)
225  {
226  if (hypersphere.center[i] < hyperrectangle.min[i])
227  {
228  const T difference = hyperrectangle.min[i] - hypersphere.center[i];
230  }
231  else if (hypersphere.center[i] > hyperrectangle.max[i])
232  {
233  const T difference = hypersphere.center[i] - hyperrectangle.max[i];
235  }
236  }
237 
239 }
240 
241 template <class T, std::size_t N>
242 [[nodiscard]] inline constexpr bool intersection(const hypersphere<T, N>& hypersphere, const hyperrectangle<T, N>& hyperrectangle) noexcept
243 {
244  return intersection<T, N>(hyperrectangle, hypersphere);
245 }
247 
256 template <class T, std::size_t N>
257 [[nodiscard]] inline constexpr bool intersection(const hypersphere<T, N>& a, const hypersphere<T, N>& b) noexcept
258 {
259  return a.intersects(b);
260 }
261 
262 } // namespace geom
263 
264 #endif // ANTKEEPER_GEOM_INTERSECTION_HPP
constexpr int difference(T x, T y) noexcept
Returns the number of differing bits between two values, known as Hamming distance.
Definition: bit-math.hpp:280
Geometric algorithms.
constexpr std::optional< T > intersection(const ray< T, N > &ray, const hyperplane< T, N > &hyperplane) noexcept
Ray-hyperplane intersection test.
@ a
Vertex A region.
@ c
Vertex C region.
@ b
Vertex B region.
constexpr T sqr_distance(const vector< T, N > &p0, const vector< T, N > &p1) noexcept
Calculates the square distance between two points.
Definition: vector.hpp:1514
constexpr vector< T, N > max(const vector< T, N > &x, const vector< T, N > &y)
Returns a vector containing the maximum elements of two vectors.
Definition: vector.hpp:1328
constexpr vector< T, 3 > cross(const vector< T, 3 > &x, const vector< T, 3 > &y) noexcept
Calculates the cross product of two vectors.
Definition: vector.hpp:1095
vector< T, N > sqrt(const vector< T, N > &x)
Takes the square root of each element.
constexpr T dot(const quaternion< T > &a, const quaternion< T > &b) noexcept
Calculates the dot product of two quaternions.
Definition: quaternion.hpp:572
constexpr vector< T, N > min(const vector< T, N > &x, const vector< T, N > &y)
Returns a vector containing the minimum elements of two vectors.
Definition: vector.hpp:1347
n-dimensional plane.
Definition: hyperplane.hpp:36
constexpr T distance(const vector_type &point) const noexcept
Calculates the signed distance from the hyperplane to a point.
Definition: hyperplane.hpp:78
vector_type normal
Hyperplane normal.
Definition: hyperplane.hpp:41
n-dimensional axis-aligned rectangle.
vector_type min
Minimum extent of the hyperrectangle.
vector_type max
Maximum extent of the hyperrectangle.
n-dimensional sphere.
Definition: hypersphere.hpp:37
vector_type center
Hypersphere center.
Definition: hypersphere.hpp:42
T radius
Hypersphere radius.
Definition: hypersphere.hpp:45
Half of a line proceeding from an initial point.
Definition: ray.hpp:38
vector_type direction
Ray direction vector.
Definition: ray.hpp:46
vector_type origin
Ray origin position.
Definition: ray.hpp:43
n-dimensional vector.
Definition: vector.hpp:44