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
00008
00009 extern lux_wins *get_currentwin();
00010
00011 lux_set_step(min, max, ln, step, start, tick)
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
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
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
00130
00131
00132
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
00254
00255 float newfx = 0;
00256 while (newfx - xstep >= current->win.xmin) newfx -= xstep;
00257
00258
00259 fx = newfx;
00260 }
00261
00262 xs = xstep/xt;
00263 while (fx <= current->win.xmax + epsx) {
00264
00265
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
00358
00359 float newfy = 0;
00360 while (newfy - ystep >= current->win.ymin) newfy -= ystep;
00361
00362
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
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