Updated copyright text/header in most source files.
[geda-gaf/peter-b.git] / libgeda / src / o_line_basic.c
blobcdc1a1742deb43187a1cce240b43aaa460bd7729
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)
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_line_basic.c
22 * \brief functions for the line object
25 #include <config.h>
27 #include <stdio.h>
28 #include <math.h>
30 #include "libgeda_priv.h"
32 #ifdef HAVE_LIBDMALLOC
33 #include <dmalloc.h>
34 #endif
36 /*! Default setting for line draw function. */
37 void (*line_draw_func)() = NULL;
39 /*! \brief Create and add line OBJECT to list.
40 * \par Function Description
41 * This function creates a new object representing a line.
43 * The line is described by its two ends - <B>x1</B>,<B>y1</B> and
44 * <B>x2</B>,<B>y2</B>.
45 * The <B>type</B> parameter must be equal to #OBJ_LINE.
46 * The <B>color</B> parameter corresponds to the color the box
47 * will be drawn with.
49 * The #OBJECT structure is allocated with the #s_basic_new_object()
50 * function. The structure describing the line is allocated and
51 * initialized with the parameters given to the function.
53 * Both the line type and the filling type are set to default
54 * values : solid line type with a width of 0, and no filling.
55 * It can be changed after with the #o_set_line_options() and
56 * #o_set_fill_options().
58 * \param [in] toplevel The TOPLEVEL object.
59 * \param [in] type Must be OBJ_LINE.
60 * \param [in] color Circle line color.
61 * \param [in] x1 Upper x coordinate.
62 * \param [in] y1 Upper y coordinate.
63 * \param [in] x2 Lower x coordinate.
64 * \param [in] y2 Lower y coordinate.
65 * \return A pointer to the new end of the object list.
67 OBJECT *o_line_new(TOPLEVEL *toplevel,
68 char type, int color,
69 int x1, int y1, int x2, int y2)
71 OBJECT *new_node;
73 /* create the object */
74 new_node = s_basic_new_object(type, "line");
75 new_node->color = color;
77 new_node->line = (LINE *) g_malloc(sizeof(LINE));
79 /* describe the line with its two ends */
80 new_node->line->x[0] = x1;
81 new_node->line->y[0] = y1;
82 new_node->line->x[1] = x2;
83 new_node->line->y[1] = y2;
85 /* line type and filling initialized to default */
86 o_set_line_options(toplevel, new_node,
87 END_NONE, TYPE_SOLID, 0, -1, -1);
88 o_set_fill_options(toplevel, new_node,
89 FILLING_HOLLOW, -1, -1, -1, -1, -1);
91 new_node->draw_func = line_draw_func;
92 new_node->sel_func = select_func;
94 /* compute bounding box */
95 o_line_recalc(toplevel, new_node);
97 return new_node;
100 /*! \brief Create a copy of a line.
101 * \par Function Description
102 * This function creates a verbatim copy of the
103 * object pointed by <B>o_current</B> describing a line.
105 * \param [in] toplevel The TOPLEVEL object.
106 * \param [in] o_current Line OBJECT to copy.
107 * \return The new OBJECT
109 OBJECT *o_line_copy(TOPLEVEL *toplevel, OBJECT *o_current)
111 OBJECT *new_obj;
113 /* A new line object is created with #o_line_new().
114 * Values for its fields are default and need to be modified. */
115 new_obj = o_line_new (toplevel, OBJ_LINE, o_current->color,
116 o_current->line->x[0], o_current->line->y[0],
117 o_current->line->x[1], o_current->line->y[1]);
120 * The coordinates of the ends of the new line are set with the ones
121 * of the original line. The two lines have the sale line type and
122 * filling options.
124 * The bounding box are computed with
125 * #o_line_recalc().
128 /* copy the line type and filling options */
129 o_set_line_options(toplevel, new_obj, o_current->line_end,
130 o_current->line_type, o_current->line_width,
131 o_current->line_length, o_current->line_space);
132 o_set_fill_options(toplevel, new_obj,
133 o_current->fill_type, o_current->fill_width,
134 o_current->fill_pitch1, o_current->fill_angle1,
135 o_current->fill_pitch2, o_current->fill_angle2);
137 /* calc the bounding box */
138 o_line_recalc(toplevel, o_current);
140 /* new_obj->attribute = 0;*/
142 /* return the new tail of the object list */
143 return new_obj;
146 /*! \brief Modify the description of a line OBJECT.
147 * \par Function Description
148 * This function modifies the coordinates of one of the two ends of
149 * the line described by <B>*object</B>. The new coordinates of this end,
150 * identified by <B>whichone</B>, are given by <B>x</B> and <B>y</B>
151 * in world unit.
153 * The coordinates of the end of line is modified in the world
154 * coordinate system. Screen coordinates and boundings are then updated.
156 * \param [in] toplevel The TOPLEVEL object.
157 * \param [in,out] object Line OBJECT to modify.
158 * \param [in] x New x coordinate.
159 * \param [in] y New y coordinate.
160 * \param [in] whichone Which line parameter to modify.
162 * <B>whichone</B> can have the following values:
163 * <DL>
164 * <DT>*</DT><DD>LINE_END1
165 * <DT>*</DT><DD>LINE_END2
166 * </DL>
168 void o_line_modify(TOPLEVEL *toplevel, OBJECT *object,
169 int x, int y, int whichone)
171 /* change one of the end of the line */
172 switch(whichone) {
173 case LINE_END1:
174 object->line->x[0] = x;
175 object->line->y[0] = y;
176 break;
178 case LINE_END2:
179 object->line->x[1] = x;
180 object->line->y[1] = y;
181 break;
183 default:
184 return;
187 /* recalculate the bounding box */
188 o_line_recalc(toplevel, object);
192 /*! \brief Create line OBJECT from character string.
193 * \par Function Description
194 * This function creates a line OBJECT from the character string
195 * <B>*buf</B> the description of a box.
197 * The function returns a pointer on the new last element, that is
198 * the added line object.
200 * Depending on <B>*version</B>, the correct file format is considered.
201 * Currently two file format revisions are supported :
202 * <DL>
203 * <DT>*</DT><DD>the file format used until 20010704 release.
204 * <DT>*</DT><DD>the file format used for the releases after 20010704.
205 * </DL>
207 * \param [in] toplevel The TOPLEVEL object.
208 * \param [in] buf Character string with line description.
209 * \param [in] release_ver libgeda release version number.
210 * \param [in] fileformat_ver libgeda file format version number.
211 * \return A pointer to the new line object.
213 OBJECT *o_line_read (TOPLEVEL *toplevel, char buf[],
214 unsigned int release_ver, unsigned int fileformat_ver)
216 OBJECT *new_obj;
217 char type;
218 int x1, y1;
219 int x2, y2;
220 int line_width, line_space, line_length;
221 int line_end;
222 int line_type;
223 int color;
225 if (release_ver <= VERSION_20000704) {
227 * The old geda file format, i.e. releases 20000704 and older, does
228 * not handle the line type and the filling - here filling is irrelevant.
229 * They are set to default.
231 sscanf (buf, "%c %d %d %d %d %d\n", &type,
232 &x1, &y1, &x2, &y2, &color);
234 line_width = 0;
235 line_end = END_NONE;
236 line_type = TYPE_SOLID;
237 line_length= -1;
238 line_space = -1;
239 } else {
241 * The current line format to describe a line is a space separated
242 * list of characters and numbers in plain ASCII on a single line.
243 * The meaning of each item is described in the file format documentation.
245 sscanf (buf, "%c %d %d %d %d %d %d %d %d %d %d\n", &type,
246 &x1, &y1, &x2, &y2, &color,
247 &line_width, &line_end, &line_type, &line_length, &line_space);
251 * Null length line are not allowed. If such a line is detected a
252 * message is issued.
254 * It also checks is the required color is valid.
256 if (x1 == x2 && y1 == y2) {
257 s_log_message (_("Found a zero length line [ %c %d %d %d %d %d ]\n"),
258 type, x1, y1, x2, y2, color);
261 if (color < 0 || color > MAX_COLORS) {
262 s_log_message (_("Found an invalid color [ %s ]\n"), buf);
263 s_log_message (_("Setting color to default color\n"));
264 color = DEFAULT_COLOR;
268 * A line is internally described by its two ends. A new object is
269 * allocated, initialized and added to the list of objects. Its line
270 * type is set according to the values of the fields on the line.
272 /* create and add the line to the list */
273 new_obj = o_line_new (toplevel, type, color, x1, y1, x2, y2);
274 /* set its line options */
275 o_set_line_options (toplevel, new_obj,
276 line_end, line_type, line_width, line_length,
277 line_space);
278 /* filling is irrelevant for line, just set to default */
279 o_set_fill_options (toplevel, new_obj,
280 FILLING_HOLLOW, -1, -1, -1, -1, -1);
282 return new_obj;
285 /*! \brief Create a character string representation of a line OBJECT.
286 * \par Function Description
287 * The function formats a string in the buffer <B>*buff</B> to describe
288 * the box object <B>*object</B>.
289 * It follows the post-20000704 release file format that handle the
290 * line type and fill options - filling is irrelevant here.
292 * \param [in] object Line OBJECT to create string from.
293 * \return A pointer to the line OBJECT character string.
295 * \note
296 * Caller must g_free returned character string.
299 char *o_line_save(OBJECT *object)
301 int x1, x2, y1, y2;
302 int line_width, line_space, line_length;
303 char *buf;
304 OBJECT_END line_end;
305 OBJECT_TYPE line_type;
307 /* get the two ends */
308 x1 = object->line->x[0];
309 y1 = object->line->y[0];
310 x2 = object->line->x[1];
311 y2 = object->line->y[1];
313 /* description of the line type */
314 line_width = object->line_width;
315 line_end = object->line_end;
316 line_type = object->line_type;
317 line_length= object->line_length;
318 line_space = object->line_space;
320 buf = g_strdup_printf("%c %d %d %d %d %d %d %d %d %d %d", object->type,
321 x1, y1, x2, y2, object->color,
322 line_width, line_end, line_type,
323 line_length, line_space);
325 return(buf);
328 /*! \brief Translate a line position in WORLD coordinates by a delta.
329 * \par Function Description
330 * This function applies a translation of (<B>x1</B>,<B>y1</B>) to the line
331 * described by <B>*object</B>. <B>x1</B> and <B>y1</B> are in world unit.
333 * \param [in] toplevel The TOPLEVEL object.
334 * \param [in] dx x distance to move.
335 * \param [in] dy y distance to move.
336 * \param [in,out] object Line OBJECT to translate.
338 void o_line_translate_world(TOPLEVEL *toplevel,
339 int dx, int dy, OBJECT *object)
341 if (object == NULL) printf("ltw NO!\n");
343 /* Update world coords */
344 object->line->x[0] = object->line->x[0] + dx;
345 object->line->y[0] = object->line->y[0] + dy;
346 object->line->x[1] = object->line->x[1] + dx;
347 object->line->y[1] = object->line->y[1] + dy;
349 /* Update bounding box */
350 o_line_recalc (toplevel, object);
353 /*! \brief Rotate Line OBJECT using WORLD coordinates.
354 * \par Function Description
355 * This function rotates the line described by
356 * <B>*object</B> around the (<B>world_centerx</B>,<B>world_centery</B>)
357 * point by <B>angle</B> degrees.
358 * The center of rotation is in world units.
360 * \param [in] toplevel The TOPLEVEL object.
361 * \param [in] world_centerx Rotation center x coordinate in WORLD units.
362 * \param [in] world_centery Rotation center y coordinate in WORLD units.
363 * \param [in] angle Rotation angle in degrees (See note below).
364 * \param [in,out] object Line OBJECT to rotate.
366 void o_line_rotate_world(TOPLEVEL *toplevel,
367 int world_centerx, int world_centery, int angle,
368 OBJECT *object)
370 int newx, newy;
372 if (angle == 0)
373 return;
375 /* angle must be positive */
376 if(angle < 0) angle = -angle;
377 /* angle must be 90 multiple or no rotation performed */
378 if((angle % 90) != 0) return;
381 * The center of rotation (<B>world_centerx</B>,<B>world_centery</B>)
382 * is translated to the origin. The rotation of the two ends of
383 * the line is performed. FInally, the rotated line is translated
384 * back to its previous location.
386 /* translate object to origin */
387 o_line_translate_world(toplevel, -world_centerx, -world_centery, object);
389 /* rotate line end 1 */
390 rotate_point_90(object->line->x[0], object->line->y[0], angle,
391 &newx, &newy);
393 object->line->x[0] = newx;
394 object->line->y[0] = newy;
396 /* rotate line end 2 */
397 rotate_point_90(object->line->x[1], object->line->y[1], angle,
398 &newx, &newy);
400 object->line->x[1] = newx;
401 object->line->y[1] = newy;
403 /* translate object back to normal position */
404 o_line_translate_world(toplevel, world_centerx, world_centery, object);
408 /*! \brief Mirror a line using WORLD coordinates.
409 * \par Function Description
410 * This function mirrors the line from the point
411 * (<B>world_centerx</B>,<B>world_centery</B>) in world unit.
413 * The line if first translated to the origin, then mirrored
414 * and finally translated back at its previous position.
416 * \param [in] toplevel The TOPLEVEL object.
417 * \param [in] world_centerx Origin x coordinate in WORLD units.
418 * \param [in] world_centery Origin y coordinate in WORLD units.
419 * \param [in,out] object Line OBJECT to mirror.
421 void o_line_mirror_world(TOPLEVEL *toplevel, int world_centerx,
422 int world_centery, OBJECT *object)
424 /* translate object to origin */
425 o_line_translate_world(toplevel, -world_centerx, -world_centery, object);
427 /* mirror the line ends */
428 object->line->x[0] = -object->line->x[0];
429 object->line->x[1] = -object->line->x[1];
431 /* translate back in position */
432 o_line_translate_world(toplevel, world_centerx, world_centery, object);
436 /*! \brief Recalculate line coordinates in SCREEN units.
437 * \par Function Description
438 * This function recalculate the bounding box of the <B>o_current</B>
440 * \param [in] toplevel The TOPLEVEL object.
441 * \param [in,out] o_current Line OBJECT to be recalculated.
443 void o_line_recalc(TOPLEVEL *toplevel, OBJECT *o_current)
445 int left, right, top, bottom;
447 if (o_current->line == NULL) {
448 return;
451 /* update the bounding box - screen unit */
452 world_get_line_bounds(toplevel, o_current,
453 &left, &top, &right, &bottom);
454 o_current->w_left = left;
455 o_current->w_top = top;
456 o_current->w_right = right;
457 o_current->w_bottom = bottom;
458 o_current->w_bounds_valid = TRUE;
461 /*! \brief Get line bounding rectangle in WORLD coordinates.
462 * \par Function Description
463 * This function sets the <B>left</B>, <B>top</B>, <B>right</B> and
464 * <B>bottom</B> parameters to the boundings of the line object described
465 * in <B>*line</B> in world units.
467 * \param [in] toplevel The TOPLEVEL object.
468 * \param [in] object Line OBJECT to read coordinates from.
469 * \param [out] left Left line coordinate in WORLD units.
470 * \param [out] top Top line coordinate in WORLD units.
471 * \param [out] right Right line coordinate in WORLD units.
472 * \param [out] bottom Bottom line coordinate in WORLD units.
474 void world_get_line_bounds(TOPLEVEL *toplevel, OBJECT *object,
475 int *left, int *top, int *right, int *bottom)
477 int halfwidth;
479 halfwidth = object->line_width / 2;
481 *left = min( object->line->x[0], object->line->x[1] );
482 *top = min( object->line->y[0], object->line->y[1] );
483 *right = max( object->line->x[0], object->line->x[1] );
484 *bottom = max( object->line->y[0], object->line->y[1] );
486 /* This isn't strictly correct, but a 1st order approximation */
487 *left -= halfwidth;
488 *top -= halfwidth;
489 *right += halfwidth;
490 *bottom += halfwidth;
493 /*! \brief get the position of the first line point
494 * \par Function Description
495 * This function gets the position of the first point of a line object.
497 * \param [in] toplevel The toplevel environment.
498 * \param [out] x pointer to the x-position
499 * \param [out] y pointer to the y-position
500 * \param [in] object The object to get the position.
501 * \return TRUE if successfully determined the position, FALSE otherwise
503 gboolean o_line_get_position (TOPLEVEL *toplevel, gint *x, gint *y,
504 OBJECT *object)
506 *x = object->line->x[0];
507 *y = object->line->y[0];
508 return TRUE;
512 /*! \brief Print line to Postscript document.
513 * \par Function Description
514 * This function prints the line described by the <B>o_current</B>
515 * parameter to a Postscript document.
516 * The Postscript document is described by the <B>fp</B> file pointer.
518 * Parameters of the line are extracted from object pointed by
519 * <B>o_current</B>.
521 * \param [in] toplevel The TOPLEVEL object.
522 * \param [in] fp FILE pointer to Postscript document.
523 * \param [in] o_current Line OBJECT to write to document.
524 * \param [in] origin_x Page x coordinate to place line OBJECT.
525 * \param [in] origin_y Page y coordinate to place line OBJECT.
527 void o_line_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current,
528 int origin_x, int origin_y)
530 int x1, y1, x2, y2;
531 int color;
532 int line_width, length, space;
533 void (*outl_func)() = NULL;
535 if (o_current == NULL) {
536 printf("got null in o_line_print\n");
537 return;
540 x1 = o_current->line->x[0];
541 y1 = o_current->line->y[0];
542 x2 = o_current->line->x[1];
543 y2 = o_current->line->y[1];
544 color = o_current->color;
547 * Depending on the type of the line for this particular line, the
548 * appropriate function is chosen among
549 * #o_line_print_solid(), #o_line_print_dotted()#, #o_line_print_dashed(),
550 * #o_line_print_center() and #o_line_print_phantom().
552 * The needed parameters for each of these types are extracted from the
553 * <B>o_current</B> object. Depending on the type, unused parameters are
554 * set to -1.
556 * In the eventuality of a length and/or space null, the line is printed
557 * solid to avoid and endless loop produced by other functions.
559 line_width = o_current->line_width;
560 if(line_width <=2) {
561 if(toplevel->line_style == THICK) {
562 line_width=LINE_WIDTH;
563 } else {
564 line_width=2;
568 length = o_current->line_length;
569 space = o_current->line_space;
571 switch(o_current->line_type) {
572 case(TYPE_SOLID):
573 length = -1; space = -1;
574 outl_func = o_line_print_solid;
575 break;
577 case(TYPE_DOTTED):
578 length = -1;
579 outl_func = o_line_print_dotted;
580 break;
582 case(TYPE_DASHED):
583 outl_func = o_line_print_dashed;
584 break;
586 case(TYPE_CENTER):
587 outl_func = o_line_print_center;
588 break;
590 case(TYPE_PHANTOM):
591 outl_func = o_line_print_phantom;
592 break;
594 case(TYPE_ERASE):
595 /* Unused for now, print it solid */
596 length = -1; space = -1;
597 outl_func = o_line_print_solid;
598 break;
601 if((length == 0) || (space == 0)) {
602 length = -1; space = -1;
603 outl_func = o_line_print_solid;
606 (*outl_func)(toplevel, fp,
607 x1 - origin_x, y1 - origin_y,
608 x2 - origin_x, y2 - origin_y,
609 color,
610 line_width, length, space,
611 origin_x, origin_y);
614 /*! \brief Print a solid line to Postscript document.
615 * \par Function Description
616 * This function prints a line when a solid line type is required.
617 * The line is defined by the coordinates of its two ends in
618 * (<B>x1</B>,<B>y1</B>) and (<B>x2</B>,<B>y2</B>).
619 * The Postscript document is defined by the file pointer <B>fp</B>.
620 * The parameters <B>length</B> and <B>space</B> are ignored whereas
621 * <B>line_width</B> specifies the width of the printed line.
623 * \param [in] toplevel The TOPLEVEL object.
624 * \param [in] fp FILE pointer to Postscript document.
625 * \param [in] x1 Upper x coordinate.
626 * \param [in] y1 Upper y coordinate.
627 * \param [in] x2 Lower x coordinate.
628 * \param [in] y2 Lower y coordinate.
629 * \param [in] color Line color.
630 * \param [in] line_width Width of line.
631 * \param [in] length (unused).
632 * \param [in] space (unused).
633 * \param [in] origin_x Page x coordinate to place line OBJECT.
634 * \param [in] origin_y Page y coordinate to place line OBJECT.
636 void o_line_print_solid(TOPLEVEL *toplevel, FILE *fp,
637 int x1, int y1, int x2, int y2,
638 int color,
639 int line_width, int length, int space,
640 int origin_x, int origin_y)
642 f_print_set_color(toplevel, fp, color);
644 fprintf(fp,"%d %d %d %d %d line\n",
645 x1,y1,x2,y2, line_width);
648 /*! \brief Print a dotted line to Postscript document.
649 * \par Function Description
650 * This function prints a line when a dotted line type is required.
651 * The line is defined by the coordinates of its two ends in
652 * (<B>x1</B>,<B>y1</B>) and (<B>x2</B>,<B>y2</B>).
653 * The Postscript document is defined by the file pointer <B>fp</B>.
654 * The parameter <B>length</B> is ignored whereas <B>line_width</B>
655 * specifies the diameter of the dots and <B>space</B> the distance
656 * between two dots.
658 * A negative value for <B>space</B> leads to an endless loop.
660 * All dimensions are in mils.
662 * The function sets the color in which the line will be printed with.
664 * \param [in] toplevel The TOPLEVEL object.
665 * \param [in] fp FILE pointer to Postscript document.
666 * \param [in] x1 Upper x coordinate.
667 * \param [in] y1 Upper y coordinate.
668 * \param [in] x2 Lower x coordinate.
669 * \param [in] y2 Lower y coordinate.
670 * \param [in] color Line color.
671 * \param [in] line_width Width of line.
672 * \param [in] length (unused).
673 * \param [in] space Space between dots.
674 * \param [in] origin_x Page x coordinate to place line OBJECT.
675 * \param [in] origin_y Page y coordinate to place line OBJECT.
677 void o_line_print_dotted(TOPLEVEL *toplevel, FILE *fp,
678 int x1, int y1, int x2, int y2,
679 int color,
680 int line_width, int length, int space,
681 int origin_x, int origin_y)
683 double dx, dy, l, d;
684 double dx1, dy1;
685 double xa, ya;
687 f_print_set_color(toplevel, fp, color);
689 /* The dotted line command takes an array of dots so print out the
690 * beginnings of the array
692 fprintf(fp,"[");
693 /* is the width relevant for a dot (circle) ? */
694 /* f_print_set_line_width(fp, line_width); */
697 * Depending on the slope of the line the space parameter is
698 * projected on each of the two directions x and y resulting
699 * in <B>dx1</B> and <B>dy1</B>. Starting from one end by increments
700 * of space the dots are printed.
702 * A dot is represented by a filled circle. Position of the
703 * circle is (<B>xa</B>, <B>ya</B>) and its radius is the <B>line_width</B>
704 * parameter.
707 dx = (double) (x2 - x1);
708 dy = (double) (y2 - y1);
709 l = sqrt((dx * dx) + (dy * dy));
711 dx1 = (dx * space) / l;
712 dy1 = (dy * space) / l;
714 d = 0;
715 xa = x1; ya = y1;
716 while(d < l) {
718 fprintf(fp,"[%d %d] ",
719 (int)xa, (int)ya);
720 d = d + space;
721 xa = xa + dx1;
722 ya = ya + dy1;
725 fprintf(fp,"] %d dashed\n",line_width);
730 /*! \brief Print a dashed line to Postscript document.
731 * \par Function Description
732 * This function prints a line when a dashed line type is required.
733 * The line is defined by the coordinates of its two ends in
734 * (<B>x1</B>,<B>y1</B>) and (<B>x2</B>,<B>y2</B>).
735 * The postscript file is defined by the file pointer <B>fp</B>.
737 * A negative value for <B>space</B> or <B>length</B> leads to an
738 * endless loop.
740 * All dimensions are in mils.
742 * The function sets the color in which the line will be printed and
743 * the width of the line - that is the width of the dashes.
745 * \param [in] toplevel The TOPLEVEL object.
746 * \param [in] fp FILE pointer to Postscript document.
747 * \param [in] x1 Upper x coordinate.
748 * \param [in] y1 Upper y coordinate.
749 * \param [in] x2 Lower x coordinate.
750 * \param [in] y2 Lower y coordinate.
751 * \param [in] color Line color.
752 * \param [in] line_width Width of line.
753 * \param [in] length Length of a dash.
754 * \param [in] space Space between dashes.
755 * \param [in] origin_x Page x coordinate to place line OBJECT.
756 * \param [in] origin_y Page y coordinate to place line OBJECT.
758 void o_line_print_dashed(TOPLEVEL *toplevel, FILE *fp,
759 int x1, int y1, int x2, int y2,
760 int color,
761 int line_width, int length, int space,
762 int origin_x, int origin_y)
764 double dx, dy, l, d;
765 double dx1, dy1, dx2, dy2;
766 double xa, ya, xb, yb;
768 f_print_set_color(toplevel, fp, color);
770 /* the dashed line function takes an array of start-finish pairs
771 * output the beginnings of the array now
773 fprintf(fp,"[");
776 * Depending on the slope of the line the <B>length</B> (resp. <B>space</B>)
777 * parameter is projected on each of the two directions x and y
778 * resulting in <B>dx1</B> and <B>dy1</B> (resp. <B>dx2</B> and <B>dy2</B>).
779 * Starting from one end and incrementing alternatively by <B>space</B>
780 * and <B>length</B> the dashes are printed.
782 * It prints as many dashes of length <B>length</B> as possible.
784 dx = (double) (x2 - x1);
785 dy = (double) (y2 - y1);
786 l = sqrt((dx * dx) + (dy * dy));
788 dx1 = (dx * length) / l;
789 dy1 = (dy * length) / l;
791 dx2 = (dx * space) / l;
792 dy2 = (dy * space) / l;
794 d = 0;
795 xa = x1; ya = y1;
796 while((d + length + space) < l) {
797 d = d + length;
798 xb = xa + dx1;
799 yb = ya + dy1;
801 fprintf(fp, "[%d %d %d %d] ",
802 (int) xa, (int) ya,
803 (int) xb, (int) yb);
805 d = d + space;
806 xa = xb + dx2;
807 ya = yb + dy2;
810 * When the above condition is no more satisfied, then it is not possible
811 * to print a dash of length <B>length</B>. However it may be possible to
812 * print the complete dash or a shorter one.
815 if((d + length) < l) {
816 d = d + length;
817 xb = xa + dx1;
818 yb = ya + dy1;
819 } else {
820 xb = x2;
821 yb = y2;
824 fprintf(fp, "[%d %d %d %d] ",
825 (int) xa, (int) ya,
826 (int) xb, (int) yb);
828 fprintf(fp,"] %d dashed\n", line_width);
832 /*! \brief Print a centered line type line to Postscript document.
833 * \par Function Description
834 * This function prints a line when a centered line type is required.
835 * The line is defined by the coordinates of its two ends in
836 * (<B>x1</B>,<B>y1</B>) and (<B>x2</B>,<B>y2</B>).
837 * The Postscript document is defined by the file pointer <B>fp</B>.
839 * A negative value for <B>space</B> or <B>length</B> leads to an
840 * endless loop.
842 * All dimensions are in mils.
844 * The function sets the color in which the line will be printed and the
845 * width of the line - that is the width of the dashes and the diameter
846 * of the dots.
848 * \param [in] toplevel The TOPLEVEL object.
849 * \param [in] fp FILE pointer to Postscript document.
850 * \param [in] x1 Upper x coordinate.
851 * \param [in] y1 Upper y coordinate.
852 * \param [in] x2 Lower x coordinate.
853 * \param [in] y2 Lower y coordinate.
854 * \param [in] color Line color.
855 * \param [in] line_width Width of line.
856 * \param [in] length Length of a dash.
857 * \param [in] space Space between dashes.
858 * \param [in] origin_x Page x coordinate to place line OBJECT.
859 * \param [in] origin_y Page y coordinate to place line OBJECT.
861 void o_line_print_center(TOPLEVEL *toplevel, FILE *fp,
862 int x1, int y1, int x2, int y2,
863 int color,
864 int line_width, int length, int space,
865 int origin_x, int origin_y)
867 double dx, dy, l, d;
868 double dx1, dy1, dx2, dy2;
869 double xa, ya, xb, yb;
871 f_print_set_color(toplevel, fp, color);
873 fprintf(fp, "[");
876 * Depending on the slope of the line the <B>length</B> (resp. <B>space</B>)
877 * parameter is projected on each of the two directions x and y resulting
878 * in <B>dx1</B> and <B>dy1</B> (resp. <B>dx2</B> and <B>dy2</B>).
879 * Starting from one end and incrementing alternatively by <B>space</B>
880 * and <B>length</B> the dashes and dots are printed.
882 * It prints as many sets of dash and dot as possible.
884 dx = (double) (x2 - x1);
885 dy = (double) (y2 - y1);
886 l = sqrt((dx * dx) + (dy * dy));
888 dx1 = (dx * length) / l;
889 dy1 = (dy * length) / l;
891 dx2 = (dx * space) / l;
892 dy2 = (dy * space) / l;
894 d = 0;
895 xa = x1; ya = y1;
896 while((d + length + 2 * space) < l) {
897 d = d + length;
898 xb = xa + dx1;
899 yb = ya + dy1;
901 fprintf(fp, "[%d %d %d %d] ",
902 (int) xa, (int) ya,
903 (int) xb, (int) yb);
905 d = d + space;
906 xa = xb + dx2;
907 ya = yb + dy2;
909 fprintf(fp,"[%d %d] ",(int) xa, (int) ya);
911 d = d + space;
912 xa = xa + dx2;
913 ya = ya + dy2;
916 * When the above condition is no more satisfied, then it is not possible
917 * to print a dash of length <B>length</B>.
918 * However two cases are possible :
919 * <DL>
920 * <DT>*</DT><DD>it is possible to print the dash and the dot.
921 * <DT>*</DT><DD>it is possible to print the dash or a part
922 * of the original dash.
923 * </DL>
926 if((d + length + space) < l) {
927 d = d + length;
928 xb = xa + dx1;
929 yb = ya + dy1;
931 fprintf(fp, "[%d %d %d %d] ",
932 (int) xa, (int) ya,
933 (int) xb, (int) yb);
935 d = d + space;
936 xa = xb + dx2;
937 ya = yb + dy2;
939 fprintf(fp,"[%d %d] ",(int) xa, (int) ya);
941 } else {
942 if(d + length < l) {
943 xb = xa + dx1;
944 yb = ya + dy1;
945 } else {
946 xb = x2;
947 yb = y2;
950 fprintf(fp, "[%d %d %d %d] ",
951 (int) xa, (int) ya,
952 (int) xb, (int) yb);
956 fprintf(fp,"] %d dashed\n", line_width);
959 * A dot is represented by a filled circle. Position of the circle is
960 * (<B>xa</B>, <B>ya</B>) and its radius by the <B>line_width</B> parameter.
964 /*! \brief Print a phantom line type line to Postscript document.
965 * \par Function Description
966 * This function prints a line when a phantom line type is required.
967 * The line is defined by the coordinates of its two ends in
968 * (<B>x1</B>,<B>y1</B>) and (<B>x2</B>,<B>y2</B>).
969 * The Postscript document is defined by the file pointer <B>fp</B>.
971 * A negative value for <B>space</B> or <B>length</B> leads to an
972 * endless loop.
974 * All dimensions are in mils.
976 * The function sets the color in which the line will be printed and the
977 * width of the line - that is the width of the dashes and the diameter
978 * of the dots.
980 * \param [in] toplevel The TOPLEVEL object.
981 * \param [in] fp FILE pointer to Postscript document.
982 * \param [in] x1 Upper x coordinate.
983 * \param [in] y1 Upper y coordinate.
984 * \param [in] x2 Lower x coordinate.
985 * \param [in] y2 Lower y coordinate.
986 * \param [in] color Line color.
987 * \param [in] line_width Width of line.
988 * \param [in] length Length of a dash.
989 * \param [in] space Space between dashes.
990 * \param [in] origin_x Page x coordinate to place line OBJECT.
991 * \param [in] origin_y Page y coordinate to place line OBJECT.
993 void o_line_print_phantom(TOPLEVEL *toplevel, FILE *fp,
994 int x1, int y1, int x2, int y2,
995 int color,
996 int line_width, int length, int space,
997 int origin_x, int origin_y)
999 double dx, dy, l, d;
1000 double dx1, dy1, dx2, dy2;
1001 double xa, ya, xb, yb;
1003 f_print_set_color(toplevel, fp, color);
1005 fprintf(fp,"[");
1008 * Depending on the slope of the line the <B>length</B> (resp. <B>space</B>)
1009 * parameter is projected on each of the two directions x and y resulting
1010 * in <B>dx1</B> and <B>dy1</B> (resp. <B>dx2</B> and <B>dy2</B>).
1011 * Starting from one end and incrementing alternatively by <B>space</B>
1012 * and <B>length</B> the dashes and dots are printed.
1014 * It prints as many sets of dash-dot-dot as possible.
1016 dx = (double) (x2 - x1);
1017 dy = (double) (y2 - y1);
1018 l = sqrt((dx * dx) + (dy * dy));
1020 dx1 = (dx * length) / l;
1021 dy1 = (dy * length) / l;
1023 dx2 = (dx * space) / l;
1024 dy2 = (dy * space) / l;
1026 d = 0;
1027 xa = x1; ya = y1;
1028 while((d + length + 3 * space) < l) {
1029 d = d + length;
1030 xb = xa + dx1;
1031 yb = ya + dy1;
1033 fprintf(fp,"[%d %d %d %d] ",
1034 (int) xa, (int)ya,
1035 (int) xb, (int)yb);
1037 d = d + space;
1038 xa = xb + dx2;
1039 ya = yb + dy2;
1041 fprintf(fp,"[%d %d] ",(int) xa, (int) ya);
1043 d = d + space;
1044 xa = xa + dx2;
1045 ya = ya + dy2;
1047 fprintf(fp,"[%d %d] ",(int) xa, (int) ya);
1049 d = d + space;
1050 xa = xa + dx2;
1051 ya = ya + dy2;
1054 * When the above condition is no more satisfied, then it is not possible
1055 * to print a complete set of dash-dot-dot.
1056 * However three cases are possible :
1057 * <DL>
1058 * <DT>*</DT><DD>it is possible to print a dash and a dot and a dot.
1059 * <DT>*</DT><DD>it is possible to print a dash and a dot.
1060 * <DT>*</DT><DD>it is possible to print the dash or a part
1061 * of the original dash.
1062 * </DL>
1065 if((d + length + 2 * space) < l) {
1066 d = d + length;
1067 xb = xa + dx1;
1068 yb = ya + dy1;
1070 fprintf(fp,"[%d %d %d %d] ",
1071 (int) xa, (int)ya,
1072 (int) xb, (int)yb);
1074 d = d + space;
1075 xa = xb + dx2;
1076 ya = yb + dy2;
1078 fprintf(fp,"[%d %d] ",(int) xa, (int)ya);
1080 d = d + space;
1081 xa = xb + dx2;
1082 ya = yb + dy2;
1084 fprintf(fp,"[%d %d] ",(int) xa, (int)ya);
1086 } else {
1087 if(d + length + space < l) {
1088 d = d + length;
1089 xb = xa + dx1;
1090 yb = ya + dy1;
1092 fprintf(fp,"[%d %d %d %d] ",
1093 (int) xa, (int)ya,
1094 (int) xb, (int)yb);
1096 d = d + space;
1097 xa = xb + dx2;
1098 ya = yb + dy2;
1100 fprintf(fp,"[%d %d] ",(int) xa, (int)ya);
1102 } else {
1103 if(d + length < l) {
1104 xb = xa + dx1;
1105 yb = ya + dy1;
1106 } else {
1107 xb = x2;
1108 yb = y2;
1111 fprintf(fp,"[%d %d %d %d] ",
1112 (int) xa, (int)ya,
1113 (int) xb, (int)yb);
1118 fprintf(fp,"] %d dashed\n", line_width);
1122 /*! \brief
1123 * \par Function Description
1125 * \param [in] toplevel The TOPLEVEL object.
1126 * \param [in] x_scale
1127 * \param [in] y_scale
1128 * \param [in] object
1130 void o_line_scale_world(TOPLEVEL *toplevel, int x_scale, int y_scale,
1131 OBJECT *object)
1133 if (object == NULL) printf("lsw NO!\n");
1135 /* scale the line world coords */
1136 object->line->x[0] = object->line->x[0] * x_scale;
1137 object->line->y[0] = object->line->y[0] * y_scale;
1138 object->line->x[1] = object->line->x[1] * x_scale;
1139 object->line->y[1] = object->line->y[1] * y_scale;
1141 /* update boundingbox */
1142 o_line_recalc(toplevel, object);
1147 /*! \brief calculate the lenght of a line object
1148 * \par Function Description
1149 * This function calculates the length of a line object
1151 * \param [in] object a line OBJECT
1152 * \return The length of the line
1154 double o_line_length(OBJECT *object)
1156 double length;
1157 double dx, dy;
1159 if (!object->line) {
1160 return 0.0;
1163 dx = object->line->x[0]-object->line->x[1];
1164 dy = object->line->y[0]-object->line->y[1];
1166 length = sqrt((dx*dx) + (dy*dy));
1168 return(length);
1171 /*! \brief Calculates the distance between the given point and the closest
1172 * point on the given line segment.
1174 * If the closest point on the line resides beyond the line segment's
1175 * end point, this function returns the distance from the given point to the
1176 * closest end point.
1178 * If the line represents a single point (the endpoints are the same), this
1179 * function calcualtes the distance to that point.
1181 * \param [in] object The line OBJECT.
1182 * \param [in] x The x coordinate of the given point.
1183 * \param [in] y The y coordinate of the given point.
1184 * \param [in] force_solid If true, force treating the object as solid.
1185 * \return The shortest distance from the object to the point. With an
1186 * invalid parameter, this function returns G_MAXDOUBLE.
1188 double o_line_shortest_distance (OBJECT *object, int x, int y, int force_solid)
1190 return m_line_shortest_distance (object->line, x, y);