1 /*
2 * FIG : Facility for Interactive Generation of figures
3 * This part Copyright (c) 1999-2002 Alexander Durner
4 *
5 * Any party obtaining a copy of these files is granted, free of charge, a
6 * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
7 * nonexclusive right and license to deal in this software and documentation
8 * files (the "Software"), including without limitation the rights to use,
9 * copy, modify, merge, publish, distribute, sublicense and/or sell copies of
10 * the Software, and to permit persons who receive copies from any such
11 * party to do so, with the only requirement being that the above copyright
12 * and this permission notice remain intact.
13 *
14 */
15
16 #include "e_tangent.h"
17
18 #include <math.h>
19 #include <stddef.h>
20
21 #include "resources.h"
22 #include "mode.h"
23 #include "object.h"
24 #include "paintop.h"
25 #include "f_util.h"
26 #include "u_create.h"
27 #include "u_draw.h"
28 #include "u_list.h"
29 #include "u_markers.h"
30 #include "u_smartsearch.h"
31 #include "w_canvas.h"
32 #include "w_cursor.h"
33 #include "w_mousefun.h"
34 #include "w_msgpanel.h"
35 #include "w_setup.h"
36 #include "xfig_math.h"
37
38 #define ZERO_TOLERANCE 2.0
39
40 static void init_tangent_adding(char *p, int type, int x, int y,
41 int px, int py);
42 static void init_normal_adding(char *p, int type, int x, int y,
43 int px, int py);
44 static void tangent_or_normal(int x, int y, int flag);
45 static void tangent_normal_line(int x, int y, float vx, float vy);
46
47
48 void
tangent_selected(void)49 tangent_selected(void)
50 {
51 set_mousefun("add tangent", "add normal", "", LOC_OBJ, LOC_OBJ, LOC_OBJ);
52 canvas_kbd_proc = null_proc;
53 canvas_locmove_proc = smart_null_proc;
54 canvas_ref_proc = smart_null_proc;
55 init_smart_searchproc_left(init_tangent_adding);
56 init_smart_searchproc_middle(init_normal_adding);
57 canvas_leftbut_proc = smart_object_search_left;
58 canvas_middlebut_proc = smart_object_search_middle;
59 canvas_rightbut_proc = smart_null_proc;
60 set_cursor(pick9_cursor);
61 /* force_nopositioning(); */
62 reset_action_on();
63 }
64
65 /* smart_point1, smart_point2 are two points of the tangent */
66
67 static void
init_tangent_adding(char * p,int type,int x,int y,int px,int py)68 init_tangent_adding(char *p, int type, int x, int y, int px, int py)
69 {
70 (void)p; (void)type; (void)x; (void)y;
71
72 tangent_or_normal(px, py, 0);
73 }
74
75 static void
init_normal_adding(char * p,int type,int x,int y,int px,int py)76 init_normal_adding(char *p, int type, int x, int y, int px, int py)
77 {
78 (void)p; (void)type; (void)x; (void)y;
79
80 tangent_or_normal(px, py, 1);
81 }
82
83 static void
tangent_or_normal(int x,int y,int flag)84 tangent_or_normal(int x, int y, int flag)
85 {
86 float dx, dy, length, sx, sy, tanlen;
87
88 dx = (float)(smart_point2.x - smart_point1.x);
89 dy = (float)(smart_point2.y - smart_point1.y);
90 if (dx == 0.0 && dy == 0.0)
91 length = 0.0;
92 else
93 length = sqrt(dx * dx + dy * dy);
94 if (length < ZERO_TOLERANCE) {
95 put_msg("%s", "singularity, can't draw tangent/normal");
96 beep();
97 return;
98 }
99 tanlen = cur_tangnormlen * (appres.INCHES? PIX_PER_INCH: PIX_PER_CM) / 2.0;
100 sx = dx * tanlen / length;
101 sy = dy * tanlen / length;
102 if (flag) {
103 tangent_normal_line(x, y, -sy, sx);
104 put_msg("%s", "added normal");
105 }
106 else {
107 tangent_normal_line(x, y, sx, sy);
108 put_msg("%s", "added tangent");
109 }
110 }
111
112 static void
tangent_normal_line(int x,int y,float vx,float vy)113 tangent_normal_line(int x, int y, float vx, float vy)
114 {
115 int dx, dy, xl, yl, xr, yr;
116 F_line *line;
117
118 dx = round(vx);
119 dy = round(vy);
120
121 xl = x - dx;
122 yl = y - dy;
123 xr = x + dx;
124 yr = y + dy;
125
126 if ((first_point = create_point()) == NULL)
127 return;
128 cur_point = first_point;
129 first_point->x = xl;
130 first_point->y = yl;
131 first_point->next = NULL;
132 append_point(x, y, &cur_point);
133 append_point(xr, yr, &cur_point);
134
135 if ((line = create_line()) == NULL)
136 return; /* an error occured */
137 line->type = T_POLYLINE;
138 line->style = cur_linestyle;
139 line->thickness = cur_linewidth;
140 line->pen_color = cur_pencolor;
141 line->fill_color = cur_fillcolor;
142 line->depth = cur_depth;
143 line->pen_style = -1;
144 line->join_style = cur_joinstyle;
145 line->cap_style = cur_capstyle;
146 line->fill_style = cur_fillstyle;
147 line->style_val = cur_styleval * (cur_linewidth + 1) / 2;
148 line->points = first_point;
149 /* polyline; draw any arrows */
150 if (autoforwardarrow_mode)
151 line->for_arrow = forward_arrow();
152 /* arrow will be drawn in draw_line below */
153 if (autobackwardarrow_mode)
154 line->back_arrow = backward_arrow();
155 /* arrow will be drawn in draw_line below */
156 draw_line(line, PAINT); /* draw final */
157 add_line(line);
158 toggle_linemarker(line);
159 }
160