Antkeeper  0.0.1
coordinates.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_COORDINATES_HPP
21 #define ANTKEEPER_GEOM_COORDINATES_HPP
22 
24 #include <bit>
25 #include <cstdint>
26 #include <cmath>
27 
28 namespace geom {
29 
33 enum class triangle_region: std::uint8_t
34 {
36  abc = 0b000,
37 
39  ab = 0b100,
40 
42  bc = 0b001,
43 
45  ca = 0b010,
46 
48  a = 0b110,
49 
51  b = 0b101,
52 
54  c = 0b011
55 };
56 
64 [[nodiscard]] inline constexpr bool is_face_region(triangle_region region) noexcept
65 {
66  return !static_cast<bool>(region);
67 }
68 
76 [[nodiscard]] inline constexpr bool is_edge_region(triangle_region region) noexcept
77 {
78  return std::has_single_bit(static_cast<std::uint8_t>(region));
79 }
80 
88 [[nodiscard]] inline constexpr bool is_vertex_region(triangle_region region) noexcept
89 {
90  return static_cast<bool>(region) && !std::has_single_bit(static_cast<std::uint8_t>(region));
91 }
92 
100 [[nodiscard]] inline constexpr std::uint8_t edge_index(triangle_region region) noexcept
101 {
102  return static_cast<std::uint8_t>(region) & std::uint8_t{0b11};
103 }
104 
112 [[nodiscard]] inline constexpr std::uint8_t vertex_index(triangle_region region) noexcept
113 {
114  return std::uint8_t{3} - (static_cast<std::uint8_t>(region) >> 1);
115 }
116 
126 template <class T>
127 [[nodiscard]] constexpr triangle_region barycentric_to_region(const point<T, 3>& p) noexcept
128 {
129  std::uint8_t region = static_cast<std::uint8_t>(p.x() <= T{0});
130  region |= static_cast<std::uint8_t>(p.y() <= T{0}) << std::uint8_t{1};
131  region |= static_cast<std::uint8_t>(p.z() <= T{0}) << std::uint8_t{2};
132  return static_cast<triangle_region>(region);
133 }
134 
147 template <class T>
148 [[nodiscard]] inline constexpr point<T, 3> barycentric_to_cartesian(const point<T, 3>& p, const point<T, 3>& a, const point<T, 3>& b, const point<T, 3>& c) noexcept
149 {
150  return a * p.x() + b * p.y() + c * p.z();
151 }
152 
165 template <class T>
166 [[nodiscard]] constexpr point<T, 3> cartesian_to_barycentric(const point<T, 3>& p, const point<T, 3>& a, const point<T, 3>& b, const point<T, 3>& c) noexcept
167 {
168  point<T, 3> uvw;
169 
170  // Cross product version:
171  const auto ab = b - a;
172  const auto ca = a - c;
173  const auto ap = p - a;
174  const auto n = math::cross(ab, ca);
175  const auto d = math::sqr_length(n);
176  const auto q = math::cross(n, ap);
177  uvw.z() = math::dot(q, ab) / d;
178  uvw.y() = math::dot(q, ca) / d;
179  uvw.x() = T{1} - uvw.y() - uvw.z();
180 
181  // Dot product version:
182  // const auto ab = b - a;
183  // const auto ac = c - a;
184  // const auto ap = p - a;
185  // const auto ab_dot_ab = math::dot(ab, ab);
186  // const auto ab_dot_ac = math::dot(ab, ac);
187  // const auto ac_dot_ac = math::dot(ac, ac);
188  // const auto ap_dot_ab = math::dot(ap, ab);
189  // const auto ap_dot_ac = math::dot(ap, ac);
190  // const auto d = ab_dot_ab * ac_dot_ac - ab_dot_ac * ab_dot_ac;
191  // uvw.z() = (ab_dot_ab * ap_dot_ac - ab_dot_ac * ap_dot_ab) / d;
192  // uvw.y() = (ac_dot_ac * ap_dot_ab - ab_dot_ac * ap_dot_ac) / d;
193  // uvw.x() = T{1} - uvw.y() - uvw.z();
194 
195  return uvw;
196 }
197 
207 template <class T>
209 {
210  const T xx_yy = p.x() * p.x() + p.y() * p.y();
211 
212  return
213  {
214  std::sqrt(xx_yy + p.z() * p.z()),
215  std::atan2(p.z(), std::sqrt(xx_yy)),
216  std::atan2(p.y(), p.x())
217  };
218 }
219 
229 template <class T>
231 {
232  const T x = p.x() * std::cos(p.y());
233 
234  return
235  {
236  x * std::cos(p.z()),
237  x * std::sin(p.z()),
238  p.x() * std::sin(p.y())
239  };
240 }
241 
242 } // namespace geom
243 
244 #endif // ANTKEEPER_GEOM_COORDINATES_HPP
Geometric algorithms.
constexpr bool is_edge_region(triangle_region region) noexcept
Checks whether a triangle voronoi region is an edge region.
Definition: coordinates.hpp:76
point< T, 3 > spherical_to_cartesian(const point< T, 3 > &p)
Converts spherical coordinates to Cartesian (rectangular) coordinates.
constexpr std::uint8_t vertex_index(triangle_region region) noexcept
Returns the vertex index of a vertex region.
constexpr point< T, 3 > barycentric_to_cartesian(const point< T, 3 > &p, const point< T, 3 > &a, const point< T, 3 > &b, const point< T, 3 > &c) noexcept
Converts Cartesian coordinates to barycentric coordinates.
point< T, 3 > cartesian_to_spherical(const point< T, 3 > &p)
Converts Cartesian (rectangular) coordinates to spherical coordinates.
constexpr bool is_face_region(triangle_region region) noexcept
Checks whether a triangle voronoi region is a face region.
Definition: coordinates.hpp:64
triangle_region
Voronoi regions of a triangle.
Definition: coordinates.hpp:34
@ a
Vertex A region.
@ ab
Edge AB region.
@ c
Vertex C region.
@ bc
Edge BC region.
@ ca
Edge CA region.
@ abc
Face ABC region.
@ b
Vertex B region.
constexpr point< T, 3 > cartesian_to_barycentric(const point< T, 3 > &p, const point< T, 3 > &a, const point< T, 3 > &b, const point< T, 3 > &c) noexcept
Converts Cartesian coordinates to barycentric coordinates.
constexpr bool is_vertex_region(triangle_region region) noexcept
Checks whether a triangle voronoi region is a vertex region.
Definition: coordinates.hpp:88
constexpr triangle_region barycentric_to_region(const point< T, 3 > &p) noexcept
Classifies barycentric coordinates according to their Voronoi region.
constexpr std::uint8_t edge_index(triangle_region region) noexcept
Returns the edge index of an edge region.
constexpr T sqr_length(const quaternion< T > &q) noexcept
Calculates the square length of a quaternion.
Definition: quaternion.hpp:744
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
n-dimensional vector.
Definition: vector.hpp:44
constexpr element_type & x() noexcept
Returns a reference to the first element.
Definition: vector.hpp:164
constexpr element_type & y() noexcept
Returns a reference to the second element.
Definition: vector.hpp:180
constexpr element_type & z() noexcept
Returns a reference to the third element.
Definition: vector.hpp:196