Updated copyright text/header in most source files.
[geda-gaf/peter-b.git] / gschem / src / o_arc.c
blob16c5b1a9c5ed1985e72ba683a9dd4f3d2bfac835
1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
20 #include <config.h>
21 #include <stdio.h>
22 #include <math.h>
24 #include "gschem.h"
26 #ifdef HAVE_LIBDMALLOC
27 #include <dmalloc.h>
28 #endif
31 /*! \brief Draw an arc on the screen.
32 * \par Function Description
33 * This function is used to draw an arc on screen. The arc is described
34 * in the object which is referred by <B>o_current</B>. The arc is displayed
35 * according to the current state, described in the GSCHEM_TOPLEVEL object
36 * pointed by <B>w_current</B>.
38 * It first checkes if the object is valid or not. If not it returns
39 * and do not output anything. That should never happen though.
41 * \param [in] w_current The GSCHEM_TOPLEVEL object.
42 * \param [in] o_current The arc OBJECT to draw.
44 void o_arc_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
46 TOPLEVEL *toplevel = w_current->toplevel;
48 if (o_current->arc == NULL) {
49 return;
52 if (toplevel->DONT_REDRAW == 1)
53 return;
55 gschem_cairo_arc (w_current, o_current->line_width,
56 o_current->arc->x,
57 o_current->arc->y,
58 o_current->arc->width / 2,
59 o_current->arc->start_angle,
60 o_current->arc->end_angle);
62 gschem_cairo_set_source_color (w_current,
63 o_drawing_color (w_current, o_current));
64 gschem_cairo_stroke (w_current, o_current->line_type,
65 o_current->line_end,
66 o_current->line_width,
67 o_current->line_length,
68 o_current->line_space);
70 if (o_current->selected && w_current->draw_grips == TRUE) {
71 o_arc_draw_grips (w_current, o_current);
75 /*! \todo Finish function documentation!!!
76 * \brief
77 * \par Function Description
80 void o_arc_invalidate_rubber (GSCHEM_TOPLEVEL *w_current)
82 int cx, cy, radius;
84 WORLDtoSCREEN (w_current, w_current->first_wx, w_current->first_wy, &cx, &cy);
85 radius = SCREENabs (w_current, w_current->distance);
87 /* FIXME: This isn't a tight bounding box */
88 o_invalidate_rect (w_current, cx - radius, cy - radius,
89 cx + radius, cy + radius);
92 /*! \brief Draw an arc described by OBJECT with translation
93 * \par Function Description
94 * This function draws the arc object described by <B>*o_current</B>
95 * translated by the vector (<B>dx</B>,<B>dy</B>).
96 * The translation vector is in screen unit.
98 * The arc is displayed with the color of the object.
100 * \param [in] w_current The GSCHEM_TOPLEVEL object.
101 * \param [in] dx Delta x coordinate for arc.
102 * \param [in] dy Delta y coordinate for arc.
103 * \param [in] o_current Arc OBJECT to draw.
105 void o_arc_draw_place (GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *o_current)
107 g_return_if_fail (o_current->arc != NULL);
109 gschem_cairo_arc (w_current, 0, o_current->arc->x + dx,
110 o_current->arc->y + dy,
111 o_current->arc->width / 2,
112 o_current->arc->start_angle,
113 o_current->arc->end_angle);
115 gschem_cairo_set_source_color (w_current,
116 x_color_lookup_dark (o_current->color));
117 gschem_cairo_stroke (w_current, TYPE_SOLID, END_NONE, 0, -1, -1);
120 /*! \brief Start process to input a new arc.
121 * \par Function Description
122 * This function starts the process to input a new arc. Parameters for
123 * this arc are put into/extracted from the <B>w_current</B> toplevel structure.
124 * <B>w_x</B> and <B>w_y</B> are current coordinates of the pointer in screen unit.
126 * First step of the arc input is to set the radius of the arc. The center
127 * of the arc is kept in (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>).
128 * The radius of the arc is in <B>w_current->distance</B>.
130 * \param [in] w_current The GSCHEM_TOPLEVEL object.
131 * \param [in] w_x Current x coordinate of pointer in world units.
132 * \param [in] w_y Current y coordinate of pointer in world units.
134 void o_arc_start(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
136 /* set the center of the arc */
137 w_current->first_wx = w_x;
138 w_current->first_wy = w_y;
140 /* set the radius */
141 w_current->distance = 0;
143 /* set the start and end angles */
144 w_current->second_wx = w_current->second_wy = 0;
146 /* start the rubberbanding process of the radius */
147 o_arc_invalidate_rubber (w_current);
148 w_current->rubber_visible = 1;
151 /*! \brief End the input of an arc.
152 * \par Function Description
153 * This function ends the input of the radius of the arc.
154 * The (<B>w_x</B>,<B>w_y</B>) point is taken as the other end of the radius segment.
155 * The distance between this point and the center is the radius of the arc.
156 * <B>w_x</B> and <B>w_y</B> are in world coords.
158 * At the end of this function, the center of the arc is at
159 * (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>) and its radius is
160 * <B>w_current->distance</B>.
162 * The two angles needs to be input to fully define the arc.
164 * \param [in] w_current The GSCHEM_TOPLEVEL object.
165 * \param [in] w_x (unused)
166 * \param [in] w_y (unused)
168 void o_arc_end1(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
170 g_assert( w_current->inside_action != 0 );
172 /* erases the previous temporary radius segment */
173 /* o_arc_invalidate_rubber (w_current); */
174 w_current->rubber_visible = 0;
176 /* ack! zero length radius */
177 if (w_current->distance == 0) {
178 return;
181 #if DEBUG
182 printf("DIST: %d\n", w_current->distance);
183 #endif
185 /* open a dialog to input the start and end angle */
186 arc_angle_dialog(w_current, NULL);
189 /*! \brief Ends the process of arc input.
190 * \par Function Description
191 * The #o_arc_end4() function ends the process of the input of an arc.
192 * <B>start_angle</B> and <B>end_angle</B> are the start and end angle of the
193 * arc in degrees. The partial internal representation of the arc, i.e.
194 * the center and the radius of the arc, are converted in world units.
195 * A new object is created and linked to the object list.
197 * \param [in] w_current The GSCHEM_TOPLEVEL object.
198 * \param [in] radius Radius of the arc
199 * \param [in] start_angle Start of angle in degrees.
200 * \param [in] end_angle End of angle in degrees.
202 void o_arc_end4(GSCHEM_TOPLEVEL *w_current, int radius,
203 int start_angle, int end_angle)
205 TOPLEVEL *toplevel = w_current->toplevel;
206 OBJECT *new_obj;
208 /* create, initialize and link the new arc object */
209 new_obj = o_arc_new (toplevel, OBJ_ARC, GRAPHIC_COLOR,
210 w_current->first_wx, w_current->first_wy,
211 radius, start_angle, end_angle);
212 s_page_append (toplevel, toplevel->page_current, new_obj);
214 /* draw the new object */
215 o_invalidate (w_current, new_obj);
217 w_current->first_wx = -1;
218 w_current->first_wy = -1;
219 w_current->distance = 0;
221 toplevel->page_current->CHANGED = 1;
223 o_undo_savestate(w_current, UNDO_ALL);
226 /*! \brief Draw an arc using one angle modification.
227 * \par Function Description
228 * This function draws an arc according to its internal representation
229 * and allows the modification of one of its angle. The start or end
230 * angle of the arc is updated according to <B>whichone</B> with the angle
231 * that the current pointer and the arc center are making with the horizontal.
233 * The previous temporary arc is erased, the angle is then computed
234 * and updated and finally a new temporary arc with the new angle is drawn.
236 * The arc is internally described by :
237 * <DL>
238 * <DT>*</DT><DD>(<B>w_current->first_wx</B>,<B>w_current->first_wy</B>) as
239 * its center.
240 * <DT>*</DT><DD><B>w_current->distance</B> as its radius.
241 * <DT>*</DT><DD><B>w_current->second_wx</B> and <B>w_current->second_wx</B> as its
242 * start and end angle respectively.
243 * </DL>
245 * \param [in] w_current The GSCHEM_TOPLEVEL object.
246 * \param [in] w_x Current x coordinate of pointer in world units.
247 * \param [in] w_y Current y coordinate of pointer in world units.
248 * \param [in] whichone Which angle to change.
250 * <B>whichone</B> can have one of the following values:
251 * <DL>
252 * <DT>ARC_RADIUS</DT>
253 * <DD>at the center of the arc. This grip is used to modify
254 * the radius of the arc.
255 * <DT>ARC_START_ANGLE</DT>
256 * <DD>at one end of the arc. It corresponds to the starting
257 * angle of the arc.
258 * <DT>ARC_END_ANGLE</DT>
259 * <DD>at the other end of the arc. It corresponds to the
260 * ending angle of the arc.
261 * </DL>
263 void o_arc_motion (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y, int whichone)
265 int diff_x, diff_y, angle_deg;
267 /* erase the previous temporary arc */
268 if (w_current->rubber_visible)
269 o_arc_invalidate_rubber (w_current);
271 if(whichone == ARC_RADIUS) {
273 * The radius is taken as the biggest distance on the x and y
274 * axis between the center of the arc and the mouse position.
276 diff_x = abs(w_current->first_wx - snap_grid (w_current, w_x));
277 diff_y = abs(w_current->first_wy - snap_grid (w_current, w_y));
278 w_current->distance = max(diff_x, diff_y);
280 else if((whichone == ARC_START_ANGLE) || (whichone == ARC_END_ANGLE)) {
281 /* compute the angle */
282 diff_x = w_x - w_current->first_wx;
283 diff_y = w_y - w_current->first_wy;
284 angle_deg = atan2 (diff_y, diff_x) * 180 / M_PI;
286 /* set the start or end angle with this angle */
287 switch(whichone) {
288 case ARC_START_ANGLE:
289 w_current->second_wx = (angle_deg + 360) % 360;
290 break;
292 case ARC_END_ANGLE:
293 w_current->second_wy = (((angle_deg + 360) % 360) -
294 w_current->second_wx + 360) % 360;
295 if (w_current->which_object->arc->end_angle < 0)
296 w_current->second_wy = w_current->second_wy - 360;
297 if (w_current->second_wy == 0)
298 w_current->second_wy = 360;
299 break;
301 default:
302 return;
307 /* draw the new temporary arc */
308 o_arc_invalidate_rubber (w_current);
309 w_current->rubber_visible = 1;
312 /*! \brief Draw arc from GSCHEM_TOPLEVEL object.
313 * \par Function Description
314 * This function draws the arc from the variables in the GSCHEM_TOPLEVEL
315 * structure <B>*w_current</B>.
316 * The center of the arc is at (<B>w_current->first_wx</B>,
317 * <B>w_current->first_wy</B>), its radius equal to <B>w_current->distance</B>,
318 * and the start and end angle are given by <B>w_current->second_wx</B> and
319 * <B>w_current->second_wy</B>.
321 * \param [in] w_current The GSCHEM_TOPLEVEL object.
323 void o_arc_draw_rubber (GSCHEM_TOPLEVEL *w_current)
325 double rad_angle;
326 int rdx, rdy;
328 gschem_cairo_arc (w_current, 0, w_current->first_wx,
329 w_current->first_wy,
330 w_current->distance,
331 w_current->second_wx,
332 w_current->second_wy);
334 gschem_cairo_set_source_color (w_current,
335 x_color_lookup_dark (SELECT_COLOR));
337 /* draw the radius line */
338 rad_angle = ((double) w_current->second_wx) * M_PI / 180;
339 rdx = (double) w_current->distance * cos (rad_angle);
340 rdy = (double) w_current->distance * sin (rad_angle);
342 gschem_cairo_line (w_current, END_NONE, 0, w_current->first_wx,
343 w_current->first_wy,
344 w_current->first_wx + rdx,
345 w_current->first_wy + rdy);
347 gschem_cairo_stroke (w_current, TYPE_SOLID, END_NONE, 0, -1, -1);
350 /*! \brief Draw grip marks on arc.
351 * \par Function Description
352 * This function draws three grips on the center and on the ends of
353 * the arc object described by <B>*o_current</B>.
355 * \param [in] w_current The GSCHE_TOPLEVEL object.
356 * \param [in] o_current Arc OBJECT to draw grip points on.
358 void o_arc_draw_grips(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
360 double radius, start_angle, end_angle;
361 int x1, y1, x2, y2, x3, y3;
363 if (w_current->draw_grips == FALSE)
364 return;
367 * An arc has three grips:
368 * <DL>
369 * <DT>*</DT><DD>one at the center that allows changes on the
370 * radius - at (<B>x</B>,<B>y</B>).
371 * <DT>*</DT><DD>one at the start of the arc - at (<B>x1</B>,<B>y1</B>).
372 * <DT>*</DT><DD>one at the end of the arc - at (<B>x2</B>,<B>y2</B>).
375 x1 = o_current->arc->x;
376 y1 = o_current->arc->y;
378 radius = o_current->arc->width / 2.;
379 start_angle = o_current->arc->start_angle;
380 end_angle = o_current->arc->end_angle;
382 x2 = x1 + radius * cos ( start_angle * M_PI / 180);
383 y2 = y1 + radius * sin ( start_angle * M_PI / 180);
384 x3 = x1 + radius * cos ((start_angle + end_angle) * M_PI / 180);
385 y3 = y1 + radius * sin ((start_angle + end_angle) * M_PI / 180);
387 /* draw the grip at the center */
388 o_grips_draw (w_current, x1, y1);
390 /* draw the grip at the start_angle end of the arc */
391 o_grips_draw (w_current, x2, y2);
393 /* draw the grip at the end_angle end of the arc */
394 o_grips_draw (w_current, x3, y3);