Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

utility.c

Go to the documentation of this file.
00001 #include "win.h"
00002 
00003 #define FABS(x)    ((x)>=0.0?(x):-((x)))
00004 #define FINT(x)    ((x)>=0.0?(long)((x)):(long)((x)-0.999999999999999999))
00005 #define FMOD(x,y)  ((x) - FINT((x)/(y))*(y))
00006 
00007 #define MAXSIZE  1000     /*Maximum screen size in pixel */
00008 
00009 extern lux_wins *get_currentwin();
00010 
00011 lux_set_step(min, max, ln, step, start, tick)  /* Assume min < max always */
00012 double min, max, *step, *start;
00013 long  *tick, ln;
00014 {
00015     double xlog,x,tt,eps;
00016     long   ilog;
00017 
00018     if (ln) {
00019         xlog = log10(max) - log10(min);
00020         eps  = xlog/10.0/MAXSIZE;
00021         ilog = (long) (xlog + 0.5);
00022         if (ilog>=4) {
00023             *step  = pow(10.0, (double)((long)((ilog+2)/4)));
00024             *tick  = (ilog+2)/4*10;
00025         }
00026         else {
00027             *step  = 10.0;
00028             *tick  = 10;          
00029         }
00030         xlog = log10(min);
00031         *start = pow(10.0,(double)(FINT(xlog)));
00032 /*      fprintf(stderr,"min=%lg  start=%lg step=%lg\n",min,*start,*step);*/
00033         while(FABS(log10(*start/min)) > eps && *start < min) *start *= 10.0;
00034     }
00035     else {
00036         eps = (max - min)/10.0/MAXSIZE;
00037         xlog = log10(max - min);
00038         ilog = FINT(xlog);
00039         x = pow(10.0, (double)ilog);
00040         tt = (max - min)/x;
00041         if (tt - (long)tt > 0.49999) tt = tt + 1.0;
00042         switch((long)tt) {
00043             case 1: 
00044             case 5: 
00045             case 10:
00046               *step = ((long)tt)/5.0*x; 
00047               *tick = 10;
00048               break;
00049             case 2: *step = ((long)tt)/4.0*x; *tick = 10;  break;
00050             case 4: 
00051             case 8: 
00052               *step = ((long)tt)/4.0*x; 
00053               *tick = 10; 
00054               break;
00055             case 3: 
00056             case 7: 
00057               *step = ((long)tt+1)/4.0*x; 
00058               *tick = 10;
00059               break;
00060             case 6: 
00061               *step = ((long)tt-1)/5.0*x; 
00062               *tick = 10;
00063               break;
00064             case 9: 
00065               *step = ((long)tt+1)/5.0*x; 
00066               *tick = 10;
00067               break;
00068             default:
00069               fprintf(stderr,"Calculation error!\nCheck your axis limits!!\n");
00070         }
00071 
00072 
00073         if (FABS(min) < *step) {
00074             if (FABS(*step - 2.0*FABS(min)) < eps) {
00075                 *start = min;
00076             }
00077             else
00078               *start = (min>=0.0)?0.0:-(*step);
00079         }
00080         else {
00081             xlog = log10(FABS(min));
00082             ilog = FINT(xlog);
00083             x = pow(10.0, (double)ilog);
00084             *start = FINT(min/x)*x;
00085             if (FMOD(min-*start,*step/2.0) < eps || 
00086                 FMOD(min-*start,*step/2.0) > *step/2.0 - eps)
00087               *start = min - *step;
00088         }
00089 /*      fprintf(stderr,"min=%lg  start=%lg step=%lg mod=%lg eps=%lg\n",min,*start,*step, FMOD(min-*start,*step/2.0),eps); */
00090         while(FABS(min-*start) > eps && min > *start) *start = *start + *step;
00091     }
00092 }
00093 
00094 
00095 lux_draw_axis(win)
00096 Window win;
00097 {
00098     register lux_wins *current;
00099     char  msg[20];
00100     double fx,fy,rfx,rfy,epsx,epsy;
00101     double ystep,xstep,ys,xs,x,y;
00102     double maxt,mayt,mixt,miyt,sxt,syt,rmaxt,rmayt,rmixt,rmiyt,rsxt,rsyt;
00103     long   i,xt,yt;
00104 
00105     current = get_currentwin(win);
00106 
00107     if (current->win.xmin >=  current->win.xmax ||
00108         current->win.ymin >=  current->win.ymax)  {
00109         fprintf(stderr,
00110                 "Inproper limits setting in window %ld, can't draw axis!\n",
00111                 win);
00112         fprintf(stderr, "xmin=%lg, xmax=%lg;  ymin=%lg, ymax=%lg\n",
00113                 current->win.xmin,current->win.xmax,
00114                 current->win.ymin,current->win.ymax);
00115         return(0);
00116     }
00117       
00118 
00119     lux_draw_linef(win, current->win.xmin, current->win.ymin, 
00120                         current->win.xmax, current->win.ymin);
00121     lux_draw_linef(win, current->win.xmax, current->win.ymin,
00122                         current->win.xmax, current->win.ymax);
00123     lux_draw_linef(win, current->win.xmax, current->win.ymax,
00124                         current->win.xmin, current->win.ymax);
00125     lux_draw_linef(win, current->win.xmin, current->win.ymax,
00126                         current->win.xmin, current->win.ymin);
00127 
00128 /* 
00129    Setup tick-mark ponits 
00130    (maxt, mayt) (rmaxt, rmayt) Major tick marks(leftside, rightside) 
00131    (mixt, miyt) (rmixt, rmiyt) Minor tick marks(leftside, rightside) 
00132    (sxt,  syt)  (rsxt,  rsyt)  Small tick marks(leftside, rightside) 
00133 */
00134 
00135     if (current->win.lnx) epsx = (log10(current->win.xmax) - 
00136                                  log10(current->win.xmin))/10.0/MAXSIZE;
00137     else epsx = (current->win.xmax - current->win.xmin)/10.0/MAXSIZE;
00138     if (current->win.lny) epsy = (log10(current->win.ymax) - 
00139                                  log10(current->win.ymin))/10.0/MAXSIZE;
00140     else epsy = (current->win.ymax - current->win.ymin)/10.0/MAXSIZE;
00141 
00142     if (current->win.lnx) {
00143         double dx, minlog, maxlog;
00144 
00145         minlog = log10(current->win.xmin);
00146         maxlog = log10(current->win.xmax);
00147         dx = (maxlog - minlog)/60.0;
00148         
00149         maxt  = pow(10.0, dx + minlog);
00150         rmaxt = pow(10.0, maxlog - dx);
00151 
00152         mixt  = pow(10.0, dx*3.0/4.0 + minlog);
00153         rmixt = pow(10.0, maxlog - dx*3.0/4.0);
00154 
00155         sxt   = pow(10.0, dx/2.0 + minlog);
00156         rsxt  = pow(10.0, maxlog - dx/2.0);
00157     }
00158     else {
00159         double dx;
00160 
00161         dx = (current->win.xmax - current->win.xmin)/60.0;
00162 
00163         maxt  = dx + current->win.xmin;
00164         rmaxt = current->win.xmax - dx;
00165 
00166         mixt  = dx*3.0/4.0 + current->win.xmin;
00167         rmixt = current->win.xmax - dx*3.0/4.0;
00168         
00169         sxt   = dx/2.0 + current->win.xmin;
00170         rsxt  = current->win.xmax - dx/2.0;
00171     }
00172 
00173     if (current->win.lny) {
00174         double dy, minlog, maxlog;
00175 
00176         minlog = log10(current->win.ymin);
00177         maxlog = log10(current->win.ymax);
00178         dy = (maxlog - minlog)/60.0;
00179 
00180         mayt  = pow(10.0, dy + minlog);
00181         rmayt = pow(10.0, maxlog - dy);
00182 
00183         miyt  = pow(10.0, dy*3.0/4.0 + minlog);
00184         rmiyt = pow(10.0, maxlog - dy*3.0/4.0);
00185 
00186         syt   = pow(10.0, dy/2.0 + minlog);
00187         rsyt  = pow(10.0, maxlog - dy/2.0);
00188         
00189     }
00190     else {
00191         double dy;
00192         dy = (current->win.ymax - current->win.ymin)/60.0;
00193 
00194         mayt  = dy + current->win.ymin;
00195         rmayt = current->win.ymax - dy;
00196 
00197         miyt  = dy*3.0/4.0 + current->win.ymin;
00198         rmiyt = current->win.ymax - dy*3.0/4.0;
00199         
00200         syt   = dy/2.0 + current->win.ymin;
00201         rsyt  = current->win.ymax - dy/2.0;
00202     }
00203 
00204 
00205      fy = current->win.ymin;
00206     rfy = current->win.ymax;
00207 
00208     lux_set_step(current->win.xmin, current->win.xmax, current->win.lnx, 
00209                  &xstep, &fx, &xt);
00210 
00211     if (current->win.lnx) {
00212         while(log10(fx) <= log10(current->win.xmax) + epsx) {
00213             for(i=0;i<xt;i++) {
00214                 x = (i%10+1)*pow(10.0,(double)(i/10))*fx/xstep;
00215                 if (x < current->win.xmin) continue;
00216                 if (i%10 == 0) {
00217                     lux_draw_linef(current->win.window, x,  fy, x,  mayt);
00218                     lux_draw_linef(current->win.window, x, rfy, x, rmayt);
00219                 }
00220                 else {
00221                     lux_draw_linef(current->win.window, x,  fy, x,  syt);
00222                     lux_draw_linef(current->win.window, x, rfy, x, rsyt);
00223                 }
00224             }
00225             sprintf(msg,"%lg",fx);
00226             lux_draw_string(current->win.window,fx,fy,-1.1,msg,0);
00227             fx = fx * xstep;
00228         }
00229 
00230         for(i=0;i<xt;i++) {
00231             x = (i%10+1)*pow(10.0,(double)(i/10))*fx/xstep;
00232             if (x > current->win.xmax) break;
00233             if (i%10 == 0) {
00234                 lux_draw_linef(current->win.window, x,  fy, x,  mayt);
00235                 lux_draw_linef(current->win.window, x, rfy, x, rmayt);
00236             }
00237             else {
00238                 lux_draw_linef(current->win.window, x,  fy, x,  syt);
00239                 lux_draw_linef(current->win.window, x, rfy, x, rsyt);
00240             }
00241         }
00242     }
00243     else {
00244 
00245         float axmax = (current->win.xmax < 0 ? -current->win.xmax
00246                                              : current->win.xmax);
00247         float axmin = (current->win.xmin < 0 ? -current->win.xmin
00248                                              : current->win.xmin);
00249         if (axmin > axmax) axmax = axmin;
00250 
00251         if (current->win.xmin * current->win.xmax <= 0) {
00252 
00253             /* If the limits change sign, try to ensure that 0 is plotted. */
00254 
00255             float newfx = 0;
00256             while (newfx - xstep >= current->win.xmin) newfx -= xstep;
00257 
00258             /* fprintf(stderr, "changing fx from %f to %f\n", fx, newfx); */
00259             fx = newfx;
00260         }
00261 
00262         xs = xstep/xt;
00263         while (fx <= current->win.xmax + epsx) {
00264 
00265             /* Deal with rounding error... */
00266 
00267             float afx = (fx < 0 ? -fx : fx);
00268             if (afx < 1.e-6*axmax) fx = 0;
00269 
00270             for(i=0;i<xt;i++) {
00271                 x = (i-xt)*xs + fx;
00272                 if (x < current->win.xmin) continue;
00273                 if (i%10 == 0) { 
00274                     lux_draw_linef(current->win.window, x,  fy, x,  mayt);
00275                     lux_draw_linef(current->win.window, x, rfy, x, rmayt);
00276                 }
00277                 else if (i%5 == 0) {
00278                     lux_draw_linef(current->win.window, x,  fy, x,  miyt);
00279                     lux_draw_linef(current->win.window, x, rfy, x, rmiyt);
00280                 }
00281                 else {
00282                     lux_draw_linef(current->win.window, x,  fy, x,  syt);
00283                     lux_draw_linef(current->win.window, x, rfy, x, rsyt);
00284                 }
00285             }
00286             sprintf(msg,"%.4lg",fx);
00287             lux_draw_string(current->win.window,fx,fy,-1.1,msg,0);
00288             fx = fx + xstep;
00289         }
00290 
00291         for(i=0;i<xt;i++) {
00292             x = (i-xt)*xs + fx;
00293             if (x > current->win.xmax) break;
00294             if (i%10 == 0) {
00295                 lux_draw_linef(current->win.window, x,  fy, x,  mayt);
00296                 lux_draw_linef(current->win.window, x, rfy, x, rmayt);
00297             }
00298             else if (i%5 == 0) {
00299                 lux_draw_linef(current->win.window, x,  fy, x,  miyt);
00300                 lux_draw_linef(current->win.window, x, rfy, x, rmiyt);
00301             }
00302             else {
00303                 lux_draw_linef(current->win.window, x,  fy, x,  syt);
00304                 lux_draw_linef(current->win.window, x, rfy, x, rsyt);
00305             }
00306         }
00307     }
00308 
00309 
00310      fx = current->win.xmin;
00311     rfx = current->win.xmax;
00312 
00313     lux_set_step(current->win.ymin, current->win.ymax, current->win.lny, 
00314                  &ystep, &fy, &yt);
00315 
00316     if (current->win.lny) {
00317         while(log10(fy) <= log10(current->win.ymax) + epsy) {
00318             for(i=0;i<yt;i++) {
00319                 y = (i%10+1)*pow(10.0,(double)(i/10))*fy/ystep;
00320                 if (y < current->win.ymin) continue;
00321                 if (i%10 == 0) {
00322                     lux_draw_linef(current->win.window,  fx, y,  maxt, y);
00323                     lux_draw_linef(current->win.window, rfx, y, rmaxt, y);
00324                 }
00325                 else {
00326                     lux_draw_linef(current->win.window,  fx, y,  sxt,  y);
00327                     lux_draw_linef(current->win.window, rfx, y, rsxt,  y);
00328                 }
00329             }
00330             sprintf(msg,"%lg",fy);
00331             lux_draw_vstring(current->win.window,fx,fy,0.1,msg,0);
00332             fy = fy * ystep;
00333         }
00334         for(i=0;i<yt;i++) {
00335             y = (i%10+1)*pow(10.0,(double)(i/10))*fy/ystep;
00336             if (y > current->win.ymax) break;
00337             if (i%10 == 0) {
00338                 lux_draw_linef(current->win.window,  fx, y,  maxt, y);
00339                 lux_draw_linef(current->win.window, rfx, y, rmaxt, y);
00340             }
00341             else {
00342                 lux_draw_linef(current->win.window,  fx, y,  sxt,  y);
00343                 lux_draw_linef(current->win.window, rfx, y, rsxt,  y);
00344             }
00345         }
00346     }
00347     else {
00348 
00349         float aymax = (current->win.ymax < 0 ? -current->win.ymax
00350                                              : current->win.ymax);
00351         float aymin = (current->win.ymin < 0 ? -current->win.ymin
00352                                              : current->win.ymin);
00353         if (aymin > aymax) aymax = aymin;
00354 
00355         if (current->win.ymin * current->win.ymax <= 0) {
00356 
00357             /* If the limits change sign, try to ensure that 0 is plotted. */
00358 
00359             float newfy = 0;
00360             while (newfy - ystep >= current->win.ymin) newfy -= ystep;
00361 
00362             /* fprintf(stderr, "changing fy from %f to %f\n", fy, newfy); */
00363             fy = newfy;
00364         }
00365 
00366         ys = ystep/yt;
00367         while(fy <= current->win.ymax + epsy) {
00368             for(i=0;i<yt;i++) {
00369 
00370                 /* Deal with rounding error... */
00371 
00372                 float afy = (fy < 0 ? -fy : fy);
00373                 if (afy < 1.e-6*aymax) fy = 0;
00374 
00375                 y = (i-yt)*ys + fy;
00376                 if (y < current->win.ymin) continue;
00377                 if (i%10 == 0) {
00378                     lux_draw_linef(current->win.window,  fx, y,  maxt, y);
00379                     lux_draw_linef(current->win.window, rfx, y, rmaxt, y);
00380                 }
00381                 else if (i%5 == 0) {
00382                     lux_draw_linef(current->win.window,  fx, y,  mixt, y);
00383                     lux_draw_linef(current->win.window, rfx, y, rmixt, y);
00384                 }
00385                 else {
00386                     lux_draw_linef(current->win.window,  fx, y,  sxt,  y);
00387                     lux_draw_linef(current->win.window, rfx, y, rsxt,  y);
00388                 }
00389             }
00390             sprintf(msg,"%.4lg",fy);
00391             lux_draw_vstring(current->win.window,fx,fy,0.1,msg,0);
00392             fy = fy + ystep;
00393         }
00394         for(i=0;i<yt;i++) {
00395             y = (i-yt)*ys + fy;
00396             if (y > current->win.ymax) break;
00397             if (i%10 == 0) {
00398                 lux_draw_linef(current->win.window,  fx, y,  maxt, y);
00399                 lux_draw_linef(current->win.window, rfx, y, rmaxt, y);
00400             }
00401             else if (i%5 == 0) {
00402                 lux_draw_linef(current->win.window,  fx, y,  mixt, y);
00403                 lux_draw_linef(current->win.window, rfx, y, rmixt, y);
00404             }
00405             else {
00406                 lux_draw_linef(current->win.window,  fx, y,  sxt,  y);
00407                 lux_draw_linef(current->win.window, rfx, y, rsxt,  y);
00408             }
00409         }
00410     }
00411     return(1);
00412 }
00413 

Generated at Sun Feb 24 09:57:20 2002 for STARLAB by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001