1 /* gEDA - GPL Electronic Design Automation
2  * libgeda - gEDA's library
3  * Copyright (C) 1998-2010 Ales Hvezda
4  * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
5  *
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.
10  *
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.
15  *
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /*! \file o_arc_basic.c
22  *  \brief functions for the arc object
23  */
24 
25 #include <config.h>
26 
27 #include <stdio.h>
28 #include <math.h>
29 
30 #include "libgeda_priv.h"
31 
32 #ifdef HAVE_LIBDMALLOC
33 #include <dmalloc.h>
34 #endif
35 
36 /*! \brief
37  *  \par Function Description
38  *  The function creates a new OBJECT of type arc.
39  *
40  *  The arc is defined by its center in parameters x and y.
41  *  The radius parameter specifies the radius of the arc. The start
42  *  angle is given by start_angle and the end angle by end_angle.
43  *  The line and fill type of the created arc are set to default.
44  *
45  *  All dimensions are in world unit, except start_angle and
46  *  end_angle in degrees.
47  *
48  *  A new object of type OBJECT is allocated. Its type and color
49  *  are initilized. The description of the arc characteristics
50  *  are stored in a new ARC structure.
51  *
52  *  Now fixed for world coordinates.
53  *
54  *  \param [in] toplevel    The TOPLEVEL object.
55  *  \param [in] type
56  *  \param [in] color
57  *  \param [in] x
58  *  \param [in] y
59  *  \param [in] radius
60  *  \param [in] start_angle
61  *  \param [in] end_angle
62  *  \return
63  */
o_arc_new(TOPLEVEL * toplevel,char type,int color,int x,int y,int radius,int start_angle,int end_angle)64 OBJECT *o_arc_new(TOPLEVEL *toplevel,
65 		  char type, int color,
66 		  int x, int y, int radius, int start_angle, int end_angle)
67 {
68 
69   OBJECT *new_node;
70 
71   new_node = s_basic_new_object(type, "arc");
72 
73   new_node->color = color;
74 
75   new_node->arc = (ARC *) g_malloc(sizeof(ARC));
76 
77   /*! \note
78    *  The ARC structure is initialized with the parameters.
79    *  A default initialization is performed for the line and
80    *  fill type to avoid misunderstanding.
81    *
82    *  The functions relative to the use of the object are sets.
83    */
84 
85   /* World coordinates */
86   new_node->arc->x      = x;
87   new_node->arc->y      = y;
88   new_node->arc->width  = 2 * radius;
89   new_node->arc->height = 2 * radius;
90 
91   /* must check the sign of start_angle, end_angle ... */
92   if(end_angle < 0) {
93     start_angle = start_angle + end_angle;
94     end_angle = -end_angle;
95   }
96   if(start_angle < 0) start_angle = 360 + start_angle;
97 
98   new_node->arc->start_angle = start_angle;
99   new_node->arc->end_angle   = end_angle;
100 
101   /* Default init */
102   o_set_line_options(toplevel, new_node,
103                      END_NONE, TYPE_SOLID, 0, -1, -1);
104   o_set_fill_options(toplevel, new_node,
105                      FILLING_HOLLOW, -1, -1, -1, -1, -1);
106 
107   o_arc_recalc(toplevel, new_node);
108 
109   /* new_node->graphical = arc; eventually */
110 
111   return new_node;
112 }
113 
114 /*! \brief
115  *  \par Function Description
116  *  This function creates a new object representing an arc.
117  *
118  *  The values of the <B>o_current</B> pointed OBJECT are then copied to the new object.
119  *
120  *  The arc, the line options are initialized whereas the fill options are
121  *  initialized to passive values - as an arc can not be filled.
122  *
123  *  \param [in] toplevel  The TOPLEVEL object
124  *  \param [in] o_current
125  *  \return The new OBJECT
126  */
o_arc_copy(TOPLEVEL * toplevel,OBJECT * o_current)127 OBJECT *o_arc_copy(TOPLEVEL *toplevel, OBJECT *o_current)
128 {
129   OBJECT *new_obj;
130 
131   new_obj = o_arc_new (toplevel, OBJ_ARC, o_current->color,
132                        o_current->arc->x, o_current->arc->y,
133                        o_current->arc->width / 2,
134                        o_current->arc->start_angle,
135                        o_current->arc->end_angle);
136   o_set_line_options(toplevel, new_obj,
137                      o_current->line_end, o_current->line_type,
138                      o_current->line_width,
139                      o_current->line_length, o_current->line_space);
140   o_set_fill_options(toplevel, new_obj,
141                      FILLING_HOLLOW, -1, -1, -1, -1, -1);
142 
143   return new_obj;
144 }
145 
146 /*! \brief
147  *  \par Function Description
148  *  This function modifies the internal values of the arc object
149  *  *object according to the whichone parameter.
150  *
151  *  The new values are given by <B>x</B> and/or <B>y</B>. Their meaning depends on the value of whichone.
152  *
153  *  If <B>whichone</B> is equal to #ARC_CENTER, the (<B>x</B>,<B>y</B>) point is taken as the new center
154  *  of the arc in world unit.
155  *
156  *  If <B>whichone</B> is equal to #ARC_RADIUS, the <B>x</B> parameter is taken to be the radius
157  *  of the arc in world unit. The <B>y</B> parameter is ignored.
158  *
159  *  If <B>whichone</B> is equal to #ARC_START_ANGLE, the <B>x</B> parameter is the starting angle of the arc.
160  *  <B>x</B> is in degrees. <B>y</B> is ignored.
161  *
162  *  If <B>whichone</B> is equal to #ARC_END_ANGLE, the <B>x</B> parameter is the ending angle of the arc.
163  *  <B>x</B> is in degrees. <B>y</B> is ignored.
164  *
165  *  \param [in]     toplevel  The TOPLEVEL object.
166  *  \param [in,out] object
167  *  \param [in]     x
168  *  \param [in]     y
169  *  \param [in]     whichone
170  */
o_arc_modify(TOPLEVEL * toplevel,OBJECT * object,int x,int y,int whichone)171 void o_arc_modify(TOPLEVEL *toplevel, OBJECT *object,
172 		  int x, int y, int whichone)
173 {
174 
175 	o_emit_pre_change_notify (toplevel, object);
176 
177 	switch(whichone) {
178 		case ARC_CENTER:
179 		/* modify the center of arc object */
180 		object->arc->x = x;
181 		object->arc->y = y;
182 		break;
183 
184 		case ARC_RADIUS:
185 		/* modify the radius of arc object */
186 		object->arc->width  = 2 * x;
187 		object->arc->height = 2 * x;
188 		break;
189 
190 		case ARC_START_ANGLE:
191 		/* modify the start angle of the arc object */
192 		object->arc->start_angle = x;
193 		break;
194 
195 		case ARC_END_ANGLE:
196 		/* modify the end angle of the arc object */
197 		object->arc->end_angle = x;
198 		break;
199 
200 		default:
201 		break;
202 	}
203 
204 	/* update the screen coords and the bounding box */
205 	o_arc_recalc(toplevel, object);
206 	o_emit_change_notify (toplevel, object);
207 }
208 
209 /*! \brief
210  *  \par Function Description
211  *  This function reads a formatted text buffer describing an arc
212  *  in the gEDA file format and initializes the corresponding object.
213  *
214  *  Depending on the version of the file format the data extraction is
215  *  performed differently : currently pre-20000704 and 20000704 on one
216  *  hand and post-20000704 file format version on the other hand are supported.
217  *  The version is specified in string pointed by <B>fileformat_ver</B>.
218  *
219  *  To get information on the various file formats have a
220  *  look to the fileformats.html document.
221  *
222  *  The object is initialized with the functions #o_set_line_options() and #o_set_fill_options().
223  *  The second one is only used to put initialize unused values for an arc as an arc can not be filled.
224  *
225  *  The arc is allocated initialized with the function #o_arc_new().
226  *
227  *  A negative or null radius is not allowed.
228  *
229  *  \param [in] toplevel    The TOPLEVEL object.
230  *  \param [in] buf
231  *  \param [in] release_ver
232  *  \param [in] fileformat_ver
233  *  \return The ARC OBJECT that was created, or NULL on error.
234  */
o_arc_read(TOPLEVEL * toplevel,const char buf[],unsigned int release_ver,unsigned int fileformat_ver,GError ** err)235 OBJECT *o_arc_read (TOPLEVEL *toplevel, const char buf[],
236            unsigned int release_ver, unsigned int fileformat_ver, GError **err)
237 {
238   OBJECT *new_obj;
239   char type;
240   int x1, y1;
241   int radius;
242   int start_angle, end_angle;
243   int color;
244   int arc_width, arc_length, arc_space;
245   int arc_type;
246   int arc_end;
247 
248   /*! \note
249    *  Depending on the version of the file format used to describe this arc,
250    *  the buffer is parsed differently. The unknown parameters of the less
251    *  restrictive - the oldest - file format are set to common values
252    */
253   if(release_ver <= VERSION_20000704) {
254     if (sscanf(buf, "%c %d %d %d %d %d %d", &type,
255 	       &x1, &y1, &radius, &start_angle, &end_angle, &color) != 7) {
256       g_set_error (err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse arc object"));
257       return NULL;
258     }
259 
260     arc_width = 0;
261     arc_end   = END_NONE;
262     arc_type  = TYPE_SOLID;
263     arc_space = -1;
264     arc_length= -1;
265   } else {
266     if (sscanf(buf, "%c %d %d %d %d %d %d %d %d %d %d %d", &type,
267 	       &x1, &y1, &radius, &start_angle, &end_angle, &color,
268 	       &arc_width, &arc_end, &arc_type, &arc_length, &arc_space) != 12) {
269       g_set_error (err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse arc object"));
270       return NULL;
271     }
272   }
273 
274   /* Error check */
275   if (radius <= 0) {
276     s_log_message (_("Found a zero radius arc [ %c %d, %d, %d, %d, %d, %d ]\n"),
277                    type, x1, y1, radius, start_angle, end_angle, color);
278     radius = 0;
279   }
280 
281   if (color < 0 || color > MAX_COLORS) {
282     s_log_message(_("Found an invalid color [ %s ]\n"), buf);
283     s_log_message(_("Setting color to default color\n"));
284     color = DEFAULT_COLOR;
285   }
286 
287   /* Allocation and initialization */
288   new_obj = o_arc_new(toplevel, OBJ_ARC, color,
289                       x1, y1, radius, start_angle, end_angle);
290   o_set_line_options(toplevel, new_obj,
291                      arc_end, arc_type, arc_width, arc_length,
292                      arc_space);
293   o_set_fill_options(toplevel, new_obj,
294                      FILLING_HOLLOW, -1, -1, -1,
295                      -1, -1);
296 
297   return new_obj;
298 }
299 
300 /*! \brief create the string representation of an arc object
301  *  \par Function Description
302  *  This function formats a string in the buffer <B>*buf</B> to describe
303  *  the arc object <B>*object</B>.
304  *  A pointer to the new allocated and formated string is returned.
305  *  The string must be freed at some point.
306  *
307  *  \param [in] toplevel
308  *  \param [in] object
309  *  \return the string representation of the arc object
310  */
o_arc_save(TOPLEVEL * toplevel,OBJECT * object)311 char *o_arc_save(TOPLEVEL *toplevel, OBJECT *object)
312 {
313   int x, y, radius, start_angle, end_angle;
314   int arc_width, arc_length, arc_space;
315   char *buf;
316   OBJECT_END arc_end;
317   OBJECT_TYPE arc_type;
318 
319   /* radius, center and angles of the arc */
320   radius      = object->arc->width / 2;
321   x           = object->arc->x;
322   y           = object->arc->y;
323   start_angle = object->arc->start_angle;
324   end_angle   = object->arc->end_angle;
325 
326   /* line type parameters */
327   arc_width  = object->line_width;
328   arc_end    = object->line_end;
329   arc_type   = object->line_type;
330   arc_length = object->line_length;
331   arc_space  = object->line_space;
332 
333   /* Describe a circle with post-20000704 file format */
334   buf = g_strdup_printf("%c %d %d %d %d %d %d %d %d %d %d %d", object->type,
335 			x, y, radius, start_angle, end_angle, object->color,
336 			arc_width, arc_end, arc_type, arc_length, arc_space);
337 
338   return(buf);
339 }
340 
341 /*! \brief
342  *  \par Function Description
343  *  This function applies a translation of (<B>dx</B>,<B>dy</B>)
344  *  to the arc described in <B>*object</B>. <B>dx</B> and <B>dy</B> are in world unit.
345  *
346  *  \param [in] toplevel  The TOPLEVEL object.
347  *  \param [in] dx
348  *  \param [in] dy
349  *  \param [in] object
350  */
o_arc_translate_world(TOPLEVEL * toplevel,int dx,int dy,OBJECT * object)351 void o_arc_translate_world(TOPLEVEL *toplevel, int dx, int dy,
352 			   OBJECT *object)
353 {
354   if (object == NULL) {
355     return;
356   }
357 
358   /* Do world coords */
359   object->arc->x = object->arc->x + dx;
360   object->arc->y = object->arc->y + dy;
361 
362 
363   /* Recalculate screen coords from new world coords */
364   o_arc_recalc(toplevel, object);
365 }
366 
367 /*! \brief
368  *  \par Function Description
369  *  This function rotates the world coordinates of an arc of an angle
370  *  specified by <B>angle</B>. The center of the rotation is given by
371  *  (<B>world_centerx</B>,<B>world_centery</B>).
372  *
373  *  The arc is translated in order to put the center of the rotation
374  *  on the origin. The center of the arc is then rotated of the angle
375  *  specified by <B>angle</B>. The start angle of the arc is incremented by <B>angle</B>.
376  *
377  *  The arc is finally back translated to its previous location on the page.
378  *
379  *  <B>world_centerx</B> and <B>world_centery</B> are in world units, <B>angle</B> is in degrees.
380  *
381  *  \param [in] toplevel      The TOPLEVEL object.
382  *  \param [in] world_centerx
383  *  \param [in] world_centery
384  *  \param [in] angle
385  *  \param [in] object
386  */
o_arc_rotate_world(TOPLEVEL * toplevel,int world_centerx,int world_centery,int angle,OBJECT * object)387 void o_arc_rotate_world(TOPLEVEL *toplevel,
388 			int world_centerx, int world_centery, int angle,
389 			OBJECT *object)
390 {
391   int x, y, newx, newy;
392 
393   /* translate object to origin */
394   object->arc->x -= world_centerx;
395   object->arc->y -= world_centery;
396 
397   /* get center, and rotate center */
398   x = object->arc->x;
399   y = object->arc->y;
400   if(angle % 90 == 0) {
401 	  rotate_point_90(x, y, angle % 360, &newx, &newy);
402   } else {
403 	  rotate_point(x, y, angle % 360, &newx, &newy);
404   }
405   object->arc->x = newx;
406   object->arc->y = newy;
407 
408   /* apply rotation to angles */
409   object->arc->start_angle = (object->arc->start_angle + angle) % 360;
410   /* end_angle is unchanged as it is the sweep of the arc */
411   /* object->arc->end_angle = (object->arc->end_angle); */
412 
413   /* translate object to its previous place */
414   object->arc->x += world_centerx;
415   object->arc->y += world_centery;
416 
417   /* update the screen coords and the bounding box */
418   o_arc_recalc(toplevel, object);
419 
420 }
421 
422 /*! \brief Mirror the WORLD coordinates of an ARC.
423  *  \par Function Description
424  *  This function mirrors the world coordinates of an arc.
425  *  The symetry axis is given by the vertical line going through the point (<B>world_centerx</B>,<B>world_centery</B>).
426  *
427  *  The arc is translated in order to put the point (<B>world_centerx</B>,<B>world_centery</B>)
428  *  on the origin. The center of the arc is then mirrored. The start angle of the arc
429  *  and the sweep of the arc are also mirrored.
430  *
431  *  The arc is finally back translated to its previous location on the page.
432  *
433  *  \param [in] toplevel      The TOPLEVEL object.
434  *  \param [in] world_centerx
435  *  \param [in] world_centery
436  *  \param [in] object
437  */
o_arc_mirror_world(TOPLEVEL * toplevel,int world_centerx,int world_centery,OBJECT * object)438 void o_arc_mirror_world(TOPLEVEL *toplevel,
439 			int world_centerx, int world_centery,
440 			OBJECT *object)
441 {
442   /* translate object to origin */
443   object->arc->x -= world_centerx;
444   object->arc->y -= world_centery;
445 
446   /* get center, and mirror it (vertical mirror) */
447   object->arc->x = -object->arc->x;
448   object->arc->y =  object->arc->y;
449 
450   /* apply mirror to angles (vertical mirror) */
451   object->arc->start_angle = (180 - object->arc->start_angle) % 360;
452   /* start_angle *MUST* be positive */
453   if(object->arc->start_angle < 0) object->arc->start_angle += 360;
454   object->arc->end_angle = -object->arc->end_angle;
455 
456   /* translate object back to its previous position */
457   object->arc->x += world_centerx;
458   object->arc->y += world_centery;
459 
460   /* update the screen coords and bounding box */
461   o_arc_recalc(toplevel, object);
462 
463 }
464 
465 /*! \brief
466  *  \par Function Description
467  *  This function recalculates internal parameters in screen units
468  *  of an object containing an arc. The object is given as parameters <B>o_current</B>.
469  *  The calculation is done according to the zoom factor detailed in the <B>toplevel</B>
470  *  pointed structure.
471  *  It also recalculates the <B>OBJECT</B> specific fields and the bounding box of the arc.
472  *
473  *  The bounding box - in world units - is recalculated with the <B>world_get_arc_bounds()</B> function.
474  *
475  *  \param [in] toplevel  The TOPLEVEL object.
476  *  \param [in] o_current
477  */
o_arc_recalc(TOPLEVEL * toplevel,OBJECT * o_current)478 void o_arc_recalc(TOPLEVEL *toplevel, OBJECT *o_current)
479 {
480   int left, right, top, bottom;
481 
482   if (o_current->arc == NULL) {
483     return;
484   }
485 
486   /* recalculates the bounding box */
487   world_get_arc_bounds(toplevel, o_current, &left, &top, &right, &bottom);
488   o_current->w_left   = left;
489   o_current->w_top    = top;
490   o_current->w_right  = right;
491   o_current->w_bottom = bottom;
492   o_current->w_bounds_valid = TRUE;
493 }
494 
495 
496 /*! \brief
497  *  \par Function Description
498  *  This function calculates the smallest rectangle the arc can be drawn into.
499  *  The <B>OBJECT</B> pointed by object is assumed to be an arc.
500  *  The <B>left</B>, <B>top</B>, <B>right</B> and <B>bottom</B> pointed integers define
501  *  this rectangle at the end of the function. It is expressed in world units.
502  *  The process is divided into two steps : the first step is to calculate the
503  *  coordinates of the two ends of the arc and the coordinates of the center.
504  *  They forms a first rectangle but (depending on the start angle and the
505  *  sweep of the arc) not the right.
506  *
507  *  \param [in]  toplevel  The TOPLEVEL object.
508  *  \param [in]  object
509  *  \param [out] left
510  *  \param [out] top
511  *  \param [out] right
512  *  \param [out] bottom
513  */
world_get_arc_bounds(TOPLEVEL * toplevel,OBJECT * object,int * left,int * top,int * right,int * bottom)514 void world_get_arc_bounds(TOPLEVEL *toplevel, OBJECT *object, int *left,
515 			  int *top, int *right, int *bottom)
516 {
517   int x1, y1, x2, y2, x3, y3;
518   int radius, start_angle, end_angle;
519   int i, angle;
520   int halfwidth;
521 
522   halfwidth = object->line_width / 2;
523 
524   radius      = object->arc->width / 2;
525   start_angle = object->arc->start_angle;
526   end_angle   = object->arc->end_angle;
527 
528   x1 = object->arc->x;
529   y1 = object->arc->y;
530   x2 = x1 + radius * cos(start_angle * M_PI / 180);
531   y2 = y1 + radius * sin(start_angle * M_PI / 180);
532   x3 = x1 + radius * cos((start_angle + end_angle) * M_PI / 180);
533   y3 = y1 + radius * sin((start_angle + end_angle) * M_PI / 180);
534 
535   *left   = (x1 < x2) ? ((x1 < x3) ? x1 : x3) : ((x2 < x3) ? x2 : x3);
536   *right  = (x1 > x2) ? ((x1 > x3) ? x1 : x3) : ((x2 > x3) ? x2 : x3);
537   *bottom = (y1 > y2) ? ((y1 > y3) ? y1 : y3) : ((y2 > y3) ? y2 : y3);
538   *top    = (y1 < y2) ? ((y1 < y3) ? y1 : y3) : ((y2 < y3) ? y2 : y3);
539 
540   /*! \note
541    *  The previous rectangle is extended to the final one
542    *  by checking whether the arc is over a main axis (vertical or horizontal).
543    *  If so, the rectangle is extended in these directions.
544    *
545    *  In the mirror mode, the sweep angle is negativ. To get a
546    *  CCW arc before this calculation we have to move the
547    *  start angle to the end angle and reverse the sweep angle.
548    */
549   if (end_angle < 0) {
550     start_angle = (start_angle + end_angle + 360) % 360;
551     end_angle = -end_angle;
552   }
553   angle = ((int) (start_angle / 90)) * 90;
554   for(i = 0; i < 4; i++) {
555     angle = angle + 90;
556     if(angle < start_angle + end_angle) {
557       if(angle % 360 == 0)   *right  = x1 + radius;
558       if(angle % 360 == 90)  *bottom = y1 + radius;
559       if(angle % 360 == 180) *left   = x1 - radius;
560       if(angle % 360 == 270) *top    = y1 - radius;
561     } else {
562       break;
563     }
564   }
565 
566   /* This isn't strictly correct, but a 1st order approximation */
567   *left   -= halfwidth;
568   *top    -= halfwidth;
569   *right  += halfwidth;
570   *bottom += halfwidth;
571 
572 }
573 
574 /*! \brief get the position of the center point
575  *  \par Function Description
576  *  This function gets the position of the center point of an arc object.
577  *
578  *  \param [in] toplevel The toplevel environment.
579  *  \param [out] x       pointer to the x-position
580  *  \param [out] y       pointer to the y-position
581  *  \param [in] object   The object to get the position.
582  *  \return TRUE if successfully determined the position, FALSE otherwise
583  */
o_arc_get_position(TOPLEVEL * toplevel,gint * x,gint * y,OBJECT * object)584 gboolean o_arc_get_position (TOPLEVEL *toplevel, gint *x, gint *y,
585                              OBJECT *object)
586 {
587   *x = object->arc->x;
588   *y = object->arc->y;
589   return TRUE;
590 }
591 
592 /*! \brief
593  *  \par Function Description
594  *  This function writes in a postscript file the arc described by
595  *  the <B>o_current</B> pointed object.
596  *  The postscript resulting file is described by the <B>fp</B> file pointer.
597  *
598  *  Parameters of the arc are extracted from object pointed by <B>o_current</B>
599  *  and formatted to suit future calls to specialized arc printing functions.
600  *
601  *  \param [in] toplevel  The TOPLEVEL object.
602  *  \param [in] fp         The postscript document to print to.
603  *  \param [in] o_current
604  *  \param [in] origin_x
605  *  \param [in] origin_y
606  */
o_arc_print(TOPLEVEL * toplevel,FILE * fp,OBJECT * o_current,int origin_x,int origin_y)607 void o_arc_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current,
608 		 int origin_x, int origin_y)
609 {
610   int x, y, radius, start_angle, end_angle;
611   int color;
612   int arc_width, space, length;
613   void (*outl_func)() = NULL;
614 
615   if (o_current == NULL) {
616     printf("got null in o_arc_print\n");
617     return;
618   }
619 
620   x      = o_current->arc->x;
621   y      = o_current->arc->y;
622   radius = o_current->arc->width / 2;
623   start_angle = o_current->arc->start_angle;
624   end_angle   = o_current->arc->end_angle;
625   color  = o_current->color;
626 
627   /*! \note
628    *  Depending on the type of the line for this particular arc, the
629    *  appropriate function is chosen among #o_arc_print_solid(),
630    *  #o_arc_print_dotted(), #o_arc_print_dashed(), #o_arc_print_center() and #o_arc_print_phantom().
631    *
632    *  The needed parameters for each of these types are extracted from the <B>o_current</B> object.
633    *  Depending on the type, unused parameters are set to -1.
634    *
635    *  In the eventuality of a length and/or space null, the arc is printed solid to avoid and
636    *  endless loop produced by other functions.
637    */
638 
639 #if 0  /* was causing arcs which are solid to be much thinner compared to */
640   /* lines, boxes, also of zero width */
641   if (o_current->line_width > 0) {
642     arc_width = o_current->line_width;
643   } else {
644     arc_width = 1;
645   }
646 #endif
647   arc_width = o_current->line_width;	/* Added instead of above */
648   if(arc_width <=2) {
649     if(toplevel->line_style == THICK) {
650       arc_width=LINE_WIDTH;
651     } else {
652       arc_width=2;
653     }
654   }
655 
656   length = o_current->line_length;
657   space  = o_current->line_space;
658 
659   switch(o_current->line_type) {
660     case(TYPE_SOLID):
661       length = -1; space = -1;
662       outl_func = o_arc_print_solid;
663       break;
664 
665     case(TYPE_DOTTED):
666       length = -1;
667       outl_func = o_arc_print_dotted;
668       break;
669 
670     case(TYPE_DASHED):
671       outl_func = o_arc_print_dashed;
672       break;
673 
674     case(TYPE_CENTER):
675       outl_func = o_arc_print_center;
676       break;
677 
678     case(TYPE_PHANTOM):
679       outl_func = o_arc_print_phantom;
680       break;
681 
682     case(TYPE_ERASE):
683       /* Unused for now, print it solid */
684       length = -1; space = -1;
685       outl_func = o_arc_print_solid;
686       break;
687   }
688 
689   if((space == 0) || (length == 0)) {
690     length = -1; space = -1;
691     outl_func = o_arc_print_solid;
692   }
693 
694   (*outl_func)(toplevel, fp,
695                x - origin_x, y - origin_x, radius,
696                start_angle, end_angle,
697                color, arc_width, length, space, origin_x, origin_y);
698 }
699 
700 
701 /*! \brief
702  *  \par Function Description
703  *  This function prints an arc when a solid line type is required.
704  *  The arc is defined by its center in <B>x</B> and <B>y</B>, its radius
705  *  in <B>radius</B> and the start and end angles of the arc on the circle.
706  *  The postscript file is defined by the file pointer <B>fp</B>.
707  *
708  *  The parameters <B>length</B> and <B>space</B> are ignored
709  *  whereas <B>arc_width</B> specifies the width of the printed line.
710  *
711  *  All dimensions are in mils, except <B>angle1</B> and <B>angle2</B> in degrees.
712  *
713  *  \param [in] toplevel  The TOPLEVEL object.
714  *  \param [in] fp         FILE pointer to postscript document.
715  *  \param [in] x
716  *  \param [in] y
717  *  \param [in] radius
718  *  \param [in] angle1
719  *  \param [in] angle2
720  *  \param [in] color
721  *  \param [in] arc_width
722  *  \param [in] length
723  *  \param [in] space
724  *  \param [in] origin_x
725  *  \param [in] origin_y
726  */
o_arc_print_solid(TOPLEVEL * toplevel,FILE * fp,int x,int y,int radius,int angle1,int angle2,int color,int arc_width,int length,int space,int origin_x,int origin_y)727 void o_arc_print_solid(TOPLEVEL *toplevel, FILE *fp,
728 		       int x, int y, int radius,
729 		       int angle1, int angle2,
730 		       int color,
731 		       int arc_width, int length, int space,
732 		       int origin_x, int origin_y)
733 {
734   f_print_set_color(toplevel, fp, color);
735 
736   /* inverting angle2 if < 0 and changing angle1 accordingly */
737   if (angle2 < 0) {
738     angle1 = angle1 + angle2;
739     angle2 = -angle2;
740   }
741 
742   fprintf(fp, "%d %d %d %d %d %d darc\n",
743 	  x,y, radius, angle1, angle1 + angle2,
744 	  arc_width);
745 
746 }
747 
748 /*! \brief
749  *  \par Function Description
750  *  This function prints an arc when a dotted line type is required.
751  *  The arc is defined by its center in <B>x</B> and <B>y</B>, its
752  *  radius in <B>radius</B> and the start and end angles of the arc on the circle.
753  *  The postscript file is defined by the file pointer <B>fp</B>.
754  *  The parameter <B>length</B> is ignored whereas <B>arc_width</B> specifies
755  *  the diameter of the dots of the printed line and <B>space</B> the distance
756  *  between two dots.
757  *
758  *  A negative value for <B>space</B> leads to an endless loop.
759  *
760  *  All dimensions are in mils, except <B>angle1</B> and <B>angle2</B> in degrees.
761  *
762  *  The function sets the color the line will be printed with.
763  *
764  *  \param [in] toplevel  The TOPLEVEL object.
765  *  \param [in] fp         FILE pointer to postscript document.
766  *  \param [in] x
767  *  \param [in] y
768  *  \param [in] radius
769  *  \param [in] angle1
770  *  \param [in] angle2
771  *  \param [in] color
772  *  \param [in] arc_width
773  *  \param [in] length
774  *  \param [in] space
775  *  \param [in] origin_x
776  *  \param [in] origin_y
777  */
o_arc_print_dotted(TOPLEVEL * toplevel,FILE * fp,int x,int y,int radius,int angle1,int angle2,int color,int arc_width,int length,int space,int origin_x,int origin_y)778 void o_arc_print_dotted(TOPLEVEL *toplevel, FILE *fp,
779 			int x, int y, int radius,
780 			int angle1, int angle2,
781 			int color,
782 			int arc_width, int length, int space,
783 			int origin_x, int origin_y)
784 {
785   int da, d;
786 
787   f_print_set_color(toplevel, fp, color);
788 
789   /*! \note
790    *  Depending on the radius of the arc, the <B>space</B> parameter is
791    *  changed into a small angle <B>da</B>.
792    *  Starting from <B>angle1</B> - the start angle - the dots are printed
793    *  along the arc by increments of this new angle.
794    *
795    *  As <B>da</B> is rounded as an integer, it can take a null value which
796    *  will make the function enter an endless loop. In such a case, the arc
797    *  is printed solid. The <B>da</B> variable should never be negative
798    *  except if <B>space</B> is negative.
799    */
800 
801   /* Inverting angle2 if < 0 and changing angle1 accordingly */
802   /* the loop test assume that da > 0 */
803   if (angle2 < 0) {
804     angle1 = angle1 + angle2;
805     angle2 = -angle2;
806   }
807   da = (int) ((space * 180) / (M_PI * ((double) radius)));
808 
809 	/* If da or db too small for arc to be displayed as dotted,
810            draw a solid arc */
811   if (da <= 0) {
812     o_arc_print_solid(toplevel, fp,
813                       x, y, radius,
814                       angle1, angle2,
815                       color,
816                       arc_width, length, space, origin_x, origin_y);
817     return;
818   }
819 
820   fprintf(fp,"[");
821   d = angle1;
822   while (d < (angle2 + angle1)) {
823     /*xa = ((double) x) + ((double) radius) * cos(d * M_PI / 180);
824     ya = ((double) y) + ((double) radius) * sin(d * M_PI / 180);
825     */
826     fprintf(fp,"[%d] ",d);
827 
828     d = d + da;
829   }
830   fprintf(fp,"] %d %d %d %d dashedarc %% dotted\n",
831 	  x,y, radius, arc_width);
832 }
833 
834 /*! \brief
835  *  \par Function Description
836  *  This function prints an arc when a dashed line type is required.
837  *  The arc is defined by its center in <B>x</B> and <B>y</B>, its radius
838  *  in <B>radius</B> and the start and end angles of the arc on the circle.
839  *  The postscript file is defined by the file pointer <B>fp</B>.
840  *  The parameter <B>arc_width</B> specifies the diameter of the dots of the printed line.
841  *
842  *  A negative value for <B>space</B> or <B>length</B> leads to an endless loop.
843  *
844  *  All dimensions are in mils, except <B>angle1</B> and <B>angle2</B> in degrees.
845  *
846  *  The function sets the color the line will be printed with.
847  *
848  *  \param [in] toplevel  The TOPLEVEL object.
849  *  \param [in] fp         FILE pointer to postscript document.
850  *  \param [in] x
851  *  \param [in] y
852  *  \param [in] radius
853  *  \param [in] angle1
854  *  \param [in] angle2
855  *  \param [in] color
856  *  \param [in] arc_width
857  *  \param [in] length
858  *  \param [in] space
859  *  \param [in] origin_x
860  *  \param [in] origin_y
861  */
o_arc_print_dashed(TOPLEVEL * toplevel,FILE * fp,int x,int y,int radius,int angle1,int angle2,int color,int arc_width,int length,int space,int origin_x,int origin_y)862 void o_arc_print_dashed(TOPLEVEL *toplevel, FILE *fp,
863 			int x, int y, int radius,
864 			int angle1, int angle2,
865 			int color,
866 			int arc_width, int length, int space,
867 			int origin_x, int origin_y)
868 {
869   int da, db, a1, d;
870 
871   f_print_set_color(toplevel, fp, color);
872 
873   /*! \note
874    *  Depending on the radius of the arc, the <B>space</B> (resp. <B>length</B>)
875    *  parameter is changed into a small angle <B>da</B> (resp. <B>db</B>).
876    *  Starting from <B>angle1</B> - the start angle - the dashes are printed
877    *  along the arc by increments of these new angles.
878    *
879    *  As <B>da</B> (resp. <B>db</B>) is rounded as an integer, it can take a
880    *  null value which will make the function enter an endless loop. In such a case,
881    *  the arc is printed solid. The <B>da</B> (resp. <B>db</B>) variable should never
882    *  be negative except if <B>space</B> (resp. <B>length</B>) is negative.
883    *
884    *  It prints as many dashes of length <B>length</B> as possible.
885    */
886 
887   /* Inverting angle2 if < 0 and changing angle1 accordingly */
888   /* the loop test assume that da > 0 */
889   if (angle2 < 0) {
890     angle1 = angle1 + angle2;
891     angle2 = -angle2;
892   }
893   da = (int) ((length * 180) / (M_PI * ((double) radius)));
894   db = (int) ((space  * 180) / (M_PI * ((double) radius)));
895 
896   /* If da or db too small for arc to be displayed as dotted,
897            draw a solid arc */
898   if ((da <= 0) || (db <= 0)) {
899     o_arc_print_solid(toplevel, fp,
900                       x, y, radius,
901                       angle1, angle2,
902                       color,
903                       arc_width, length, space, origin_x, origin_y);
904     return;
905   }
906 
907   fprintf(fp,"[");
908   d = angle1;
909   while ((d + da + db) < (angle1 + angle2)) {
910     a1 = d;
911     d = d + da;
912 
913     fprintf(fp,"[%d %d] ",
914 	    a1, a1+da);
915 
916     d = d + db;
917   }
918   /*! \note
919    *  When the above condition is no more satisfied, then it is not
920    *  possible to print a dash of length <B>length</B> and the following <B>space</B>.
921    *  However it may be possible to print the complete dash or a shorter one.
922    */
923 
924   if ((d + da) < (angle1 + angle2)) {
925     a1 = d;
926   } else {
927     a1 = d;
928   }
929 
930   fprintf(fp,"[%d %d] ",
931 	  a1, a1+da);
932 
933 
934   fprintf(fp,"] %d %d %d %d dashedarc %% dashed\n",
935 	  x,y, radius, arc_width);
936 
937 }
938 
939 /*! \brief
940  *  \par Function Description
941  *  This function prints an arc when a centered line type is required.
942  *  The arc is defined by its center in <B>x</B> and <B>y</B>, its radius in
943  *  <B>radius</B> and the start and end angles of the arc on the circle.
944  *  The postscript file is defined by the file pointer <B>fp</B>.
945  *  The parameter <B>arc_width</B> specifies the diameter of the dots and the width of the dashes of the printed line.
946  *
947  *  A negative value for <B>space</B> or <B>length</B> leads to an endless loop.
948  *
949  *  All dimensions are in mils, except <B>angle1</B> and <B>angle2</B> in degrees.
950  *
951  *  The function sets the color in which the line will be printed with.
952  *
953  *  \param [in] toplevel  The TOPLEVEL object.
954  *  \param [in] fp         FILE pointer to postscript document.
955  *  \param [in] x
956  *  \param [in] y
957  *  \param [in] radius
958  *  \param [in] angle1
959  *  \param [in] angle2
960  *  \param [in] color
961  *  \param [in] arc_width
962  *  \param [in] length
963  *  \param [in] space
964  *  \param [in] origin_x
965  *  \param [in] origin_y
966  */
o_arc_print_center(TOPLEVEL * toplevel,FILE * fp,int x,int y,int radius,int angle1,int angle2,int color,int arc_width,int length,int space,int origin_x,int origin_y)967 void o_arc_print_center(TOPLEVEL *toplevel, FILE *fp,
968 			int x, int y, int radius,
969 			int angle1, int angle2,
970 			int color,
971 			int arc_width, int length, int space,
972 			int origin_x, int origin_y)
973 {
974   int da, db, a1, d;
975 
976   f_print_set_color(toplevel, fp, color);
977 
978   /*! \note
979    *  Depending on the radius of the arc, the <B>space</B> (resp. <B>length</B>)
980    *  parameter is changed into a small angle <B>da</B> (resp. <B>db</B>).
981    *  Starting from <B>angle1</B> - the start angle - the dashes are printed
982    *  along the arc by increments of these new angles.
983    *
984    *  As <B>da</B> (resp. <B>db</B>) is rounded as an integer, it can take a null
985    *  value which will make the function enter an endless loop. In such a case,
986    *  the arc is printed solid. The <B>da</B> (resp. <B>db</B>) variable should never
987    *  be negative except if <B>space</B> (resp. <B>length</B>) is negative.
988    *
989    *  It prints as many sets of dash-dot as possible.
990    */
991 
992   /* Inverting angle2 if < 0 and changing angle1 accordingly */
993   /* the loop test assume that da > 0 */
994   if (angle2 < 0) {
995     angle1 = angle1 + angle2;
996     angle2 = -angle2;
997   }
998 
999   da = (int) ((length * 180) / (M_PI * ((double) radius)));
1000   db = (int) ((space  * 180) / (M_PI * ((double) radius)));
1001 
1002   /* If da or db too small to be displayed, draw an arc */
1003   if ((da <= 0) || (db <= 0)) {
1004     o_arc_print_solid(toplevel, fp,
1005 		      x, y, radius,
1006 		      angle1, angle2,
1007 		      color,
1008 		      arc_width, length, space, origin_x, origin_y);
1009     return;
1010   }
1011 
1012   fprintf(fp, "[");
1013   d = angle1;
1014   while ((d + da + 2 * db) < (angle1 + angle2)) {
1015     a1 = d;
1016     d = d + da;
1017     fprintf(fp,"[%d %d] ",(int) a1, (int) a1 + da);
1018 
1019     d = d + db;
1020     /*
1021       xa = ((double) x) + ((double) radius) * cos(d * (M_PI / 180));
1022       ya = ((double) y) + ((double) radius) * sin(d * (M_PI / 180));
1023     */
1024     fprintf(fp,"[%d] ",d);
1025     d = d + db;
1026   }
1027   /*! \note
1028    *  When the above condition is no more satisfied, then it is not
1029    *  possible to print a dash of length <B>length</B>. However two cases are possible :
1030    *  <DL>
1031    *      <DT>*</DT><DD>it is possible to print the dash and the dot
1032    *      <DT>*</DT><DD>it is possible to print the dash or a part of the original dash
1033    *  </DL>
1034    */
1035 
1036   if ((d + da) < (angle1 + angle2)) {
1037     a1 = d;
1038 
1039     d = d + da;
1040   } else {
1041     a1 = d;
1042 
1043     d = d + da;
1044   }
1045 
1046   fprintf(fp,"[%d %d] ",(int) a1, (int) a1 + da);
1047 
1048 
1049   if ((d + db) < (angle1 + angle2)) {
1050     /*
1051       xa = ((double) x) + ((double) radius) * cos(d * (M_PI / 180));
1052       ya = ((double) y) + ((double) radius) * sin(d * (M_PI / 180));
1053     */
1054     fprintf(fp,"[%d] ",d);
1055 
1056   }
1057 
1058   fprintf(fp,"] %d %d %d %d dashedarc %% center\n",
1059 	  x,y, radius, arc_width);
1060 }
1061 
1062 /*! \note
1063  *  A dot is represented by a filled circle. Position of the circle is (<B>xa</B>, <B>ya</B>)
1064  *  and its radius is the <B>arc_width</B> parameter.
1065  */
1066 
1067 /*! \brief
1068  *  \par Function Description
1069  *  This function prints an arc when a phantom line type is required.
1070  *  The arc is defined by its center in <B>x</B> and <B>y</B>, its radius
1071  *  in <B>radius</B> and the start and end angles of the arc on the circle.
1072  *  The postscript file is defined by the file pointer <B>fp</B>.
1073  *  The parameter <B>arc_width</B> specifies the diameter of the dots and the width of the dashes of the printed line.
1074  *
1075  *  A negative value for <B>space</B> or <B>length</B> leads to an endless loop.
1076  *
1077  *  All dimensions are in mils, except <B>angle1</B> and <B>angle2</B> in degrees.
1078  *
1079  * The function sets the color in which the line will be printed with.
1080  *
1081  *  \param [in] toplevel  The TOPLEVEL object.
1082  *  \param [in] fp         FILE pointer to postscript document.
1083  *  \param [in] x
1084  *  \param [in] y
1085  *  \param [in] radius
1086  *  \param [in] angle1
1087  *  \param [in] angle2
1088  *  \param [in] color
1089  *  \param [in] arc_width
1090  *  \param [in] length
1091  *  \param [in] space
1092  *  \param [in] origin_x
1093  *  \param [in] origin_y
1094  */
o_arc_print_phantom(TOPLEVEL * toplevel,FILE * fp,int x,int y,int radius,int angle1,int angle2,int color,int arc_width,int length,int space,int origin_x,int origin_y)1095 void o_arc_print_phantom(TOPLEVEL *toplevel, FILE *fp,
1096 			 int x, int y, int radius,
1097 			 int angle1, int angle2,
1098 			 int color,
1099 			 int arc_width, int length, int space,
1100 			 int origin_x, int origin_y)
1101 {
1102   int da, db, a1, d;
1103 
1104   f_print_set_color(toplevel, fp, color);
1105 
1106   /*! \note
1107    *  Depending on the radius of the arc, the <B>space</B> (resp. <B>length</B>)
1108    *  parameter is changed into a small angle <B>da</B> (resp. <B>db</B>).
1109    *  Starting from <B>angle1</B> - the start angle - the dashes are printed
1110    *  along the arc by increments of these new angles.
1111    *
1112    *  As <B>da</B> (resp. <B>db</B>) is rounded as an integer, it can take a
1113    *  null value which will make the function enter an endless loop. In such
1114    *  a case, the arc is printed solid. The <B>da</B> (resp. <B>db</B>) variable
1115    *  should never be negative except if <B>space</B> (resp. <B>length</B>) is negative.
1116    *
1117    *  It prints as many sets of dash-dot-dot as possible.
1118    */
1119 
1120   /* Inverting angle2 if < 0 and changing angle1 accordingly */
1121   /* the loop test assume that da > 0 */
1122   if (angle2 < 0) {
1123     angle1 = angle1 + angle2;
1124     angle2 = -angle2;
1125   }
1126   da = (int) ((length * 180) / (((double) radius) * M_PI));
1127   db = (int) ((space  * 180) / (((double) radius) * M_PI));
1128 
1129   /* If da or db too small for arc to be displayed as dotted,
1130      draw a solid arc */
1131   if ((da <= 0) || (db <= 0)) {
1132     o_arc_print_solid(toplevel, fp,
1133 		      x, y, radius,
1134 		      angle1, angle2,
1135 		      color,
1136 		      arc_width, length, space, origin_x, origin_y);
1137     return;
1138   }
1139 
1140   fprintf(fp,"[");
1141 
1142   d = angle1;
1143   while ((d + da + 3 * db) < (angle1 + angle2)) {
1144     a1 = d;
1145     d = d + da;
1146 
1147     fprintf(fp,"[%d %d] ",(int) a1, (int) a1 + da);
1148 
1149     d = d + db;
1150     /*
1151       xa = ((double) x) + ((double) radius) * cos(d * (M_PI / 180));
1152       ya = ((double) y) + ((double) radius) * sin(d * (M_PI / 180));
1153     */
1154     fprintf(fp,"[%d] ",d);
1155 
1156     d = d + db;
1157 
1158     /*
1159       xa = ((double) x) + ((double) radius) * cos(d * (M_PI / 180));
1160       ya = ((double) y) + ((double) radius) * sin(d * (M_PI / 180));
1161     */
1162     fprintf(fp,"[%d] ",d);
1163 
1164     d = d + db;
1165   }
1166 
1167   /*! \note
1168    *  When the above condition is no more satisfied, then it is not
1169    *  possible to print a dash of length <B>length</B>.
1170    *  However three cases are possible :
1171    *  <DL>
1172    *    <DT>*</DT><DD>it is possible to print a dash and a dot and a dot
1173    *    <DT>*</DT><DD>it is possible to print a dash and a dot
1174    *    <DT>*</DT><DD>it is possible to print the dash or a part of the original dash
1175    *  </DL>
1176    */
1177 
1178   if ((d + da) < (angle1 + angle2)) {
1179     a1 = d;
1180     d = d + da;
1181   } else {
1182     a1 = d;
1183     d = d + da;
1184   }
1185 
1186   fprintf(fp,"[%d %d] ",(int) a1, (int) a1 + da);
1187 
1188   if ((d + db) < (angle1 + angle2)) {
1189     d = d + db;
1190 
1191     /*
1192       xa = ((double) x) + ((double) radius) * cos(d * (M_PI / 180));
1193       ya = ((double) y) + ((double) radius) * sin(d * (M_PI / 180));
1194     */
1195     fprintf(fp,"[%d] ",d);
1196 
1197   }
1198 
1199   if ((d + db) < (angle1 + angle2)) {
1200     d = d + db;
1201 
1202     /*
1203       xa = ((double) x) + ((double) radius) * cos(d * (M_PI / 180));
1204       ya = ((double) y) + ((double) radius) * sin(d * (M_PI / 180));
1205     */
1206 
1207     fprintf(fp,"[%d] ",d);
1208 
1209 
1210   }
1211 
1212   fprintf(fp,"] %d %d %d %d dashedarc %% phantom\n",
1213 	  x,y, radius, arc_width);
1214 }
1215 
1216 /*! \brief Calculates the distance between the given point and the closest
1217  * point on the perimeter of the arc.
1218  *
1219  *  \param [in] object       The arc OBJECT.
1220  *  \param [in] x            The x coordinate of the given point.
1221  *  \param [in] y            The y coordinate of the given point.
1222  *  \param [in] force_solid  If true, force treating the object as solid.
1223  *  \return The shortest distance from the object to the point. With an
1224  *  invalid parameter, this function returns G_MAXDOUBLE.
1225  */
o_arc_shortest_distance(OBJECT * object,int x,int y,int force_solid)1226 double o_arc_shortest_distance (OBJECT *object, int x, int y, int force_solid)
1227 {
1228   double shortest_distance;
1229   double radius;
1230 
1231   g_return_val_if_fail (object->arc != NULL, G_MAXDOUBLE);
1232 
1233   radius = ((double)object->arc->width) / 2.0;
1234 
1235   if (o_arc_within_sweep (object->arc, x, y)) {
1236     double distance_to_center;
1237     double dx;
1238     double dy;
1239 
1240     dx = ((double)x) - ((double)object->arc->x);
1241     dy = ((double)y) - ((double)object->arc->y);
1242 
1243     distance_to_center = sqrt ((dx * dx) + (dy * dy));
1244 
1245     shortest_distance = fabs (distance_to_center - radius);
1246 
1247   } else {
1248     double angle;
1249     double distance_to_end0;
1250     double distance_to_end1;
1251     double dx, dy;
1252 
1253     angle = G_PI * ((double)object->arc->start_angle) / 180;
1254 
1255     dx = ((double)x) - radius * cos (angle) - ((double)object->arc->x);
1256     dy = ((double)y) - radius * sin (angle) - ((double)object->arc->y);
1257 
1258     distance_to_end0 = sqrt ((dx * dx) + (dy * dy));
1259 
1260     angle += G_PI * ((double)object->arc->end_angle) / 180;
1261 
1262     dx = ((double)x) - radius * cos (angle) - ((double)object->arc->x);
1263     dy = ((double)y) - radius * sin (angle) - ((double)object->arc->y);
1264 
1265     distance_to_end1 = sqrt ((dx * dx) + (dy * dy));
1266 
1267     shortest_distance = min (distance_to_end0, distance_to_end1);
1268   }
1269 
1270   return shortest_distance;
1271 }
1272 
1273 /*! \brief Determines if a point lies within the sweep of the arc.
1274  *
1275  *  \param [in] arc The arc of object
1276  *  \param [in] x The x coordinate of the given point.
1277  *  \param [in] y The y coordinate of the given point.
1278  *  \return TRUE if the point lies within the sweep of the arc.
1279  *  FALSE if the point lies outside the sweep of the arc. With an
1280  *  invalid parameter, this function returns FALSE.
1281  */
o_arc_within_sweep(ARC * arc,gint x,gint y)1282 gboolean o_arc_within_sweep(ARC *arc, gint x, gint y)
1283 {
1284   gdouble a0;
1285   gdouble a1;
1286   gdouble angle;
1287   gdouble dx;
1288   gdouble dy;
1289 
1290   if (arc == NULL) {
1291     g_critical("o_arc_within_sweep(): arc == NULL\n");
1292     return FALSE;
1293   }
1294 
1295   dx = ((gdouble) x) - ((gdouble) arc->x);
1296   dy = ((gdouble) y) - ((gdouble) arc->y);
1297 
1298   angle = 180 * atan2(dy, dx) / G_PI;
1299 
1300   if (arc->end_angle > 0) {
1301     a0 = arc->start_angle;
1302     a1 = arc->start_angle + arc->end_angle;
1303   } else {
1304     a0 = arc->start_angle + arc->end_angle + 360;
1305     a1 = arc->start_angle + 360;
1306   }
1307 
1308   while (angle < a0) {
1309     angle+=360;
1310   }
1311 
1312   return (angle < a1);
1313 }
1314 
1315