summaryrefslogtreecommitdiff
path: root/src/helpers/Vector2D.hpp
blob: 3c5d4a2c0c873987fa1c7f4daf5c18d13fff6df8 (plain)
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#pragma once

#include <cmath>
#include <format>
#include "../macros.hpp"

class Vector2D {
  public:
    Vector2D(double, double);
    Vector2D();
    ~Vector2D();

    double x = 0;
    double y = 0;

    // returns the scale
    double   normalize();

    Vector2D operator+(const Vector2D& a) const {
        return Vector2D(this->x + a.x, this->y + a.y);
    }
    Vector2D operator-(const Vector2D& a) const {
        return Vector2D(this->x - a.x, this->y - a.y);
    }
    Vector2D operator*(const float& a) const {
        return Vector2D(this->x * a, this->y * a);
    }
    Vector2D operator/(const float& a) const {
        return Vector2D(this->x / a, this->y / a);
    }

    bool operator==(const Vector2D& a) const {
        return a.x == x && a.y == y;
    }

    bool operator!=(const Vector2D& a) const {
        return a.x != x || a.y != y;
    }

    Vector2D operator*(const Vector2D& a) const {
        return Vector2D(this->x * a.x, this->y * a.y);
    }

    Vector2D operator/(const Vector2D& a) const {
        return Vector2D(this->x / a.x, this->y / a.y);
    }

    bool operator>(const Vector2D& a) const {
        return this->x > a.x && this->y > a.y;
    }

    bool operator<(const Vector2D& a) const {
        return this->x < a.x && this->y < a.y;
    }

    double   distance(const Vector2D& other) const;

    Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D()) const;

    Vector2D floor() const;

    bool     inTriangle(const Vector2D& p1, const Vector2D& p2, const Vector2D& p3) const;
};

/**
    format specification
    - 'j', as json array
    - 'X', same as std::format("{}x{}", vec.x, vec.y)
    - number, floating point precision, use `0` to format as integer
*/
template <typename CharT>
struct std::formatter<Vector2D, CharT> : std::formatter<CharT> {
    bool        formatJson = false;
    bool        formatX    = false;
    std::string precision  = "";
    FORMAT_PARSE(FORMAT_FLAG('j', formatJson) //
                 FORMAT_FLAG('X', formatX)    //
                 FORMAT_NUMBER(precision),
                 Vector2D)

    template <typename FormatContext>
    auto format(const Vector2D& vec, FormatContext& ctx) const {
        std::string formatString = precision.empty() ? "{}" : std::format("{{:.{}f}}", precision);

        if (formatJson)
            formatString = std::format("[{0}, {0}]", formatString);
        else if (formatX)
            formatString = std::format("{0}x{0}", formatString);
        else
            formatString = std::format("[Vector2D: x: {0}, y: {0}]", formatString);
        try {
            string buf = std::vformat(formatString, std::make_format_args(vec.x, vec.y));
            return std::format_to(ctx.out(), "{}", buf);
        } catch (std::format_error& e) { return std::format_to(ctx.out(), "[{}, {}]", vec.x, vec.y); }
    }
};