#pragma once // clang-format off #define MSG_INFO "[INFO] " #define MSG_WARN "[WARN] " #define MSG_ERROR "[ERRO] " // clang-format on struct Pt { int x{}, y{}; Pt operator+(Pt o) const { return { x + o.x, y + o.y }; } Pt operator-(Pt o) const { return { x - o.x, y - o.y }; } Pt operator*(int k) const { return { x * k, y * k }; } Pt operator/(int k) const { return { x / k, y / k }; } Pt& operator+=(Pt o) { x += o.x; y += o.y; return *this; } Pt& operator-=(Pt o) { x -= o.x; y -= o.y; return *this; } Pt& operator*=(Pt o) { x *= o.x; y *= o.y; return *this; } Pt& operator/=(Pt o) { x /= o.x; y /= o.y; return *this; } bool operator==(const Pt&) const = default; }; // avoid including #define MMIN(x, y) ((x) < (y) ? (x) : (y)) #define MMAX(x, y) ((x) > (y) ? (x) : (y)) inline Pt pt_min(Pt a, Pt b) { return Pt{ MMIN(a.x, b.x), MMIN(a.y, b.y) }; } inline Pt pt_max(Pt a, Pt b) { return Pt{ MMAX(a.x, b.x), MMAX(a.y, b.y) }; } struct Rect { Pt bl, tr; Rect() {} Rect(Pt tl, Pt br) : bl(tl), tr(br) {} Rect(int x0, int y0, int x1, int y1) : bl(x0, y0), tr(x1, y1) {} bool operator==(const Rect&) const = default; }; inline Rect rect_union(Rect a, Rect b) { return Rect(pt_min(a.bl, b.bl), pt_max(a.tr, b.tr)); } inline Rect rect_union(Rect a, Pt b) { return Rect(pt_min(a.bl, b), pt_max(a.tr, b)); } inline Rect rect_intersect(Rect a, Rect b) { // https://stackoverflow.com/a/19754915 int x0 = MMAX(a.bl.x, b.bl.x); int y0 = MMAX(a.bl.y, b.bl.y); int x1 = MMIN(a.tr.x, b.tr.x); int y1 = MMIN(a.tr.y, b.tr.y); return Rect(x0, y0, x1, y1); } #undef MMIN #undef MMAX