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