gschem

m_basic.c

Go to the documentation of this file.
00001 /* gEDA - GPL Electronic Design Automation
00002  * gschem - gEDA Schematic Capture
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 #include <config.h>
00021 
00022 #include <stdio.h>
00023 #include <math.h>
00024 
00025 #include <gschem.h>
00026 
00027 #ifdef HAVE_LIBDMALLOC
00028 #include <dmalloc.h>
00029 #endif
00030 
00031 
00040 int mil_x (GSCHEM_TOPLEVEL *w_current, int val)
00041 {
00042   double i;
00043   double fval;
00044   int j;
00045 
00046   fval = val;
00047   i = fval * w_current->toplevel->page_current->to_world_x_constant +
00048       w_current->toplevel->page_current->left;
00049 
00050 #ifdef HAS_RINT
00051   j = rint(i);
00052 #else
00053   j = i;
00054 #endif
00055 
00056   return(j);
00057 }
00058 
00067 int mil_y(GSCHEM_TOPLEVEL *w_current, int val)
00068 {
00069   double i;
00070   double fval;
00071   int j;
00072 
00073   fval = w_current->toplevel->height - val;
00074   i = fval * w_current->toplevel->page_current->to_world_y_constant +
00075       w_current->toplevel->page_current->top;
00076 
00077 #ifdef HAS_RINT
00078   j = rint(i);
00079 #else
00080   j = i;
00081 #endif
00082 
00083   return(j);
00084 }
00085 
00094 int pix_x (GSCHEM_TOPLEVEL *w_current, int val)
00095 {
00096 
00097   double i;
00098   int j;
00099 
00100   i = w_current->toplevel->page_current->to_screen_x_constant *
00101         (double)(val - w_current->toplevel->page_current->left);
00102 
00103 #ifdef HAS_RINT
00104   j = rint(i);
00105 #else
00106   j = i;
00107 #endif
00108 
00109   /* this is a temp solution to fix the wrapping associated with */
00110   /* X coords being greated/less than than 2^15 */
00111   if (j >= 32768) {
00112     j = 32767;
00113   }
00114   if (j <= -32768) {
00115     j = -32767;
00116   }
00117 
00118   return(j);
00119 }
00120 
00129 int pix_y(GSCHEM_TOPLEVEL *w_current, int val)
00130 {
00131   double i;
00132   int j;
00133 
00134   i = w_current->toplevel->height -
00135         (w_current->toplevel->page_current->to_screen_y_constant *
00136          (double)(val - w_current->toplevel->page_current->top));
00137 
00138 #ifdef HAS_RINT
00139   j = rint(i);
00140 #else
00141   j = i;
00142 #endif
00143 
00144   /* this is a temp solution to fix the wrapping associated with */
00145   /* X coords being greated/less than than 2^15 */
00146   if (j >= 32768) {
00147     j = 32767;
00148   }
00149   if (j <= -32768) {
00150     j = -32767;
00151   }
00152 
00153   return(j);
00154 }
00155 
00167 void WORLDtoSCREEN (GSCHEM_TOPLEVEL *w_current, int x, int y, int *px, int *py)
00168 {
00169   *px = pix_x (w_current, x);
00170   *py = pix_y (w_current, y);
00171 }
00172 
00187 void SCREENtoWORLD (GSCHEM_TOPLEVEL *w_current, int mx, int my, int *x, int *y)
00188 {
00189   *x = mil_x (w_current, mx);
00190   *y = mil_y (w_current, my);
00191 }
00192 
00202 int snap_grid(GSCHEM_TOPLEVEL *w_current, int input)
00203 {
00204   int p, m, n;
00205   int sign, value, snap_grid;
00206 
00207   if (w_current->snap == SNAP_OFF ||
00208       w_current->snap_size <= 0) {
00209     return(input);
00210   }
00211 
00212   snap_grid = w_current->snap_size;
00213 
00214   /* this code was inspired from killustrator, it's much simpler than mine */
00215   sign = ( input < 0 ? -1 : 1 );
00216   value = abs(input);
00217 
00218   p = value / snap_grid;
00219   m = value % snap_grid;
00220   n = p * snap_grid;
00221   if (m > snap_grid / 2)
00222   n += snap_grid;
00223 
00224 #if DEBUG
00225   printf("p: %d\n", p);
00226   printf("m: %d\n", m);
00227   printf("m > snap_grid / 2: %d\n", (m > snap_grid / 2));
00228   printf("n: %d\n", n);
00229   printf("n*s: %d\n", n*sign);
00230 #endif
00231 
00232   return(sign*n);
00233 }
00234 
00243 int SCREENabs(GSCHEM_TOPLEVEL *w_current, int val)
00244 {
00245   double f0,f1,f;
00246 
00247   double i;
00248   int j;
00249 
00250   f0 = w_current->toplevel->page_current->left;
00251   f1 = w_current->toplevel->page_current->right;
00252   f = w_current->toplevel->width / (f1 - f0);
00253   i = f * (double)(val);
00254 
00255 #ifdef HAS_RINT
00256   j = rint(i);
00257 #else
00258   j = i;
00259 #endif
00260 
00261   return(j);
00262 
00263 }
00264 
00273 int WORLDabs(GSCHEM_TOPLEVEL *w_current, int val)
00274 {
00275   double fw0,fw1,fw,fval;
00276 
00277   double i;
00278   int j;
00279 
00280   fw1 = w_current->toplevel->page_current->right;
00281   fw0 = w_current->toplevel->page_current->left;
00282   fw  = w_current->toplevel->width;
00283   fval = val;
00284   i = fval * (fw1 - fw0) / fw;
00285 
00286 #ifdef HAS_RINT
00287   j = rint(i);
00288 #else
00289   j = i;
00290 #endif
00291 
00292   return(j);
00293 }
00294 
00295 
00297 typedef struct st_halfspace HALFSPACE;
00298 
00300 struct st_halfspace {
00301   int left; /* these are booleans */
00302   int top;
00303   int right;
00304   int bottom;
00305 };
00306 
00307 /* \note
00308  * encode_halfspace and clip are part of the cohen-sutherland clipping
00309  * algorithm.  They are used to determine if an object is visible or not
00310  */
00323 static void WORLDencode_halfspace (GSCHEM_TOPLEVEL *w_current,
00324                                    sPOINT *point, HALFSPACE *halfspace)
00325 {
00326   halfspace->left = point->x < w_current->toplevel->page_current->left;
00327   halfspace->right = point->x > w_current->toplevel->page_current->right;
00328   halfspace->bottom = point->y > w_current->toplevel->page_current->bottom;
00329   halfspace->top = point->y < w_current->toplevel->page_current->top;
00330 }
00331 
00346 int WORLDclip_change (GSCHEM_TOPLEVEL *w_current,
00347                       int *x1, int *y1, int *x2, int *y2)
00348 {
00349   HALFSPACE half1, half2;
00350   HALFSPACE tmp_half;
00351   sPOINT tmp_point;
00352   sPOINT point1, point2;
00353   float slope;
00354   int in1, in2, done;
00355   int visible;
00356   int w_l, w_t, w_r, w_b;
00357 
00358   point1.x = *x1;
00359   point1.y = *y1;
00360   point2.x = *x2;
00361   point2.y = *y2;
00362 
00363   w_l = w_current->toplevel->page_current->left;
00364   w_t = w_current->toplevel->page_current->top;
00365   w_r = w_current->toplevel->page_current->right;
00366   w_b = w_current->toplevel->page_current->bottom;
00367 
00368   done = FALSE;
00369   visible = FALSE;
00370 
00371   do {
00372     WORLDencode_halfspace (w_current, &point1, &half1);
00373     WORLDencode_halfspace (w_current, &point2, &half2);
00374 
00375 #if DEBUG
00376     printf("starting loop\n");
00377     printf("1 %d %d %d %d\n", half1.left, half1.top, half1.right, half1.bottom);
00378     printf("2 %d %d %d %d\n", half2.left, half2.top, half2.right, half2.bottom);
00379 #endif
00380 
00381     in1 = (!half1.left) &&
00382       (!half1.top) &&
00383       (!half1.right) &&
00384       (!half1.bottom);
00385 
00386     in2 = (!half2.left) &&
00387       (!half2.top) &&
00388       (!half2.right) &&
00389       (!half2.bottom);
00390 
00391 
00392     if (in1 && in2) { /* trivally accept */
00393       done = TRUE;
00394       visible = TRUE;
00395     } else if ( ((half1.left && half2.left) ||
00396                  (half1.right && half2.right)) ||
00397                 ((half1.top && half2.top) ||
00398                  (half1.bottom && half2.bottom)) ) {
00399       done = TRUE; /* trivially reject */
00400       visible = FALSE;
00401     } else { /* at least one point outside */
00402       if (in1) {
00403         tmp_half = half1;
00404         half1 = half2;
00405         half2 = tmp_half;
00406 
00407         tmp_point = point1;
00408         point1 = point2;
00409         point2 = tmp_point;
00410       }
00411 
00412       if (point2.x == point1.x) { /* vertical line */
00413         if (half1.top) {
00414           point1.y = w_t;
00415         } else if (half1.bottom) {
00416           point1.y = w_b;
00417         }
00418       } else { /* not a vertical line */
00419 
00420         /* possible fix for alpha core dumping */
00421         /* assume the object is visible */
00422         if ((point2.x - point1.x) == 0) {
00423           return(TRUE);
00424         }
00425 
00426         slope = (float) (point2.y - point1.y) /
00427           (float) (point2.x - point1.x);
00428 
00429         /* possible fix for alpha core dumping */
00430         /* assume the object is visible */
00431         if (slope == 0.0) {
00432           return(TRUE);
00433         }
00434 
00435         if (half1.left) {
00436           point1.y = point1.y +
00437             (w_l - point1.x) * slope;
00438           point1.x = w_l;
00439         } else if (half1.right) {
00440           point1.y = point1.y +
00441             (w_r - point1.x) * slope;
00442           point1.x = w_r;
00443         } else if (half1.bottom) {
00444           point1.x = point1.x +
00445             (w_b - point1.y) / slope;
00446           point1.y = w_b;
00447         } else if (half1.top) {
00448           point1.x = point1.x +
00449             (w_t - point1.y) / slope;
00450           point1.y = w_t;
00451         }
00452       } /* end of not a vertical line */
00453     } /* end of at least one outside */
00454   } while (!done);
00455 
00456   /*printf("after: %d %d %d %d\n", point1.x, point1.y, point2.x, point2.y);*/
00457   *x1 = point1.x;
00458   *y1 = point1.y;
00459   *x2 = point2.x;
00460   *y2 = point2.y;
00461   return(visible);
00462 }
00463 
00477 int clip_nochange (GSCHEM_TOPLEVEL *w_current, int x1, int y1, int x2, int y2)
00478 {
00479   HALFSPACE half1, half2;
00480   HALFSPACE tmp_half;
00481   sPOINT tmp_point;
00482   sPOINT point1, point2;
00483   float slope;
00484   int in1, in2, done;
00485   int visible;
00486   int w_l, w_t, w_r, w_b;
00487 
00488   point1.x = x1;
00489   point1.y = y1;
00490   point2.x = x2;
00491   point2.y = y2;
00492 
00493   /*printf("before: %d %d %d %d\n", x1, y1, x2, y2);*/
00494 
00495   w_l = w_current->toplevel->page_current->left;
00496   w_t = w_current->toplevel->page_current->top;
00497   w_r = w_current->toplevel->page_current->right;
00498   w_b = w_current->toplevel->page_current->bottom;
00499 
00500   done = FALSE;
00501   visible = FALSE;
00502 
00503   do {
00504     WORLDencode_halfspace (w_current, &point1, &half1);
00505     WORLDencode_halfspace (w_current, &point2, &half2);
00506 
00507 #if DEBUG
00508     printf("starting loop\n");
00509     printf("1 %d %d %d %d\n", half1.left, half1.top, half1.right, half1.bottom);
00510     printf("2 %d %d %d %d\n", half2.left, half2.top, half2.right, half2.bottom);
00511 #endif
00512 
00513     in1 = (!half1.left) &&
00514       (!half1.top) &&
00515       (!half1.right) &&
00516       (!half1.bottom);
00517 
00518     in2 = (!half2.left) &&
00519       (!half2.top) &&
00520       (!half2.right) &&
00521       (!half2.bottom);
00522 
00523 
00524     if (in1 && in2) { /* trivally accept */
00525       done = TRUE;
00526       visible = TRUE;
00527     } else if ( ((half1.left && half2.left) ||
00528                  (half1.right && half2.right)) ||
00529                 ((half1.top && half2.top) ||
00530                  (half1.bottom && half2.bottom)) ) {
00531       done = TRUE; /* trivially reject */
00532       visible = FALSE;
00533     } else { /* at least one point outside */
00534       if (in1) {
00535         tmp_half = half1;
00536         half1 = half2;
00537         half2 = tmp_half;
00538 
00539         tmp_point = point1;
00540         point1 = point2;
00541         point2 = tmp_point;
00542       }
00543 
00544       if (point2.x == point1.x) { /* vertical line */
00545         if (half1.top) {
00546           point1.y = w_t;
00547         } else if (half1.bottom) {
00548           point1.y = w_b;
00549         }
00550       } else { /* not a vertical line */
00551 
00552         /* possible fix for alpha core dumping */
00553         /* assume the object is visible */
00554         if ((point2.x - point1.x) == 0) {
00555           return(TRUE);
00556         }
00557 
00558         slope = (float) (point2.y - point1.y) /
00559           (float) (point2.x - point1.x);
00560 
00561         /* possible fix for alpha core dumping */
00562         /* assume the object is visible */
00563         if (slope == 0.0) {
00564           return(TRUE);
00565         }
00566 
00567         if (half1.left) {
00568           point1.y = point1.y +
00569             (w_l - point1.x) * slope;
00570           point1.x = w_l;
00571         } else if (half1.right) {
00572           point1.y = point1.y +
00573             (w_r - point1.x) * slope;
00574           point1.x = w_r;
00575         } else if (half1.bottom) {
00576           point1.x = point1.x +
00577             (w_b - point1.y) / slope;
00578           point1.y = w_b;
00579         } else if (half1.top) {
00580           point1.x = point1.x +
00581             (w_t - point1.y) / slope;
00582           point1.y = w_t;
00583         }
00584       } /* end of not a vertical line */
00585     } /* end of at least one outside */
00586   } while (!done);
00587 
00588   return(visible);
00589 }
00590 
00606 int visible (GSCHEM_TOPLEVEL *w_current,
00607              int wleft, int wtop, int wright, int wbottom)
00608 {
00609   int visible=FALSE;
00610 
00611   /* don't do object clipping if this is false */
00612   if (!w_current->toplevel->object_clipping) {
00613     return(TRUE);
00614   }
00615 
00616   visible = clip_nochange (w_current, wleft, wtop, wright, wtop);
00617 
00618 #if DEBUG
00619   printf("vis1 %d\n", visible);
00620 #endif
00621 
00622   if (!visible) {
00623     visible = clip_nochange (w_current, wleft, wbottom, wright, wbottom);
00624   } else {
00625     return(visible);
00626   }
00627 
00628 #if DEBUG
00629   printf("vis2 %d\n", visible);
00630 #endif
00631 
00632   if (!visible) {
00633     visible = clip_nochange (w_current, wleft, wtop, wleft, wbottom);
00634   } else {
00635     return(visible);
00636   }
00637 
00638 #if DEBUG
00639   printf("vis3 %d\n", visible);
00640 #endif
00641 
00642   if (!visible) {
00643     visible = clip_nochange (w_current, wright, wtop, wright, wbottom);
00644   } else {
00645     return(visible);
00646   }
00647 
00648 #if DEBUG
00649   printf("vis4 %d\n", visible);
00650 #endif
00651 
00652 #if DEBUG
00653   printf("%d %d %d\n", wleft, w_current->toplevel->page_current->top, wright);
00654   printf("%d %d %d\n", wtop, w_current->toplevel->page_current->top, wbottom);
00655   printf("%d %d %d\n", wleft, w_current->toplevel->page_current->right, wright);
00656   printf("%d %d %d\n", wtop, w_current->toplevel->page_current->bottom, wbottom);
00657 #endif
00658 
00659   /*
00660    * now check to see if bounding box encompasses the entire viewport.
00661    * We only need to test if one point on the screen clipping boundary
00662    * is indide the bounding box of the object.
00663    */
00664   if (w_current->toplevel->page_current->left >= wleft  &&
00665       w_current->toplevel->page_current->left <= wright &&
00666       w_current->toplevel->page_current->top >= wtop    &&
00667       w_current->toplevel->page_current->top <= wbottom ) {
00668     visible = 1;
00669   }
00670 
00671 #if DEBUG
00672   printf("vis5 %d\n", visible);
00673 #endif
00674 
00675   return(visible);
00676 }
00677 
00678 
00691 /* rounds for example 1235 to 1000, 670 to 500, 0.234 to 0.2 ...
00692 int would be enough if there are no numbers smaller 1 (hw)*/
00693 double round_5_2_1(double unrounded)
00694 {
00695   int digits;
00696   double betw_1_10;
00697 
00698   /*only using the automatic cast */
00699   digits = log10(unrounded);
00700   /* creates numbers between 1 and 10 */
00701   betw_1_10 = unrounded / pow(10,digits);
00702 
00703   if (betw_1_10 < 1.5) {
00704     return(pow(10,digits));
00705   }
00706   if (betw_1_10 > 1.4 && betw_1_10 < 3.5 ) {
00707     return(2*pow(10,digits));
00708   }
00709   if (betw_1_10 > 3.4 && betw_1_10 < 7.5 ) {
00710     return(5*pow(10,digits));
00711   }
00712   else {
00713     return(10*pow(10,digits));
00714   }
00715 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines