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 "conic.h"
26 #include "utils.h"
27 #include "parser.tab.h"
28
create_point_cartesian(void)29 void create_point_cartesian(void)
30 {
31 _point *val;
32
33 get_mem(val, _point);
34 val->y = POPn;
35 val->x = POPn;
36 PSH(val);
37 }
38
create_point_polar(void)39 void create_point_polar(void)
40 {
41 double r, a;
42 _point *val;
43
44 get_mem(val, _point);
45 a = POPn;
46 r = POPn;
47 val->x = r*Cos(a);
48 val->y = r*Sin(a);
49 PSH(val);
50 }
51
create_point_on_segment(void)52 void create_point_on_segment(void)
53 {
54 double x;
55 _set *set;
56 _point *A, *B;
57 _point *val;
58
59 x = POPn;
60 set = POP(_set);
61 A = get_point(&set);
62 B = get_point(&set);
63 get_mem(val, _point);
64 val->x = A->x + x*(B->x - A->x);
65 val->y = A->y + x*(B->y - A->y);
66 PSH(val);
67 }
68
create_point_on_line(void)69 void create_point_on_line(void)
70 {
71 double x;
72 _line *l;
73 _point *val;
74
75 x = POPn;
76 l = POP(_line);
77 get_mem(val, _point);
78 val->x = l->x + x*Cos(l->a);
79 val->y = l->y + x*Sin(l->a);
80 PSH(val);
81 }
82
create_point_with_abscissa(void)83 void create_point_with_abscissa(void)
84 {
85 double x, c;
86 _line *l;
87 _point *val;
88
89 x = POPn;
90 l = POP(_line);
91 c = Cos(l->a);
92 if (ZERO(c)) runtime_error(_("invalid line"));
93 get_mem(val, _point);
94 val->x = x;
95 val->y = l->y + (x-l->x)*Sin(l->a)/c;
96 PSH(val);
97 }
98
create_point_with_ordinate(void)99 void create_point_with_ordinate(void)
100 {
101 double y, s;
102 _line *l;
103 _point *val;
104
105 y = POPn;
106 l = POP(_line);
107 s = Sin(l->a);
108 if (ZERO(s)) runtime_error(_("invalid line"));
109 get_mem(val, _point);
110 val->x = l->x + (y-l->y)*Cos(l->a)/s;
111 val->y = y;
112 PSH(val);
113 }
114
create_point_on_circle(void)115 void create_point_on_circle(void)
116 {
117 double a;
118 _circle *c;
119 _point *val;
120
121 a = POPn;
122 c = POP(_circle);
123 get_mem(val, _point);
124 val->x = c->x + c->r*Cos(a);
125 val->y = c->y + c->r*Sin(a);
126 PSH(val);
127 }
128
create_point_on_conic(void)129 void create_point_on_conic(void)
130 {
131 _conic *C;
132 _point *val;
133 double c, s, t;
134
135 t = POPn;
136 C = POP(_conic);
137 c = Cos(C->d);
138 s = Sin(C->d);
139 get_mem(val, _point);
140 switch (C->type) {
141 case ELLIPSE:
142 parametric_ellipse(&(val->x), &(val->y), t,
143 C->x, C->y, C->a, C->b, c, s);
144 break;
145 case HYPERBOLA:
146 if (t <= -180 || t >= 180 || t == 0)
147 runtime_error("invalid argument");
148 parametric_hyperbola(&(val->x), &(val->y), t,
149 C->x, C->y, C->a, C->b, c, s);
150 break;
151 case PARABOLA:
152 if (t <= -180 || t >= 180) runtime_error("invalid argument");
153 parametric_parabola(&(val->x), &(val->y), t,
154 C->x, C->y, C->a, c, s);
155 break;
156 }
157 PSH(val);
158 }
159
create_midpoint(void)160 void create_midpoint(void)
161 {
162 _set *set;
163 _point *A, *B;
164 _point *val;
165
166 set = POP(_set);
167 A = get_point(&set);
168 B = get_point(&set);
169 get_mem(val, _point);
170 val->x = (A->x + B->x)/2;
171 val->y = (A->y + B->y)/2;
172 PSH(val);
173 }
174
create_isobarycenter(void)175 void create_isobarycenter(void)
176 {
177 int n = 0;
178 _set *set;
179 _point *val;
180
181 set = POP(_set);
182 if (set == NULL) runtime_error(_("empty set"));
183 get_mem(val, _point);
184 val->x = 0;
185 val->y = 0;
186 do {
187 val->x += set->p->x;
188 val->y += set->p->y;
189 n++;
190 set = set->next;
191 } while (set != NULL);
192 val->x /= n;
193 val->y /= n;
194 PSH(val);
195 }
196
create_barycenter(void)197 void create_barycenter(void)
198 {
199 double c, s = 0;
200 _point *cur, *val;
201
202 get_mem(val, _point);
203 val->x = 0;
204 val->y = 0;
205 c = POPn;
206 cur = POP(_point);
207 do {
208 val->x += c*cur->x;
209 val->y += c*cur->y;
210 s += c;
211 c = POPn;
212 cur = POP(_point);
213 } while (cur != NULL);
214 val->x /= s;
215 val->y /= s;
216 PSH(val);
217 }
218
219 #define cosine(a, b, c) (b*b + c*c - a*a)/(2*b*c)
220
221 #define tangent(x) sqrt(1-x*x)/x
222
create_orthocenter(void)223 void create_orthocenter(void)
224 {
225 _point *A, *B, *C, *val;
226 double a, b, c, ca, cb, cc, d;
227
228 C = POP(_point);
229 B = POP(_point);
230 A = POP(_point);
231 get_mem(val, _point);
232 a = distance(B, C);
233 b = distance(C, A);
234 c = distance(A, B);
235 if (ZERO(a) || ZERO(b) || ZERO(c)) runtime_error(_("invalid triangle"));
236 ca = cosine(a, b, c);
237 cb = cosine(b, c, a);
238 cc = cosine(c, a, b);
239 if (ca == 0) {
240 ca = 1; cb = 0; cc = 0;
241 } else if (cb == 0) {
242 ca = 0; cb = 1; cc = 0;
243 } else if (cc == 0) {
244 ca = 0; cb = 0; cc = 1;
245 } else {
246 ca = tangent(ca); cb = tangent(cb); cc = tangent(cc);
247 }
248 d = ca + cb + cc;
249 val->x = (ca*A->x + cb*B->x + cc*C->x)/d;
250 val->y = (ca*A->y + cb*B->y + cc*C->y)/d;
251 PSH(val);
252 }
253
translate_point(void)254 void translate_point(void)
255 {
256 _point *A, *val;
257 _vector *u;
258
259 u = POP(_vector);
260 A = POP(_point);
261 get_mem(val, _point);
262 val->x = A->x + u->x;
263 val->y = A->y + u->y;
264 PSH(val);
265 }
266
reflect_point(void)267 void reflect_point(void)
268 {
269 _point *A, *val;
270 _line *l;
271 double c, s, x, y, p;
272
273 l = POP(_line);
274 A = POP(_point);
275 c = Cos(l->a);
276 s = Sin(l->a);
277 x = A->x - l->x;
278 y = A->y - l->y;
279 p = 2*(c*x + s*y);
280 get_mem(val, _point);
281 val->x = l->x + p*c - x;
282 val->y = l->y + p*s - y;
283 PSH(val);
284 }
285
symetric_point(void)286 void symetric_point(void)
287 {
288 _point *A, *O, *val;
289
290 O = POP(_point);
291 A = POP(_point);
292 get_mem(val, _point);
293 val->x = 2*O->x - A->x;
294 val->y = 2*O->y - A->y;
295 PSH(val);
296 }
297
rotate_point(void)298 void rotate_point(void)
299 {
300 _point *A, *O, *val;
301 double a, c, s, x, y;
302
303 a = POPn;
304 O = POP(_point);
305 A = POP(_point);
306 c = Cos(a);
307 s = Sin(a);
308 x = A->x - O->x;
309 y = A->y - O->y;
310 get_mem(val, _point);
311 val->x = O->x + c*x - s*y;
312 val->y = O->y + s*x + c*y;
313 PSH(val);
314 }
315
homothetic_point(void)316 void homothetic_point(void)
317 {
318 _point *A, *O, *val;
319 double k;
320
321 k = POPn;
322 O = POP(_point);
323 A = POP(_point);
324 get_mem(val, _point);
325 val->x = O->x + k*(A->x - O->x);
326 val->y = O->y + k*(A->y - O->y);
327 PSH(val);
328 }
329
point_abscissa(void)330 void point_abscissa(void)
331 {
332 PSHn((POP(_point))->x);
333 }
334
point_ordinate(void)335 void point_ordinate(void)
336 {
337 PSHn((POP(_point))->y);
338 }
339
points_distance(void)340 void points_distance(void)
341 {
342 _point *A, *B;
343
344 A = POP(_point);
345 B = POP(_point);
346 PSHn(distance(A, B));
347 }
348