AUI Framework  develop
Cross-platform base for C++ UI apps
Loading...
Searching...
No Matches
ALineSegment.h
1/*
2 * AUI Framework - Declarative UI toolkit for modern C++20
3 * Copyright (C) 2020-2024 Alex2772 and Contributors
4 *
5 * SPDX-License-Identifier: MPL-2.0
6 *
7 * This Source Code Form is subject to the terms of the Mozilla Public
8 * License, v. 2.0. If a copy of the MPL was not distributed with this
9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 */
11
12#pragma once
13
14#include "APoint2D.h"
15#include <array>
16
21template<typename T>
23 APoint2D<T> p1, p2;
24
25 [[nodiscard]]
26 T length() const noexcept {
27 return glm::distance(p1, p2);
28 }
29
30 [[nodiscard]]
31 bool isIntersects(ALineSegment other) const noexcept {
32 // suppose the two line segments run from p to p + r
33 auto p = p1;
34 auto r = p2 - p1;
35 // and from q to q + s
36 auto q = other.p1;
37 auto s = other.p2 - other.p1;
38 // then any point on the first line is representable as p + tr (for a scalar parameter t) and any point on the
39 // second line as q + us (for a scalar parameter u) where both t and u >= 0 and <= 1.
40 //
41 // the two lines intersect if we can find t and u such that:
42 //
43 // p + tr = q + us
44 //
45 // solve for t:
46 // cross both sides by s
47 //
48 // (p + tr) cross s = (q + us) cross s
49 //
50 // since s cross s = 0, this means
51 //
52 // p cross s + tr cross s = q cross s
53 // tr cross s = (q - p) cross s
54 // t = (q - p) cross s / (r cross s)
55 //
56 // solve for u as well:
57 //
58 // u = (q - p) cross r / (r cross s)
59
60 auto cross = [](glm::vec<2, T> v, glm::vec<2, T> w) {
61 return v.x * w.y - v.y * w.x;
62 };
63
64 // slightly modified to use lambda cross above:
65 // t = cross(q - p, s) / cross(r, s); t >= 0; t <= 1
66 // u = cross(q - p, r) / cross(r, s); u >= 0; u <= 1
67 //
68 // to support integer values properly, lets avoid division by multiplying both sides by cross(r, s)
69 //
70 // t = cross(q - p, s); t >= 0; t <= cross(r, s)
71 // u = cross(q - p, r); u >= 0; u <= cross(r, s)
72 auto rCrossS = cross(r, s);
73 auto t = cross(q - p, s) * glm::sign(rCrossS);
74 auto u = cross(q - p, r) * glm::sign(rCrossS);
75 rCrossS = glm::abs(rCrossS);
76
77 return t >= 0 && u >= 0 && t <= rCrossS && u <= rCrossS;
78 }
79};
glm::vec< 2, T > APoint2D
2D point.
Definition APoint2D.h:21
2D line segment.
Definition ALineSegment.h:22