-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathShapes.h
More file actions
129 lines (104 loc) · 3.43 KB
/
Shapes.h
File metadata and controls
129 lines (104 loc) · 3.43 KB
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#pragma once
struct PointDouble {
public:
double x;
double y;
bool operator==(const PointDouble& b) const {
return x == b.x and y == b.y;
}
bool operator!=(const PointDouble& b) const {
return not (*this == b);
}
};
struct PointInt {
public:
int x;
int y;
};
struct RectInt {
int x;
int y;
int width;
int height;
bool contains(const PointInt p) const {
return (x <= p.x and p.x <= (x+width)) and (y <= p.y and p.y <= (y + height));
}
bool intersect(const RectInt r) const {
return (contains(PointInt{r.x, r.y}) or contains(PointInt{r.x + r.width, r.y}) or contains(PointInt{r.x, r.y + height}) or contains(PointInt{r.x + width, r.y + height}));
}
};
struct RectDouble {
double x;
double y;
int width;
int height;
RectInt toRectInt() const {
return RectInt{round(x), round(y), width, height};
}
PointInt toPointInt () const {
RectInt r = toRectInt();
return PointInt{r.x, r.y};
}
bool contains(const PointDouble p) const {
return (x <= p.x and p.x <= (x+width)) and (y <= p.y and p.y <= (y + height));
}
bool intersect(const RectDouble r) const {
//Code adapted from the SFML graphics library
const double interLeft = max(x, r.x);
const double interTop = max(y, r.y);
const double interRight = min(x + width, r.x + r.width);
const double interBottom = min(y + height, r.y + r.height);
return (interLeft < interRight) && (interTop < interBottom);
}
};
static PointDouble NO_POINT{-69, -420};
//TFW no algebraic-type like enums from rust :_(
//Seriously this could just be an enum like
//
//enum Intersects {
// Yes(PointDouble),
// No,
//};
//
//Which is so much more expressive and clear than having a dummy value to test against or having multiple functions
//This is why I hate C++ grrr (Clash Royale);
struct LineDouble {
PointDouble p1;
PointDouble p2;
PointDouble intersects(const LineDouble l) const {
double m0 = slope();
double m1 = l.slope();
if (m0 == m1) return NO_POINT; //Lines are parallel
//Calculate intersection point
double x = (m1 * l.p1.x - m0 * p1.x + p1.y - l.p1.y) / (m1 - m0);
double y = m0 * (x - p1.x) + p1.y;
PointDouble intersect{x, y};
//Make sure intersection is actually on the line segment itself (and not just the line)
if(p1.x <= x and x <= p2.x) return intersect;
else return NO_POINT;
}
double slope() const {
return (p2.y - p1.y) / (p2.x - p1.x);
}
};
struct CircleDouble {
PointDouble center;
int radius;
//Finds point of intersect on rectangle (if there is one);
PointDouble intersectRect(const RectDouble r) const {
LineDouble l_1{PointDouble{r.x, r.y}, PointDouble{r.x + r.width, r.y}};
LineDouble l_2{PointDouble{r.x, r.y}, PointDouble{r.x, r.y + r.height}};
LineDouble l_3{PointDouble{r.x + r.width, r.y}, PointDouble{r.x + r.width, r.y + r.height}};
LineDouble l_4{PointDouble{r.x, r.y+r.height}, PointDouble{r.x + r.width, r.y+r.height}};
LineDouble c_to_r{center, PointDouble{r.x + r.width / 2, r.y + r.height / 2}};
PointDouble i1 = c_to_r.intersects(l_1);
PointDouble i2 = c_to_r.intersects(l_2);
PointDouble i3 = c_to_r.intersects(l_3);
PointDouble i4 = c_to_r.intersects(l_4);
if(i1 != NO_POINT) { return i1; }
else if(i2 != NO_POINT) { return i2; }
else if(i3 != NO_POINT) { return i3; }
else if(i4 != NO_POINT) { return i4; }
else { return NO_POINT; }
}
};