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