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
29 #include "libgeda_priv.h"
31 #ifdef HAVE_LIBDMALLOC
36 int center_x
, center_y
; /* world */
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
,
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)
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
)
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
);
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
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
)
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
);
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
)
155 if (o_current
->saved_color
== -1) {
156 color
= o_current
->color
;
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
170 * The bounding box coordinates are computed with
171 * #o_circle_recalc().
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;*/
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 :
201 * <DT>*</DT><DD>the file format used until 2000704 release.
202 * <DT>*</DT><DD>the file format used for the releases after 20000704.
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
)
219 int circle_width
, circle_space
, circle_length
;
220 int fill_width
, angle1
, pitch1
, angle2
, pitch2
;
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
231 sscanf(buf
, "%c %d %d %d %d\n", &type
, &x1
, &y1
, &radius
, &color
);
234 circle_end
= END_NONE
;
235 circle_type
= TYPE_SOLID
;
239 circle_fill
= FILLING_HOLLOW
;
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
);
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"));
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
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
);
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.
301 * Caller must g_free returned character string.
304 char *o_circle_save(OBJECT
*object
)
309 int circle_width
, circle_space
, circle_length
;
310 int fill_width
, angle1
, pitch1
, angle2
, pitch2
;
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
;
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
);
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
,
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
;
426 double r_cos_theta
, r_sin_theta
;
428 o
->circle
->center_x
= x
;
429 o
->circle
->center_y
= y
;
430 o
->circle
->radius
= 0;
431 retval
= GRIP_CIRCLE_RADIUS
;
434 case GRIP_CIRCLE_CENTER
:
435 o
->circle
->center_x
= x
;
436 o
->circle
->center_y
= y
;
437 retval
= GRIP_CIRCLE_RADIUS
;
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
));
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
));
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
,
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
,
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
) {
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>
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
)
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 */
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
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
)
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");
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
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
659 circle_width
= o_current
->line_width
;
660 if(circle_width
<=2) {
661 if(toplevel
->line_style
== THICK
) {
662 circle_width
=LINE_WIDTH
;
667 length
= o_current
->line_length
;
668 space
= o_current
->line_space
;
670 switch(o_current
->line_type
) {
672 length
= -1; space
= -1;
673 outl_func
= o_circle_print_solid
;
678 outl_func
= o_circle_print_dotted
;
682 outl_func
= o_circle_print_dashed
;
686 outl_func
= o_circle_print_center
;
690 outl_func
= o_circle_print_phantom
;
694 /* Unused for now print it solid */
695 length
= -1; space
= -1;
696 outl_func
= o_circle_print_solid
;
700 if((length
== 0) || (space
== 0)) {
701 length
= -1; space
= -1;
702 outl_func
= o_circle_print_solid
;
705 (*outl_func
)(toplevel
, fp
,
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
) {
731 angle1
= -1; pitch1
= 1;
732 angle2
= -1; pitch2
= 1;
734 fill_func
= o_circle_print_filled
;
738 fill_func
= o_circle_print_mesh
;
742 angle2
= -1; pitch2
= 1;
743 fill_func
= o_circle_print_hatch
;
747 /* Unused for now, print it filled */
748 angle1
= -1; pitch1
= 1;
749 angle2
= -1; pitch2
= 1;
751 fill_func
= o_circle_print_filled
;
754 case(FILLING_HOLLOW
):
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
,
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
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
,
800 int circle_width
, int length
, int space
)
802 o_arc_print_solid(toplevel
, fp
,
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
,
837 int circle_width
, int length
, int space
)
839 o_arc_print_dotted(toplevel
, fp
,
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
,
873 int circle_width
, int length
, int space
)
875 o_arc_print_dashed(toplevel
, fp
,
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
,
909 int circle_width
, int length
, int space
)
911 o_arc_print_center(toplevel
, fp
,
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
,
945 int circle_width
, int length
, int space
)
947 o_arc_print_phantom(toplevel
, fp
,
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
,
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
,
1027 int angle1
, int pitch1
,
1028 int angle2
, int pitch2
)
1030 o_circle_print_hatch(toplevel
, o_current
, fp
,
1036 o_circle_print_hatch(toplevel
, o_current
, fp
,
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
,
1077 int angle1
, int pitch1
,
1078 int angle2
, int pitch2
)
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
;
1113 gdouble shortest_distance
;
1115 if (circle
== NULL
) {
1116 g_critical("o_circle_shortest_distance(): circle == NULL\n");
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
;