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-2025 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