UFO 1.0.0
An Efficient Probabilistic 3D Mapping Framework That Embraces the Unknown
Loading...
Searching...
No Matches
line.hpp
1
42#ifndef UFO_GEOMETRY_LINE_HPP
43#define UFO_GEOMETRY_LINE_HPP
44
45// UFO
46#include <ufo/geometry/aabb.hpp>
47#include <ufo/numeric/vec.hpp>
48
49// STL
50#include <concepts>
51#include <cstddef>
52#include <format>
53#include <limits>
54#include <ostream>
55
56namespace ufo
57{
58template <std::size_t Dim = 3, std::floating_point T = float>
59struct Line {
60 using value_type = T;
61
66
71
75 constexpr Line() noexcept = default;
76
80 constexpr Line(Line const&) noexcept = default;
81
88 constexpr Line(Vec<Dim, T> const& origin, Vec<Dim, T> const& direction) noexcept
90 {
91 }
92
100 [[nodiscard]] static constexpr Line fromPoints(Vec<Dim, T> const& v_1,
101 Vec<Dim, T> const& v_2) noexcept
102 {
103 return Line(v_1, v_2 - v_1);
104 }
105
112 template <std::convertible_to<T> U>
113 constexpr explicit Line(Line<Dim, U> const& other) noexcept
114 : origin(Vec<Dim, T>(other.origin)), direction(Vec<Dim, T>(other.direction))
115 {
116 }
117
122 [[nodiscard]] static constexpr std::size_t dimension() noexcept { return Dim; }
123
127 [[nodiscard]] constexpr Line& operator=(Line const&) noexcept = default;
128
133 [[nodiscard]] constexpr bool isDegenerate() const noexcept
134 {
135 return dot(direction, direction) < std::numeric_limits<T>::epsilon();
136 }
137
142 [[nodiscard]] constexpr Vec<Dim, T> center() const noexcept { return origin; }
143
149 [[nodiscard]] constexpr Vec<Dim, T> at(T t) const noexcept
150 {
151 return origin + t * direction;
152 }
153
158 [[nodiscard]] constexpr T diameter() const noexcept
159 {
160 return std::numeric_limits<T>::infinity();
161 }
162
167 [[nodiscard]] constexpr T volume() const noexcept { return T(0); }
168
173 [[nodiscard]] constexpr AABB<Dim, T> aabb() const noexcept
174 {
175 // A line is infinite
176 return AABB<Dim, T>(Vec<Dim, T>(-std::numeric_limits<T>::infinity()),
177 Vec<Dim, T>(std::numeric_limits<T>::infinity()));
178 }
179};
180
190template <std::size_t Dim, std::floating_point T>
191[[nodiscard]] constexpr Vec<Dim, T> intersectionPoint(Line<Dim, T> const& a,
192 Line<Dim, T> const& b)
193{
194 if constexpr (2 == Dim) {
195 T det = a.direction.x() * b.direction.y() - a.direction.y() * b.direction.x();
196 if (std::abs(det) < std::numeric_limits<T>::epsilon()) {
197 return Vec<Dim, T>(std::numeric_limits<T>::infinity());
198 }
199 T t = ((b.origin.x() - a.origin.x()) * b.direction.y() -
200 (b.origin.y() - a.origin.y()) * b.direction.x()) /
201 det;
202 return a.origin + t * a.direction;
203 } else if constexpr (3 == Dim) {
204 Vec<3, T> w0 = a.origin - b.origin;
205 T a_dot = T(1); // a.direction is normalized
206 T b_dot = T(1); // b.direction is normalized
207 T ab_dot = dot(a.direction, b.direction);
208 T aw_dot = dot(a.direction, w0);
209 T bw_dot = dot(b.direction, w0);
210 T denom = a_dot * b_dot - ab_dot * ab_dot;
211 if (std::abs(denom) < std::numeric_limits<T>::epsilon()) {
212 return Vec<Dim, T>(std::numeric_limits<T>::infinity());
213 }
214 T sc = (ab_dot * bw_dot - b_dot * aw_dot) / denom;
215 return a.origin + sc * a.direction;
216 } else {
217 // TODO: Implement for 4D
218 return Vec<Dim, T>(std::numeric_limits<T>::quiet_NaN());
219 }
220}
221
225template <std::size_t Dim, std::floating_point T>
226[[nodiscard]] bool operator==(Line<Dim, T> const& lhs, Line<Dim, T> const& rhs) noexcept
227{
228 // Lines are equal if they are collinear (same direction and origin lies on the other
229 // line) Or same origin and direction/opposite direction
230 T d = dot(lhs.direction, rhs.direction);
231 if (std::abs(std::abs(d) - T(1)) > std::numeric_limits<T>::epsilon()) {
232 return false;
233 }
234 Vec<Dim, T> diff = lhs.origin - rhs.origin;
235 if (normSquared(diff) < std::numeric_limits<T>::epsilon()) {
236 return true;
237 }
238 diff = normalize(diff);
239 return std::abs(std::abs(dot(diff, lhs.direction)) - T(1)) <
240 std::numeric_limits<T>::epsilon();
241}
242
246template <std::size_t Dim, std::floating_point T>
247std::ostream& operator<<(std::ostream& out, Line<Dim, T> const& line)
248{
249 return out << "Origin: [" << line.origin << "], Direction: [" << line.direction << "]";
250}
251
252template <std::floating_point T>
253using Line1 = Line<1, T>;
254template <std::floating_point T>
255using Line2 = Line<2, T>;
256template <std::floating_point T>
257using Line3 = Line<3, T>;
258template <std::floating_point T>
259using Line4 = Line<4, T>;
260
261using Line1f = Line<1, float>;
262using Line2f = Line<2, float>;
263using Line3f = Line<3, float>;
264using Line4f = Line<4, float>;
265
266using Line1d = Line<1, double>;
267using Line2d = Line<2, double>;
268using Line3d = Line<3, double>;
269using Line4d = Line<4, double>;
270
271} // namespace ufo
272
273template <std::size_t Dim, std::floating_point T>
274 requires std::formattable<T, char>
275struct std::formatter<ufo::Line<Dim, T>> {
276 constexpr auto parse(std::format_parse_context& ctx) { return ctx.begin(); }
277
278 auto format(ufo::Line<Dim, T> const& line, std::format_context& ctx) const
279 {
280 return std::format_to(ctx.out(), "Origin: [{}], Direction: [{}]", line.origin,
281 line.direction);
282 }
283};
284
285#endif // UFO_GEOMETRY_LINE_HPP
constexpr T dot(Quat< T > const &a, Quat< T > const &b) noexcept
Computes the four-component dot product a.w*b.w + a.x*b.x + a.y*b.y + a.z*b.z.
Definition quat.hpp:643
All vision-related classes and functions.
Definition cloud.hpp:49
constexpr T normSquared(Quat< T > const &q) noexcept
Returns the squared norm (dot product with itself).
Definition quat.hpp:655
constexpr T b(Lab< T, Flags > color) noexcept
Returns the un-weighted blue–yellow axis value.
Definition lab.hpp:326
constexpr T a(Lab< T, Flags > color) noexcept
Returns the un-weighted green–red axis value.
Definition lab.hpp:310
constexpr Vec< Dim, T > intersectionPoint(Line< Dim, T > const &a, Line< Dim, T > const &b)
Computes the intersection point of two lines.
Definition line.hpp:191
constexpr Quat< T > normalize(Quat< T > const &q) noexcept
Returns a unit quaternion in the same direction as q.
Definition quat.hpp:679
Axis-Aligned Bounding Box (AABB) in Dim-dimensional space.
Definition aabb.hpp:70
constexpr Vec< Dim, T > center() const noexcept
Returns the center of the line.
Definition line.hpp:142
constexpr Line() noexcept=default
Default constructor.
static constexpr Line fromPoints(Vec< Dim, T > const &v_1, Vec< Dim, T > const &v_2) noexcept
Constructs a line from two points.
Definition line.hpp:100
static constexpr std::size_t dimension() noexcept
Returns the dimensionality of the line.
Definition line.hpp:122
constexpr AABB< Dim, T > aabb() const noexcept
Returns the AABB of the line.
Definition line.hpp:173
constexpr bool isDegenerate() const noexcept
Returns whether the line is degenerate.
Definition line.hpp:133
constexpr Vec< Dim, T > at(T t) const noexcept
Returns the point at distance t along the line.
Definition line.hpp:149
Vec< Dim, T > origin
The origin point of the line.
Definition line.hpp:65
Vec< Dim, T > direction
The direction of the line.
Definition line.hpp:70
constexpr Line & operator=(Line const &) noexcept=default
Copy assignment operator.
constexpr T volume() const noexcept
Returns the volume of the line.
Definition line.hpp:167
constexpr T diameter() const noexcept
Returns the diameter of the line.
Definition line.hpp:158
constexpr Line(Line< Dim, U > const &other) noexcept
Converting constructor from a line with a different scalar type.
Definition line.hpp:113
A fixed-size arithmetic vector of up to 4 dimensions.
Definition vec.hpp:76
constexpr auto & x(this auto &self) noexcept
Accesses the first component (x).
Definition vec.hpp:136