]> git.lizzy.rs Git - nothing.git/blob - src/rect.c
Rename goal -> goals (#58)
[nothing.git] / src / rect.c
1 #include <string.h>
2 #include <assert.h>
3 #include <math.h>
4 #include "./rect.h"
5
6 rect_t rect_int_area(rect_t rect1, rect_t rect2)
7 {
8     float x1 = fmaxf(rect1.x, rect2.x);
9     float y1 = fmaxf(rect1.y, rect2.y);
10     float x2 = fminf(rect1.x + rect1.w, rect2.x + rect2.w);
11     float y2 = fminf(rect1.y + rect1.h, rect2.y + rect2.h);
12
13     rect_t result = {
14         .x = x1,
15         .y = y1,
16         .w = fmaxf(0.0f, x2 - x1),
17         .h = fmaxf(0.0f, y2 - y1)
18     };
19     return result;
20 }
21
22 int is_rect_int(rect_t rect1, rect_t rect2)
23 {
24     rect_t int_area = rect_int_area(rect1, rect2);
25     return int_area.w * int_area.h > 0.0f;
26 }
27
28 float line_length(line_t line)
29 {
30     float dx = line.p1.x - line.p2.x;
31     float dy = line.p1.y - line.p2.y;
32     return sqrtf(dx * dx + dy * dy);
33 }
34
35 void rect_object_impact(const rect_t *object,
36                         const rect_t *obstacle,
37                         int *sides)
38 {
39     assert(object);
40     assert(obstacle);
41     assert(sides);
42
43     rect_t int_area = rect_int_area(*object, *obstacle);
44
45     if (int_area.w * int_area.h > 0.0f) {
46         for (int side = 0; side < RECT_SIDE_N; ++side) {
47             line_t object_side = rect_side(*object, side);
48             line_t int_side = rect_side(int_area, side);
49
50             if (line_length(int_side) > 10.0f) {
51                 sides[side] = sides[side] ||
52                     (fabs(object_side.p1.x - object_side.p2.x) < 1e-6
53                      && fabs(object_side.p1.x - int_side.p1.x) < 1e-6
54                      && fabs(object_side.p1.x - int_side.p2.x) < 1e-6)
55                     || (fabs(object_side.p1.y - object_side.p2.y) < 1e-6
56                         && fabs(object_side.p1.y - int_side.p1.y) < 1e-6
57                         && fabs(object_side.p1.y - int_side.p2.y) < 1e-6);
58             }
59         }
60     }
61 }
62
63 line_t rect_side(rect_t rect, rect_side_t side)
64 {
65     const float x1 = rect.x;
66     const float y1 = rect.y;
67     const float x2 = rect.x + rect.w;
68     const float y2 = rect.y + rect.h;
69
70     line_t result;
71
72     switch (side) {
73     case RECT_SIDE_LEFT:
74         result.p1.x = x1;
75         result.p1.y = y1;
76         result.p2.x = x1;
77         result.p2.y = y2;
78         break;
79     case RECT_SIDE_RIGHT:
80         result.p1.x = x2;
81         result.p1.y = y1;
82         result.p2.x = x2;
83         result.p2.y = y2;
84         break;
85     case RECT_SIDE_TOP:
86         result.p1.x = x1;
87         result.p1.y = y1;
88         result.p2.x = x2;
89         result.p2.y = y1;
90         break;
91     case RECT_SIDE_BOTTOM:
92         result.p1.x = x1;
93         result.p1.y = y2;
94         result.p2.x = x2;
95         result.p2.y = y2;
96         break;
97     default: {}
98     }
99
100     return result;
101 }
102
103 rect_t rect_from_point(point_t p, float w, float h)
104 {
105     rect_t result = {
106         .x = p.x,
107         .y = p.y,
108         .w = w,
109         .h = h
110     };
111
112     return result;
113 }