-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLineSegment.h
82 lines (63 loc) · 1.9 KB
/
LineSegment.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#pragma once
#include "Vec2.h"
#include <optional>
namespace crushedpixel {
template<typename Vec2>
struct LineSegment {
LineSegment(const Vec2 &a, const Vec2 &b) :
a(a), b(b) {}
Vec2 a, b;
/**
* @return A copy of the line segment, offset by the given vector.
*/
LineSegment operator+(const Vec2 &toAdd) const {
return {Vec2Maths::add(a, toAdd), Vec2Maths::add(b, toAdd)};
}
/**
* @return A copy of the line segment, offset by the given vector.
*/
LineSegment operator-(const Vec2 &toRemove) const {
return {Vec2Maths::subtract(a, toRemove), Vec2Maths::subtract(b, toRemove)};
}
/**
* @return The line segment's normal vector.
*/
Vec2 normal() const {
auto dir = direction();
// return the direction vector
// rotated by 90 degrees counter-clockwise
return {-dir.y, dir.x};
}
/**
* @return The line segment's direction vector.
*/
Vec2 direction(bool normalized = true) const {
auto vec = Vec2Maths::subtract(b, a);
return normalized
? Vec2Maths::normalized(vec)
: vec;
}
static std::optional<Vec2> intersection(const LineSegment &a, const LineSegment &b, bool infiniteLines) {
// calculate un-normalized direction vectors
auto r = a.direction(false);
auto s = b.direction(false);
auto originDist = Vec2Maths::subtract(b.a, a.a);
auto uNumerator = Vec2Maths::cross(originDist, r);
auto denominator = Vec2Maths::cross(r, s);
if (std::abs(denominator) < 0.0001f) {
// The lines are parallel
return std::nullopt;
}
// solve the intersection positions
auto u = uNumerator / denominator;
auto t = Vec2Maths::cross(originDist, s) / denominator;
if (!infiniteLines && (t < 0 || t > 1 || u < 0 || u > 1)) {
// the intersection lies outside of the line segments
return std::nullopt;
}
// calculate the intersection point
// a.a + r * t;
return Vec2Maths::add(a.a, Vec2Maths::multiply(r, t));
}
};
} // namespace crushedpixel