libgeda: Remove some exit() calls and assertions.
[geda-gaf/peter-b.git] / libgeda / src / o_line_basic.c
blob887c525116f578867aaa5957688d0f5de0becc1d
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 /*! \brief Create and add line OBJECT to list.
37 * \par Function Description
38 * This function creates a new object representing a line.
40 * The line is described by its two ends - <B>x1</B>,<B>y1</B> and
41 * <B>x2</B>,<B>y2</B>.
42 * The <B>type</B> parameter must be equal to #OBJ_LINE.
43 * The <B>color</B> parameter corresponds to the color the box
44 * will be drawn with.
46 * The #OBJECT structure is allocated with the #s_basic_new_object()
47 * function. The structure describing the line is allocated and
48 * initialized with the parameters given to the function.
50 * Both the line type and the filling type are set to default
51 * values : solid line type with a width of 0, and no filling.
52 * It can be changed after with the #o_set_line_options() and
53 * #o_set_fill_options().
55 * \param [in] toplevel The TOPLEVEL object.
56 * \param [in] type Must be OBJ_LINE.
57 * \param [in] color Circle line color.
58 * \param [in] x1 Upper x coordinate.
59 * \param [in] y1 Upper y coordinate.
60 * \param [in] x2 Lower x coordinate.
61 * \param [in] y2 Lower y coordinate.
62 * \return A pointer to the new end of the object list.
64 OBJECT *o_line_new(TOPLEVEL *toplevel,
65 char type, int color,
66 int x1, int y1, int x2, int y2)
68 OBJECT *new_node;
70 /* create the object */
71 new_node = s_basic_new_object(type, "line");
72 new_node->color = color;
74 new_node->line = (LINE *) g_malloc(sizeof(LINE));
76 /* describe the line with its two ends */
77 new_node->line->x[0] = x1;
78 new_node->line->y[0] = y1;
79 new_node->line->x[1] = x2;
80 new_node->line->y[1] = y2;
82 /* line type and filling initialized to default */
83 o_set_line_options(toplevel, new_node,
84 END_NONE, TYPE_SOLID, 0, -1, -1);
85 o_set_fill_options(toplevel, new_node,
86 FILLING_HOLLOW, -1, -1, -1, -1, -1);
88 /* compute bounding box */
89 o_line_recalc(toplevel, new_node);
91 return new_node;
94 /*! \brief Create a copy of a line.
95 * \par Function Description
96 * This function creates a verbatim copy of the
97 * object pointed by <B>o_current</B> describing a line.
99 * \param [in] toplevel The TOPLEVEL object.
100 * \param [in] o_current Line OBJECT to copy.
101 * \return The new OBJECT
103 OBJECT *o_line_copy(TOPLEVEL *toplevel, OBJECT *o_current)
105 OBJECT *new_obj;
107 /* A new line object is created with #o_line_new().
108 * Values for its fields are default and need to be modified. */
109 new_obj = o_line_new (toplevel, OBJ_LINE, o_current->color,
110 o_current->line->x[0], o_current->line->y[0],
111 o_current->line->x[1], o_current->line->y[1]);
114 * The coordinates of the ends of the new line are set with the ones
115 * of the original line. The two lines have the sale line type and
116 * filling options.
118 * The bounding box are computed with
119 * #o_line_recalc().
122 /* copy the line type and filling options */
123 o_set_line_options(toplevel, new_obj, o_current->line_end,
124 o_current->line_type, o_current->line_width,
125 o_current->line_length, o_current->line_space);
126 o_set_fill_options(toplevel, new_obj,
127 o_current->fill_type, o_current->fill_width,
128 o_current->fill_pitch1, o_current->fill_angle1,
129 o_current->fill_pitch2, o_current->fill_angle2);
131 /* calc the bounding box */
132 o_line_recalc(toplevel, o_current);
134 /* new_obj->attribute = 0;*/
136 /* return the new tail of the object list */
137 return new_obj;
140 /*! \brief Modify the description of a line OBJECT.
141 * \par Function Description
142 * This function modifies the coordinates of one of the two ends of
143 * the line described by <B>*object</B>. The new coordinates of this end,
144 * identified by <B>whichone</B>, are given by <B>x</B> and <B>y</B>
145 * in world unit.
147 * The coordinates of the end of line is modified in the world
148 * coordinate system. Screen coordinates and boundings are then updated.
150 * \param [in] toplevel The TOPLEVEL object.
151 * \param [in,out] object Line OBJECT to modify.
152 * \param [in] x New x coordinate.
153 * \param [in] y New y coordinate.
154 * \param [in] whichone Which line parameter to modify.
156 * <B>whichone</B> can have the following values:
157 * <DL>
158 * <DT>*</DT><DD>LINE_END1
159 * <DT>*</DT><DD>LINE_END2
160 * </DL>
162 void o_line_modify(TOPLEVEL *toplevel, OBJECT *object,
163 int x, int y, int whichone)
165 o_emit_pre_change_notify (toplevel, object);
167 /* change one of the end of the line */
168 switch (whichone) {
169 case LINE_END1:
170 object->line->x[0] = x;
171 object->line->y[0] = y;
172 break;
174 case LINE_END2:
175 object->line->x[1] = x;
176 object->line->y[1] = y;
177 break;
179 default:
180 return;
183 /* recalculate the bounding box */
184 o_line_recalc(toplevel, object);
185 o_emit_change_notify (toplevel, object);
188 /*! \brief Create line OBJECT from character string.
189 * \par Function Description
190 * This function creates a line OBJECT from the character string
191 * <B>*buf</B> the description of a box.
193 * The function returns a pointer on the new last element, that is
194 * the added line object.
196 * Depending on <B>*version</B>, the correct file format is considered.
197 * Currently two file format revisions are supported :
198 * <DL>
199 * <DT>*</DT><DD>the file format used until 20010704 release.
200 * <DT>*</DT><DD>the file format used for the releases after 20010704.
201 * </DL>
203 * \param [in] toplevel The TOPLEVEL object.
204 * \param [in] buf Character string with line description.
205 * \param [in] release_ver libgeda release version number.
206 * \param [in] fileformat_ver libgeda file format version number.
207 * \return A pointer to the new line object.
209 OBJECT *o_line_read (TOPLEVEL *toplevel, char buf[],
210 unsigned int release_ver, unsigned int fileformat_ver)
212 OBJECT *new_obj;
213 char type;
214 int x1, y1;
215 int x2, y2;
216 int line_width, line_space, line_length;
217 int line_end;
218 int line_type;
219 int color;
221 if (release_ver <= VERSION_20000704) {
223 * The old geda file format, i.e. releases 20000704 and older, does
224 * not handle the line type and the filling - here filling is irrelevant.
225 * They are set to default.
227 sscanf (buf, "%c %d %d %d %d %d\n", &type,
228 &x1, &y1, &x2, &y2, &color);
230 line_width = 0;
231 line_end = END_NONE;
232 line_type = TYPE_SOLID;
233 line_length= -1;
234 line_space = -1;
235 } else {
237 * The current line format to describe a line is a space separated
238 * list of characters and numbers in plain ASCII on a single line.
239 * The meaning of each item is described in the file format documentation.
241 sscanf (buf, "%c %d %d %d %d %d %d %d %d %d %d\n", &type,
242 &x1, &y1, &x2, &y2, &color,
243 &line_width, &line_end, &line_type, &line_length, &line_space);
247 * Null length line are not allowed. If such a line is detected a
248 * message is issued.
250 * It also checks is the required color is valid.
252 if (x1 == x2 && y1 == y2) {
253 s_log_message (_("Found a zero length line [ %c %d %d %d %d %d ]\n"),
254 type, x1, y1, x2, y2, color);
257 if (color < 0 || color > MAX_COLORS) {
258 s_log_message (_("Found an invalid color [ %s ]\n"), buf);
259 s_log_message (_("Setting color to default color\n"));
260 color = DEFAULT_COLOR;
264 * A line is internally described by its two ends. A new object is
265 * allocated, initialized and added to the list of objects. Its line
266 * type is set according to the values of the fields on the line.
268 /* create and add the line to the list */
269 new_obj = o_line_new (toplevel, type, color, x1, y1, x2, y2);
270 /* set its line options */
271 o_set_line_options (toplevel, new_obj,
272 line_end, line_type, line_width, line_length,
273 line_space);
274 /* filling is irrelevant for line, just set to default */
275 o_set_fill_options (toplevel, new_obj,
276 FILLING_HOLLOW, -1, -1, -1, -1, -1);
278 return new_obj;
281 /*! \brief Create a character string representation of a line OBJECT.
282 * \par Function Description
283 * The function formats a string in the buffer <B>*buff</B> to describe
284 * the box object <B>*object</B>.
285 * It follows the post-20000704 release file format that handle the
286 * line type and fill options - filling is irrelevant here.
288 * \param [in] toplevel a TOPLEVEL structure.
289 * \param [in] object Line OBJECT to create string from.
290 * \return A pointer to the line OBJECT character string.
292 * \note
293 * Caller must g_free returned character string.
296 char *o_line_save(TOPLEVEL *toplevel, OBJECT *object)
298 int x1, x2, y1, y2;
299 int line_width, line_space, line_length;
300 char *buf;
301 OBJECT_END line_end;
302 OBJECT_TYPE line_type;
304 /* get the two ends */
305 x1 = object->line->x[0];
306 y1 = object->line->y[0];
307 x2 = object->line->x[1];
308 y2 = object->line->y[1];
310 /* description of the line type */
311 line_width = object->line_width;
312 line_end = object->line_end;
313 line_type = object->line_type;
314 line_length= object->line_length;
315 line_space = object->line_space;
317 buf = g_strdup_printf("%c %d %d %d %d %d %d %d %d %d %d", object->type,
318 x1, y1, x2, y2, object->color,
319 line_width, line_end, line_type,
320 line_length, line_space);
322 return(buf);
325 /*! \brief Translate a line position in WORLD coordinates by a delta.
326 * \par Function Description
327 * This function applies a translation of (<B>x1</B>,<B>y1</B>) to the line
328 * described by <B>*object</B>. <B>x1</B> and <B>y1</B> are in world unit.
330 * \param [in] toplevel The TOPLEVEL object.
331 * \param [in] dx x distance to move.
332 * \param [in] dy y distance to move.
333 * \param [in,out] object Line OBJECT to translate.
335 void o_line_translate_world(TOPLEVEL *toplevel,
336 int dx, int dy, OBJECT *object)
338 if (object == NULL) printf("ltw NO!\n");
340 /* Update world coords */
341 object->line->x[0] = object->line->x[0] + dx;
342 object->line->y[0] = object->line->y[0] + dy;
343 object->line->x[1] = object->line->x[1] + dx;
344 object->line->y[1] = object->line->y[1] + dy;
346 /* Update bounding box */
347 o_line_recalc (toplevel, object);
350 /*! \brief Rotate Line OBJECT using WORLD coordinates.
351 * \par Function Description
352 * This function rotates the line described by
353 * <B>*object</B> around the (<B>world_centerx</B>,<B>world_centery</B>)
354 * point by <B>angle</B> degrees.
355 * The center of rotation is in world units.
357 * \param [in] toplevel The TOPLEVEL object.
358 * \param [in] world_centerx Rotation center x coordinate in WORLD units.
359 * \param [in] world_centery Rotation center y coordinate in WORLD units.
360 * \param [in] angle Rotation angle in degrees (See note below).
361 * \param [in,out] object Line OBJECT to rotate.
363 void o_line_rotate_world(TOPLEVEL *toplevel,
364 int world_centerx, int world_centery, int angle,
365 OBJECT *object)
367 int newx, newy;
369 if (angle == 0)
370 return;
372 /* angle must be positive */
373 if(angle < 0) angle = -angle;
374 /* angle must be 90 multiple or no rotation performed */
375 if((angle % 90) != 0) return;
378 * The center of rotation (<B>world_centerx</B>,<B>world_centery</B>)
379 * is translated to the origin. The rotation of the two ends of
380 * the line is performed. FInally, the rotated line is translated
381 * back to its previous location.
383 /* translate object to origin */
384 o_line_translate_world(toplevel, -world_centerx, -world_centery, object);
386 /* rotate line end 1 */
387 rotate_point_90(object->line->x[0], object->line->y[0], angle,
388 &newx, &newy);
390 object->line->x[0] = newx;
391 object->line->y[0] = newy;
393 /* rotate line end 2 */
394 rotate_point_90(object->line->x[1], object->line->y[1], angle,
395 &newx, &newy);
397 object->line->x[1] = newx;
398 object->line->y[1] = newy;
400 /* translate object back to normal position */
401 o_line_translate_world(toplevel, world_centerx, world_centery, object);
405 /*! \brief Mirror a line using WORLD coordinates.
406 * \par Function Description
407 * This function mirrors the line from the point
408 * (<B>world_centerx</B>,<B>world_centery</B>) in world unit.
410 * The line if first translated to the origin, then mirrored
411 * and finally translated back at its previous position.
413 * \param [in] toplevel The TOPLEVEL object.
414 * \param [in] world_centerx Origin x coordinate in WORLD units.
415 * \param [in] world_centery Origin y coordinate in WORLD units.
416 * \param [in,out] object Line OBJECT to mirror.
418 void o_line_mirror_world(TOPLEVEL *toplevel, int world_centerx,
419 int world_centery, OBJECT *object)
421 /* translate object to origin */
422 o_line_translate_world(toplevel, -world_centerx, -world_centery, object);
424 /* mirror the line ends */
425 object->line->x[0] = -object->line->x[0];
426 object->line->x[1] = -object->line->x[1];
428 /* translate back in position */
429 o_line_translate_world(toplevel, world_centerx, world_centery, object);
433 /*! \brief Recalculate line coordinates in SCREEN units.
434 * \par Function Description
435 * This function recalculate the bounding box of the <B>o_current</B>
437 * \param [in] toplevel The TOPLEVEL object.
438 * \param [in,out] o_current Line OBJECT to be recalculated.
440 void o_line_recalc(TOPLEVEL *toplevel, OBJECT *o_current)
442 int left, right, top, bottom;
444 if (o_current->line == NULL) {
445 return;
448 /* update the bounding box - screen unit */
449 world_get_line_bounds(toplevel, o_current,
450 &left, &top, &right, &bottom);
451 o_current->w_left = left;
452 o_current->w_top = top;
453 o_current->w_right = right;
454 o_current->w_bottom = bottom;
455 o_current->w_bounds_valid = TRUE;
458 /*! \brief Get line bounding rectangle in WORLD coordinates.
459 * \par Function Description
460 * This function sets the <B>left</B>, <B>top</B>, <B>right</B> and
461 * <B>bottom</B> parameters to the boundings of the line object described
462 * in <B>*line</B> in world units.
464 * \param [in] toplevel The TOPLEVEL object.
465 * \param [in] object Line OBJECT to read coordinates from.
466 * \param [out] left Left line coordinate in WORLD units.
467 * \param [out] top Top line coordinate in WORLD units.
468 * \param [out] right Right line coordinate in WORLD units.
469 * \param [out] bottom Bottom line coordinate in WORLD units.
471 void world_get_line_bounds(TOPLEVEL *toplevel, OBJECT *object,
472 int *left, int *top, int *right, int *bottom)
474 int halfwidth;
476 halfwidth = object->line_width / 2;
478 *left = min( object->line->x[0], object->line->x[1] );
479 *top = min( object->line->y[0], object->line->y[1] );
480 *right = max( object->line->x[0], object->line->x[1] );
481 *bottom = max( object->line->y[0], object->line->y[1] );
483 /* This isn't strictly correct, but a 1st order approximation */
484 *left -= halfwidth;
485 *top -= halfwidth;
486 *right += halfwidth;
487 *bottom += halfwidth;
490 /*! \brief get the position of the first line point
491 * \par Function Description
492 * This function gets the position of the first point of a line object.
494 * \param [in] toplevel The toplevel environment.
495 * \param [out] x pointer to the x-position
496 * \param [out] y pointer to the y-position
497 * \param [in] object The object to get the position.
498 * \return TRUE if successfully determined the position, FALSE otherwise
500 gboolean o_line_get_position (TOPLEVEL *toplevel, gint *x, gint *y,
501 OBJECT *object)
503 *x = object->line->x[0];
504 *y = object->line->y[0];
505 return TRUE;
509 /*! \brief Print line to Postscript document.
510 * \par Function Description
511 * This function prints the line described by the <B>o_current</B>
512 * parameter to a Postscript document.
513 * The Postscript document is described by the <B>fp</B> file pointer.
515 * Parameters of the line are extracted from object pointed by
516 * <B>o_current</B>.
518 * \param [in] toplevel The TOPLEVEL object.
519 * \param [in] fp FILE pointer to Postscript document.
520 * \param [in] o_current Line OBJECT to write to document.
521 * \param [in] origin_x Page x coordinate to place line OBJECT.
522 * \param [in] origin_y Page y coordinate to place line OBJECT.
524 void o_line_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current,
525 int origin_x, int origin_y)
527 int x1, y1, x2, y2;
528 int color;
529 int line_width, length, space;
530 void (*outl_func)() = NULL;
532 if (o_current == NULL) {
533 printf("got null in o_line_print\n");
534 return;
537 x1 = o_current->line->x[0];
538 y1 = o_current->line->y[0];
539 x2 = o_current->line->x[1];
540 y2 = o_current->line->y[1];
541 color = o_current->color;
544 * Depending on the type of the line for this particular line, the
545 * appropriate function is chosen among
546 * #o_line_print_solid(), #o_line_print_dotted()#, #o_line_print_dashed(),
547 * #o_line_print_center() and #o_line_print_phantom().
549 * The needed parameters for each of these types are extracted from the
550 * <B>o_current</B> object. Depending on the type, unused parameters are
551 * set to -1.
553 * In the eventuality of a length and/or space null, the line is printed
554 * solid to avoid and endless loop produced by other functions.
556 line_width = o_current->line_width;
557 if(line_width <=2) {
558 if(toplevel->line_style == THICK) {
559 line_width=LINE_WIDTH;
560 } else {
561 line_width=2;
565 length = o_current->line_length;
566 space = o_current->line_space;
568 switch(o_current->line_type) {
569 case(TYPE_SOLID):
570 length = -1; space = -1;
571 outl_func = o_line_print_solid;
572 break;
574 case(TYPE_DOTTED):
575 length = -1;
576 outl_func = o_line_print_dotted;
577 break;
579 case(TYPE_DASHED):
580 outl_func = o_line_print_dashed;
581 break;
583 case(TYPE_CENTER):
584 outl_func = o_line_print_center;
585 break;
587 case(TYPE_PHANTOM):
588 outl_func = o_line_print_phantom;
589 break;
591 case(TYPE_ERASE):
592 /* Unused for now, print it solid */
593 length = -1; space = -1;
594 outl_func = o_line_print_solid;
595 break;
598 if((length == 0) || (space == 0)) {
599 length = -1; space = -1;
600 outl_func = o_line_print_solid;
603 (*outl_func)(toplevel, fp,
604 x1 - origin_x, y1 - origin_y,
605 x2 - origin_x, y2 - origin_y,
606 color,
607 line_width, length, space,
608 origin_x, origin_y);
611 /*! \brief Print a solid line to Postscript document.
612 * \par Function Description
613 * This function prints a line when a solid line type is required.
614 * The line is defined by the coordinates of its two ends in
615 * (<B>x1</B>,<B>y1</B>) and (<B>x2</B>,<B>y2</B>).
616 * The Postscript document is defined by the file pointer <B>fp</B>.
617 * The parameters <B>length</B> and <B>space</B> are ignored whereas
618 * <B>line_width</B> specifies the width of the printed line.
620 * \param [in] toplevel The TOPLEVEL object.
621 * \param [in] fp FILE pointer to Postscript document.
622 * \param [in] x1 Upper x coordinate.
623 * \param [in] y1 Upper y coordinate.
624 * \param [in] x2 Lower x coordinate.
625 * \param [in] y2 Lower y coordinate.
626 * \param [in] color Line color.
627 * \param [in] line_width Width of line.
628 * \param [in] length (unused).
629 * \param [in] space (unused).
630 * \param [in] origin_x Page x coordinate to place line OBJECT.
631 * \param [in] origin_y Page y coordinate to place line OBJECT.
633 void o_line_print_solid(TOPLEVEL *toplevel, FILE *fp,
634 int x1, int y1, int x2, int y2,
635 int color,
636 int line_width, int length, int space,
637 int origin_x, int origin_y)
639 f_print_set_color(toplevel, fp, color);
641 fprintf(fp,"%d %d %d %d %d line\n",
642 x1,y1,x2,y2, line_width);
645 /*! \brief Print a dotted line to Postscript document.
646 * \par Function Description
647 * This function prints a line when a dotted line type is required.
648 * The line is defined by the coordinates of its two ends in
649 * (<B>x1</B>,<B>y1</B>) and (<B>x2</B>,<B>y2</B>).
650 * The Postscript document is defined by the file pointer <B>fp</B>.
651 * The parameter <B>length</B> is ignored whereas <B>line_width</B>
652 * specifies the diameter of the dots and <B>space</B> the distance
653 * between two dots.
655 * A negative value for <B>space</B> leads to an endless loop.
657 * All dimensions are in mils.
659 * The function sets the color in which the line will be printed with.
661 * \param [in] toplevel The TOPLEVEL object.
662 * \param [in] fp FILE pointer to Postscript document.
663 * \param [in] x1 Upper x coordinate.
664 * \param [in] y1 Upper y coordinate.
665 * \param [in] x2 Lower x coordinate.
666 * \param [in] y2 Lower y coordinate.
667 * \param [in] color Line color.
668 * \param [in] line_width Width of line.
669 * \param [in] length (unused).
670 * \param [in] space Space between dots.
671 * \param [in] origin_x Page x coordinate to place line OBJECT.
672 * \param [in] origin_y Page y coordinate to place line OBJECT.
674 void o_line_print_dotted(TOPLEVEL *toplevel, FILE *fp,
675 int x1, int y1, int x2, int y2,
676 int color,
677 int line_width, int length, int space,
678 int origin_x, int origin_y)
680 double dx, dy, l, d;
681 double dx1, dy1;
682 double xa, ya;
684 f_print_set_color(toplevel, fp, color);
686 /* The dotted line command takes an array of dots so print out the
687 * beginnings of the array
689 fprintf(fp,"[");
690 /* is the width relevant for a dot (circle) ? */
691 /* f_print_set_line_width(fp, line_width); */
694 * Depending on the slope of the line the space parameter is
695 * projected on each of the two directions x and y resulting
696 * in <B>dx1</B> and <B>dy1</B>. Starting from one end by increments
697 * of space the dots are printed.
699 * A dot is represented by a filled circle. Position of the
700 * circle is (<B>xa</B>, <B>ya</B>) and its radius is the <B>line_width</B>
701 * parameter.
704 dx = (double) (x2 - x1);
705 dy = (double) (y2 - y1);
706 l = sqrt((dx * dx) + (dy * dy));
708 dx1 = (dx * space) / l;
709 dy1 = (dy * space) / l;
711 d = 0;
712 xa = x1; ya = y1;
713 while(d < l) {
715 fprintf(fp,"[%d %d] ",
716 (int)xa, (int)ya);
717 d = d + space;
718 xa = xa + dx1;
719 ya = ya + dy1;
722 fprintf(fp,"] %d dashed\n",line_width);
727 /*! \brief Print a dashed line to Postscript document.
728 * \par Function Description
729 * This function prints a line when a dashed line type is required.
730 * The line is defined by the coordinates of its two ends in
731 * (<B>x1</B>,<B>y1</B>) and (<B>x2</B>,<B>y2</B>).
732 * The postscript file is defined by the file pointer <B>fp</B>.
734 * A negative value for <B>space</B> or <B>length</B> leads to an
735 * endless loop.
737 * All dimensions are in mils.
739 * The function sets the color in which the line will be printed and
740 * the width of the line - that is the width of the dashes.
742 * \param [in] toplevel The TOPLEVEL object.
743 * \param [in] fp FILE pointer to Postscript document.
744 * \param [in] x1 Upper x coordinate.
745 * \param [in] y1 Upper y coordinate.
746 * \param [in] x2 Lower x coordinate.
747 * \param [in] y2 Lower y coordinate.
748 * \param [in] color Line color.
749 * \param [in] line_width Width of line.
750 * \param [in] length Length of a dash.
751 * \param [in] space Space between dashes.
752 * \param [in] origin_x Page x coordinate to place line OBJECT.
753 * \param [in] origin_y Page y coordinate to place line OBJECT.
755 void o_line_print_dashed(TOPLEVEL *toplevel, FILE *fp,
756 int x1, int y1, int x2, int y2,
757 int color,
758 int line_width, int length, int space,
759 int origin_x, int origin_y)
761 double dx, dy, l, d;
762 double dx1, dy1, dx2, dy2;
763 double xa, ya, xb, yb;
765 f_print_set_color(toplevel, fp, color);
767 /* the dashed line function takes an array of start-finish pairs
768 * output the beginnings of the array now
770 fprintf(fp,"[");
773 * Depending on the slope of the line the <B>length</B> (resp. <B>space</B>)
774 * parameter is projected on each of the two directions x and y
775 * resulting in <B>dx1</B> and <B>dy1</B> (resp. <B>dx2</B> and <B>dy2</B>).
776 * Starting from one end and incrementing alternatively by <B>space</B>
777 * and <B>length</B> the dashes are printed.
779 * It prints as many dashes of length <B>length</B> as possible.
781 dx = (double) (x2 - x1);
782 dy = (double) (y2 - y1);
783 l = sqrt((dx * dx) + (dy * dy));
785 dx1 = (dx * length) / l;
786 dy1 = (dy * length) / l;
788 dx2 = (dx * space) / l;
789 dy2 = (dy * space) / l;
791 d = 0;
792 xa = x1; ya = y1;
793 while((d + length + space) < l) {
794 d = d + length;
795 xb = xa + dx1;
796 yb = ya + dy1;
798 fprintf(fp, "[%d %d %d %d] ",
799 (int) xa, (int) ya,
800 (int) xb, (int) yb);
802 d = d + space;
803 xa = xb + dx2;
804 ya = yb + dy2;
807 * When the above condition is no more satisfied, then it is not possible
808 * to print a dash of length <B>length</B>. However it may be possible to
809 * print the complete dash or a shorter one.
812 if((d + length) < l) {
813 d = d + length;
814 xb = xa + dx1;
815 yb = ya + dy1;
816 } else {
817 xb = x2;
818 yb = y2;
821 fprintf(fp, "[%d %d %d %d] ",
822 (int) xa, (int) ya,
823 (int) xb, (int) yb);
825 fprintf(fp,"] %d dashed\n", line_width);
829 /*! \brief Print a centered line type line to Postscript document.
830 * \par Function Description
831 * This function prints a line when a centered line type is required.
832 * The line is defined by the coordinates of its two ends in
833 * (<B>x1</B>,<B>y1</B>) and (<B>x2</B>,<B>y2</B>).
834 * The Postscript document is defined by the file pointer <B>fp</B>.
836 * A negative value for <B>space</B> or <B>length</B> leads to an
837 * endless loop.
839 * All dimensions are in mils.
841 * The function sets the color in which the line will be printed and the
842 * width of the line - that is the width of the dashes and the diameter
843 * of the dots.
845 * \param [in] toplevel The TOPLEVEL object.
846 * \param [in] fp FILE pointer to Postscript document.
847 * \param [in] x1 Upper x coordinate.
848 * \param [in] y1 Upper y coordinate.
849 * \param [in] x2 Lower x coordinate.
850 * \param [in] y2 Lower y coordinate.
851 * \param [in] color Line color.
852 * \param [in] line_width Width of line.
853 * \param [in] length Length of a dash.
854 * \param [in] space Space between dashes.
855 * \param [in] origin_x Page x coordinate to place line OBJECT.
856 * \param [in] origin_y Page y coordinate to place line OBJECT.
858 void o_line_print_center(TOPLEVEL *toplevel, FILE *fp,
859 int x1, int y1, int x2, int y2,
860 int color,
861 int line_width, int length, int space,
862 int origin_x, int origin_y)
864 double dx, dy, l, d;
865 double dx1, dy1, dx2, dy2;
866 double xa, ya, xb, yb;
868 f_print_set_color(toplevel, fp, color);
870 fprintf(fp, "[");
873 * Depending on the slope of the line the <B>length</B> (resp. <B>space</B>)
874 * parameter is projected on each of the two directions x and y resulting
875 * in <B>dx1</B> and <B>dy1</B> (resp. <B>dx2</B> and <B>dy2</B>).
876 * Starting from one end and incrementing alternatively by <B>space</B>
877 * and <B>length</B> the dashes and dots are printed.
879 * It prints as many sets of dash and dot as possible.
881 dx = (double) (x2 - x1);
882 dy = (double) (y2 - y1);
883 l = sqrt((dx * dx) + (dy * dy));
885 dx1 = (dx * length) / l;
886 dy1 = (dy * length) / l;
888 dx2 = (dx * space) / l;
889 dy2 = (dy * space) / l;
891 d = 0;
892 xa = x1; ya = y1;
893 while((d + length + 2 * space) < l) {
894 d = d + length;
895 xb = xa + dx1;
896 yb = ya + dy1;
898 fprintf(fp, "[%d %d %d %d] ",
899 (int) xa, (int) ya,
900 (int) xb, (int) yb);
902 d = d + space;
903 xa = xb + dx2;
904 ya = yb + dy2;
906 fprintf(fp,"[%d %d] ",(int) xa, (int) ya);
908 d = d + space;
909 xa = xa + dx2;
910 ya = ya + dy2;
913 * When the above condition is no more satisfied, then it is not possible
914 * to print a dash of length <B>length</B>.
915 * However two cases are possible :
916 * <DL>
917 * <DT>*</DT><DD>it is possible to print the dash and the dot.
918 * <DT>*</DT><DD>it is possible to print the dash or a part
919 * of the original dash.
920 * </DL>
923 if((d + length + space) < l) {
924 d = d + length;
925 xb = xa + dx1;
926 yb = ya + dy1;
928 fprintf(fp, "[%d %d %d %d] ",
929 (int) xa, (int) ya,
930 (int) xb, (int) yb);
932 d = d + space;
933 xa = xb + dx2;
934 ya = yb + dy2;
936 fprintf(fp,"[%d %d] ",(int) xa, (int) ya);
938 } else {
939 if(d + length < l) {
940 xb = xa + dx1;
941 yb = ya + dy1;
942 } else {
943 xb = x2;
944 yb = y2;
947 fprintf(fp, "[%d %d %d %d] ",
948 (int) xa, (int) ya,
949 (int) xb, (int) yb);
953 fprintf(fp,"] %d dashed\n", line_width);
956 * A dot is represented by a filled circle. Position of the circle is
957 * (<B>xa</B>, <B>ya</B>) and its radius by the <B>line_width</B> parameter.
961 /*! \brief Print a phantom line type line to Postscript document.
962 * \par Function Description
963 * This function prints a line when a phantom line type is required.
964 * The line is defined by the coordinates of its two ends in
965 * (<B>x1</B>,<B>y1</B>) and (<B>x2</B>,<B>y2</B>).
966 * The Postscript document is defined by the file pointer <B>fp</B>.
968 * A negative value for <B>space</B> or <B>length</B> leads to an
969 * endless loop.
971 * All dimensions are in mils.
973 * The function sets the color in which the line will be printed and the
974 * width of the line - that is the width of the dashes and the diameter
975 * of the dots.
977 * \param [in] toplevel The TOPLEVEL object.
978 * \param [in] fp FILE pointer to Postscript document.
979 * \param [in] x1 Upper x coordinate.
980 * \param [in] y1 Upper y coordinate.
981 * \param [in] x2 Lower x coordinate.
982 * \param [in] y2 Lower y coordinate.
983 * \param [in] color Line color.
984 * \param [in] line_width Width of line.
985 * \param [in] length Length of a dash.
986 * \param [in] space Space between dashes.
987 * \param [in] origin_x Page x coordinate to place line OBJECT.
988 * \param [in] origin_y Page y coordinate to place line OBJECT.
990 void o_line_print_phantom(TOPLEVEL *toplevel, FILE *fp,
991 int x1, int y1, int x2, int y2,
992 int color,
993 int line_width, int length, int space,
994 int origin_x, int origin_y)
996 double dx, dy, l, d;
997 double dx1, dy1, dx2, dy2;
998 double xa, ya, xb, yb;
1000 f_print_set_color(toplevel, fp, color);
1002 fprintf(fp,"[");
1005 * Depending on the slope of the line the <B>length</B> (resp. <B>space</B>)
1006 * parameter is projected on each of the two directions x and y resulting
1007 * in <B>dx1</B> and <B>dy1</B> (resp. <B>dx2</B> and <B>dy2</B>).
1008 * Starting from one end and incrementing alternatively by <B>space</B>
1009 * and <B>length</B> the dashes and dots are printed.
1011 * It prints as many sets of dash-dot-dot as possible.
1013 dx = (double) (x2 - x1);
1014 dy = (double) (y2 - y1);
1015 l = sqrt((dx * dx) + (dy * dy));
1017 dx1 = (dx * length) / l;
1018 dy1 = (dy * length) / l;
1020 dx2 = (dx * space) / l;
1021 dy2 = (dy * space) / l;
1023 d = 0;
1024 xa = x1; ya = y1;
1025 while((d + length + 3 * space) < l) {
1026 d = d + length;
1027 xb = xa + dx1;
1028 yb = ya + dy1;
1030 fprintf(fp,"[%d %d %d %d] ",
1031 (int) xa, (int)ya,
1032 (int) xb, (int)yb);
1034 d = d + space;
1035 xa = xb + dx2;
1036 ya = yb + dy2;
1038 fprintf(fp,"[%d %d] ",(int) xa, (int) ya);
1040 d = d + space;
1041 xa = xa + dx2;
1042 ya = ya + dy2;
1044 fprintf(fp,"[%d %d] ",(int) xa, (int) ya);
1046 d = d + space;
1047 xa = xa + dx2;
1048 ya = ya + dy2;
1051 * When the above condition is no more satisfied, then it is not possible
1052 * to print a complete set of dash-dot-dot.
1053 * However three cases are possible :
1054 * <DL>
1055 * <DT>*</DT><DD>it is possible to print a dash and a dot and a dot.
1056 * <DT>*</DT><DD>it is possible to print a dash and a dot.
1057 * <DT>*</DT><DD>it is possible to print the dash or a part
1058 * of the original dash.
1059 * </DL>
1062 if((d + length + 2 * space) < l) {
1063 d = d + length;
1064 xb = xa + dx1;
1065 yb = ya + dy1;
1067 fprintf(fp,"[%d %d %d %d] ",
1068 (int) xa, (int)ya,
1069 (int) xb, (int)yb);
1071 d = d + space;
1072 xa = xb + dx2;
1073 ya = yb + dy2;
1075 fprintf(fp,"[%d %d] ",(int) xa, (int)ya);
1077 d = d + space;
1078 xa = xb + dx2;
1079 ya = yb + dy2;
1081 fprintf(fp,"[%d %d] ",(int) xa, (int)ya);
1083 } else {
1084 if(d + length + space < l) {
1085 d = d + length;
1086 xb = xa + dx1;
1087 yb = ya + dy1;
1089 fprintf(fp,"[%d %d %d %d] ",
1090 (int) xa, (int)ya,
1091 (int) xb, (int)yb);
1093 d = d + space;
1094 xa = xb + dx2;
1095 ya = yb + dy2;
1097 fprintf(fp,"[%d %d] ",(int) xa, (int)ya);
1099 } else {
1100 if(d + length < l) {
1101 xb = xa + dx1;
1102 yb = ya + dy1;
1103 } else {
1104 xb = x2;
1105 yb = y2;
1108 fprintf(fp,"[%d %d %d %d] ",
1109 (int) xa, (int)ya,
1110 (int) xb, (int)yb);
1115 fprintf(fp,"] %d dashed\n", line_width);
1119 /*! \brief
1120 * \par Function Description
1122 * \param [in] toplevel The TOPLEVEL object.
1123 * \param [in] x_scale
1124 * \param [in] y_scale
1125 * \param [in] object
1127 void o_line_scale_world(TOPLEVEL *toplevel, int x_scale, int y_scale,
1128 OBJECT *object)
1130 if (object == NULL) printf("lsw NO!\n");
1132 /* scale the line world coords */
1133 object->line->x[0] = object->line->x[0] * x_scale;
1134 object->line->y[0] = object->line->y[0] * y_scale;
1135 object->line->x[1] = object->line->x[1] * x_scale;
1136 object->line->y[1] = object->line->y[1] * y_scale;
1138 /* update boundingbox */
1139 o_line_recalc(toplevel, object);
1144 /*! \brief calculate the lenght of a line object
1145 * \par Function Description
1146 * This function calculates the length of a line object
1148 * \param [in] object a line OBJECT
1149 * \return The length of the line
1151 double o_line_length(OBJECT *object)
1153 double length;
1154 double dx, dy;
1156 if (!object->line) {
1157 return 0.0;
1160 dx = object->line->x[0]-object->line->x[1];
1161 dy = object->line->y[0]-object->line->y[1];
1163 length = sqrt((dx*dx) + (dy*dy));
1165 return(length);
1168 /*! \brief Calculates the distance between the given point and the closest
1169 * point on the given line segment.
1171 * If the closest point on the line resides beyond the line segment's
1172 * end point, this function returns the distance from the given point to the
1173 * closest end point.
1175 * If the line represents a single point (the endpoints are the same), this
1176 * function calcualtes the distance to that point.
1178 * \param [in] object The line OBJECT.
1179 * \param [in] x The x coordinate of the given point.
1180 * \param [in] y The y coordinate of the given point.
1181 * \param [in] force_solid If true, force treating the object as solid.
1182 * \return The shortest distance from the object to the point. With an
1183 * invalid parameter, this function returns G_MAXDOUBLE.
1185 double o_line_shortest_distance (OBJECT *object, int x, int y, int force_solid)
1187 return m_line_shortest_distance (object->line, x, y);