1 /*
2 * FIG : Facility for Interactive Generation of figures
3 * Copyright (c) 1985-1988 by Supoj Sutanthavibul
4 * Parts Copyright (c) 1989-2015 by Brian V. Smith
5 * Parts Copyright (c) 1991 by Paul King
6 * Parts Copyright (c) 2016-2020 by Thomas Loimer
7 *
8 * Any party obtaining a copy of these files is granted, free of charge, a
9 * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
10 * nonexclusive right and license to deal in this software and documentation
11 * files (the "Software"), including without limitation the rights to use,
12 * copy, modify, merge, publish, distribute, sublicense and/or sell copies of
13 * the Software, and to permit persons who receive copies from any such
14 * party to do so, with the only requirement being that the above copyright
15 * and this permission notice remain intact.
16 *
17 */
18
19 #include "d_ellipse.h"
20
21 #include <stdlib.h>
22 #include <math.h>
23
24 #include "resources.h"
25 #include "mode.h"
26 #include "object.h"
27 #include "u_create.h"
28 #include "u_elastic.h"
29 #include "u_list.h"
30 #include "u_markers.h"
31 #include "u_redraw.h"
32 #include "w_canvas.h"
33 #include "w_cursor.h"
34 #include "w_mousefun.h"
35 #include "xfig_math.h"
36
37 /************************* local procedures ********************/
38
39 static void init_ellipsebyradius_drawing(int x, int y);
40 static void init_ellipsebydiameter_drawing(int x, int y);
41 static void init_circlebyradius_drawing(int x, int y);
42 static void init_circlebydiameter_drawing(int x, int y);
43 static void create_ellipsebydia(int x, int y);
44 static void create_ellipsebyrad(int x, int y);
45 static void create_circlebyrad(int x, int y);
46 static void create_circlebydia(int x, int y);
47 static void cancel_ellipsebydia(void);
48 static void cancel_ellipsebyrad(void);
49 static void cancel_circlebyrad(void);
50 static void cancel_circlebydia(void);
51
52
53
54 void
circle_ellipse_byradius_drawing_selected(void)55 circle_ellipse_byradius_drawing_selected(void)
56 {
57 canvas_kbd_proc = null_proc;
58 canvas_locmove_proc = null_proc;
59 canvas_leftbut_proc = init_circlebyradius_drawing;
60 canvas_middlebut_proc = init_ellipsebyradius_drawing;
61 canvas_rightbut_proc = null_proc;
62 set_cursor(crosshair_cursor);
63 set_mousefun("Circle center", "Ellipse center", "", "", "", "");
64 reset_action_on();
65 }
66
67 static void
init_ellipsebyradius_drawing(int x,int y)68 init_ellipsebyradius_drawing(int x, int y)
69 {
70 cur_mode = F_ELLIPSE_BY_RAD;
71 cur_x = fix_x = x;
72 cur_y = fix_y = y;
73 cur_angle = cur_elltextangle/180.0*M_PI;
74 center_marker(fix_x, fix_y);
75 set_mousefun("Ellipse corner", "Ellipse corner", "cancel", "", "", "");
76 draw_mousefun_canvas();
77 canvas_locmove_proc = resizing_ebr;
78 canvas_leftbut_proc = create_ellipsebyrad;
79 canvas_middlebut_proc = create_ellipsebyrad;
80 canvas_rightbut_proc = cancel_ellipsebyrad;
81 set_cursor(null_cursor);
82 elastic_ebr();
83 set_action_on();
84 }
85
86 static void
cancel_ellipsebyrad(void)87 cancel_ellipsebyrad(void)
88 {
89 elastic_ebr();
90 center_marker(fix_x, fix_y);
91 circle_ellipse_byradius_drawing_selected();
92 draw_mousefun_canvas();
93 }
94
95 static void
create_ellipsebyrad(int x,int y)96 create_ellipsebyrad(int x, int y)
97 {
98 F_ellipse *ellipse;
99
100 elastic_ebr();
101 center_marker(fix_x, fix_y);
102 if ((ellipse = create_ellipse()) == NULL)
103 return;
104
105 ellipse->type = T_ELLIPSE_BY_RAD;
106 ellipse->style = cur_linestyle;
107 ellipse->thickness = cur_linewidth;
108 ellipse->style_val = cur_styleval * (cur_linewidth + 1) / 2;
109 ellipse->angle = cur_elltextangle/180.0*M_PI; /* convert to radians */
110 ellipse->pen_color = cur_pencolor;
111 ellipse->fill_color = cur_fillcolor;
112 ellipse->depth = cur_depth;
113 ellipse->pen_style = -1;
114 ellipse->fill_style = cur_fillstyle;
115 ellipse->direction = 1;
116 ellipse->center.x = fix_x;
117 ellipse->center.y = fix_y;
118 ellipse->radiuses.x = abs(x - fix_x);
119 ellipse->radiuses.y = abs(y - fix_y);
120 ellipse->start.x = fix_x;
121 ellipse->start.y = fix_y;
122 ellipse->end.x = x;
123 ellipse->end.y = y;
124 ellipse->next = NULL;
125 add_ellipse(ellipse);
126 reset_action_on(); /* this signals redisplay_curobj() not to refresh */
127 /* draw it and anything on top of it */
128 redisplay_ellipse(ellipse);
129 circle_ellipse_byradius_drawing_selected();
130 draw_mousefun_canvas();
131 }
132
circle_ellipse_bydiameter_drawing_selected(void)133 void circle_ellipse_bydiameter_drawing_selected(void)
134 {
135 set_mousefun("Circle diameter", "Ellipse corner", "", "", "", "");
136 canvas_kbd_proc = null_proc;
137 canvas_locmove_proc = null_proc;
138 canvas_leftbut_proc = init_circlebydiameter_drawing;
139 canvas_middlebut_proc = init_ellipsebydiameter_drawing;
140 canvas_rightbut_proc = null_proc;
141 set_cursor(crosshair_cursor);
142 reset_action_on();
143 }
144
145 static void
init_ellipsebydiameter_drawing(int x,int y)146 init_ellipsebydiameter_drawing(int x, int y)
147 {
148 cur_mode = F_ELLIPSE_BY_DIA;
149 cur_x = fix_x = x;
150 cur_y = fix_y = y;
151 cur_angle = cur_elltextangle/180.0*M_PI;
152 center_marker(fix_x, fix_y);
153 set_mousefun("final corner", "final corner", "cancel", "", "", "");
154 draw_mousefun_canvas();
155 canvas_locmove_proc = resizing_ebd;
156 canvas_leftbut_proc = create_ellipsebydia;
157 canvas_middlebut_proc = create_ellipsebydia;
158 canvas_rightbut_proc = cancel_ellipsebydia;
159 set_cursor(null_cursor);
160 elastic_ebd();
161 set_action_on();
162 }
163
164 static void
cancel_ellipsebydia(void)165 cancel_ellipsebydia(void)
166 {
167 elastic_ebd();
168 center_marker(fix_x, fix_y);
169 circle_ellipse_bydiameter_drawing_selected();
170 draw_mousefun_canvas();
171 }
172
173 static void
create_ellipsebydia(int x,int y)174 create_ellipsebydia(int x, int y)
175 {
176 F_ellipse *ellipse;
177
178 elastic_ebd();
179 center_marker(fix_x, fix_y);
180 if ((ellipse = create_ellipse()) == NULL)
181 return;
182
183 ellipse->type = T_ELLIPSE_BY_DIA;
184 ellipse->style = cur_linestyle;
185 ellipse->thickness = cur_linewidth;
186 ellipse->style_val = cur_styleval * (cur_linewidth + 1) / 2;
187 ellipse->angle = cur_elltextangle/180.0*M_PI; /* convert to radians */
188 ellipse->pen_color = cur_pencolor;
189 ellipse->fill_color = cur_fillcolor;
190 ellipse->depth = cur_depth;
191 ellipse->pen_style = -1;
192 ellipse->fill_style = cur_fillstyle;
193 ellipse->direction = 1;
194 ellipse->center.x = (fix_x + x) / 2;
195 ellipse->center.y = (fix_y + y) / 2;
196 ellipse->radiuses.x = abs(ellipse->center.x - fix_x);
197 ellipse->radiuses.y = abs(ellipse->center.y - fix_y);
198 ellipse->start.x = fix_x;
199 ellipse->start.y = fix_y;
200 ellipse->end.x = x;
201 ellipse->end.y = y;
202 ellipse->next = NULL;
203 add_ellipse(ellipse);
204 reset_action_on(); /* this signals redisplay_curobj() not to refresh */
205 /* draw it and anything on top of it */
206 redisplay_ellipse(ellipse);
207 circle_ellipse_bydiameter_drawing_selected();
208 draw_mousefun_canvas();
209 }
210
211 /*************************** circle section ************************/
212
213 static void
init_circlebyradius_drawing(int x,int y)214 init_circlebyradius_drawing(int x, int y)
215 {
216 cur_mode = F_CIRCLE_BY_RAD;
217 cur_x = fix_x = x;
218 cur_y = fix_y = y;
219 center_marker(fix_x, fix_y);
220 set_mousefun("set radius", "", "cancel", "", "", "");
221 draw_mousefun_canvas();
222 canvas_locmove_proc = resizing_cbr;
223 canvas_leftbut_proc = create_circlebyrad;
224 canvas_middlebut_proc = null_proc;
225 canvas_rightbut_proc = cancel_circlebyrad;
226 set_cursor(null_cursor);
227 elastic_cbr();
228 set_action_on();
229 }
230
231 static void
cancel_circlebyrad(void)232 cancel_circlebyrad(void)
233 {
234 elastic_cbr();
235 center_marker(fix_x, fix_y);
236 circle_ellipse_byradius_drawing_selected();
237 draw_mousefun_canvas();
238 }
239
240 static void
create_circlebyrad(int x,int y)241 create_circlebyrad(int x, int y)
242 {
243 F_ellipse *c;
244 double rx, ry;
245
246 elastic_cbr();
247 center_marker(fix_x, fix_y);
248 if ((c = create_ellipse()) == NULL)
249 return;
250
251 c->type = T_CIRCLE_BY_RAD;
252 c->style = cur_linestyle;
253 c->thickness = cur_linewidth;
254 c->style_val = cur_styleval * (cur_linewidth + 1) / 2;
255 c->angle = 0.0;
256 c->pen_color = cur_pencolor;
257 c->fill_color = cur_fillcolor;
258 c->depth = cur_depth;
259 c->pen_style = -1;
260 c->fill_style = cur_fillstyle;
261 c->direction = 1;
262 c->center.x = fix_x;
263 c->center.y = fix_y;
264 rx = fix_x - x;
265 ry = fix_y - y;
266 c->radiuses.x = c->radiuses.y = round(sqrt(rx * rx + ry * ry));
267 c->start.x = fix_x;
268 c->start.y = fix_y;
269 c->end.x = x;
270 c->end.y = y;
271 c->next = NULL;
272 add_ellipse(c);
273 reset_action_on(); /* this signals redisplay_curobj() not to refresh */
274 /* draw it and anything on top of it */
275 redisplay_ellipse(c);
276 circle_ellipse_byradius_drawing_selected();
277 draw_mousefun_canvas();
278 }
279
280 static void
init_circlebydiameter_drawing(int x,int y)281 init_circlebydiameter_drawing(int x, int y)
282 {
283 cur_mode = F_CIRCLE_BY_DIA;
284 cur_x = fix_x = x;
285 cur_y = fix_y = y;
286 center_marker(fix_x, fix_y);
287 set_mousefun("final point", "", "cancel", "", "", "");
288 draw_mousefun_canvas();
289 canvas_locmove_proc = resizing_cbd;
290 canvas_leftbut_proc = create_circlebydia;
291 canvas_middlebut_proc = null_proc;
292 canvas_rightbut_proc = cancel_circlebydia;
293 set_cursor(null_cursor);
294 elastic_cbd();
295 set_action_on();
296 }
297
298 static void
cancel_circlebydia(void)299 cancel_circlebydia(void)
300 {
301 elastic_cbd();
302 center_marker(fix_x, fix_y);
303 circle_ellipse_bydiameter_drawing_selected();
304 draw_mousefun_canvas();
305 }
306
307 static void
create_circlebydia(int x,int y)308 create_circlebydia(int x, int y)
309 {
310 F_ellipse *c;
311 double rx, ry;
312
313 elastic_cbd();
314 center_marker(fix_x, fix_y);
315 if ((c = create_ellipse()) == NULL)
316 return;
317
318 c->type = T_CIRCLE_BY_DIA;
319 c->style = cur_linestyle;
320 c->thickness = cur_linewidth;
321 c->style_val = cur_styleval * (cur_linewidth + 1) / 2;
322 c->angle = 0.0;
323 c->pen_color = cur_pencolor;
324 c->fill_color = cur_fillcolor;
325 c->depth = cur_depth;
326 c->pen_style = -1;
327 c->fill_style = cur_fillstyle;
328 c->direction = 1;
329 c->center.x = round((fix_x + x) / 2);
330 c->center.y = round((fix_y + y) / 2);
331 rx = x - c->center.x;
332 ry = y - c->center.y;
333 c->radiuses.x = c->radiuses.y = round(sqrt(rx * rx + ry * ry));
334 c->start.x = fix_x;
335 c->start.y = fix_y;
336 c->end.x = x;
337 c->end.y = y;
338 c->next = NULL;
339 add_ellipse(c);
340 reset_action_on(); /* this signals redisplay_curobj() not to refresh */
341 /* draw it and anything on top of it */
342 redisplay_ellipse(c);
343 circle_ellipse_bydiameter_drawing_selected();
344 draw_mousefun_canvas();
345 }
346