-
Notifications
You must be signed in to change notification settings - Fork 3
/
plane.c
117 lines (98 loc) · 2.69 KB
/
plane.c
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
/*
* Copyright (c) 2021 Justin Meiners
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include "plane.h"
// Integer square root (using binary search)
// https://en.wikipedia.org/wiki/Integer_square_root
unsigned int isqrt( unsigned int y )
{
unsigned int L = 0;
unsigned int M;
unsigned int R = y + 1;
while( L != R - 1 )
{
M = (L + R) / 2;
if( M * M <= y )
L = M;
else
R = M;
}
return L;
}
CcRect cc_rect_around_points(const CcCoord* points, int n)
{
assert(n > 0);
int min_x = points[0].x;
int min_y = points[0].y;
int max_x = min_x;
int max_y = min_y;
for (int i = 1; i < n; ++i)
{
extend_interval(points[i].x, &min_x, &max_x);
extend_interval(points[i].y, &min_y, &max_y);
}
return cc_rect_from_extrema(min_x, min_y, max_x, max_y);
}
CcRect cc_rect_pad(CcRect r, int pad_w, int pad_h)
{
r.x -= pad_w;
r.y -= pad_h;
r.w += 2 * pad_w;
r.h += 2 * pad_h;
return r;
}
void cc_line_align_to_45(int start_x, int start_y, int end_x, int end_y, int* out_x, int* out_y)
{
int dx = (end_x - start_x);
int dy = (end_y - start_y);
int best_x = 0;
int best_y = 0;
int best = 0;
for (int i = -1; i <= 1; ++i)
{
for (int j = -1; j <= 1; ++j)
{
if (i == 0 && j == 0) { continue; }
int dot = i * dx + j * dy;
if (i != 0 && j != 0)
{
// sqrt(2) ~= 1.41
dot = (dot * 100) / 141;
}
if (dot > best)
{
best_x = i;
best_y = j;
best = dot;
}
}
}
if (best_x != 0 && best_y != 0)
{
// one more time
best = (best * 100) / 141;
}
*out_x = start_x + best_x * best;
*out_y = start_y + best_y * best;
}
void align_rect_to_square(int start_x, int start_y, int end_x, int end_y, int* out_x, int* out_y)
{
int dx = (end_x - start_x);
int dy = (end_y - start_y);
int side_length = MIN(abs(dx), abs(dy));
*out_x = start_x + sign_of_int(dx) * side_length;
*out_y = start_y + sign_of_int(dy) * side_length;
}