00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <stdlib.h>
00014 #include <math.h>
00015 #include <stdio.h>
00016
00017 #include "xyax.h"
00018
00019 const char* xy_id_xyax_cpp="$Id: xyax.cpp,v 1.22 1999/12/09 21:47:46 rborges Exp $";
00020 const double XYAxis::_arrow_size = 0.03;
00021
00022 XYAxis::XYAxis (double mn,
00023 double mx,
00024 XYCoordinate x,
00025 XYCoordinate y,
00026 long color,
00027 double size,
00028 double rot,
00029 double step,
00030 XYScaleDecorator* decorator,
00031 XYText* title,
00032 xybool arrow,
00033 xybool visible)
00034 : XYObject(x, y, visible),
00035 _mn(mn), _mx(mx), _color(color), _size(size), _rot(rot),
00036 _step(step), _referenceTick(mn), _decor(decorator),
00037 _title(title), _arrow(arrow), _leftTick(xytrue)
00038 {
00039 }
00040
00041 XYAxis::XYAxis (double mn,
00042 double mx,
00043 XYCoordinate x,
00044 XYCoordinate y,
00045 long color,
00046 double size,
00047 double rot,
00048 xybool arrow,
00049 xybool visible)
00050 : XYObject(x, y, visible),
00051 _mn(mn), _mx(mx), _color(color), _size(size), _rot(rot),
00052 _step(0), _referenceTick(mn), _decor(NULL),
00053 _title(NULL), _arrow(arrow), _leftTick(xytrue)
00054 {
00055 }
00056
00057 XYAxis::XYAxis (double mn,
00058 double mx,
00059 XYCoordinate x,
00060 XYCoordinate y,
00061 long color,
00062 double size,
00063 double rot,
00064 double step,
00065 xybool arrow,
00066 xybool visible)
00067 : XYObject(x, y, visible),
00068 _mn(mn), _mx(mx), _color(color), _size(size), _rot(rot),
00069 _step(step), _referenceTick(mn), _decor(NULL),
00070 _title(NULL), _arrow(arrow), _leftTick(xytrue)
00071 {
00072 }
00073
00074 void XYAxis::min (double min)
00075 {
00076 _mn = min;
00077 }
00078
00079 double XYAxis::min (void) const
00080 {
00081 return _mn;
00082 }
00083
00084 void XYAxis::max (double max)
00085 {
00086 _mx = max;
00087 }
00088
00089 double XYAxis::max (void) const
00090 {
00091 return _mx;
00092 }
00093
00094 void XYAxis::color (long c)
00095 {
00096 _color = c;
00097 }
00098
00099 long XYAxis::color (void) const
00100 {
00101 return _color;
00102 }
00103
00104 void XYAxis::size (double sz)
00105 {
00106 if ((0.0 <= sz) && (sz <= 1.0))
00107 _size = sz;
00108 }
00109
00110 double XYAxis::size (void) const
00111 {
00112 return _size;
00113 }
00114
00115 void XYAxis::rotation (double rot)
00116 {
00117 _rot = rot;
00118 }
00119
00120 double XYAxis::rotation (void) const
00121 {
00122 return _rot;
00123 }
00124
00125 void XYAxis::step (double s)
00126 {
00127 _step = s;
00128 }
00129
00130 double XYAxis::step (void) const
00131 {
00132 return _step;
00133 }
00134
00135 void XYAxis::referenceTick (double f)
00136 {
00137 _referenceTick = f;
00138 }
00139
00140 double XYAxis::referenceTick (void) const
00141 {
00142 return _referenceTick;
00143 }
00144
00145 void XYAxis::leftTick (xybool left)
00146 {
00147 _leftTick = left;
00148 }
00149
00150 xybool XYAxis::leftTick (void) const
00151 {
00152 return _leftTick;
00153 }
00154
00155 double XYAxis::first (void) const
00156 {
00157 double first = _referenceTick;
00158
00159 if (_referenceTick < _mn)
00160 for ( ;first < _mn; first += _step)
00161 ;
00162 else
00163
00164 for ( ;mtLessEqual(_mn, first - _step); first -= _step)
00165 ;
00166
00167 return first;
00168 }
00169
00170 void XYAxis::scaleDecorator(XYScaleDecorator* decor)
00171 {
00172 _decor = decor;
00173 }
00174
00175 XYScaleDecorator* XYAxis::scaleDecorator(void) const
00176 {
00177 return _decor;
00178 }
00179
00180 void XYAxis::arrow (xybool a)
00181 {
00182 _arrow = a;
00183 }
00184
00185 xybool XYAxis::arrow (void) const
00186 {
00187 return _arrow;
00188 }
00189
00190 void XYAxis::title (XYText* t)
00191 {
00192 _title = t;
00193 }
00194
00195 XYText* XYAxis::title (void) const
00196 {
00197 return _title;
00198 }
00199
00200 double XYAxis::transform (double e) const
00201 {
00202 return e;
00203 }
00204
00205 double XYAxis::defineMinPoint(double, int, int) const
00206 {
00207 return _mn;
00208 }
00209
00210 double XYAxis::defineMaxPoint(double, int, int) const
00211 {
00212 return _mx;
00213 }
00214
00215 double XYAxis::valueInPoint(int, int) const
00216 {
00217 return (_mx - _mn) / 2;
00218 }
00219
00220 double XYAxis::valueInPoint(double, double) const
00221 {
00222 return (_mx - _mn) / 2;
00223 }
00224
00225 xybool XYAxis::pick (int px, int py)
00226 {
00227 if (visible() == xyfalse)
00228 return xyfalse;
00229
00230
00231 int x1, y1, x2, y2;
00232 boundingBox (x1, y1, x2, y2);
00233
00234 return mtPointInRect (px, py, x1, y1, x2, y2);
00235 }
00236
00237 xybool XYAxis::fence (int x2, int y2, int x3, int y3)
00238 {
00239 if (visible() == xyfalse)
00240 return xyfalse;
00241
00242
00243 int x0, y0, x1, y1;
00244 boundingBox (x0, y0, x1, y1);
00245
00246 return mtInclude (x0, y0, x1, y1, x2, y2, x3, y3);
00247 }
00248
00249 void XYAxis::firstTick (double& tx1, double& ty1, double& tx2, double& ty2)
00250 const
00251 {
00252 double tick_size = 0.01;
00253
00254
00255 double rot_rad = _rot * XY_PI / 180.0;
00256
00257
00258 double f = (first() - _mn) * _size / (_mx - _mn);
00259
00260
00261 double x0, y0;
00262 position (&x0, &y0);
00263
00264
00265 double x1 = x0 + f * cos (rot_rad);
00266 double y1 = y0 + f * sin (rot_rad);
00267
00268
00269 double x2 = x1 + _size * cos (rot_rad);
00270 double y2 = y1 + _size * sin (rot_rad);
00271
00272
00273 if (mtEqual(x1, x2))
00274 x2 = x1;
00275 if (mtEqual(y1, y2))
00276 y2 = y1;
00277
00278
00279 tx1 = x1;
00280 ty1 = y1;
00281
00282 if (_leftTick)
00283 mtRotate(tick_size, 0.0, rot_rad + XY_PI / 2.0, &tx2, &ty2);
00284 else
00285 mtRotate(tick_size, 0.0, rot_rad - XY_PI / 2.0, &tx2, &ty2);
00286
00287 tx2 += x1;
00288 ty2 += y1;
00289
00290
00291 if (mtEqual(tx1, tx2))
00292 tx2 = tx1;
00293 if (mtEqual(ty1, ty2))
00294 ty2 = ty1;
00295 }
00296
00297 void XYAxis::drawArrow(double x0, double y0, double x1, double y1) const
00298 {
00299
00300 double ca = (x1 - x0) / mtDistance(x0, y0, x1, y1);
00301 double sa = (y1 - y0) / mtDistance(x0, y0, x1, y1);
00302
00303
00304 double as = mtDistance(x0, y0, x1, y1) * _arrow_size;
00305
00306
00307 wdBegin (CD_FILL);
00308 wdVertex(x1 + 0.3333 * as * sa, y1 - 0.3333 * as * ca);
00309 wdVertex(x1 + as * ca, y1 + as * sa);
00310 wdVertex(x1 - 0.3333 * as * sa, y1 + 0.3333 * as * ca);
00311 wdEnd();
00312 }
00313
00314 void XYAxis::boxArrow(double x0, double y0, double x1, double y1, double& xmin,
00315 double& ymin, double& xmax, double& ymax) const
00316 {
00317
00318 double ca = (x1 - x0) / mtDistance(x0, y0, x1, y1);
00319 double sa = (y1 - y0) / mtDistance(x0, y0, x1, y1);
00320
00321
00322 double as = mtDistance(x0, y0, x1, y1) * _arrow_size;
00323
00324
00325 xmin = xmax = x1 + 0.3333 * as * sa;
00326
00327 if (x1 + as * ca < xmin)
00328 xmin = x1 + as * ca;
00329 else if (x1 + as * ca > xmax)
00330 xmax = x1 + as * ca;
00331
00332 if ((x1 - 0.3333 * as * sa) < xmin)
00333 xmin = x1 - 0.3333 * as * sa;
00334 else if ((x1 - 0.3333 * as * sa) > xmax)
00335 xmax = x1 - 0.3333 * as * sa;
00336
00337 ymin = ymax = y1 + 0.3333 * as * ca;
00338
00339 if (y1 + as * sa < ymin)
00340 ymin = y1 + as * sa;
00341 else if (y1 + as * sa > ymax)
00342 ymax = y1 + as * sa;
00343
00344 if ((y1 - 0.3333 * as * ca) < ymin)
00345 ymin = y1 - 0.3333 * as * ca;
00346 else if ((y1 - 0.3333 * as * ca) > ymax)
00347 ymax = y1 - 0.3333 * as * ca;
00348 }
00349
00350 void XYAxis::adjustSize (void)
00351 {
00352 if ((_xmin == _xmax) && (_ymin == _ymax))
00353 return;
00354
00355
00356 double step_n = _step * _size / (_mx - _mn);
00357
00358
00359 double rot_rad = _rot * XY_PI / 180.0;
00360
00361
00362 double dx;
00363 double dy;
00364 mtRotate (step_n, 0, rot_rad, &dx, &dy);
00365
00366
00367 int pdx, pdy;
00368 wdWorld2Canvas (dx, dy, &pdx, &pdy);
00369
00370
00371 wdCanvas2World (pdx, pdy, &dx, &dy);
00372
00373 step_n = mtDistance (dx, 0.0, 0.0, dy);
00374
00375 _size = (_mx - _mn) * step_n / _step;
00376
00377 int pdx1;
00378 wdWorld2Canvas (_step * _size / (_mx - _mn), 0, &pdx1, 0);
00379
00380
00381 }
00382
00383 void XYAxis::calcMinMax(double *min, double *max, double *step) const
00384 {
00385 #define OCUP_MIN 0.8 // taxa de ocupação no eixo
00386 #define MAX_DIGIT 8 // dígitos representados num inteiro
00387 #define MIN_MARCAS 4 // número mínimo de ticks
00388 #define MAX_MARCAS 12 // número máximo de ticks
00389
00390 double y, expo;
00391 int expoente, passo, i;
00392 int imax, imin, resid, rmin, zero, zmin, exces, emin;
00393
00394 if (*max == *min)
00395 if (*max == 0)
00396 {
00397 *max = (double) 1.0;
00398 *min = (double) -1.0;
00399 }
00400 else
00401 {
00402 *max += (double) (0.1 * fabs(*max));
00403 *min -= (double) (0.1 * fabs(*min));
00404 }
00405
00406 if (*max + *min >= 0.0)
00407 y = *max;
00408 else
00409 y = - *min;
00410
00411 expoente = (int) floor(log10(y));
00412 expo = (double) pow(10.0, expoente);
00413
00414 imax = 0;
00415
00416 if (*max >= 0.0)
00417 while (imax * expo < *max) imax++;
00418 else
00419 while ((imax - 1) * expo >= *max) imax--;
00420
00421 imin = 0;
00422
00423 if (*min > 0.0)
00424 while ((imin + 1) * expo <= *min) imin++;
00425 else
00426 while (imin * expo > *min) imin--;
00427
00428 i = 1;
00429
00430 while (((*max - *min) < OCUP_MIN * (imax - imin) * expo) && (i < MAX_DIGIT))
00431 {
00432 i++;
00433 expoente--;
00434 expo = (double) pow(10.0, expoente);
00435
00436 imax = 10 * imax;
00437 imin = 10 * imin;
00438
00439 while ((imax - 1) * expo >= *max)
00440 imax--;
00441 while ((imin + 1) * expo <= *min)
00442 imin++;
00443 }
00444
00445 *step = (double) (imax - imin + 1);
00446
00447 if (*step > MAX_MARCAS)
00448 {
00449 *step = (double) 0;
00450 zmin = 30000;
00451 rmin = 30000;
00452 emin = 30000;
00453
00454 for (i = MIN_MARCAS; i <= MAX_MARCAS; i++)
00455 {
00456 passo = (int) ceil((double) (imax - imin) / (i - 1));
00457
00458 if (imax >= 0 && imin <= 0)
00459 zero = (int) (imin + passo * ceil(- (double) imin / passo));
00460 else
00461 zero = 0;
00462
00463 resid = (i - 1) * passo - (imax - imin);
00464
00465 if (resid >= zero)
00466 exces = 0;
00467 else
00468 exces = zero = resid;
00469
00470 if ((emin != 0 && exces == 0) || ( resid <= rmin && ((emin != 0) ||
00471 (emin == 0 && exces == 0 ))))
00472 {
00473 *step = (double) i;
00474 emin = exces;
00475 rmin = resid;
00476 zmin = zero;
00477 }
00478 }
00479
00480 if (emin == 0)
00481 {
00482 imin -= zmin;
00483 imax += rmin - zmin;
00484 }
00485 else
00486 imin -= rmin;
00487 }
00488 else
00489 while (*step < MIN_MARCAS)
00490 *step += *step - 1;
00491
00492 *max = imax * expo;
00493 *min = imin * expo;
00494 *step = (*max - *min) / (*step - 1);
00495 }
00496