AUI Framework  master
Cross-platform base for C++ UI apps
Loading...
Searching...
No Matches
ARect.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 "ALineSegment.h"
   16#include <array>
   17#include <range/v3/algorithm/any_of.hpp>
   18
   23template<typename T>
   24struct ARect {
   25    APoint2D<T> p1, p2;
   26
   27    static ARect fromTopLeftPositionAndSize(APoint2D<T> position, APoint2D<T> size) {
   28        return { .p1 = position, .p2 = position + size };
   29    }
   30
   31    static ARect fromCenterPositionAndSize(APoint2D<T> position, APoint2D<T> size) {
   32        return { .p1 = position - size / static_cast<T>(2), .p2 = position + size / static_cast<T>(2) };
   33    }
   34
   35    [[nodiscard]]
   36    bool operator==(const ARect&) const noexcept = default;
   37
   38    [[nodiscard]]
   39    APoint2D<T> leftTop() const noexcept {
   40        return min();
   41    }
   42
   43    [[nodiscard]]
   44    APoint2D<T> rightBottom() const noexcept {
   45        return max();
   46    }
   47
   48    [[nodiscard]]
   49    APoint2D<T> rightTop() const noexcept {
   50        return { glm::max(p1.x, p2.x), glm::min(p1.y, p2.y) };
   51    }
   52
   53    [[nodiscard]]
   54    APoint2D<T> leftBottom() const noexcept {
   55        return { glm::min(p1.x, p2.x), glm::max(p1.y, p2.y) };
   56    }
   57
   58    [[nodiscard]]
   59    bool isInside(APoint2D<T> other) const noexcept {
   60        return glm::all(glm::greaterThan(other, p1)) && glm::all(glm::lessThan(other, p2));
   61    }
   62
   63    [[nodiscard]]
   64    bool isIntersects(APoint2D<T> other) const noexcept {
   65        return glm::all(glm::greaterThanEqual(other, p1)) && glm::all(glm::lessThanEqual(other, p2));
   66    }
   67
   68    [[nodiscard]]
   69    std::array<APoint2D<T>, 4> vertices() const noexcept {
   70        return std::array<APoint2D<T>, 4>{
   71            p1,
   72            APoint2D<T>(p1.x, p2.y),
   73            APoint2D<T>(p2.x, p1.y),
   74            p2
   75        };
   76    }
   77
   78    [[nodiscard]]
   79    APoint2D<T> center() const noexcept {
   80        return (p1 + p2) / static_cast<T>(2);
   81    }
   82
   83    [[nodiscard]]
   84    APoint2D<T> min() const noexcept {
   85        return glm::min(p1, p2);
   86    }
   87
   88    [[nodiscard]]
   89    APoint2D<T> max() const noexcept {
   90        return glm::max(p1, p2);
   91    }
   92
   93    [[nodiscard]]
   94    T area() const noexcept {
   95        return size().x * size().y;
   96    }
   97
   98    [[nodiscard]]
   99    ALineSegment<T> topLineSegment() const noexcept {
  100        return { .p1 = APoint2D<T>(p1.x, p1.y), .p2 = APoint2D<T>(p2.x, p1.y) };
  101    }
  102
  103    [[nodiscard]]
  104    ALineSegment<T> leftLineSegment() const noexcept {
  105        return { .p1 = APoint2D<T>(p1.x, p1.y), .p2 = APoint2D<T>(p1.x, p2.y) };
  106    }
  107
  108    [[nodiscard]]
  109    ALineSegment<T> rightLineSegment() const noexcept {
  110        return { .p1 = APoint2D<T>(p2.x, p1.y), .p2 = APoint2D<T>(p2.x, p2.y) };
  111    }
  112
  113
  114    [[nodiscard]]
  115    ALineSegment<T> bottomLineSegment() const noexcept {
  116        return { .p1 = APoint2D<T>(p1.x, p2.y), .p2 = APoint2D<T>(p2.x, p2.y) };
  117    }
  118
  122    [[nodiscard]]
  123    bool isIntersects(ARect other) const noexcept {
  124        // equal rects intersects.
  125        if (*this == other) {
  126            return true;
  127        }
  128
  129        // at least one of their point
  130        if (ranges::any_of(other.vertices(), [&](APoint2D<T> p) { return isIntersects(p); })) {
  131            return true;
  132        }
  133
  134        // at least one of our point
  135        if (ranges::any_of(vertices(), [&](APoint2D<T> p) { return other.isIntersects(p); })) {
  136            return true;
  137        }
  138
  139        {
  140            auto verticalLines = [](const ARect& r) {
  141                return std::array<ALineSegment<T>, 2>{ r.leftLineSegment(), r.rightLineSegment() };
  142            };
  143            auto horizontalLines = [](const ARect& r) {
  144                return std::array<ALineSegment<T>, 2>{ r.topLineSegment(), r.bottomLineSegment() };
  145            };
  146
  147            //        this
  148            //      +------+
  149            //      |      |
  150            //+-----+------+-----+
  151            //|     |      |     |
  152            //|     |      |     | other
  153            //|     |      |     |
  154            //+-----+------+-----+
  155            //      |      |
  156            //      +------+
  157            if (ranges::any_of(verticalLines(*this), [&](const ALineSegment<T>& l) {
  158                return ranges::any_of(horizontalLines(other), [&](const ALineSegment<T>& r) {
  159                    return l.isIntersects(r);
  160                });
  161            })) {
  162                return true;
  163            }
  164
  165            //       other
  166            //      +------+
  167            //      |      |
  168            //+-----+------+-----+
  169            //|     |      |     |
  170            //|     |      |     | this
  171            //|     |      |     |
  172            //+-----+------+-----+
  173            //      |      |
  174            //      +------+
  175            if (ranges::any_of(horizontalLines(*this), [&](const ALineSegment<T>& l) {
  176                return ranges::any_of(verticalLines(other), [&](const ALineSegment<T>& r) {
  177                    return l.isIntersects(r);
  178                });
  179            })) {
  180                return true;
  181            }
  182        }
  183
  184        return false;
  185    }
  186
  187    [[nodiscard]]
  188    APoint2D<T> size() const noexcept {
  189        return glm::abs(p2 - p1);
  190    }
  191
  192    ARect& translate(glm::ivec2 by) noexcept {
  193        p1 += by;
  194        p2 += by;
  195        return *this;
  196    }
  197};
glm::vec< 2, T > APoint2D
2D point.
Definition APoint2D.h:21
2D line segment.
Definition ALineSegment.h:22
Axis aligned 2D rectangle.
Definition ARect.h:24
bool isIntersects(ARect other) const noexcept
Definition ARect.h:123