Stop pretending to use an explicit printing origin.
[geda-gaf/berndj.git] / libgeda / src / o_circle_basic.c
blob61989095b54fb20e0e06bbc4898bf3c26ee949f4
1 /* gEDA - GPL Electronic Design Automation
2 * libgeda - gEDA's library
3 * Copyright (C) 1998-2007 Ales Hvezda
4 * Copyright (C) 1998-2007 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
21 /*! \file o_circle_basic.c
22 * \brief functions for the circle object
25 #include <config.h>
26 #include <stdio.h>
27 #include <math.h>
29 #include "libgeda_priv.h"
31 #ifdef HAVE_LIBDMALLOC
32 #include <dmalloc.h>
33 #endif
35 struct st_circle {
36 int center_x, center_y; /* world */
37 int radius;
40 static OBJECT *o_circle_copy(TOPLEVEL *toplevel, OBJECT *o_current);
41 static void o_circle_grip_foreach(OBJECT *o,
42 gboolean (*fn)(OBJECT *o,
43 int grip_x, int grip_y,
44 enum grip_t whichone,
45 void *userdata),
46 void *userdata);
47 static int o_circle_grip_move(OBJECT *o, int whichone, int x, int y);
48 static void o_circle_recalc(OBJECT *o_current);
50 /*! Default setting for circle draw function. */
51 void (*circle_draw_func)() = NULL;
53 /*! \brief calculate the distance between two points
54 * \par Function Description
55 * This function calculates the distance between two points.
56 * The two points are defined by the (\a x1, \a y1) and (\a x2, \a y2)
57 * parameters.
58 * \param [in] x1 x-value of the first point
59 * \param [in] y1 y-value of the first point
60 * \param [in] x2 x-value of the second point
61 * \param [in] y2 y-value of the second point
62 * \return the distance
63 * \todo Move this function to a different place
65 int dist(int x1, int y1, int x2, int y2)
67 return sqrt(pow(x1-x2,2)+pow(y1-y2,2));
70 OBJECT *o_circle_new_at_xy(TOPLEVEL *toplevel, char type, int color, int x, int y)
72 OBJECT *new_node;
74 /* create the object */
75 new_node = s_toplevel_new_object(toplevel, type, "circle");
76 new_node->color = color;
78 new_node->circle = (CIRCLE *) g_malloc(sizeof(CIRCLE));
80 new_node->circle->center_x = x;
81 new_node->circle->center_y = y;
82 new_node->circle->radius = 0;
84 new_node->copy_func = &o_circle_copy;
85 new_node->bounds_recalc_func = o_circle_recalc;
86 new_node->draw_func = circle_draw_func;
87 new_node->grip_foreach_func = &o_circle_grip_foreach;
88 new_node->grip_move_func = &o_circle_grip_move;
90 /* line type and filling initialized to default */
91 o_set_line_options(new_node, END_NONE, TYPE_SOLID, 0, -1, -1);
92 o_set_fill_options(new_node, FILLING_HOLLOW, -1, -1, -1, -1, -1);
94 o_circle_recalc(new_node);
96 return new_node;
99 /*! \brief Create and add circle OBJECT to list.
100 * \par Function Description
101 * This function creates a new object representing a circle.
103 * The circle is described by its center (<B>x</B>,<B>y</B>) and its radius
104 * <B>radius</B>.
105 * The <B>type</B> parameter must be equal to <B>OBJ_CIRCLE</B>. The <B>color</B>
106 * corresponds to the color the box will be drawn with.
108 * The <B>OBJECT</B> structure is allocated with the object factory.
109 * The structure describing the circle is allocated and initialized
110 * with the parameters given to the function.
112 * Both the line type and the filling type are set to default values : solid
113 * line type with a width of 0, and no filling. It can be changed after
114 * with #o_set_line_options() and #o_set_fill_options().
116 * \param [in] toplevel The TOPLEVEL object.
117 * \param [in] type Must be OBJ_CIRCLE.
118 * \param [in] color Circle line color.
119 * \param [in] x Center x coordinate.
120 * \param [in] y Center y coordinate.
121 * \param [in] radius Radius of new circle.
122 * \return A pointer to the new end of the object list.
124 OBJECT *o_circle_new(TOPLEVEL *toplevel,
125 char type, int color,
126 int x, int y, int radius)
128 OBJECT *new_node;
130 new_node = o_circle_new_at_xy(toplevel, type, color, x, y);
132 /* describe the circle with its center and radius */
133 new_node->circle->radius = radius;
135 /* compute the bounding box coords */
136 o_circle_recalc(new_node);
138 return new_node;
141 /*! \brief Create a copy of a circle.
142 * \par Function Description
143 * The function #o_circle_copy() creates a verbatim copy of the object
144 * pointed by <B>o_current</B> describing a circle.
146 * \param [in] toplevel The TOPLEVEL object.
147 * \param [in] o_current Circle OBJECT to copy.
148 * \return The new OBJECT
150 static OBJECT *o_circle_copy(TOPLEVEL *toplevel, OBJECT *o_current)
152 OBJECT *new_obj;
153 int color;
155 if (o_current->saved_color == -1) {
156 color = o_current->color;
157 } else {
158 color = o_current->saved_color;
161 /* A new circle object is created with #o_circle_new().
162 * Values for its fields are default and need to be modified. */
163 new_obj = o_circle_new (toplevel, OBJ_CIRCLE, color, 0, 0, 0);
166 * The parameters of the new circle are set with the ones of the original
167 * circle. The two circle have the same line type and the same filling
168 * options.
170 * The bounding box coordinates are computed with
171 * #o_circle_recalc().
173 /* modify */
174 new_obj->circle->center_x = o_current->circle->center_x;
175 new_obj->circle->center_y = o_current->circle->center_y;
176 new_obj->circle->radius = o_current->circle->radius;
178 o_set_line_options(new_obj, o_current->line_end,
179 o_current->line_type, o_current->line_width,
180 o_current->line_length, o_current->line_space);
181 o_set_fill_options(new_obj,
182 o_current->fill_type, o_current->fill_width,
183 o_current->fill_pitch1, o_current->fill_angle1,
184 o_current->fill_pitch2, o_current->fill_angle2);
186 o_circle_recalc(new_obj);
188 /* new_obj->attribute = 0;*/
190 return new_obj;
193 /*! \brief Create circle OBJECT from character string.
194 * \par Function Description
195 * The #o_circle_read() function gets from the character string <B>*buff</B> the
196 * description of a circle.
198 * Depending on <B>*version</B>, the right file format is considered.
199 * Currently two file format revisions are supported :
200 * <DL>
201 * <DT>*</DT><DD>the file format used until 2000704 release.
202 * <DT>*</DT><DD>the file format used for the releases after 20000704.
203 * </DL>
205 * \param [in] toplevel The TOPLEVEL object.
206 * \param [in] buf Character string with circle description.
207 * \param [in] release_ver libgeda release version number.
208 * \param [in] fileformat_ver libgeda file format version number.
209 * \return A pointer to the new circle object.
211 OBJECT *o_circle_read(TOPLEVEL *toplevel, char buf[],
212 unsigned int release_ver, unsigned int fileformat_ver)
214 OBJECT *new_obj;
215 char type;
216 int x1, y1;
217 int radius;
218 int color;
219 int circle_width, circle_space, circle_length;
220 int fill_width, angle1, pitch1, angle2, pitch2;
221 int circle_end;
222 int circle_type;
223 int circle_fill;
225 if(release_ver <= VERSION_20000704) {
227 * The old geda file format, i.e. releases 20000704 and older, does not
228 * handle the line type and the filling of the box object. They are set
229 * to default.
231 sscanf(buf, "%c %d %d %d %d\n", &type, &x1, &y1, &radius, &color);
233 circle_width = 0;
234 circle_end = END_NONE;
235 circle_type = TYPE_SOLID;
236 circle_length= -1;
237 circle_space = -1;
239 circle_fill = FILLING_HOLLOW;
240 fill_width = 0;
241 angle1 = -1;
242 pitch1 = -1;
243 angle2 = -1;
244 pitch2 = -1;
246 } else {
249 * The current line format to describe a circle is a space separated
250 * list of characters and numbers in plain ASCII on a single line. The
251 * meaning of each item is described in the file format documentation.
253 sscanf(buf, "%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
254 &type, &x1, &y1, &radius, &color,
255 &circle_width, &circle_end, &circle_type,
256 &circle_length, &circle_space, &circle_fill,
257 &fill_width, &angle1, &pitch1, &angle2, &pitch2);
261 if (radius == 0) {
262 s_log_message(_("Found a zero radius circle [ %c %d %d %d %d ]\n"),
263 type, x1, y1, radius, color);
267 if (color < 0 || color > MAX_COLORS) {
268 s_log_message(_("Found an invalid color [ %s ]\n"), buf);
269 s_log_message(_("Setting color to WHITE\n"));
270 color = WHITE;
274 * A circle is internally described by its center and its radius.
276 * A new object is allocated and initialized.
277 * Its filling and line type are set according to the values of the field
278 * on the line.
280 new_obj = o_circle_new(toplevel, type, color, x1, y1, radius);
281 o_set_line_options(new_obj,
282 circle_end, circle_type, circle_width,
283 circle_length, circle_space);
284 o_set_fill_options(new_obj,
285 circle_fill, fill_width, pitch1, angle1, pitch2, angle2);
287 return new_obj;
290 /*! \brief Create a character string representation of a circle OBJECT.
291 * \par Function Description
292 * This function formats a string in the buffer <B>*buff</B> to describe the
293 * circle object <B>*object</B>.
294 * It follows the post-20000704 release file format that handle the line
295 * type and fill options.
297 * \param [in] object Circle OBJECT to create string from.
298 * \return A pointer to the circle OBJECT character string.
300 * \note
301 * Caller must g_free returned character string.
304 char *o_circle_save(OBJECT *object)
306 int x,y;
307 int radius;
308 int color;
309 int circle_width, circle_space, circle_length;
310 int fill_width, angle1, pitch1, angle2, pitch2;
311 char *buf;
312 OBJECT_END circle_end;
313 OBJECT_TYPE circle_type;
314 OBJECT_FILLING circle_fill;
316 /* circle center and radius */
317 x = object->circle->center_x;
318 y = object->circle->center_y;
319 radius = object->circle->radius;
321 /* line type parameters */
322 circle_width = object->line_width;
323 circle_end = object->line_end;
324 circle_type = object->line_type;
325 circle_length= object->line_length;
326 circle_space = object->line_space;
328 /* filling parameters */
329 circle_fill = object->fill_type;
330 fill_width = object->fill_width;
331 angle1 = object->fill_angle1;
332 pitch1 = object->fill_pitch1;
333 angle2 = object->fill_angle2;
334 pitch2 = object->fill_pitch2;
336 /* Use the right color */
337 if (object->saved_color == -1) {
338 color = object->color;
339 } else {
340 color = object->saved_color;
343 buf = g_strdup_printf("%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
344 object->type, x, y, radius, color,
345 circle_width, circle_end, circle_type, circle_length,
346 circle_space, circle_fill,
347 fill_width, angle1, pitch1, angle2, pitch2);
348 return(buf);
351 /*! \brief Translate a circle position in WORLD coordinates by a delta.
352 * \par Function Description
353 * This function applies a translation of (<B>x1</B>,<B>y1</B>) to the circle
354 * described by <B>*object</B>. <B>x1</B> and <B>y1</B> are in world unit.
356 * \param [in] dx x distance to move.
357 * \param [in] dy y distance to move.
358 * \param [in,out] object Circle OBJECT to translate.
360 void o_circle_translate_world(int dx, int dy, OBJECT *object)
362 if (object == NULL) printf("ctw NO!\n");
364 /* Do world coords */
365 object->circle->center_x = object->circle->center_x + dx;
366 object->circle->center_y = object->circle->center_y + dy;
368 /* recalc the screen coords and the bounding box */
369 o_circle_recalc(object);
373 int o_circle_get_radius(OBJECT const *o_current)
375 return (o_current->circle->radius);
378 static void o_circle_grip_foreach(OBJECT *o,
379 gboolean (*fn)(OBJECT *o,
380 int grip_x, int grip_y,
381 enum grip_t whichone,
382 void *userdata),
383 void *userdata)
385 const GRIP circle_grips[] = {
387 .x = o->circle->center_x,
388 .y = o->circle->center_y,
389 .whichone = GRIP_CIRCLE_CENTER,
392 .x = o->circle->center_x + o->circle->radius,
393 .y = o->circle->center_y - o->circle->radius,
394 .whichone = GRIP_CIRCLE_RADIUS,
397 .x = o->circle->center_x - o->circle->radius,
398 .y = o->circle->center_y,
399 .whichone = GRIP_CIRCLE_RADIUS_LEFT,
402 .x = o->circle->center_x + o->circle->radius,
403 .y = o->circle->center_y,
404 .whichone = GRIP_CIRCLE_RADIUS_RIGHT,
407 .x = o->circle->center_x,
408 .y = o->circle->center_y + o->circle->radius,
409 .whichone = GRIP_CIRCLE_RADIUS_TOP,
412 .x = o->circle->center_x,
413 .y = o->circle->center_y - o->circle->radius,
414 .whichone = GRIP_CIRCLE_RADIUS_BOTTOM,
416 { .whichone = GRIP_NONE }
419 s_basic_grip_foreach_helper(o, circle_grips, fn, userdata);
422 static int o_circle_grip_move(OBJECT *o, int whichone, int x, int y)
424 int retval = whichone;
425 switch (whichone) {
426 double r_cos_theta, r_sin_theta;
427 case GRIP_NONE:
428 o->circle->center_x = x;
429 o->circle->center_y = y;
430 o->circle->radius = 0;
431 retval = GRIP_CIRCLE_RADIUS;
432 break;
434 case GRIP_CIRCLE_CENTER:
435 o->circle->center_x = x;
436 o->circle->center_y = y;
437 retval = GRIP_CIRCLE_RADIUS;
438 break;
439 case GRIP_CIRCLE_RADIUS:
440 r_cos_theta = x - o->circle->center_x;
441 r_sin_theta = y - o->circle->center_y;
442 o->circle->radius = rint(sqrt(0.5*r_cos_theta*r_cos_theta +
443 0.5*r_sin_theta*r_sin_theta));
444 retval = GRIP_NONE;
445 break;
446 case GRIP_CIRCLE_RADIUS_LEFT:
447 case GRIP_CIRCLE_RADIUS_RIGHT:
448 case GRIP_CIRCLE_RADIUS_TOP:
449 case GRIP_CIRCLE_RADIUS_BOTTOM:
450 r_cos_theta = x - o->circle->center_x;
451 r_sin_theta = y - o->circle->center_y;
452 o->circle->radius = rint(sqrt(r_cos_theta*r_cos_theta +
453 r_sin_theta*r_sin_theta));
454 retval = GRIP_NONE;
455 break;
458 o_circle_recalc(o);
460 return retval;
463 /*! \brief Rotate Circle OBJECT using WORLD coordinates.
464 * \par Function Description
465 * The function #o_circle_rotate_world() rotate the circle described by
466 * <B>*object</B> around the (<B>world_centerx</B>,<B>world_centery</B>) point by
467 * angle <B>angle</B> degrees.
468 * The center of rotation is in world unit.
470 * \param [in] world_centerx Rotation center x coordinate in WORLD units.
471 * \param [in] world_centery Rotation center y coordinate in WORLD units.
472 * \param [in] angle Rotation angle in degrees (See note below).
473 * \param [in,out] object Circle OBJECT to rotate.
475 void o_circle_rotate_world(int world_centerx, int world_centery, int angle,
476 OBJECT *object)
478 int newx, newy;
479 int x, y;
481 /* Only 90 degree multiple and positive angles are allowed. */
482 /* angle must be positive */
483 if(angle < 0) angle = -angle;
484 /* angle must be a 90 multiple or no rotation performed */
485 if((angle % 90) != 0) return;
488 * The center of rotation (<B>world_centerx</B>,<B>world_centery</B>) is
489 * translated to the origin. The rotation of the center around the origin
490 * is then performed. Finally, the rotated circle is translated back to
491 * its previous location.
494 /* translate object to origin */
495 object->circle->center_x -= world_centerx;
496 object->circle->center_y -= world_centery;
498 /* rotate the center of the circle around the origin */
499 x = object->circle->center_x;
500 y = object->circle->center_y;
501 rotate_point_90(x, y, angle, &newx, &newy);
502 object->circle->center_x = newx;
503 object->circle->center_y = newy;
505 /* translate back in position */
506 object->circle->center_x += world_centerx;
507 object->circle->center_y += world_centery;
509 o_circle_recalc(object);
513 /*! \brief Mirror circle using WORLD coordinates.
514 * \par Function Description
515 * This function recalculates the screen coords of the <B>o_current</B> pointed
516 * circle object from its world coords.
518 * The circle coordinates and its bounding are recalculated as well as the
519 * OBJECT specific (line width, filling ...).
521 * \param [in] world_centerx Origin x coordinate in WORLD units.
522 * \param [in] world_centery Origin y coordinate in WORLD units.
523 * \param [in,out] object Circle OBJECT to mirror.
525 void o_circle_mirror_world(int world_centerx, int world_centery,
526 OBJECT *object)
528 /* translate object to origin */
529 object->circle->center_x -= world_centerx;
530 object->circle->center_y -= world_centery;
532 /* mirror the center of the circle */
533 object->circle->center_x = -object->circle->center_x;
534 object->circle->center_y = object->circle->center_y;
536 /* translate back in position */
537 object->circle->center_x += world_centerx;
538 object->circle->center_y += world_centery;
540 /* recalc boundings and screen coords */
541 o_circle_recalc(object);
545 /*! \brief Recalculate circle coordinates in SCREEN units.
546 * \par Function Description
547 * This function recalculates the screen coords of the <B>o_current</B> pointed
548 * circle object from its world coords.
550 * The circle coordinates and its bounding are recalculated as well as the
551 * OBJECT specific (line width, filling ...).
553 * \param [in,out] o_current Circle OBJECT to be recalculated.
555 static void o_circle_recalc(OBJECT *o_current)
557 int left, right, top, bottom;
559 if (o_current->circle == NULL) {
560 return;
563 /* update the bounding box - world unit */
564 world_get_circle_bounds(o_current, &left, &top, &right, &bottom);
565 o_current->w_left = left;
566 o_current->w_top = top;
567 o_current->w_right = right;
568 o_current->w_bottom = bottom;
569 o_current->w_bounds_valid = TRUE;
572 /*! \brief Get circle bounding rectangle in WORLD coordinates.
573 * \par Function Description
574 * This function sets the <B>left</B>, <B>top</B>, <B>right</B> and <B>bottom</B>
575 * parameters to the boundings of the circle object described in <B>*circle</B>
576 * in world units.
578 * \param [in] object Circle OBJECT to read coordinates from.
579 * \param [out] left Left circle coordinate in WORLD units.
580 * \param [out] top Top circle coordinate in WORLD units.
581 * \param [out] right Right circle coordinate in WORLD units.
582 * \param [out] bottom Bottom circle coordinate in WORLD units.
584 void world_get_circle_bounds(OBJECT *object, int *left,
585 int *top, int *right, int *bottom)
587 int halfwidth;
589 halfwidth = object->line_width / 2;
591 *left = object->circle->center_x - object->circle->radius;
592 *top = object->circle->center_y - object->circle->radius;
593 *right = object->circle->center_x + object->circle->radius;
594 *bottom = object->circle->center_y + object->circle->radius;
596 /* This isn't strictly correct, but a 1st order approximation */
597 *left -= halfwidth;
598 *top -= halfwidth;
599 *right += halfwidth;
600 *bottom += halfwidth;
604 /*! \brief Print circle to Postscript document.
605 * \par Function Description
606 * This function prints the circle described by the <B>o_current</B>
607 * parameter to a Postscript document. It takes into account its line type
608 * and fill type.
609 * The Postscript document is described by the file pointer <B>fp</B>.
611 * The validity of the <B>o_current</B> pointer is checked :
612 * a null pointer causes an error message and a return.
614 * The description of the circle is extracted from the <B>o_current</B>
615 * parameter : the coordinates of the center of the circle, its radius,
616 * its line type, its fill type.
618 * The outline and the inside of the circle are successively handled by
619 * two different sets of functions.
621 * \param [in] toplevel The TOPLEVEL object.
622 * \param [in] fp FILE pointer to Postscript document.
623 * \param [in] o_current Circle OBJECT to write to document.
625 void o_circle_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current)
627 int x, y, radius;
628 int color;
629 int circle_width, length, space;
630 int fill_width, angle1, pitch1, angle2, pitch2;
631 void (*outl_func)() = NULL;
632 void (*fill_func)() = NULL;
634 if (o_current == NULL) {
635 printf("got null in o_circle_print\n");
636 return;
639 x = o_current->circle->center_x;
640 y = o_current->circle->center_y;
641 radius = o_current->circle->radius;
643 color = o_current->color;
646 * Depending on the type of the line for this particular circle, the
647 * appropriate function is chosen among #o_circle_print_solid(),
648 * #o_circle_print_dotted(), #o_circle_print_dashed(),
649 * #o_circle_print_center() and #o_circle_print_phantom().
651 * The needed parameters for each of these type is extracted from the
652 * <B>o_current</B> object. Depending on the type, unused parameters are
653 * set to -1.
655 * In the eventuality of a length and/or space null, the line is
656 * printed solid to avoid and endless loop produced by other functions
657 * in such a case.
659 circle_width = o_current->line_width;
660 if(circle_width <=2) {
661 if(toplevel->line_style == THICK) {
662 circle_width=LINE_WIDTH;
663 } else {
664 circle_width=2;
667 length = o_current->line_length;
668 space = o_current->line_space;
670 switch(o_current->line_type) {
671 case(TYPE_SOLID):
672 length = -1; space = -1;
673 outl_func = o_circle_print_solid;
674 break;
676 case(TYPE_DOTTED):
677 length = -1;
678 outl_func = o_circle_print_dotted;
679 break;
681 case(TYPE_DASHED):
682 outl_func = o_circle_print_dashed;
683 break;
685 case(TYPE_CENTER):
686 outl_func = o_circle_print_center;
687 break;
689 case(TYPE_PHANTOM):
690 outl_func = o_circle_print_phantom;
691 break;
693 case(TYPE_ERASE):
694 /* Unused for now print it solid */
695 length = -1; space = -1;
696 outl_func = o_circle_print_solid;
697 break;
700 if((length == 0) || (space == 0)) {
701 length = -1; space = -1;
702 outl_func = o_circle_print_solid;
705 (*outl_func)(toplevel, fp,
706 x, y,
707 radius,
708 color,
709 circle_width, length, space);
712 * If the filling type of the circle is not <B>HOLLOW</B>, the appropriate
713 * function is chosen among #o_circle_print_filled(), #o_circle_print_mesh()
714 * and #o_circle_print_hatch(). The corresponding parameters are extracted
715 * from the <B>o_current</B> object and corrected afterward.
717 * The case where <B>pitch1</B> and <B>pitch2</B> are null or negative is
718 * avoided as it leads to an endless loop in most of the called functions.
719 * In such a case, the circle is printed filled. Unused parameters for
720 * each of these functions are set to -1 or any passive value.
722 if(o_current->fill_type != FILLING_HOLLOW) {
723 fill_width = o_current->fill_width;
724 angle1 = o_current->fill_angle1;
725 pitch1 = o_current->fill_pitch1;
726 angle2 = o_current->fill_angle2;
727 pitch2 = o_current->fill_pitch2;
729 switch(o_current->fill_type) {
730 case(FILLING_FILL):
731 angle1 = -1; pitch1 = 1;
732 angle2 = -1; pitch2 = 1;
733 fill_width = -1;
734 fill_func = o_circle_print_filled;
735 break;
737 case(FILLING_MESH):
738 fill_func = o_circle_print_mesh;
739 break;
741 case(FILLING_HATCH):
742 angle2 = -1; pitch2 = 1;
743 fill_func = o_circle_print_hatch;
744 break;
746 case(FILLING_VOID):
747 /* Unused for now, print it filled */
748 angle1 = -1; pitch1 = 1;
749 angle2 = -1; pitch2 = 1;
750 fill_width = -1;
751 fill_func = o_circle_print_filled;
752 break;
754 case(FILLING_HOLLOW):
755 /* nop */
756 break;
759 if((pitch1 <= 0) || (pitch2 <= 0)) {
760 angle1 = -1; pitch1 = 1;
761 angle2 = -1; pitch2 = 1;
762 fill_func = o_circle_print_filled;
765 (*fill_func)(toplevel, fp,
766 x, y, radius,
767 color,
768 fill_width,
769 angle1, pitch1, angle2, pitch2);
773 /*! \brief Print a solid circle to Postscript document.
774 * \par Function Description
775 * This function prints the outline of a circle when a solid line type
776 * is required. The circle is defined by its center in (<B>x</B>, <B>y</B>)
777 * and its radius in <B>radius</B>. It is printed with the color given
778 * in <B>color</B>.
779 * The parameters <B>length</B> and <B>space</B> are ignored.
781 * It uses the function #o_arc_print_solid() to print the outline.
782 * Therefore it acts as an interface between the way a circle is defined
783 * and the way an arc is defined.
785 * All dimensions are in mils.
787 * \param [in] toplevel The TOPLEVEL object.
788 * \param [in] fp FILE pointer to Postscript document.
789 * \param [in] x Center x coordinate of circle.
790 * \param [in] y Center y coordinate of circle.
791 * \param [in] radius Circle radius.
792 * \param [in] color Circle color.
793 * \param [in] circle_width Width of circle.
794 * \param [in] length (unused).
795 * \param [in] space (unused).
797 void o_circle_print_solid(TOPLEVEL *toplevel, FILE *fp,
798 int x, int y, int radius,
799 int color,
800 int circle_width, int length, int space)
802 o_arc_print_solid(toplevel, fp,
803 x, y, radius,
804 0, FULL_CIRCLE / 64,
805 color,
806 circle_width, -1, -1);
810 /*! \brief Print a dotted circle to Postscript document.
811 * \par Function Description
812 * This function prints the outline of a circle when a dotted line
813 * type is required. The circle is defined by its center
814 * in (<B>x</B>, <B>y</B>) and its radius in <B>radius</B>. It is printed
815 * with the color given in <B>color</B>.
816 * The parameter <B>length</B> is ignored.
818 * It uses the function #o_arc_print_dotted() to print the outline.
819 * Therefore it acts as an interface between the way a circle is
820 * defined and the way an arc is defined.
822 * All dimensions are in mils.
824 * \param [in] toplevel The TOPLEVEL object.
825 * \param [in] fp FILE pointer to Postscript document.
826 * \param [in] x Center x coordinate of circle.
827 * \param [in] y Center y coordinate of circle.
828 * \param [in] radius Circle radius.
829 * \param [in] color Circle color.
830 * \param [in] circle_width Width of circle.
831 * \param [in] length (unused).
832 * \param [in] space Space between dots.
834 void o_circle_print_dotted(TOPLEVEL *toplevel, FILE *fp,
835 int x, int y, int radius,
836 int color,
837 int circle_width, int length, int space)
839 o_arc_print_dotted(toplevel, fp,
840 x, y, radius,
841 0, FULL_CIRCLE / 64,
842 color,
843 circle_width, -1, space);
846 /*! \brief Print a dashed circle to Postscript document.
847 * \par Function Description
848 * This function prints the outline of a circle when a dashed line type
849 * is required. The circle is defined by its center in
850 * (<B>x</B>, <B>y</B>) and its radius in <B>radius</B>. It is printed with the
851 * color given in <B>color</B>.
853 * It uses the function #o_arc_print_dashed() to print the outline.
854 * Therefore it acts as an interface between the way a circle is
855 * defined and the way an arc is defined.
857 * All dimensions are in mils.
859 * \param [in] toplevel The TOPLEVEL object.
860 * \param [in] fp FILE pointer to Postscript document.
861 * \param [in] x Center x coordinate of circle.
862 * \param [in] y Center y coordinate of circle.
863 * \param [in] radius Circle radius.
864 * \param [in] color Circle color.
865 * \param [in] circle_width Width of circle.
866 * \param [in] length Length of dashed lines.
867 * \param [in] space Space between dashes.
869 void o_circle_print_dashed(TOPLEVEL *toplevel, FILE *fp,
870 int x, int y,
871 int radius,
872 int color,
873 int circle_width, int length, int space)
875 o_arc_print_dashed(toplevel, fp,
876 x, y, radius,
877 0, FULL_CIRCLE / 64,
878 color,
879 circle_width, length, space);
882 /*! \brief Print a centered line type circle to Postscript document.
883 * \par Function Description
884 * This function prints the outline of a circle when a centered line
885 * type is required. The circle is defined by its center in
886 * (<B>x</B>, <B>y</B>) and its radius in <B>radius</B>. It is printed with the
887 * color given in <B>color</B>.
889 * It uses the function #o_arc_print_center() to print the outline.
890 * Therefore it acts as an interface between the way a circle is
891 * defined and the way an arc is defined.
893 * All dimensions are in mils.
895 * \param [in] toplevel The TOPLEVEL object.
896 * \param [in] fp FILE pointer to Postscript document.
897 * \param [in] x Center x coordinate of circle.
898 * \param [in] y Center y coordinate of circle.
899 * \param [in] radius Circle radius.
900 * \param [in] color Circle color.
901 * \param [in] circle_width Width of circle.
902 * \param [in] length Length of dashed lines.
903 * \param [in] space Space between dashes.
905 void o_circle_print_center(TOPLEVEL *toplevel, FILE *fp,
906 int x, int y,
907 int radius,
908 int color,
909 int circle_width, int length, int space)
911 o_arc_print_center(toplevel, fp,
912 x, y, radius,
913 0, FULL_CIRCLE / 64,
914 color,
915 circle_width, length, space);
918 /*! \brief Print a phantom line type circle to Postscript document.
919 * \par Function Description
920 * This function prints the outline of a circle when a phantom line type
921 * is required. The circle is defined by its center in
922 * (<B>x</B>, <B>y</B>) and its radius in <B>radius</B>. It is printed with the
923 * color given in <B>color</B>.
925 * It uses the function #o_arc_print_phantom() to print the outline.
926 * Therefore it acts as an interface between the way a circle is defined
927 * and the way an arc is defined.
929 * All dimensions are in mils.
931 * \param [in] toplevel The TOPLEVEL object.
932 * \param [in] fp FILE pointer to Postscript document.
933 * \param [in] x Center x coordinate of circle.
934 * \param [in] y Center y coordinate of circle.
935 * \param [in] radius Circle radius.
936 * \param [in] color Circle color.
937 * \param [in] circle_width Width of circle.
938 * \param [in] length Length of dashed lines.
939 * \param [in] space Space between dashes.
941 void o_circle_print_phantom(TOPLEVEL *toplevel, FILE *fp,
942 int x, int y,
943 int radius,
944 int color,
945 int circle_width, int length, int space)
947 o_arc_print_phantom(toplevel, fp,
948 x, y, radius,
949 0, FULL_CIRCLE / 64,
950 color,
951 circle_width, length, space);
954 /*! \brief Print a solid pattern circle to Postscript document.
955 * \par Function Description
956 * The function prints a filled circle with a solid pattern.
957 * No outline is printed.
958 * The circle is defined by the coordinates of its center in
959 * (<B>x</B>,<B>y</B>) and its radius given by the <B>radius</B> parameter.
960 * The postscript file is defined by the file pointer <B>fp</B>.
961 * <B>fill_width</B>, <B>angle1</B> and <B>pitch1</B>, <B>angle2</B>
962 * and <B>pitch2</B> parameters are ignored in this functions but
963 * kept for compatibility with other fill functions.
965 * All dimensions are in mils (except <B>angle1</B> and <B>angle2</B> in degree).
967 * \param [in] toplevel The TOPLEVEL object.
968 * \param [in] o_current The object to print.
969 * \param [in] fp FILE pointer to Postscript document.
970 * \param [in] x Center x coordinate of circle.
971 * \param [in] y Center y coordinate of circle.
972 * \param [in] radius Radius of circle.
973 * \param [in] color Circle color.
974 * \param [in] fill_width Circle fill width. (unused).
975 * \param [in] angle1 (unused).
976 * \param [in] pitch1 (unused).
977 * \param [in] angle2 (unused).
978 * \param [in] pitch2 (unused).
980 void o_circle_print_filled(TOPLEVEL *toplevel, OBJECT *o_current, FILE *fp,
981 int x, int y, int radius,
982 int color,
983 int fill_width,
984 int angle1, int pitch1,
985 int angle2, int pitch2)
987 if (toplevel->print_color) {
988 f_print_set_color(fp, color);
991 fprintf(fp, "%d %d %d dot\n", x, y, radius);
994 /*! \brief Print a mesh pattern circle to Postscript document.
995 * \par Function Description
996 * This function prints a meshed circle. No outline is printed.
997 * The circle is defined by the coordinates of its center in
998 * (<B>x</B>,<B>y</B>) and its radius by the <B>radius</B> parameter.
999 * The Postscript document is defined by the file pointer <B>fp</B>.
1001 * The inside mesh is achieved by two successive call to the
1002 * #o_circle_print_hatch() function, given <B>angle1</B> and <B>pitch1</B>
1003 * the first time and <B>angle2</B> and <B>pitch2</B> the second time.
1005 * Negative or null values for <B>pitch1</B> and/or <B>pitch2</B> are
1006 * not allowed as it leads to an endless loop in #o_circle_print_hatch().
1008 * All dimensions are in mils (except <B>angle1</B> and <B>angle2</B> in degree).
1010 * \param [in] toplevel The TOPLEVEL object.
1011 * \param [in] o_current The object to print.
1012 * \param [in] fp FILE pointer to Postscript document.
1013 * \param [in] x Center x coordinate of circle.
1014 * \param [in] y Center y coordinate of circle.
1015 * \param [in] radius Radius of circle.
1016 * \param [in] color Circle color.
1017 * \param [in] fill_width Circle fill width.
1018 * \param [in] angle1 1st angle for mesh pattern.
1019 * \param [in] pitch1 1st pitch for mesh pattern.
1020 * \param [in] angle2 2nd angle for mesh pattern.
1021 * \param [in] pitch2 2nd pitch for mesh pattern.
1023 void o_circle_print_mesh(TOPLEVEL *toplevel, OBJECT *o_current, FILE *fp,
1024 int x, int y, int radius,
1025 int color,
1026 int fill_width,
1027 int angle1, int pitch1,
1028 int angle2, int pitch2)
1030 o_circle_print_hatch(toplevel, o_current, fp,
1031 x, y, radius,
1032 color,
1033 fill_width,
1034 angle1, pitch1,
1035 -1, -1);
1036 o_circle_print_hatch(toplevel, o_current, fp,
1037 x, y, radius,
1038 color,
1039 fill_width,
1040 angle2, pitch2,
1041 -1, -1);
1044 /*! \brief Print a hatch pattern circle to Postscript document.
1045 * \par Function Description
1046 * The function prints a hatched circle. No outline is printed.
1047 * The circle is defined by the coordinates of its center in
1048 * (<B>x</B>,<B>y</B>) and its radius by the <B>radius</B> parameter.
1049 * The Postscript document is defined by the file pointer <B>fp</B>.
1050 * <B>angle2</B> and <B>pitch2</B> parameters are ignored in this
1051 * functions but kept for compatibility with other fill functions.
1053 * The only attribute of line here is its width from the parameter <B>width</B>.
1055 * Negative or null values for <B>pitch1</B> is not allowed as it
1056 * leads to an endless loop.
1058 * All dimensions are in mils (except <B>angle1</B> is in degrees).
1060 * \param [in] toplevel The TOPLEVEL object.
1061 * \param [in] o_current The object to print.
1062 * \param [in] fp FILE pointer to Postscript document.
1063 * \param [in] x Center x coordinate of circle.
1064 * \param [in] y Center y coordinate of circle.
1065 * \param [in] radius Radius of circle.
1066 * \param [in] color Circle color.
1067 * \param [in] fill_width Circle fill width.
1068 * \param [in] angle1 Angle for hatch pattern.
1069 * \param [in] pitch1 Pitch for hatch pattern.
1070 * \param [in] angle2 (unused).
1071 * \param [in] pitch2 (unused).
1073 void o_circle_print_hatch(TOPLEVEL *toplevel, OBJECT *o_current, FILE *fp,
1074 int x, int y, int radius,
1075 int color,
1076 int fill_width,
1077 int angle1, int pitch1,
1078 int angle2, int pitch2)
1080 GArray *lines;
1082 g_return_if_fail(toplevel != NULL);
1083 g_return_if_fail(fp != NULL);
1085 if (toplevel->print_color) {
1086 f_print_set_color(fp, color);
1089 /* Avoid printing line widths too small */
1090 if (fill_width <= 1) fill_width = 2;
1092 lines = m_hatch_new();
1094 m_hatch_circle(o_current, angle1, pitch1, lines);
1096 g_array_free(lines, TRUE);
1099 /*! \brief Calculates the distance between the given point and the closest
1100 * point on the perimeter of the circle.
1102 * \param [in] circle The circle of the OBJECT
1103 * \param [in] x The x coordinate of the given point.
1104 * \param [in] y The y coordinate of the given point.
1105 * \return The shortest distance from the object to the point. With an
1106 * invalid parameter, this function returns G_MAXDOUBLE.
1108 gdouble o_circle_shortest_distance(CIRCLE const *circle, gint x, gint y)
1110 gdouble distance_to_center;
1111 gdouble dx;
1112 gdouble dy;
1113 gdouble shortest_distance;
1115 if (circle == NULL) {
1116 g_critical("o_circle_shortest_distance(): circle == NULL\n");
1117 return FALSE;
1120 dx = ((gdouble) x) - ((gdouble) circle->center_x);
1121 dy = ((gdouble) y) - ((gdouble) circle->center_y);
1123 distance_to_center = sqrt((dx*dx) + (dy*dy));
1125 shortest_distance = fabs(distance_to_center - circle->radius);
1127 return shortest_distance;