header_utils
Loading...
Searching...
No Matches
segment.h
1
4
5#pragma once
6
7#include "geometry_common.h"
8
10{
11
12 template <std::floating_point T>
13 struct tsegment
14 {
15 using tvec = glm::tvec2<T>;
16 using value_type = T;
17
18 tvec start{};
19 tvec end{};
20
21 tvec vec() const noexcept { return end - start; }
22 tvec dir() const noexcept { return glm::normalize(vec()); }
23 auto length() const noexcept { return glm::distance(start, end); }
24 auto center() const noexcept { return (start + end) / T(2); }
25
26 static tsegment from_offset(tvec const& start, tvec const& offset) noexcept { return { start, start + offset }; }
27 static tsegment from_dir(tvec const& start, tvec const& dir, T len) noexcept { return { start, start + dir * len }; }
28
29 basic_line_t<T> line() const noexcept { return line_crossing_points(start, end); }
30
31 tsegment& set_position(tvec const& pos) noexcept { const auto d = vec(); start = pos; end = pos + d; return *this; }
32 tsegment& operator+=(tvec const& offs) noexcept { start += offs; end += offs; return *this; }
33 tsegment& operator-=(tvec const& offs) noexcept { start -= offs; end -= offs; return *this; }
34 tsegment& translate(tvec const& offs) noexcept { return this->operator+=(offs); }
35
36 tsegment& set_length(T len) noexcept { end = start + dir() * len; return *this; }
37 tsegment& set_length_around_center(T len) noexcept
38 {
39 const auto c = center();
40 const auto d = dir();
41 const auto hlen = len / T(2);
42 start = c - d * hlen;
43 end = c + d * hlen;
44 return *this;
45 }
46
47 tsegment& grow(T len) noexcept { const auto d = dir(); start -= d * len; end += d * len; return *this; }
48 tsegment& shrink(T len) noexcept { const auto d = dir(); start += d * len; end -= d * len; return *this; }
49
50 constexpr std::optional<tvec> intersection(tsegment const& other) const noexcept
51 {
53 const auto r = vec();
54 const auto s = other.vec();
55 const auto rxs = glm::cross(r, s);
56 const auto qp = other.start - start;
57 const auto qpxr = glm::cross(qp, r);
58 if (glm::abs(rxs) < std::numeric_limits<T>::epsilon() && glm::abs(qpxr) < std::numeric_limits<T>::epsilon())
59 {
61 const auto t0 = glm::dot(qp, r) / glm::dot(r, r);
62 const auto t1 = t0 + glm::dot(s, r) / glm::dot(r, r);
63 if ((t0 >= 0 && t0 <= 1) || (t1 >= 0 && t1 <= 1))
64 return std::nullopt;
65 return std::nullopt;
66 }
67 if (glm::abs(rxs) < std::numeric_limits<T>::epsilon() && glm::abs(qpxr) > std::numeric_limits<T>::epsilon())
68 return std::nullopt;
69 const auto t = glm::cross(qp, s) / rxs;
70 const auto u = glm::cross(qp, r) / rxs;
71 if (rxs != 0 && t >= 0 && t <= 1 && u >= 0 && u <= 1)
72 return start + t * r;
73 return std::nullopt;
74 }
75
77
78 T edge_length() const { return length(); }
79 tvec edge_point_alpha(T t) const { return glm::mix(start, end, t); }
80 tvec edge_point(T t) const { return glm::mix(start, end, t / edge_length()); }
81 trec2<T> bounding_box() const { return trec2<T>::from_points({ &start, &start + 2 }); }
82 tvec projected(tvec pt) const
83 {
84 const auto dir = this->vec();
85 const auto d1 = glm::dot(pt - start, dir);
86 if (d1 <= 0)
87 return start;
88 const auto d2 = glm::dot(dir, dir);
89 if (d1 > d2)
90 return end;
91 return start + dir * (d1 / d2);
92 }
93 };
94
95 using segment = tsegment<float>;
96
97 static_assert(shape<segment, float>);
98}
constexpr auto bit_count
Equal to the number of bits in the type.
Definition bits.h:33