libgeda

o_line_basic.c

Go to the documentation of this file.
00001 /* gEDA - GPL Electronic Design Automation
00002  * libgeda - gEDA's library
00003  * Copyright (C) 1998-2010 Ales Hvezda
00004  * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  */
00020 
00025 #include <config.h>
00026 
00027 #include <stdio.h>
00028 #include <math.h>
00029 
00030 #include "libgeda_priv.h"
00031 
00032 #ifdef HAVE_LIBDMALLOC
00033 #include <dmalloc.h>
00034 #endif
00035 
00064 OBJECT *o_line_new(TOPLEVEL *toplevel,
00065            char type, int color, 
00066            int x1, int y1, int x2, int y2)
00067 {
00068   OBJECT *new_node;
00069 
00070   /* create the object */
00071   new_node = s_basic_new_object(type, "line");
00072   new_node->color = color;
00073   
00074   new_node->line  = (LINE *) g_malloc(sizeof(LINE));
00075   
00076   /* describe the line with its two ends */
00077   new_node->line->x[0] = x1;
00078   new_node->line->y[0] = y1;
00079   new_node->line->x[1] = x2;
00080   new_node->line->y[1] = y2;
00081   
00082   /* line type and filling initialized to default */
00083   o_set_line_options(toplevel, new_node,
00084              END_NONE, TYPE_SOLID, 0, -1, -1);
00085   o_set_fill_options(toplevel, new_node,
00086              FILLING_HOLLOW, -1, -1, -1, -1, -1);
00087 
00088   /* compute bounding box */
00089   o_line_recalc(toplevel, new_node);
00090 
00091   return new_node;
00092 }
00093 
00103 OBJECT *o_line_copy(TOPLEVEL *toplevel, OBJECT *o_current)
00104 {
00105   OBJECT *new_obj;
00106 
00107   /* A new line object is created with #o_line_new().
00108    * Values for its fields are default and need to be modified. */
00109   new_obj = o_line_new (toplevel, OBJ_LINE, o_current->color,
00110                         o_current->line->x[0], o_current->line->y[0],
00111                         o_current->line->x[1], o_current->line->y[1]);
00112 
00113   /*
00114    * The coordinates of the ends of the new line are set with the ones
00115    * of the original line. The two lines have the sale line type and
00116    * filling options.
00117    *
00118    * The bounding box are computed with
00119    * #o_line_recalc().
00120    */
00121 
00122   /* copy the line type and filling options */
00123   o_set_line_options(toplevel, new_obj, o_current->line_end,
00124              o_current->line_type, o_current->line_width,
00125              o_current->line_length, o_current->line_space);
00126   o_set_fill_options(toplevel, new_obj,
00127              o_current->fill_type, o_current->fill_width,
00128              o_current->fill_pitch1, o_current->fill_angle1,
00129              o_current->fill_pitch2, o_current->fill_angle2);
00130   
00131   /* calc the bounding box */
00132   o_line_recalc(toplevel, o_current);
00133   
00134   /* new_obj->attribute = 0;*/
00135 
00136   /* return the new tail of the object list */
00137   return new_obj;
00138 }
00139 
00162 void o_line_modify(TOPLEVEL *toplevel, OBJECT *object,
00163                    int x, int y, int whichone)
00164 {
00165   o_emit_pre_change_notify (toplevel, object);
00166 
00167   /* change one of the end of the line */
00168   switch (whichone) {
00169     case LINE_END1:
00170       object->line->x[0] = x;
00171       object->line->y[0] = y;
00172       break;
00173 
00174     case LINE_END2:
00175       object->line->x[1] = x;
00176       object->line->y[1] = y;
00177       break;
00178 
00179     default:
00180       return;
00181   }
00182 
00183   /* recalculate the bounding box */
00184   o_line_recalc(toplevel, object);
00185   o_emit_change_notify (toplevel, object);
00186 }
00187 
00209 OBJECT *o_line_read (TOPLEVEL *toplevel, const char buf[],
00210                      unsigned int release_ver, unsigned int fileformat_ver, GError ** err)
00211 {
00212   OBJECT *new_obj;
00213   char type;
00214   int x1, y1;
00215   int x2, y2;
00216   int line_width, line_space, line_length;
00217   int line_end;
00218   int line_type;
00219   int color;
00220 
00221   if (release_ver <= VERSION_20000704) {
00222     /*
00223      * The old geda file format, i.e. releases 20000704 and older, does
00224      * not handle the line type and the filling - here filling is irrelevant.
00225      * They are set to default.
00226      */
00227     if (sscanf (buf, "%c %d %d %d %d %d\n", &type,
00228         &x1, &y1, &x2, &y2, &color) != 6) {
00229       g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse line object"));
00230       return NULL;
00231     }
00232 
00233     line_width = 0;
00234     line_end   = END_NONE;
00235     line_type  = TYPE_SOLID;
00236     line_length= -1;
00237     line_space = -1;
00238   } else {
00239     /*
00240      * The current line format to describe a line is a space separated
00241      * list of characters and numbers in plain ASCII on a single line.
00242      * The meaning of each item is described in the file format documentation.
00243      */
00244       if (sscanf (buf, "%c %d %d %d %d %d %d %d %d %d %d\n", &type,
00245           &x1, &y1, &x2, &y2, &color,
00246           &line_width, &line_end, &line_type, &line_length, &line_space) != 11) {
00247         g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse line object"));
00248         return NULL;
00249       }
00250   }
00251 
00252   /*
00253    * Null length line are not allowed. If such a line is detected a
00254    * message is issued.
00255    *
00256    * It also checks is the required color is valid.
00257    */
00258   if (x1 == x2 && y1 == y2) {
00259     s_log_message (_("Found a zero length line [ %c %d %d %d %d %d ]\n"),
00260                    type, x1, y1, x2, y2, color);
00261   }
00262 
00263   if (color < 0 || color > MAX_COLORS) {
00264     s_log_message (_("Found an invalid color [ %s ]\n"), buf);
00265     s_log_message (_("Setting color to default color\n"));
00266     color = DEFAULT_COLOR;
00267   }
00268 
00269   /*
00270    * A line is internally described by its two ends. A new object is
00271    * allocated, initialized and added to the list of objects. Its line
00272    * type is set according to the values of the fields on the line.
00273    */
00274   /* create and add the line to the list */
00275   new_obj = o_line_new (toplevel, type, color, x1, y1, x2, y2);
00276   /* set its line options */
00277   o_set_line_options (toplevel, new_obj,
00278                       line_end, line_type, line_width, line_length,
00279                       line_space);
00280   /* filling is irrelevant for line, just set to default */
00281   o_set_fill_options (toplevel, new_obj,
00282                       FILLING_HOLLOW, -1, -1, -1, -1, -1);
00283 
00284   return new_obj;
00285 }
00286 
00302 char *o_line_save(TOPLEVEL *toplevel, OBJECT *object)
00303 {
00304   int x1, x2, y1, y2;
00305   int line_width, line_space, line_length;
00306   char *buf;
00307   OBJECT_END line_end;
00308   OBJECT_TYPE line_type;
00309 
00310   /* get the two ends */
00311   x1 = object->line->x[0];
00312   y1 = object->line->y[0];
00313   x2 = object->line->x[1];
00314   y2 = object->line->y[1];
00315   
00316   /* description of the line type */
00317   line_width = object->line_width;
00318   line_end   = object->line_end;
00319   line_type  = object->line_type;
00320   line_length= object->line_length;
00321   line_space = object->line_space;
00322   
00323   buf = g_strdup_printf("%c %d %d %d %d %d %d %d %d %d %d", object->type,
00324             x1, y1, x2, y2, object->color,
00325             line_width, line_end, line_type,
00326             line_length, line_space);
00327 
00328   return(buf);
00329 }
00330 
00341 void o_line_translate_world(TOPLEVEL *toplevel,
00342                 int dx, int dy, OBJECT *object)
00343 {
00344   /* Update world coords */
00345   object->line->x[0] = object->line->x[0] + dx;
00346   object->line->y[0] = object->line->y[0] + dy;
00347   object->line->x[1] = object->line->x[1] + dx;
00348   object->line->y[1] = object->line->y[1] + dy;
00349   
00350   /* Update bounding box */
00351   o_line_recalc (toplevel, object);
00352 }
00353 
00367 void o_line_rotate_world(TOPLEVEL *toplevel,
00368              int world_centerx, int world_centery, int angle,
00369              OBJECT *object)
00370 {
00371   int newx, newy;
00372     
00373   if (angle == 0) 
00374     return;
00375 
00376   /* angle must be positive */
00377   if(angle < 0) angle = -angle;
00378   /* angle must be 90 multiple or no rotation performed */
00379   if((angle % 90) != 0) return;
00380 
00381   /*
00382    * The center of rotation (<B>world_centerx</B>,<B>world_centery</B>)
00383    * is translated to the origin. The rotation of the two ends of
00384    * the line is performed. FInally, the rotated line is translated
00385    * back to its previous location.
00386    */
00387   /* translate object to origin */
00388   o_line_translate_world(toplevel, -world_centerx, -world_centery, object);
00389 
00390   /* rotate line end 1 */
00391   rotate_point_90(object->line->x[0], object->line->y[0], angle,
00392           &newx, &newy);
00393 
00394   object->line->x[0] = newx;
00395   object->line->y[0] = newy;
00396   
00397   /* rotate line end 2 */
00398   rotate_point_90(object->line->x[1], object->line->y[1], angle,
00399           &newx, &newy);
00400   
00401   object->line->x[1] = newx;
00402   object->line->y[1] = newy;
00403 
00404   /* translate object back to normal position */
00405   o_line_translate_world(toplevel, world_centerx, world_centery, object);
00406   
00407 }
00408 
00422 void o_line_mirror_world(TOPLEVEL *toplevel, int world_centerx,
00423              int world_centery, OBJECT *object)
00424 {
00425   /* translate object to origin */
00426   o_line_translate_world(toplevel, -world_centerx, -world_centery, object);
00427 
00428   /* mirror the line ends */
00429   object->line->x[0] = -object->line->x[0];
00430   object->line->x[1] = -object->line->x[1];
00431 
00432   /* translate back in position */
00433   o_line_translate_world(toplevel, world_centerx, world_centery, object);
00434   
00435 }
00436 
00444 void o_line_recalc(TOPLEVEL *toplevel, OBJECT *o_current)
00445 {
00446   int left, right, top, bottom;
00447 
00448   if (o_current->line == NULL) {
00449     return;
00450   }
00451   
00452   /* update the bounding box - screen unit */
00453   world_get_line_bounds(toplevel, o_current,
00454           &left, &top, &right, &bottom);
00455   o_current->w_left   = left;
00456   o_current->w_top    = top;
00457   o_current->w_right  = right;
00458   o_current->w_bottom = bottom;
00459   o_current->w_bounds_valid = TRUE;
00460 }
00461 
00475 void world_get_line_bounds(TOPLEVEL *toplevel, OBJECT *object,
00476                            int *left, int *top, int *right, int *bottom)
00477 {
00478   int halfwidth;
00479 
00480   halfwidth = object->line_width / 2;
00481 
00482   *left = min( object->line->x[0], object->line->x[1] );
00483   *top = min( object->line->y[0], object->line->y[1] );
00484   *right = max( object->line->x[0], object->line->x[1] );
00485   *bottom = max( object->line->y[0], object->line->y[1] );
00486 
00487   /* This isn't strictly correct, but a 1st order approximation */
00488   *left   -= halfwidth;
00489   *top    -= halfwidth;
00490   *right  += halfwidth;
00491   *bottom += halfwidth;
00492 }
00493 
00504 gboolean o_line_get_position (TOPLEVEL *toplevel, gint *x, gint *y,
00505                               OBJECT *object)
00506 {
00507   *x = object->line->x[0];
00508   *y = object->line->y[0];
00509   return TRUE;
00510 }
00511 
00512 
00528 void o_line_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current,
00529           int origin_x, int origin_y)
00530 {
00531   int x1, y1, x2, y2;
00532   int color;
00533   int line_width, length, space;
00534   void (*outl_func)() = NULL;
00535     
00536   if (o_current == NULL) {
00537     printf("got null in o_line_print\n");
00538     return;
00539   }
00540 
00541   x1    = o_current->line->x[0];
00542   y1    = o_current->line->y[0];
00543   x2    = o_current->line->x[1];
00544   y2    = o_current->line->y[1];
00545   color = o_current->color;
00546 
00547   /*
00548    * Depending on the type of the line for this particular line, the
00549    * appropriate function is chosen among
00550    * #o_line_print_solid(), #o_line_print_dotted()#, #o_line_print_dashed(),
00551    * #o_line_print_center() and #o_line_print_phantom().
00552    *
00553    * The needed parameters for each of these types are extracted from the
00554    * <B>o_current</B> object. Depending on the type, unused parameters are
00555    * set to -1.
00556    *
00557    * In the eventuality of a length and/or space null, the line is printed
00558    * solid to avoid and endless loop produced by other functions.
00559    */
00560   line_width = o_current->line_width;
00561   if(line_width <=2) {
00562     if(toplevel->line_style == THICK) {
00563       line_width=LINE_WIDTH;
00564     } else {
00565       line_width=2;
00566     }
00567   }
00568 
00569   length = o_current->line_length;
00570   space  = o_current->line_space;
00571   
00572   switch(o_current->line_type) {
00573     case(TYPE_SOLID):
00574       length = -1; space = -1;
00575       outl_func = o_line_print_solid;
00576       break;
00577       
00578     case(TYPE_DOTTED):
00579       length = -1;
00580       outl_func = o_line_print_dotted;
00581       break;
00582       
00583     case(TYPE_DASHED):
00584       outl_func = o_line_print_dashed;
00585       break;
00586       
00587     case(TYPE_CENTER):
00588       outl_func = o_line_print_center;
00589       break;
00590       
00591     case(TYPE_PHANTOM):
00592       outl_func = o_line_print_phantom;
00593       break;
00594       
00595     case(TYPE_ERASE):
00596       /* Unused for now, print it solid */
00597       length = -1; space = -1;
00598       outl_func =  o_line_print_solid;
00599       break;
00600   }
00601 
00602   if((length == 0) || (space == 0)) {
00603     length = -1; space = -1;
00604     outl_func = o_line_print_solid;
00605   }
00606   
00607   (*outl_func)(toplevel, fp,
00608            x1 - origin_x, y1 - origin_y,
00609            x2 - origin_x, y2 - origin_y,
00610            color,
00611            line_width, length, space,
00612            origin_x, origin_y);
00613 }
00614 
00637 void o_line_print_solid(TOPLEVEL *toplevel, FILE *fp,
00638             int x1, int y1, int x2, int y2,
00639             int color,
00640             int line_width, int length, int space,
00641             int origin_x, int origin_y)
00642 {
00643   f_print_set_color(toplevel, fp, color);
00644   
00645   fprintf(fp,"%d %d %d %d %d line\n",
00646       x1,y1,x2,y2, line_width);
00647 }
00648 
00678 void o_line_print_dotted(TOPLEVEL *toplevel, FILE *fp,
00679              int x1, int y1, int x2, int y2,
00680              int color,
00681              int line_width, int length, int space,
00682              int origin_x, int origin_y)
00683 {
00684   double dx, dy, l, d;
00685   double dx1, dy1;
00686   double xa, ya;
00687   
00688   f_print_set_color(toplevel, fp, color);
00689   
00690   /* The dotted line command takes an array of dots so print out the
00691    * beginnings of the array 
00692    */
00693   fprintf(fp,"[");
00694   /* is the width relevant for a dot (circle) ? */
00695   /* f_print_set_line_width(fp, line_width); */
00696   
00697   /*
00698    * Depending on the slope of the line the space parameter is
00699    * projected on each of the two directions x and y resulting
00700    * in <B>dx1</B> and <B>dy1</B>. Starting from one end by increments
00701    * of space the dots are printed.
00702    *
00703    * A dot is represented by a filled circle. Position of the
00704    * circle is (<B>xa</B>, <B>ya</B>) and its radius is the <B>line_width</B>
00705    * parameter.
00706    */
00707   
00708   dx = (double) (x2 - x1);
00709   dy = (double) (y2 - y1);
00710   l = sqrt((dx * dx) + (dy * dy));
00711   
00712   dx1 = (dx * space) / l;
00713   dy1 = (dy * space) / l;
00714   
00715   d = 0;
00716   xa = x1; ya = y1;
00717   while(d < l) {
00718     
00719     fprintf(fp,"[%d %d] ",
00720         (int)xa, (int)ya);
00721     d = d + space;
00722     xa = xa + dx1;
00723     ya = ya + dy1;
00724   }
00725   
00726   fprintf(fp,"] %d dashed\n",line_width);
00727   
00728 }
00729 
00730 
00759 void o_line_print_dashed(TOPLEVEL *toplevel, FILE *fp,
00760              int x1, int y1, int x2, int y2,
00761              int color,
00762              int line_width, int length, int space,
00763              int origin_x, int origin_y)
00764 {
00765   double dx, dy, l, d;
00766   double dx1, dy1, dx2, dy2;
00767   double xa, ya, xb, yb;
00768   
00769   f_print_set_color(toplevel, fp, color);
00770   
00771   /* the dashed line function takes an array of start-finish pairs
00772    * output the beginnings of the array now
00773    */
00774   fprintf(fp,"[");
00775   
00776   /*
00777    * Depending on the slope of the line the <B>length</B> (resp. <B>space</B>)
00778    * parameter is projected on each of the two directions x and y
00779    * resulting in <B>dx1</B> and <B>dy1</B> (resp. <B>dx2</B> and <B>dy2</B>).
00780    * Starting from one end and incrementing alternatively by <B>space</B>
00781    * and <B>length</B> the dashes are printed.
00782    *
00783    * It prints as many dashes of length <B>length</B> as possible.
00784    */
00785   dx = (double) (x2 - x1);
00786   dy = (double) (y2 - y1);
00787   l = sqrt((dx * dx) + (dy * dy));
00788   
00789   dx1 = (dx * length) / l;
00790   dy1 = (dy * length) / l;
00791   
00792   dx2 = (dx * space) / l;
00793   dy2 = (dy * space) / l;
00794   
00795   d = 0;
00796   xa = x1; ya = y1;
00797   while((d + length + space) < l) {
00798     d = d + length;
00799     xb = xa + dx1;
00800     yb = ya + dy1;
00801     
00802     fprintf(fp, "[%d %d %d %d] ", 
00803         (int) xa, (int) ya,
00804         (int) xb, (int) yb);
00805     
00806     d = d + space;
00807     xa = xb + dx2;
00808     ya = yb + dy2;
00809   }
00810   /*
00811    * When the above condition is no more satisfied, then it is not possible
00812    * to print a dash of length <B>length</B>. However it may be possible to
00813    * print the complete dash or a shorter one.
00814    */
00815 
00816   if((d + length) < l) {
00817     d = d + length;
00818     xb = xa + dx1;
00819     yb = ya + dy1;
00820   } else {
00821     xb = x2;
00822     yb = y2;
00823   }
00824     
00825   fprintf(fp, "[%d %d %d %d] ", 
00826       (int) xa, (int) ya,
00827       (int) xb, (int) yb);
00828 
00829   fprintf(fp,"] %d dashed\n", line_width);
00830 }
00831 
00832 
00862 void o_line_print_center(TOPLEVEL *toplevel, FILE *fp,
00863              int x1, int y1, int x2, int y2,
00864              int color,
00865              int line_width, int length, int space,
00866              int origin_x, int origin_y)
00867 {
00868   double dx, dy, l, d;
00869   double dx1, dy1, dx2, dy2;
00870   double xa, ya, xb, yb;
00871   
00872   f_print_set_color(toplevel, fp, color);
00873   
00874   fprintf(fp, "[");
00875 
00876   /*
00877    * Depending on the slope of the line the <B>length</B> (resp. <B>space</B>)
00878    * parameter is projected on each of the two directions x and y resulting
00879    * in <B>dx1</B> and <B>dy1</B> (resp. <B>dx2</B> and <B>dy2</B>).
00880    * Starting from one end and incrementing alternatively by <B>space</B>
00881    * and <B>length</B> the dashes and dots are printed.
00882    *
00883    * It prints as many sets of dash and dot as possible.
00884    */
00885   dx = (double) (x2 - x1);
00886   dy = (double) (y2 - y1);
00887   l = sqrt((dx * dx) + (dy * dy));
00888   
00889   dx1 = (dx * length) / l;
00890   dy1 = (dy * length) / l;
00891   
00892   dx2 = (dx * space) / l;
00893   dy2 = (dy * space) / l;
00894   
00895   d = 0;
00896   xa = x1; ya = y1;
00897   while((d + length + 2 * space) < l) {
00898     d = d + length;
00899     xb = xa + dx1;
00900     yb = ya + dy1;
00901     
00902     fprintf(fp, "[%d %d %d %d] ", 
00903         (int) xa, (int) ya,
00904         (int) xb, (int) yb);
00905     
00906     d = d + space;
00907     xa = xb + dx2;
00908     ya = yb + dy2;
00909     
00910     fprintf(fp,"[%d %d] ",(int) xa, (int) ya);
00911     
00912     d = d + space;
00913     xa = xa + dx2;
00914     ya = ya + dy2;
00915   }
00916   /*
00917    * When the above condition is no more satisfied, then it is not possible
00918    * to print a dash of length <B>length</B>.
00919    * However two cases are possible :
00920    * <DL>
00921    *   <DT>*</DT><DD>it is possible to print the dash and the dot.
00922    *   <DT>*</DT><DD>it is possible to print the dash or a part
00923    *                 of the original dash.
00924    * </DL>
00925    */
00926 
00927   if((d + length + space) < l) {
00928     d = d + length;
00929     xb = xa + dx1;
00930     yb = ya + dy1;
00931     
00932     fprintf(fp, "[%d %d %d %d] ", 
00933         (int) xa, (int) ya,
00934         (int) xb, (int) yb);
00935     
00936     d = d + space;
00937     xa = xb + dx2;
00938     ya = yb + dy2;
00939     
00940     fprintf(fp,"[%d %d] ",(int) xa, (int) ya);
00941     
00942   } else {
00943     if(d + length < l) {
00944       xb = xa + dx1;
00945       yb = ya + dy1;
00946     } else {
00947       xb = x2;
00948       yb = y2;
00949     }
00950     
00951     fprintf(fp, "[%d %d %d %d] ", 
00952         (int) xa, (int) ya,
00953         (int) xb, (int) yb);
00954     
00955   }
00956   
00957   fprintf(fp,"] %d dashed\n", line_width);
00958 
00959   /*
00960    * A dot is represented by a filled circle. Position of the circle is
00961    * (<B>xa</B>, <B>ya</B>) and its radius by the <B>line_width</B> parameter.
00962    */
00963 }
00964 
00994 void o_line_print_phantom(TOPLEVEL *toplevel, FILE *fp,
00995               int x1, int y1, int x2, int y2,
00996               int color,
00997               int line_width, int length, int space,
00998               int origin_x, int origin_y)
00999 {
01000   double dx, dy, l, d;
01001   double dx1, dy1, dx2, dy2;
01002   double xa, ya, xb, yb;
01003   
01004   f_print_set_color(toplevel, fp, color);
01005   
01006   fprintf(fp,"[");
01007 
01008   /*
01009    * Depending on the slope of the line the <B>length</B> (resp. <B>space</B>)
01010    * parameter is projected on each of the two directions x and y resulting
01011    * in <B>dx1</B> and <B>dy1</B> (resp. <B>dx2</B> and <B>dy2</B>).
01012    * Starting from one end and incrementing alternatively by <B>space</B>
01013    * and <B>length</B> the dashes and dots are printed.
01014    *
01015    * It prints as many sets of dash-dot-dot as possible.
01016    */
01017   dx = (double) (x2 - x1);
01018   dy = (double) (y2 - y1);
01019   l = sqrt((dx * dx) + (dy * dy));
01020   
01021   dx1 = (dx * length) / l;
01022   dy1 = (dy * length) / l;
01023   
01024   dx2 = (dx * space) / l;
01025   dy2 = (dy * space) / l;
01026   
01027   d = 0;
01028   xa = x1; ya = y1;
01029   while((d + length + 3 * space) < l) {
01030     d = d + length;
01031     xb = xa + dx1;
01032     yb = ya + dy1;
01033     
01034     fprintf(fp,"[%d %d %d %d] ",
01035         (int) xa, (int)ya,
01036         (int) xb, (int)yb);
01037     
01038     d = d + space;
01039     xa = xb + dx2;
01040     ya = yb + dy2;
01041     
01042     fprintf(fp,"[%d %d] ",(int) xa, (int) ya);
01043     
01044     d = d + space;
01045     xa = xa + dx2;
01046     ya = ya + dy2;
01047     
01048     fprintf(fp,"[%d %d] ",(int) xa, (int) ya);
01049     
01050     d = d + space;
01051     xa = xa + dx2;
01052     ya = ya + dy2;
01053   }
01054   /*
01055    * When the above condition is no more satisfied, then it is not possible
01056    * to print a complete set of dash-dot-dot.
01057    * However three cases are possible :
01058    * <DL>
01059    *   <DT>*</DT><DD>it is possible to print a dash and a dot and a dot.
01060    *   <DT>*</DT><DD>it is possible to print a dash and a dot.
01061    *   <DT>*</DT><DD>it is possible to print the dash or a part
01062    *                 of the original dash.
01063    * </DL>
01064    */
01065 
01066   if((d + length + 2 * space) < l) {
01067     d = d + length;
01068     xb = xa + dx1;
01069     yb = ya + dy1;
01070     
01071     fprintf(fp,"[%d %d %d %d] ",
01072         (int) xa, (int)ya,
01073         (int) xb, (int)yb);
01074     
01075     d = d + space;
01076     xa = xb + dx2;
01077     ya = yb + dy2;
01078     
01079     fprintf(fp,"[%d %d] ",(int) xa, (int)ya);
01080     
01081     d = d + space;
01082     xa = xb + dx2;
01083     ya = yb + dy2;
01084     
01085     fprintf(fp,"[%d %d] ",(int) xa, (int)ya);
01086     
01087   } else {
01088     if(d + length + space < l) {
01089       d = d + length;
01090       xb = xa + dx1;
01091       yb = ya + dy1;
01092       
01093       fprintf(fp,"[%d %d %d %d] ",
01094           (int) xa, (int)ya,
01095           (int) xb, (int)yb);
01096       
01097       d = d + space;
01098       xa = xb + dx2;
01099       ya = yb + dy2;
01100       
01101       fprintf(fp,"[%d %d] ",(int) xa, (int)ya);
01102       
01103     } else {
01104       if(d + length < l) {
01105     xb = xa + dx1;
01106     yb = ya + dy1;
01107       } else {
01108     xb = x2;
01109     yb = y2;
01110       }
01111       
01112       fprintf(fp,"[%d %d %d %d] ",
01113           (int) xa, (int)ya,
01114           (int) xb, (int)yb);
01115       
01116     }
01117   }
01118   
01119   fprintf(fp,"] %d dashed\n", line_width);
01120 }
01121 
01122 
01131 void o_line_scale_world(TOPLEVEL *toplevel, int x_scale, int y_scale,
01132             OBJECT *object)
01133 {
01134   /* scale the line world coords */
01135   object->line->x[0] = object->line->x[0] * x_scale;
01136   object->line->y[0] = object->line->y[0] * y_scale;
01137   object->line->x[1] = object->line->x[1] * x_scale;
01138   object->line->y[1] = object->line->y[1] * y_scale;
01139 
01140   /* update boundingbox */
01141   o_line_recalc(toplevel, object);
01142   
01143 }
01144 
01145 
01153 double o_line_length(OBJECT *object)
01154 {
01155   double length;
01156   double dx, dy;
01157   
01158   if (!object->line) {
01159     return 0.0;
01160   }
01161 
01162   dx = object->line->x[0]-object->line->x[1];
01163   dy = object->line->y[0]-object->line->y[1];
01164 
01165   length = sqrt((dx*dx) + (dy*dy));
01166                 
01167   return(length);
01168 }
01169 
01187 double o_line_shortest_distance (OBJECT *object, int x, int y, int force_solid)
01188 {
01189   return m_line_shortest_distance (object->line, x, y);
01190 }
01191 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines