1 /*
2 * Eukleides version 1.5.4
3 * Copyright (c) Christian Obrecht 2004-2010
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include <stdlib.h>
21 #include <math.h>
22 #include "error.h"
23 #include "symbol.h"
24 #include "core.h"
25 #include "utils.h"
26
create_circle_with_radius(void)27 void create_circle_with_radius(void)
28 {
29 _point *center;
30 _circle *val;
31
32 get_mem(val, _circle);
33 val->r = POPn;
34 if (val->r <= 0) runtime_error("invalid radius");
35 center = POP(_point);
36 val->x = center->x;
37 val->y = center->y;
38 PSH(val);
39 }
40
circle_center(void)41 void circle_center(void)
42 {
43 _circle *cir;
44 _point *val;
45
46 cir = POP(_circle);
47 get_mem(val, _point);
48 val->x = cir->x;
49 val->y = cir->y;
50 PSH(val);
51 }
52
create_circle_with_diameter(void)53 void create_circle_with_diameter(void)
54 {
55 _set *set;
56 _point *A, *B;
57 _circle *val;
58
59 set = POP(_set);
60 A = get_point(&set);
61 B = get_point(&set);
62 get_mem(val, _circle);
63 val->r = distance(A, B)/2;
64 if (val->r <= 0) runtime_error("invalid radius");
65 val->x = (A->x + B->x)/2;
66 val->y = (A->y + B->y)/2;
67 PSH(val);
68 }
69
create_circumcircle(void)70 void create_circumcircle(void)
71 {
72 _point *A, *B, *C;
73 double a, d, e, f, s1, s2, s3;
74 _circle *val;
75
76 C = POP(_point);
77 B = POP(_point);
78 A = POP(_point);
79 get_mem(val, _circle);
80 s1 = A->x*A->x + A->y*A->y;
81 s2 = B->x*B->x + B->y*B->y;
82 s3 = C->x*C->x + C->y*C->y;
83 a = det3(A->x, B->x, C->x, A->y, B->y, C->y, 1, 1, 1);
84 if (ZERO(a)) runtime_error("invalid points");
85 d = det3(s1, s2, s3, A->y, B->y, C->y, 1, 1, 1);
86 e = det3(s1, s2, s3, A->x, B->x, C->x, 1, 1, 1);
87 f = det3(s1, s2, s3, A->x, B->x, C->x, A->y, B->y, C->y);
88 val->r = sqrt((d*d+e*e)/(4*a*a)+f/a);
89 val->x = d/(2*a);
90 val->y = -e/(2*a);
91 PSH(val);
92 }
93
create_incircle(void)94 void create_incircle(void)
95 {
96 _point *A, *B, *C;
97 double a, b, c, s, s1, s2, r, t, u, v;
98 _circle *val;
99
100 C = POP(_point);
101 B = POP(_point);
102 A = POP(_point);
103 get_mem(val, _circle);
104 a = distance(B, C);
105 b = distance(C, A);
106 c = distance(A, B);
107 s = det2(B->x-A->x, C->x-A->x, B->y-A->y, C->y-A->y) > 0 ? 1 : -1;
108 s1 = sqrt((a-b+c)*(a+b-c));
109 s2 = sqrt((b+c-a)*(b+c+a));
110 if (ZERO(s1) || ZERO(s2)) runtime_error("invalid points");
111 r = .5*s1*s2/(a+b+c);
112 t = s1/s2;
113 u = (B->x-A->x)/c;
114 v = (B->y-A->y)/c;
115 val->r = r;
116 val->x = A->x + r*(u/t-s*v);
117 val->y = A->y + r*(v/t+s*u);
118 PSH(val);
119 }
120
translate_circle(void)121 void translate_circle(void)
122 {
123 _circle *C, *val;
124 _vector *u;
125
126 u = POP(_vector);
127 C = POP(_circle);
128 get_mem(val, _circle);
129 val->x = C->x + u->x;
130 val->y = C->y + u->y;
131 val->r = C->r;
132 PSH(val);
133 }
134
reflect_circle(void)135 void reflect_circle(void)
136 {
137 _circle *C, *val;
138 _line *l;
139 double c, s, x, y, p;
140
141 l = POP(_line);
142 C = POP(_circle);
143 c = Cos(l->a);
144 s = Sin(l->a);
145 x = C->x - l->x;
146 y = C->y - l->y;
147 p = 2*(c*x + s*y);
148 get_mem(val, _circle);
149 val->x = l->x + p*c - x;
150 val->y = l->y + p*s - y;
151 val->r = C->r;
152 PSH(val);
153 }
154
symetric_circle(void)155 void symetric_circle(void)
156 {
157 _circle *C, *val;
158 _point *O;
159
160 O = POP(_point);
161 C = POP(_circle);
162 get_mem(val, _circle);
163 val->x = 2*O->x - C->x;
164 val->y = 2*O->y - C->y;
165 val->r = C->r;
166 PSH(val);
167 }
168
rotate_circle(void)169 void rotate_circle(void)
170 {
171 _circle *C, *val;
172 _point *O;
173 double a, c, s, x, y;
174
175 a = POPn;
176 O = POP(_point);
177 C = POP(_circle);
178 c = Cos(a);
179 s = Sin(a);
180 x = C->x - O->x;
181 y = C->y - O->y;
182 get_mem(val, _circle);
183 val->x = O->x + c*x - s*y;
184 val->y = O->y + s*x + c*y;
185 val->r = C->r;
186 PSH(val);
187 }
188
homothetic_circle(void)189 void homothetic_circle(void)
190 {
191 _circle *C, *val;
192 _point *O;
193 double k;
194
195 k = POPn;
196 O = POP(_point);
197 C = POP(_circle);
198 get_mem(val, _circle);
199 val->x = O->x + k*(C->x - O->x);
200 val->y = O->y + k*(C->y - O->y);
201 val->r = fabs(k)*C->r;
202 PSH(val);
203 }
204
circle_radius(void)205 void circle_radius(void)
206 {
207 PSHn((POP(_circle))->r);
208 }
209
circle_perimeter(void)210 void circle_perimeter(void)
211 {
212 PSHn(2*M_PI*(POP(_circle))->r);
213 }
214
circle_area(void)215 void circle_area(void)
216 {
217 _circle *cir;
218
219 cir = POP(_circle);
220 PSHn(M_PI*cir->r*cir->r);
221 }
222
point_on_circle_argument(void)223 void point_on_circle_argument(void)
224 {
225 _point *A;
226 _circle *cir;
227
228 cir = POP(_circle);
229 A = POP(_point);
230 PSHn(RTOD(atan2(A->y-cir->y, A->x-cir->x)));
231 }
232