VIPRA Documentation
Loading...
Searching...
No Matches
line.hpp
1#pragma once
2
3#include "vipra/geometry/f3d.hpp"
4
5#include "vipra/macros/performance.hpp"
6#include "vipra/types/float.hpp"
7
8namespace VIPRA::Geometry {
9enum class Orientation { COLLINEAR, CLOCKWISE, COUNTERCLOCKWISE };
10
11struct Line {
12 VIPRA::f3d start;
13 VIPRA::f3d end;
14
15 // TODO(rolland): issue #18 add more to the line class
16 constexpr Line(VIPRA::f3d start, VIPRA::f3d end) : start(start), end(end) {}
17
18 F3D_FUNC auto length() const noexcept -> VIPRA::f_pnt { return start.distance_to(end); }
19
25 F3D_FUNC auto direction() const noexcept -> VIPRA::f3d { return (end - start).unit(); }
26
35 [[nodiscard]] VIPRA_INLINE static constexpr auto orientation_to(
36 Line line, VIPRA::f3d point) noexcept -> Orientation
37 {
38 VIPRA::f_pnt val = (line.end.y - line.start.y) * (point.x - line.end.x) -
39 (line.end.x - line.start.x) * (point.y - line.end.y);
40
41 if ( val > 0 ) return Orientation::CLOCKWISE;
42 if ( val < 0 ) return Orientation::COUNTERCLOCKWISE;
43 return Orientation::COLLINEAR;
44 }
45
52 [[nodiscard]] VIPRA_INLINE constexpr auto closest_point(VIPRA::f3d point) const noexcept
53 -> VIPRA::f3d
54 {
55 // TODO(rolland): issue #18 verify
56 const VIPRA::f_pnt lineLength = start.distance_to(end);
57
58 if ( lineLength == 0.0 ) return start;
59
60 const VIPRA::f_pnt t =
61 std::max(static_cast<VIPRA::f_pnt>(0.0),
62 std::min(static_cast<VIPRA::f_pnt>(1.0),
63 (point - start).dot(end - start) / (lineLength * lineLength)));
64 return start + (end - start) * t;
65 }
66
74 [[nodiscard]] VIPRA_INLINE constexpr auto is_point_on(VIPRA::f3d point) const -> bool
75 {
76 return point.x <= std::max(start.x, end.x) && point.y <= std::max(start.y, end.y) &&
77 point.x >= std::min(start.x, end.x) && point.y >= std::min(start.y, end.y);
78 }
79
87 [[nodiscard]] VIPRA_INLINE constexpr auto does_intersect(Line other) const noexcept
88 -> bool
89 {
90 return do_intersect(*this, other);
91 }
92
100 [[nodiscard]] constexpr auto intersection_point(Line other) const noexcept -> VIPRA::f3d
101 {
102 assert(does_intersect(other));
103
104 const VIPRA::f_pnt a1 = end.y - start.y;
105 const VIPRA::f_pnt b1 = start.x - end.x;
106 const VIPRA::f_pnt c1 = a1 * start.x + b1 * start.y;
107
108 const VIPRA::f_pnt a2 = other.end.y - other.start.y;
109 const VIPRA::f_pnt b2 = other.start.x - other.end.x;
110 const VIPRA::f_pnt c2 = a2 * other.start.x + b2 * other.start.y;
111
112 const VIPRA::f_pnt determinant = a1 * b2 - a2 * b1;
113
114 if ( determinant == 0 ) return VIPRA::f3d{0, 0, 0};
115
116 const VIPRA::f_pnt x = (b2 * c1 - b1 * c2) / determinant;
117 const VIPRA::f_pnt y = (a1 * c2 - a2 * c1) / determinant;
118
119 return VIPRA::f3d{x, y, 0};
120 }
121
130 [[nodiscard]] static constexpr auto do_intersect(Line line1,
131 Line line2) noexcept -> bool
132 {
133 const Orientation ori1 = orientation_to(line1, line2.start);
134 const Orientation ori2 = orientation_to(line1, line2.end);
135 const Orientation ori3 = orientation_to(line2, line1.start);
136 const Orientation ori4 = orientation_to(line2, line1.end);
137
138 if ( ori1 != ori2 && ori3 != ori4 ) return true;
139
140 if ( ori1 == Orientation::COLLINEAR && line1.is_point_on(line2.start) ) return true;
141 if ( ori2 == Orientation::COLLINEAR && line1.is_point_on(line2.end) ) return true;
142 if ( ori3 == Orientation::COLLINEAR && line2.is_point_on(line1.start) ) return true;
143 if ( ori4 == Orientation::COLLINEAR && line2.is_point_on(line1.end) ) return true;
144
145 return false;
146 }
147
148 constexpr Line() = default;
149 constexpr ~Line() = default;
150 constexpr Line(const Line&) = default;
151 constexpr Line(Line&&) = default;
152 constexpr auto operator=(const Line&) -> Line& = default;
153 constexpr auto operator=(Line&&) -> Line& = default;
154};
155} // namespace VIPRA::Geometry
Definition line.hpp:11
static VIPRA_INLINE constexpr auto orientation_to(Line line, VIPRA::f3d point) noexcept -> Orientation
Calculates the orientation of a point relative to a line.
Definition line.hpp:35
VIPRA_INLINE constexpr auto closest_point(VIPRA::f3d point) const noexcept -> VIPRA::f3d
Calculates the closest point on the line to another point.
Definition line.hpp:52
VIPRA_INLINE constexpr auto is_point_on(VIPRA::f3d point) const -> bool
Checks if a point is on the line.
Definition line.hpp:74
constexpr auto intersection_point(Line other) const noexcept -> VIPRA::f3d
Calculates the intersection point of two lines.
Definition line.hpp:100
VIPRA_INLINE constexpr auto does_intersect(Line other) const noexcept -> bool
Checks if the line intersects another.
Definition line.hpp:87
static constexpr auto do_intersect(Line line1, Line line2) noexcept -> bool
Checks if two lines intersect.
Definition line.hpp:130
F3D_FUNC auto direction() const noexcept -> VIPRA::f3d
Returns unit vector in direction of line from start.
Definition line.hpp:25
Definition f3d.hpp:27
F3D_FUNC auto unit() const noexcept -> f3d
Returns the unit vector in the direction of the f3d.
Definition f3d.hpp:227