]> git.lizzy.rs Git - nothing.git/blob - src/math/rect.c
Sort includes
[nothing.git] / src / math / rect.c
1 #include <SDL2/SDL.h>
2 #include <assert.h>
3 #include <math.h>
4 #include <string.h>
5
6 #include "./rect.h"
7
8 rect_t rect(float x, float y, float w, float h)
9 {
10     const rect_t result = {
11         .x = x,
12         .y = y,
13         .w = w,
14         .h = h
15     };
16
17     return result;
18 }
19
20 rect_t rect_from_vecs(point_t position, vec_t size)
21 {
22     return rect(position.x, position.y, size.x, size.y);
23 }
24
25 rect_t rect_from_sdl(const SDL_Rect *rect)
26 {
27     const rect_t result = {
28         .x = (float) rect->x,
29         .y = (float) rect->y,
30         .w = (float) rect->w,
31         .h = (float) rect->h
32     };
33
34     return result;
35 }
36
37 rect_t rects_overlap_area(rect_t rect1, rect_t rect2)
38 {
39     float x1 = fmaxf(rect1.x, rect2.x);
40     float y1 = fmaxf(rect1.y, rect2.y);
41     float x2 = fminf(rect1.x + rect1.w, rect2.x + rect2.w);
42     float y2 = fminf(rect1.y + rect1.h, rect2.y + rect2.h);
43
44     rect_t result = {
45         .x = x1,
46         .y = y1,
47         .w = fmaxf(0.0f, x2 - x1),
48         .h = fmaxf(0.0f, y2 - y1)
49     };
50     return result;
51 }
52
53 int rects_overlap(rect_t rect1, rect_t rect2)
54 {
55     return rect1.x + rect1.w >= rect2.x
56         && rect2.x + rect2.w >= rect1.x
57         && rect2.y + rect2.h >= rect1.y
58         && rect1.y + rect1.h >= rect2.y;
59 }
60
61 float line_length(line_t line)
62 {
63     float dx = line.p1.x - line.p2.x;
64     float dy = line.p1.y - line.p2.y;
65     return sqrtf(dx * dx + dy * dy);
66 }
67
68 void rect_object_impact(const rect_t *object,
69                         const rect_t *obstacle,
70                         int *sides)
71 {
72     assert(object);
73     assert(obstacle);
74     assert(sides);
75
76     rect_t int_area = rects_overlap_area(*object, *obstacle);
77
78     if (int_area.w * int_area.h > 0.0f) {
79         for (int side = 0; side < RECT_SIDE_N; ++side) {
80             line_t object_side = rect_side(*object, side);
81             line_t int_side = rect_side(int_area, side);
82
83             if (line_length(int_side) > 10.0f) {
84                 sides[side] = sides[side] ||
85                     (fabs(object_side.p1.x - object_side.p2.x) < 1e-6
86                      && fabs(object_side.p1.x - int_side.p1.x) < 1e-6
87                      && fabs(object_side.p1.x - int_side.p2.x) < 1e-6)
88                     || (fabs(object_side.p1.y - object_side.p2.y) < 1e-6
89                         && fabs(object_side.p1.y - int_side.p1.y) < 1e-6
90                         && fabs(object_side.p1.y - int_side.p2.y) < 1e-6);
91             }
92         }
93     }
94 }
95
96 line_t rect_side(rect_t rect, rect_side_t side)
97 {
98     const float x1 = rect.x;
99     const float y1 = rect.y;
100     const float x2 = rect.x + rect.w;
101     const float y2 = rect.y + rect.h;
102
103     line_t result;
104
105     switch (side) {
106     case RECT_SIDE_LEFT:
107         result.p1.x = x1;
108         result.p1.y = y1;
109         result.p2.x = x1;
110         result.p2.y = y2;
111         break;
112     case RECT_SIDE_RIGHT:
113         result.p1.x = x2;
114         result.p1.y = y1;
115         result.p2.x = x2;
116         result.p2.y = y2;
117         break;
118     case RECT_SIDE_TOP:
119         result.p1.x = x1;
120         result.p1.y = y1;
121         result.p2.x = x2;
122         result.p2.y = y1;
123         break;
124     case RECT_SIDE_BOTTOM:
125         result.p1.x = x1;
126         result.p1.y = y2;
127         result.p2.x = x2;
128         result.p2.y = y2;
129         break;
130     default: {}
131     }
132
133     return result;
134 }
135
136 rect_t rect_from_point(point_t p, float w, float h)
137 {
138     rect_t result = {
139         .x = p.x,
140         .y = p.y,
141         .w = w,
142         .h = h
143     };
144
145     return result;
146 }
147
148 int rect_contains_point(rect_t rect, point_t p)
149 {
150     return rect.x <= p.x && p.x <= rect.x + rect.w
151         && rect.y <= p.y && p.y <= rect.y + rect.h;
152 }
153
154 SDL_Rect rect_for_sdl(rect_t rect)
155 {
156     const SDL_Rect result = {
157         .x = (int) roundf(rect.x),
158         .y = (int) roundf(rect.y),
159         .w = (int) roundf(rect.w),
160         .h = (int) roundf(rect.h)
161     };
162
163     return result;
164 }