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_circle_basic.c
22 * \brief functions for the circle object
23 */
24
25 #include <config.h>
26 #include <stdio.h>
27 #include <math.h>
28
29 #include "libgeda_priv.h"
30
31 #ifdef HAVE_LIBDMALLOC
32 #include <dmalloc.h>
33 #endif
34
35 /*! \brief calculate the distance between two points
36 * \par Function Description
37 * This function calculates the distance between two points.
38 * The two points are defined by the (\a x1, \a y1) and (\a x2, \a y2)
39 * parameters.
40 * \param [in] x1 x-value of the first point
41 * \param [in] y1 y-value of the first point
42 * \param [in] x2 x-value of the second point
43 * \param [in] y2 y-value of the second point
44 * \return the distance
45 * \todo Move this function to a different place
46 */
dist(int x1,int y1,int x2,int y2)47 int dist(int x1, int y1, int x2, int y2)
48 {
49 return sqrt(pow(x1-x2,2)+pow(y1-y2,2));
50 }
51
52 /*! \brief Create and add circle OBJECT to list.
53 * \par Function Description
54 * This function creates a new object representing a circle.
55 *
56 * The circle is described by its center (<B>x</B>,<B>y</B>) and its radius
57 * <B>radius</B>.
58 * The <B>type</B> parameter must be equal to <B>OBJ_CIRCLE</B>. The <B>color</B>
59 * corresponds to the color the box will be drawn with.
60 *
61 * The <B>OBJECT</B> structure is allocated with the #s_basic_new_object()
62 * function. The structure describing the circle is allocated and initialized
63 * with the parameters given to the function.
64 *
65 * Both the line type and the filling type are set to default values : solid
66 * line type with a width of 0, and no filling. It can be changed after
67 * with #o_set_line_options() and #o_set_fill_options().
68 *
69 * \param [in] toplevel The TOPLEVEL object.
70 * \param [in] type Must be OBJ_CIRCLE.
71 * \param [in] color Circle line color.
72 * \param [in] x Center x coordinate.
73 * \param [in] y Center y coordinate.
74 * \param [in] radius Radius of new circle.
75 * \return A pointer to the new end of the object list.
76 */
o_circle_new(TOPLEVEL * toplevel,char type,int color,int x,int y,int radius)77 OBJECT *o_circle_new(TOPLEVEL *toplevel,
78 char type, int color,
79 int x, int y, int radius)
80 {
81 OBJECT *new_node;
82
83 /* create the object */
84 new_node = s_basic_new_object(type, "circle");
85 new_node->color = color;
86
87 new_node->circle = (CIRCLE *) g_malloc(sizeof(CIRCLE));
88
89 /* describe the circle with its center and radius */
90 new_node->circle->center_x = x;
91 new_node->circle->center_y = y;
92 new_node->circle->radius = radius;
93
94 /* line type and filling initialized to default */
95 o_set_line_options(toplevel, new_node,
96 END_NONE, TYPE_SOLID, 0, -1, -1);
97 o_set_fill_options(toplevel, new_node,
98 FILLING_HOLLOW, -1, -1, -1, -1, -1);
99
100 /* compute the bounding box coords */
101 o_circle_recalc(toplevel, new_node);
102
103 return new_node;
104 }
105
106 /*! \brief Create a copy of a circle.
107 * \par Function Description
108 * The function #o_circle_copy() creates a verbatim copy of the object
109 * pointed by <B>o_current</B> describing a circle.
110 *
111 * \param [in] toplevel The TOPLEVEL object.
112 * \param [in] o_current Circle OBJECT to copy.
113 * \return The new OBJECT
114 */
o_circle_copy(TOPLEVEL * toplevel,OBJECT * o_current)115 OBJECT *o_circle_copy(TOPLEVEL *toplevel, OBJECT *o_current)
116 {
117 OBJECT *new_obj;
118
119 /* A new circle object is created with #o_circle_new().
120 * Values for its fields are default and need to be modified. */
121 new_obj = o_circle_new (toplevel, OBJ_CIRCLE, o_current->color, 0, 0, 0);
122
123 /*
124 * The parameters of the new circle are set with the ones of the original
125 * circle. The two circle have the same line type and the same filling
126 * options.
127 *
128 * The bounding box coordinates are computed with
129 * #o_circle_recalc().
130 */
131 /* modify */
132 new_obj->circle->center_x = o_current->circle->center_x;
133 new_obj->circle->center_y = o_current->circle->center_y;
134 new_obj->circle->radius = o_current->circle->radius;
135
136 o_set_line_options(toplevel, new_obj, o_current->line_end,
137 o_current->line_type, o_current->line_width,
138 o_current->line_length, o_current->line_space);
139 o_set_fill_options(toplevel, new_obj,
140 o_current->fill_type, o_current->fill_width,
141 o_current->fill_pitch1, o_current->fill_angle1,
142 o_current->fill_pitch2, o_current->fill_angle2);
143
144 o_circle_recalc(toplevel, new_obj);
145
146 /* new_obj->attribute = 0;*/
147
148 return new_obj;
149 }
150
151 /*! \brief Modify the description of a circle OBJECT.
152 * \par Function Description
153 * This function modifies the description of the circle object <B>*object</B>
154 * depending on <B>whichone</B> that give the meaning of the <B>x</B> and <B>y</B>
155 * parameters.
156 *
157 * If <B>whichone</B> is equal to <B>CIRCLE_CENTER</B>, the new center of the
158 * circle is given by (<B>x</B>,<B>y</B>) where <B>x</B> and <B>y</B> are in world units.
159 *
160 * If <B>whichone</B> is equal to <B>CIRCLE_RADIUS</B>, the radius is given by
161 * <B>x</B> - in world units. <B>y</B> is ignored.
162 *
163 * The bounding box of the circle object is updated after the modification of its
164 * parameters.
165 *
166 * \param [in] toplevel The TOPLEVEL object.
167 * \param [in,out] object Circle OBJECT to modify.
168 * \param [in] x New center x coordinate, or radius value.
169 * \param [in] y New center y coordinate.
170 * Unused if radius is being modified.
171 * \param [in] whichone Which circle parameter to modify.
172 *
173 * <B>whichone</B> can have the following values:
174 * <DL>
175 * <DT>*</DT><DD>CIRCLE_CENTER
176 * <DT>*</DT><DD>CIRCLE_RADIUS
177 * </DL>
178 */
o_circle_modify(TOPLEVEL * toplevel,OBJECT * object,int x,int y,int whichone)179 void o_circle_modify(TOPLEVEL *toplevel, OBJECT *object,
180 int x, int y, int whichone)
181 {
182 o_emit_pre_change_notify (toplevel, object);
183
184 switch(whichone) {
185 case CIRCLE_CENTER:
186 /* modify the center of the circle */
187 object->circle->center_x = x;
188 object->circle->center_y = y;
189 break;
190 case CIRCLE_RADIUS:
191 /* modify the radius of the circle */
192 if (x == 0) {
193 s_log_message(_("Null radius circles are not allowed\n"));
194 return;
195 }
196 object->circle->radius = x;
197 break;
198 default:
199 break;
200 }
201
202 /* recalculate the boundings */
203 o_circle_recalc(toplevel, object);
204 o_emit_change_notify (toplevel, object);
205 }
206
207 /*! \brief Create circle OBJECT from character string.
208 * \par Function Description
209 * The #o_circle_read() function gets from the character string <B>*buff</B> the
210 * description of a circle.
211 *
212 * Depending on <B>*version</B>, the right file format is considered.
213 * Currently two file format revisions are supported :
214 * <DL>
215 * <DT>*</DT><DD>the file format used until 2000704 release.
216 * <DT>*</DT><DD>the file format used for the releases after 20000704.
217 * </DL>
218 *
219 * \param [in] toplevel The TOPLEVEL object.
220 * \param [in] buf Character string with circle description.
221 * \param [in] release_ver libgeda release version number.
222 * \param [in] fileformat_ver libgeda file format version number.
223 * \return A pointer to the new circle object, or NULL on error.
224 */
o_circle_read(TOPLEVEL * toplevel,const char buf[],unsigned int release_ver,unsigned int fileformat_ver,GError ** err)225 OBJECT *o_circle_read (TOPLEVEL *toplevel, const char buf[],
226 unsigned int release_ver, unsigned int fileformat_ver, GError ** err)
227 {
228 OBJECT *new_obj;
229 char type;
230 int x1, y1;
231 int radius;
232 int color;
233 int circle_width, circle_space, circle_length;
234 int fill_width, angle1, pitch1, angle2, pitch2;
235 int circle_end;
236 int circle_type;
237 int circle_fill;
238
239 if(release_ver <= VERSION_20000704) {
240 /*
241 * The old geda file format, i.e. releases 20000704 and older, does not
242 * handle the line type and the filling of the box object. They are set
243 * to default.
244 */
245 if (sscanf(buf, "%c %d %d %d %d\n", &type, &x1, &y1, &radius, &color) != 5) {
246 g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse circle object"));
247 return NULL;
248 }
249
250 circle_width = 0;
251 circle_end = END_NONE;
252 circle_type = TYPE_SOLID;
253 circle_length= -1;
254 circle_space = -1;
255
256 circle_fill = FILLING_HOLLOW;
257 fill_width = 0;
258 angle1 = -1;
259 pitch1 = -1;
260 angle2 = -1;
261 pitch2 = -1;
262
263 } else {
264
265 /*
266 * The current line format to describe a circle is a space separated
267 * list of characters and numbers in plain ASCII on a single line. The
268 * meaning of each item is described in the file format documentation.
269 */
270 if (sscanf(buf, "%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
271 &type, &x1, &y1, &radius, &color,
272 &circle_width, &circle_end, &circle_type,
273 &circle_length, &circle_space, &circle_fill,
274 &fill_width, &angle1, &pitch1, &angle2, &pitch2) != 16) {
275 g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse circle object"));
276 return NULL;
277 }
278 }
279
280
281 if (radius <= 0) {
282 s_log_message(_("Found a zero or negative radius circle [ %c %d %d %d %d ]\n"),
283 type, x1, y1, radius, color);
284 s_log_message (_("Setting radius to 0\n"));
285 radius = 0;
286 }
287
288 if (color < 0 || color > MAX_COLORS) {
289 s_log_message(_("Found an invalid color [ %s ]\n"), buf);
290 s_log_message(_("Setting color to default color\n"));
291 color = DEFAULT_COLOR;
292 }
293
294 /*
295 * A circle is internally described by its center and its radius.
296 *
297 * A new object is allocated, initialized and added to the object list.
298 * Its filling and line type are set according to the values of the field
299 * on the line.
300 */
301 new_obj = o_circle_new(toplevel, type, color, x1, y1, radius);
302 o_set_line_options(toplevel, new_obj,
303 circle_end, circle_type, circle_width,
304 circle_length, circle_space);
305 o_set_fill_options(toplevel, new_obj,
306 circle_fill, fill_width, pitch1, angle1, pitch2, angle2);
307
308 return new_obj;
309 }
310
311 /*! \brief Create a character string representation of a circle OBJECT.
312 * \par Function Description
313 * This function formats a string in the buffer <B>*buff</B> to describe the
314 * circle object <B>*object</B>.
315 * It follows the post-20000704 release file format that handle the line
316 * type and fill options.
317 *
318 * \param [in] toplevel a TOPLEVEL structure.
319 * \param [in] object Circle OBJECT to create string from.
320 * \return A pointer to the circle OBJECT character string.
321 *
322 * \note
323 * Caller must g_free returned character string.
324 *
325 */
o_circle_save(TOPLEVEL * toplevel,OBJECT * object)326 char *o_circle_save(TOPLEVEL *toplevel, OBJECT *object)
327 {
328 int x,y;
329 int radius;
330 int circle_width, circle_space, circle_length;
331 int fill_width, angle1, pitch1, angle2, pitch2;
332 char *buf;
333 OBJECT_END circle_end;
334 OBJECT_TYPE circle_type;
335 OBJECT_FILLING circle_fill;
336
337 /* circle center and radius */
338 x = object->circle->center_x;
339 y = object->circle->center_y;
340 radius = object->circle->radius;
341
342 /* line type parameters */
343 circle_width = object->line_width;
344 circle_end = object->line_end;
345 circle_type = object->line_type;
346 circle_length= object->line_length;
347 circle_space = object->line_space;
348
349 /* filling parameters */
350 circle_fill = object->fill_type;
351 fill_width = object->fill_width;
352 angle1 = object->fill_angle1;
353 pitch1 = object->fill_pitch1;
354 angle2 = object->fill_angle2;
355 pitch2 = object->fill_pitch2;
356
357 buf = g_strdup_printf("%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
358 object->type, x, y, radius, object->color,
359 circle_width, circle_end, circle_type, circle_length,
360 circle_space, circle_fill,
361 fill_width, angle1, pitch1, angle2, pitch2);
362 return(buf);
363 }
364
365 /*! \brief Translate a circle position in WORLD coordinates by a delta.
366 * \par Function Description
367 * This function applies a translation of (<B>x1</B>,<B>y1</B>) to the circle
368 * described by <B>*object</B>. <B>x1</B> and <B>y1</B> are in world unit.
369 *
370 * \param [in] toplevel The TOPLEVEL object.
371 * \param [in] dx x distance to move.
372 * \param [in] dy y distance to move.
373 * \param [in,out] object Circle OBJECT to translate.
374 */
o_circle_translate_world(TOPLEVEL * toplevel,int dx,int dy,OBJECT * object)375 void o_circle_translate_world(TOPLEVEL *toplevel,
376 int dx, int dy, OBJECT *object)
377 {
378 /* Do world coords */
379 object->circle->center_x = object->circle->center_x + dx;
380 object->circle->center_y = object->circle->center_y + dy;
381
382 /* recalc the screen coords and the bounding box */
383 o_circle_recalc(toplevel, object);
384
385 }
386
387 /*! \brief Rotate Circle OBJECT using WORLD coordinates.
388 * \par Function Description
389 * The function #o_circle_rotate_world() rotate the circle described by
390 * <B>*object</B> around the (<B>world_centerx</B>,<B>world_centery</B>) point by
391 * angle <B>angle</B> degrees.
392 * The center of rotation is in world unit.
393 *
394 * \param [in] toplevel The TOPLEVEL object.
395 * \param [in] world_centerx Rotation center x coordinate in WORLD units.
396 * \param [in] world_centery Rotation center y coordinate in WORLD units.
397 * \param [in] angle Rotation angle in degrees (See note below).
398 * \param [in,out] object Circle OBJECT to rotate.
399 */
o_circle_rotate_world(TOPLEVEL * toplevel,int world_centerx,int world_centery,int angle,OBJECT * object)400 void o_circle_rotate_world(TOPLEVEL *toplevel,
401 int world_centerx, int world_centery, int angle,
402 OBJECT *object)
403 {
404 int newx, newy;
405 int x, y;
406
407 /* Only 90 degree multiple and positive angles are allowed. */
408 /* angle must be positive */
409 if(angle < 0) angle = -angle;
410 /* angle must be a 90 multiple or no rotation performed */
411 if((angle % 90) != 0) return;
412
413 /*
414 * The center of rotation (<B>world_centerx</B>,<B>world_centery</B>) is
415 * translated to the origin. The rotation of the center around the origin
416 * is then performed. Finally, the rotated circle is translated back to
417 * its previous location.
418 */
419
420 /* translate object to origin */
421 object->circle->center_x -= world_centerx;
422 object->circle->center_y -= world_centery;
423
424 /* rotate the center of the circle around the origin */
425 x = object->circle->center_x;
426 y = object->circle->center_y;
427 rotate_point_90(x, y, angle, &newx, &newy);
428 object->circle->center_x = newx;
429 object->circle->center_y = newy;
430
431 /* translate back in position */
432 object->circle->center_x += world_centerx;
433 object->circle->center_y += world_centery;
434
435 o_circle_recalc(toplevel, object);
436
437 }
438
439 /*! \brief Mirror circle using WORLD coordinates.
440 * \par Function Description
441 * This function recalculates the screen coords of the <B>o_current</B> pointed
442 * circle object from its world coords.
443 *
444 * The circle coordinates and its bounding are recalculated as well as the
445 * OBJECT specific (line width, filling ...).
446 *
447 * \param [in] toplevel The TOPLEVEL object.
448 * \param [in] world_centerx Origin x coordinate in WORLD units.
449 * \param [in] world_centery Origin y coordinate in WORLD units.
450 * \param [in,out] object Circle OBJECT to mirror.
451 */
o_circle_mirror_world(TOPLEVEL * toplevel,int world_centerx,int world_centery,OBJECT * object)452 void o_circle_mirror_world(TOPLEVEL *toplevel,
453 int world_centerx, int world_centery,
454 OBJECT *object)
455 {
456 /* translate object to origin */
457 object->circle->center_x -= world_centerx;
458 object->circle->center_y -= world_centery;
459
460 /* mirror the center of the circle */
461 object->circle->center_x = -object->circle->center_x;
462 object->circle->center_y = object->circle->center_y;
463
464 /* translate back in position */
465 object->circle->center_x += world_centerx;
466 object->circle->center_y += world_centery;
467
468 /* recalc boundings and screen coords */
469 o_circle_recalc(toplevel, object);
470
471 }
472
473 /*! \brief Recalculate circle coordinates in SCREEN units.
474 * \par Function Description
475 * This function recalculates the screen coords of the <B>o_current</B> pointed
476 * circle object from its world coords.
477 *
478 * The circle coordinates and its bounding are recalculated as well as the
479 * OBJECT specific (line width, filling ...).
480 *
481 * \param [in] toplevel The TOPLEVEL object.
482 * \param [in,out] o_current Circle OBJECT to be recalculated.
483 */
o_circle_recalc(TOPLEVEL * toplevel,OBJECT * o_current)484 void o_circle_recalc(TOPLEVEL *toplevel, OBJECT *o_current)
485 {
486 int left, right, top, bottom;
487
488 if (o_current->circle == NULL) {
489 return;
490 }
491
492 /* update the bounding box - world unit */
493 world_get_circle_bounds(toplevel, o_current,
494 &left, &top, &right, &bottom);
495 o_current->w_left = left;
496 o_current->w_top = top;
497 o_current->w_right = right;
498 o_current->w_bottom = bottom;
499 o_current->w_bounds_valid = TRUE;
500 }
501
502 /*! \brief Get circle bounding rectangle in WORLD coordinates.
503 * \par Function Description
504 * This function sets the <B>left</B>, <B>top</B>, <B>right</B> and <B>bottom</B>
505 * parameters to the boundings of the circle object described in <B>*circle</B>
506 * in world units.
507 *
508 * \param [in] toplevel The TOPLEVEL object.
509 * \param [in] object Circle OBJECT to read coordinates from.
510 * \param [out] left Left circle coordinate in WORLD units.
511 * \param [out] top Top circle coordinate in WORLD units.
512 * \param [out] right Right circle coordinate in WORLD units.
513 * \param [out] bottom Bottom circle coordinate in WORLD units.
514 */
world_get_circle_bounds(TOPLEVEL * toplevel,OBJECT * object,int * left,int * top,int * right,int * bottom)515 void world_get_circle_bounds(TOPLEVEL *toplevel, OBJECT *object, int *left,
516 int *top, int *right, int *bottom)
517 {
518 int halfwidth;
519
520 halfwidth = object->line_width / 2;
521
522 *left = object->circle->center_x - object->circle->radius;
523 *top = object->circle->center_y - object->circle->radius;
524 *right = object->circle->center_x + object->circle->radius;
525 *bottom = object->circle->center_y + object->circle->radius;
526
527 /* This isn't strictly correct, but a 1st order approximation */
528 *left -= halfwidth;
529 *top -= halfwidth;
530 *right += halfwidth;
531 *bottom += halfwidth;
532
533 }
534
535 /*! \brief get the position of the center point
536 * \par Function Description
537 * This function gets the position of the center point of a circle object.
538 *
539 * \param [in] toplevel The toplevel environment.
540 * \param [out] x pointer to the x-position
541 * \param [out] y pointer to the y-position
542 * \param [in] object The object to get the position.
543 * \return TRUE if successfully determined the position, FALSE otherwise
544 */
o_circle_get_position(TOPLEVEL * toplevel,gint * x,gint * y,OBJECT * object)545 gboolean o_circle_get_position (TOPLEVEL *toplevel, gint *x, gint *y,
546 OBJECT *object)
547 {
548 *x = object->circle->center_x;
549 *y = object->circle->center_y;
550 return TRUE;
551 }
552
553 /*! \brief Print circle to Postscript document.
554 * \par Function Description
555 * This function prints the circle described by the <B>o_current</B>
556 * parameter to a Postscript document. It takes into account its line type
557 * and fill type.
558 * The Postscript document is descibed by the file pointer <B>fp</B>.
559 *
560 * The validity of the <B>o_current</B> pointer is checked :
561 * a null pointer causes an error message and a return.
562 *
563 * The description of the circle is extracted from the <B>o_current</B>
564 * parameter : the coordinates of the center of the circle, its radius,
565 * its line type, its fill type.
566 *
567 * The outline and the inside of the circle are successively handled by
568 * two differend sets of functions.
569 *
570 * \param [in] toplevel The TOPLEVEL object.
571 * \param [in] fp FILE pointer to Postscript document.
572 * \param [in] o_current Circle OBJECT to write to document.
573 * \param [in] origin_x Page x coordinate to place circle OBJECT.
574 * \param [in] origin_y Page y coordinate to place circle OBJECT.
575 */
o_circle_print(TOPLEVEL * toplevel,FILE * fp,OBJECT * o_current,int origin_x,int origin_y)576 void o_circle_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current,
577 int origin_x, int origin_y)
578 {
579 int x, y, radius;
580 int color;
581 int circle_width, length, space;
582 int fill_width, angle1, pitch1, angle2, pitch2;
583 void (*outl_func)() = NULL;
584 void (*fill_func)() = NULL;
585
586 if (o_current == NULL) {
587 printf("got null in o_circle_print\n");
588 return;
589 }
590
591 x = o_current->circle->center_x;
592 y = o_current->circle->center_y;
593 radius = o_current->circle->radius;
594
595 color = o_current->color;
596
597 /*
598 * Depending on the type of the line for this particular circle, the
599 * appropriate function is chosen among #o_circle_print_solid(),
600 * #o_circle_print_dotted(), #o_circle_print_dashed(),
601 * #o_circle_print_center() and #o_circle_print_phantom().
602 *
603 * The needed parameters for each of these type is extracted from the
604 * <B>o_current</B> object. Depending on the type, unused parameters are
605 * set to -1.
606 *
607 * In the eventuality of a length and/or space null, the line is
608 * printed solid to avoid and endless loop produced by other functions
609 * in such a case.
610 */
611 circle_width = o_current->line_width;
612 if(circle_width <=2) {
613 if(toplevel->line_style == THICK) {
614 circle_width=LINE_WIDTH;
615 } else {
616 circle_width=2;
617 }
618 }
619 length = o_current->line_length;
620 space = o_current->line_space;
621
622 switch(o_current->line_type) {
623 case(TYPE_SOLID):
624 length = -1; space = -1;
625 outl_func = o_circle_print_solid;
626 break;
627
628 case(TYPE_DOTTED):
629 length = -1;
630 outl_func = o_circle_print_dotted;
631 break;
632
633 case(TYPE_DASHED):
634 outl_func = o_circle_print_dashed;
635 break;
636
637 case(TYPE_CENTER):
638 outl_func = o_circle_print_center;
639 break;
640
641 case(TYPE_PHANTOM):
642 outl_func = o_circle_print_phantom;
643 break;
644
645 case(TYPE_ERASE):
646 /* Unused for now print it solid */
647 length = -1; space = -1;
648 outl_func = o_circle_print_solid;
649 break;
650 }
651
652 if((length == 0) || (space == 0)) {
653 length = -1; space = -1;
654 outl_func = o_circle_print_solid;
655 }
656
657 (*outl_func)(toplevel, fp,
658 x - origin_x, y - origin_y,
659 radius,
660 color,
661 circle_width, length, space,
662 origin_x, origin_y);
663
664 /*
665 * If the filling type of the circle is not <B>HOLLOW</B>, the appropriate
666 * function is chosen among #o_circle_print_filled(), #o_circle_print_mesh()
667 * and #o_circle_print_hatch(). The corresponding parameters are extracted
668 * from the <B>o_current</B> object and corrected afterward.
669 *
670 * The case where <B>pitch1</B> and <B>pitch2</B> are null or negative is
671 * avoided as it leads to an endless loop in most of the called functions.
672 * In such a case, the circle is printed filled. Unused parameters for
673 * each of these functions are set to -1 or any passive value.
674 */
675 if(o_current->fill_type != FILLING_HOLLOW) {
676 fill_width = o_current->fill_width;
677 angle1 = o_current->fill_angle1;
678 pitch1 = o_current->fill_pitch1;
679 angle2 = o_current->fill_angle2;
680 pitch2 = o_current->fill_pitch2;
681
682 switch(o_current->fill_type) {
683 case(FILLING_FILL):
684 angle1 = -1; pitch1 = 1;
685 angle2 = -1; pitch2 = 1;
686 fill_width = -1;
687 fill_func = o_circle_print_filled;
688 break;
689
690 case(FILLING_MESH):
691 fill_func = o_circle_print_mesh;
692 break;
693
694 case(FILLING_HATCH):
695 angle2 = -1; pitch2 = 1;
696 fill_func = o_circle_print_hatch;
697 break;
698
699 case(FILLING_VOID):
700 /* Unused for now, print it filled */
701 angle1 = -1; pitch1 = 1;
702 angle2 = -1; pitch2 = 1;
703 fill_width = -1;
704 fill_func = o_circle_print_filled;
705 break;
706
707 case(FILLING_HOLLOW):
708 /* nop */
709 break;
710 }
711
712 if((pitch1 <= 0) || (pitch2 <= 0)) {
713 angle1 = -1; pitch1 = 1;
714 angle2 = -1; pitch2 = 1;
715 fill_func = o_circle_print_filled;
716 }
717
718 (*fill_func)(toplevel, fp,
719 x, y, radius,
720 color,
721 fill_width,
722 angle1, pitch1, angle2, pitch2,
723 origin_x, origin_y);
724 }
725 }
726
727 /*! \brief Print a solid circle to Postscript document.
728 * \par Function Description
729 * This function prints the outline of a circle when a solid line type
730 * is required. The circle is defined by its center in (<B>x</B>, <B>y</B>)
731 * and its radius in <B>radius</B>. It is printed with the color given
732 * in <B>color</B>.
733 * The parameters <B>length</B> and <B>space</B> are ignored.
734 *
735 * It uses the function #o_arc_print_solid() to print the outline.
736 * Therefore it acts as an interface between the way a circle is defined
737 * and the way an arc is defined.
738 *
739 * All dimensions are in mils.
740 *
741 * \param [in] toplevel The TOPLEVEL object.
742 * \param [in] fp FILE pointer to Postscript document.
743 * \param [in] x Center x coordinate of circle.
744 * \param [in] y Center y coordinate of circle.
745 * \param [in] radius Circle radius.
746 * \param [in] color Circle color.
747 * \param [in] circle_width Width of circle.
748 * \param [in] length (unused).
749 * \param [in] space (unused).
750 * \param [in] origin_x Page x coordinate to place circle OBJECT.
751 * \param [in] origin_y Page y coordinate to place circle OBJECT.
752 */
o_circle_print_solid(TOPLEVEL * toplevel,FILE * fp,int x,int y,int radius,int color,int circle_width,int length,int space,int origin_x,int origin_y)753 void o_circle_print_solid(TOPLEVEL *toplevel, FILE *fp,
754 int x, int y, int radius,
755 int color,
756 int circle_width, int length, int space,
757 int origin_x, int origin_y)
758 {
759
760 o_arc_print_solid(toplevel, fp,
761 x, y, radius,
762 0, FULL_CIRCLE / 64,
763 color,
764 circle_width, -1, -1,
765 origin_x, origin_y);
766
767 }
768
769
770 /*! \brief Print a dotted circle to Postscript document.
771 * \par Function Description
772 * This function prints the outline of a circle when a dotted line
773 * type is required. The circle is defined by its center
774 * in (<B>x</B>, <B>y</B>) and its radius in <B>radius</B>. It is printed
775 * with the color given in <B>color</B>.
776 * The parameter <B>length</B> is ignored.
777 *
778 * It uses the function #o_arc_print_dotted() to print the outline.
779 * Therefore it acts as an interface between the way a circle is
780 * defined and the way an arc is defined.
781 *
782 * All dimensions are in mils.
783 *
784 * \param [in] toplevel The TOPLEVEL object.
785 * \param [in] fp FILE pointer to Postscript document.
786 * \param [in] x Center x coordinate of circle.
787 * \param [in] y Center y coordinate of circle.
788 * \param [in] radius Circle radius.
789 * \param [in] color Circle color.
790 * \param [in] circle_width Width of circle.
791 * \param [in] length (unused).
792 * \param [in] space Space between dots.
793 * \param [in] origin_x Page x coordinate to place circle OBJECT.
794 * \param [in] origin_y Page y coordinate to place circle OBJECT.
795 */
o_circle_print_dotted(TOPLEVEL * toplevel,FILE * fp,int x,int y,int radius,int color,int circle_width,int length,int space,int origin_x,int origin_y)796 void o_circle_print_dotted(TOPLEVEL *toplevel, FILE *fp,
797 int x, int y, int radius,
798 int color,
799 int circle_width, int length, int space,
800 int origin_x, int origin_y)
801 {
802
803 o_arc_print_dotted(toplevel, fp,
804 x, y, radius,
805 0, FULL_CIRCLE / 64,
806 color,
807 circle_width, -1, space,
808 origin_x, origin_y);
809
810 }
811
812 /*! \brief Print a dashed circle to Postscript document.
813 * \par Function Description
814 * This function prints the outline of a circle when a dashed line type
815 * is required. The circle is defined by its center in
816 * (<B>x</B>, <B>y</B>) and its radius in <B>radius</B>. It is printed with the
817 * color given in <B>color</B>.
818 *
819 * It uses the function #o_arc_print_dashed() to print the outline.
820 * Therefore it acts as an interface between the way a circle is
821 * defined and the way an arc is defined.
822 *
823 * All dimensions are in mils.
824 *
825 * \param [in] toplevel The TOPLEVEL object.
826 * \param [in] fp FILE pointer to Postscript document.
827 * \param [in] x Center x coordinate of circle.
828 * \param [in] y Center y coordinate of circle.
829 * \param [in] radius Circle radius.
830 * \param [in] color Circle color.
831 * \param [in] circle_width Width of circle.
832 * \param [in] length Length of dashed lines.
833 * \param [in] space Space between dashes.
834 * \param [in] origin_x Page x coordinate to place circle OBJECT.
835 * \param [in] origin_y Page y coordinate to place circle OBJECT.
836 */
o_circle_print_dashed(TOPLEVEL * toplevel,FILE * fp,int x,int y,int radius,int color,int circle_width,int length,int space,int origin_x,int origin_y)837 void o_circle_print_dashed(TOPLEVEL *toplevel, FILE *fp,
838 int x, int y,
839 int radius,
840 int color,
841 int circle_width, int length, int space,
842 int origin_x, int origin_y)
843 {
844
845 o_arc_print_dashed(toplevel, fp,
846 x, y, radius,
847 0, FULL_CIRCLE / 64,
848 color,
849 circle_width, length, space,
850 origin_x, origin_y);
851
852 }
853
854 /*! \brief Print a centered line type circle to Postscript document.
855 * \par Function Description
856 * This function prints the outline of a circle when a centered line
857 * type is required. The circle is defined by its center in
858 * (<B>x</B>, <B>y</B>) and its radius in <B>radius</B>. It is printed with the
859 * color given in <B>color</B>.
860 *
861 * It uses the function #o_arc_print_center() to print the outline.
862 * Therefore it acts as an interface between the way a circle is
863 * defined and the way an arc is defined.
864 *
865 * All dimensions are in mils.
866 *
867 * \param [in] toplevel The TOPLEVEL object.
868 * \param [in] fp FILE pointer to Postscript document.
869 * \param [in] x Center x coordinate of circle.
870 * \param [in] y Center y coordinate of circle.
871 * \param [in] radius Circle radius.
872 * \param [in] color Circle color.
873 * \param [in] circle_width Width of circle.
874 * \param [in] length Length of dashed lines.
875 * \param [in] space Space between dashes.
876 * \param [in] origin_x Page x coordinate to place circle OBJECT.
877 * \param [in] origin_y Page y coordinate to place circle OBJECT.
878 */
o_circle_print_center(TOPLEVEL * toplevel,FILE * fp,int x,int y,int radius,int color,int circle_width,int length,int space,int origin_x,int origin_y)879 void o_circle_print_center(TOPLEVEL *toplevel, FILE *fp,
880 int x, int y,
881 int radius,
882 int color,
883 int circle_width, int length, int space,
884 int origin_x, int origin_y)
885 {
886
887 o_arc_print_center(toplevel, fp,
888 x, y, radius,
889 0, FULL_CIRCLE / 64,
890 color,
891 circle_width, length, space,
892 origin_x, origin_y);
893
894 }
895
896 /*! \brief Print a phantom line type circle to Postscript document.
897 * \par Function Description
898 * This function prints the outline of a circle when a phantom line type
899 * is required. The circle is defined by its center in
900 * (<B>x</B>, <B>y</B>) and its radius in <B>radius</B>. It is printed with the
901 * color given in <B>color</B>.
902 *
903 * It uses the function #o_arc_print_phantom() to print the outline.
904 * Therefore it acts as an interface between the way a circle is defined
905 * and the way an arc is defined.
906 *
907 * All dimensions are in mils.
908 *
909 * \param [in] toplevel The TOPLEVEL object.
910 * \param [in] fp FILE pointer to Postscript document.
911 * \param [in] x Center x coordinate of circle.
912 * \param [in] y Center y coordinate of circle.
913 * \param [in] radius Circle radius.
914 * \param [in] color Circle color.
915 * \param [in] circle_width Width of circle.
916 * \param [in] length Length of dashed lines.
917 * \param [in] space Space between dashes.
918 * \param [in] origin_x Page x coordinate to place circle OBJECT.
919 * \param [in] origin_y Page y coordinate to place circle OBJECT.
920 */
o_circle_print_phantom(TOPLEVEL * toplevel,FILE * fp,int x,int y,int radius,int color,int circle_width,int length,int space,int origin_x,int origin_y)921 void o_circle_print_phantom(TOPLEVEL *toplevel, FILE *fp,
922 int x, int y,
923 int radius,
924 int color,
925 int circle_width, int length, int space,
926 int origin_x, int origin_y)
927 {
928
929 o_arc_print_phantom(toplevel, fp,
930 x, y, radius,
931 0, FULL_CIRCLE / 64,
932 color,
933 circle_width, length, space,
934 origin_x, origin_y);
935
936 }
937
938 /*! \brief Print a solid pattern circle to Postscript document.
939 * \par Function Description
940 * The function prints a filled circle with a solid pattern.
941 * No outline is printed.
942 * The circle is defined by the coordinates of its center in
943 * (<B>x</B>,<B>y</B>) and its radius given by the <B>radius</B> parameter.
944 * The postscript file is defined by the file pointer <B>fp</B>.
945 * <B>fill_width</B>, <B>angle1</B> and <B>pitch1</B>, <B>angle2</B>
946 * and <B>pitch2</B> parameters are ignored in this functions but
947 * kept for compatibility with other fill functions.
948 *
949 * All dimensions are in mils (except <B>angle1</B> and <B>angle2</B> in degree).
950 *
951 * \param [in] toplevel The TOPLEVEL object.
952 * \param [in] fp FILE pointer to Postscript document.
953 * \param [in] x Center x coordinate of circle.
954 * \param [in] y Center y coordinate of circle.
955 * \param [in] radius Radius of circle.
956 * \param [in] color Circle color.
957 * \param [in] fill_width Circle fill width. (unused).
958 * \param [in] angle1 (unused).
959 * \param [in] pitch1 (unused).
960 * \param [in] angle2 (unused).
961 * \param [in] pitch2 (unused).
962 * \param [in] origin_x Page x coordinate to place circle OBJECT.
963 * \param [in] origin_y Page y coordinate to place circle OBJECT.
964 */
o_circle_print_filled(TOPLEVEL * toplevel,FILE * fp,int x,int y,int radius,int color,int fill_width,int angle1,int pitch1,int angle2,int pitch2,int origin_x,int origin_y)965 void o_circle_print_filled(TOPLEVEL *toplevel, FILE *fp,
966 int x, int y, int radius,
967 int color,
968 int fill_width,
969 int angle1, int pitch1,
970 int angle2, int pitch2,
971 int origin_x, int origin_y)
972 {
973 f_print_set_color(toplevel, fp, color);
974
975 fprintf(fp, "%d %d %d dot\n",
976 x-origin_x, y-origin_y,
977 radius);
978
979 }
980
981 /*! \brief Print a mesh pattern circle to Postscript document.
982 * \par Function Description
983 * This function prints a meshed circle. No outline is printed.
984 * The circle is defined by the coordinates of its center in
985 * (<B>x</B>,<B>y</B>) and its radius by the <B>radius</B> parameter.
986 * The Postscript document is defined by the file pointer <B>fp</B>.
987 *
988 * The inside mesh is achieved by two successive call to the
989 * #o_circle_print_hatch() function, given <B>angle1</B> and <B>pitch1</B>
990 * the first time and <B>angle2</B> and <B>pitch2</B> the second time.
991 *
992 * Negative or null values for <B>pitch1</B> and/or <B>pitch2</B> are
993 * not allowed as it leads to an endless loop in #o_circle_print_hatch().
994 *
995 * All dimensions are in mils (except <B>angle1</B> and <B>angle2</B> in degree).
996 *
997 * \param [in] toplevel The TOPLEVEL object.
998 * \param [in] fp FILE pointer to Postscript document.
999 * \param [in] x Center x coordinate of circle.
1000 * \param [in] y Center y coordinate of circle.
1001 * \param [in] radius Radius of circle.
1002 * \param [in] color Circle color.
1003 * \param [in] fill_width Circle fill width.
1004 * \param [in] angle1 1st angle for mesh pattern.
1005 * \param [in] pitch1 1st pitch for mesh pattern.
1006 * \param [in] angle2 2nd angle for mesh pattern.
1007 * \param [in] pitch2 2nd pitch for mesh pattern.
1008 * \param [in] origin_x Page x coordinate to place circle OBJECT.
1009 * \param [in] origin_y Page y coordinate to place circle OBJECT.
1010 */
o_circle_print_mesh(TOPLEVEL * toplevel,FILE * fp,int x,int y,int radius,int color,int fill_width,int angle1,int pitch1,int angle2,int pitch2,int origin_x,int origin_y)1011 void o_circle_print_mesh(TOPLEVEL *toplevel, FILE *fp,
1012 int x, int y, int radius,
1013 int color,
1014 int fill_width,
1015 int angle1, int pitch1,
1016 int angle2, int pitch2,
1017 int origin_x, int origin_y)
1018 {
1019 o_circle_print_hatch(toplevel, fp,
1020 x, y, radius,
1021 color,
1022 fill_width,
1023 angle1, pitch1,
1024 -1, -1,
1025 origin_x, origin_y);
1026 o_circle_print_hatch(toplevel, fp,
1027 x, y, radius,
1028 color,
1029 fill_width,
1030 angle2, pitch2,
1031 -1, -1,
1032 origin_x, origin_y);
1033
1034 }
1035
1036 /*! \brief Print a hatch pattern circle to Postscript document.
1037 * \par Function Description
1038 * The function prints a hatched circle. No outline is printed.
1039 * The circle is defined by the coordinates of its center in
1040 * (<B>x</B>,<B>y</B>) and its radius by the <B>radius</B> parameter.
1041 * The Postscript document is defined by the file pointer <B>fp</B>.
1042 * <B>angle2</B> and <B>pitch2</B> parameters are ignored in this
1043 * functions but kept for compatibility with other fill functions.
1044 *
1045 * The only attribute of line here is its width from the parameter <B>width</B>.
1046 *
1047 * Negative or null values for <B>pitch1</B> is not allowed as it
1048 * leads to an endless loop.
1049 *
1050 * All dimensions are in mils (except <B>angle1</B> is in degrees).
1051 *
1052 * \param [in] toplevel The TOPLEVEL object.
1053 * \param [in] fp FILE pointer to Postscript document.
1054 * \param [in] x Center x coordinate of circle.
1055 * \param [in] y Center y coordinate of circle.
1056 * \param [in] radius Radius of circle.
1057 * \param [in] color Circle color.
1058 * \param [in] fill_width Circle fill width.
1059 * \param [in] angle1 Angle for hatch pattern.
1060 * \param [in] pitch1 Pitch for hatch pattern.
1061 * \param [in] angle2 (unused).
1062 * \param [in] pitch2 (unused).
1063 * \param [in] origin_x Page x coordinate to place circle OBJECT.
1064 * \param [in] origin_y Page y coordinate to place circle OBJECT.
1065 */
o_circle_print_hatch(TOPLEVEL * toplevel,FILE * fp,int x,int y,int radius,int color,int fill_width,int angle1,int pitch1,int angle2,int pitch2,int origin_x,int origin_y)1066 void o_circle_print_hatch(TOPLEVEL *toplevel, FILE *fp,
1067 int x, int y, int radius,
1068 int color,
1069 int fill_width,
1070 int angle1, int pitch1,
1071 int angle2, int pitch2,
1072 int origin_x, int origin_y)
1073 {
1074 CIRCLE circle;
1075 gint index;
1076 GArray *lines;
1077
1078 g_return_if_fail(toplevel != NULL);
1079 g_return_if_fail(fp != NULL);
1080
1081 f_print_set_color(toplevel, fp, color);
1082
1083 /* Avoid printing line widths too small */
1084 if (fill_width <= 1) fill_width = 2;
1085
1086 lines = g_array_new(FALSE, FALSE, sizeof(LINE));
1087
1088 circle.center_x = x;
1089 circle.center_y = y;
1090 circle.radius = radius;
1091
1092 m_hatch_circle(&circle, angle1, pitch1, lines);
1093
1094 for(index=0; index<lines->len; index++) {
1095 LINE *line = &g_array_index(lines, LINE, index);
1096
1097 fprintf(fp,"%d %d %d %d %d line\n",
1098 line->x[0], line->y[0],
1099 line->x[1], line->y[1],
1100 fill_width);
1101 }
1102
1103 g_array_free(lines, TRUE);
1104 }
1105
1106 /*! \brief Calculates the distance between the given point and the closest
1107 * point on the perimeter of the circle.
1108 *
1109 * \param [in] object The circle OBJECT.
1110 * \param [in] x The x coordinate of the given point.
1111 * \param [in] y The y coordinate of the given point.
1112 * \param [in] force_solid If true, force treating the object as solid.
1113 * \return The shortest distance from the object to the point. With an
1114 * invalid parameter, this function returns G_MAXDOUBLE.
1115 */
o_circle_shortest_distance(OBJECT * object,int x,int y,int force_solid)1116 double o_circle_shortest_distance (OBJECT *object, int x, int y,
1117 int force_solid)
1118 {
1119 int solid;
1120
1121 g_return_val_if_fail (object->circle != NULL, G_MAXDOUBLE);
1122
1123 solid = force_solid || object->fill_type != FILLING_HOLLOW;
1124
1125 return m_circle_shortest_distance (object->circle, x, y, solid);
1126 }
1127
1128