Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

xyaxlg.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /* Módulo: xyaxlg.cpp                                                        */
00003 /* Autores: Carlos Henrique Levy e Jaudênia Cavalcante                       */
00004 /* Data: 02 maio 96                                                          */
00005 /* Comentário:                                                               */
00006 /*    Implementação de métodos da classe especializada que define um eixo    */
00007 /* com escala logaritmica.                                                   */
00008 /*****************************************************************************/
00009 
00010 #include <stdlib.h>
00011 #include <math.h>
00012 #include <stdio.h>
00013 
00014 #include "xyaxlg.h"
00015 #include "xysdlg.h"
00016                                                                 
00017 const char* xy_id_xyaxlg_cpp="$Id: xyaxlg.cpp,v 1.24 2003/01/03 16:10:34 clinio Exp $";
00018                                                                 
00019 XYLogAxis::XYLogAxis (double mn,
00020                             double mx,
00021                       XYCoordinate x,
00022                       XYCoordinate y,
00023                             long color,
00024                             double size,
00025                             double rot,
00026                             double step,
00027                               XYScaleDecorator* decorator,
00028                             XYText* title,
00029                             xybool arrow,
00030                             xybool visible)
00031                             : XYAxis (mn, mx, x, y, color, size, rot, step, decorator,
00032                                       title, arrow, visible)
00033 {
00034 }
00035 
00036 XYLogAxis::XYLogAxis (double mn,
00037                             double mx,
00038                       XYCoordinate x,
00039                       XYCoordinate y,
00040                             long color,
00041                             double size,
00042                             double rot,
00043                             xybool arrow,
00044                             xybool visible)
00045                             : XYAxis (mn, mx, x, y, color, size, rot, arrow, visible)
00046 {                                       
00047 }
00048 
00049 double XYLogAxis::transform (double e) const
00050 {
00051    if (fabs(e) <= 1e-50) return -1000.0;
00052    double value = log10(e);
00053    return value;
00054 }
00055 
00056 double XYLogAxis::defineMinPoint(double value, int x0, int y0) const
00057 {
00058    setWindow();
00059    setViewport();
00060 
00061    double dx0, dy0;
00062    wdCanvas2World(x0, y0, &dx0, &dy0);
00063 
00064    // ângulo de rotação em radianos
00065    double rot_rad = _rot * XY_PI / 180.0;
00066 
00067    // (x1, y1) ponto inferior esquerdo no eixo
00068    double x1, y1;
00069    position (&x1, &y1);
00070 
00071    // (x2, y2) ponto superior direito no eixo
00072    double x2 = x1 + _size * cos (rot_rad);
00073    double y2 = y1 + _size * sin (rot_rad);
00074 
00075    double min;
00076 
00077    if (rot_rad == 0.0)
00078       min = _mx - (_mx - value) * _size / (x2 - dx0);
00079    else
00080       min = _mx - (_mx - value) * _size / (y2 - dy0);
00081 
00082    return min;
00083 }
00084 
00085 double XYLogAxis::defineMaxPoint(double value, int x0, int y0) const
00086 {
00087    setWindow();
00088    setViewport();
00089 
00090    double dx0, dy0;
00091    wdCanvas2World(x0, y0, &dx0, &dy0);
00092 
00093    // ângulo de rotação em radianos
00094    double rot_rad = _rot * XY_PI / 180.0;
00095 
00096    // (x1, y1) ponto inferior esquerdo no eixo
00097    double x1, y1;
00098    position (&x1, &y1);
00099 
00100    double max;
00101 
00102    if (rot_rad == 0.0)
00103       max = _mn + (value - _mn) * size() / (dx0 - x1);
00104    else
00105       max = _mn + (value - _mn) * size() / (dy0 - y1);
00106 
00107    return max;
00108 }
00109 
00110 double XYLogAxis::valueInPoint(int x0, int y0) const
00111 {
00112     // salva window e viewport para restaurar no final da funcao
00113    double ow_xmin,ow_xmax,ow_ymin,ow_ymax;
00114    int oc_xmin, ov_xmax, ov_ymin, ov_ymax;
00115    wdGetWindow(&ow_xmin,&ow_xmax,&ow_ymin,&ow_ymax);
00116    wdGetViewport(&oc_xmin,&ov_xmax,&ov_ymin,&ov_ymax);
00117  
00118    setWindow();
00119    setViewport();
00120 
00121    double dx0, dy0;
00122    wdCanvas2World(x0, y0, &dx0, &dy0);
00123 
00124    // ângulo de rotação em radianos
00125    double rot_rad = _rot * XY_PI / 180.0;
00126 
00127    // (x1, y1) ponto inferior esquerdo no eixo
00128    double x1, y1;
00129    position (&x1, &y1);
00130 
00131    double value;
00132 
00133    if (rot_rad == 0.0)
00134       value = log10(_mn) + (dx0 - x1) * (log10(_mx) - log10(_mn)) / size();
00135    else
00136       value = log10(_mn) + (dy0 - y1) * (log10(_mx) - log10(_mn)) / size();
00137 
00138    wdWindow(ow_xmin,ow_xmax,ow_ymin,ow_ymax);
00139    wdViewport(oc_xmin, ov_xmax, ov_ymin, ov_ymax);
00140 
00141    return pow(10,value);
00142 }
00143 
00144 double XYLogAxis::valueInPoint(double x0, double y0) const
00145 {
00146    // salva window e viewport para restaurar no final da funcao
00147    double ow_xmin,ow_xmax,ow_ymin,ow_ymax;
00148    int oc_xmin, ov_xmax, ov_ymin, ov_ymax;
00149    wdGetWindow(&ow_xmin,&ow_xmax,&ow_ymin,&ow_ymax);
00150    wdGetViewport(&oc_xmin,&ov_xmax,&ov_ymin,&ov_ymax);
00151 
00152    // ângulo de rotação em radianos
00153    double rot_rad = _rot * XY_PI / 180.0;
00154 
00155    // (x1, y1) ponto inferior esquerdo no eixo
00156    double x1, y1;
00157    position (&x1, &y1);
00158 
00159    double value;
00160    if (rot_rad == 0.0)
00161       value = log10(_mn) + (x0 - x1) * ( log10(_mx) - log10(_mn) ) / size();
00162    else
00163       value = log10(_mn) + (y0 - y1) * ( log10(_mx) - log10(_mn) ) / size();
00164 
00165    wdWindow(ow_xmin,ow_xmax,ow_ymin,ow_ymax);
00166    wdViewport(oc_xmin, ov_xmax, ov_ymin, ov_ymax);
00167 
00168    return pow(10,value);
00169 }
00170 
00171 void XYLogAxis::pointInValue(double value, int& x0, int& y0) const
00172 {
00173    // salva window e viewport para restaurar no final da funcao
00174    double ow_xmin,ow_xmax,ow_ymin,ow_ymax;
00175    int oc_xmin, ov_xmax, ov_ymin, ov_ymax;
00176    wdGetWindow(&ow_xmin,&ow_xmax,&ow_ymin,&ow_ymax);
00177    wdGetViewport(&oc_xmin,&ov_xmax,&ov_ymin,&ov_ymax);
00178 
00179    setWindow();
00180    setViewport();
00181 
00182    // ângulo de rotação em radianos
00183    double rot_rad = _rot * XY_PI / 180.0;
00184 
00185    // (x1, y1) ponto inferior esquerdo no eixo
00186    double x1, y1;
00187    position (&x1, &y1);
00188 
00189    // (x1, y1) ponto inicial do marcador em relação a área de desenho
00190    double dx0 = x1 + (log10(value) - log10(_mn)) * _size / (log10(_mx) - log10(_mn)) * cos (rot_rad);
00191    double dy0 = y1 + (log10(value) - log10(_mn)) * _size / (log10(_mx) - log10(_mn)) * sin (rot_rad);
00192 
00193    wdWorld2Canvas(dx0, dy0, &x0, &y0);
00194    // x0 = (int)pow(10,x0);
00195    // y0 = (int)pow(10,y0);
00196 
00197    wdWindow(ow_xmin,ow_xmax,ow_ymin,ow_ymax);
00198    wdViewport(oc_xmin, ov_xmax, ov_ymin, ov_ymax);
00199 
00200 }
00201 
00202 void XYLogAxis::pointInValue(double value, double& x0, double& y0) const
00203 {
00204    // salva window e viewport para restaurar no final da funcao
00205    double ow_xmin,ow_xmax,ow_ymin,ow_ymax;
00206    int oc_xmin, ov_xmax, ov_ymin, ov_ymax;
00207    wdGetWindow(&ow_xmin,&ow_xmax,&ow_ymin,&ow_ymax);
00208    wdGetViewport(&oc_xmin,&ov_xmax,&ov_ymin,&ov_ymax);
00209 
00210    // ângulo de rotação em radianos
00211    double rot_rad = _rot * XY_PI / 180.0;
00212 
00213    // (x1, y1) ponto inferior esquerdo no eixo
00214    double x1, y1;
00215    position (&x1, &y1);
00216 
00217    // (x1, y1) ponto inicial do marcador em relação a área de desenho
00218    x0 = x1 + (log10(value) - log10(_mn)) * _size / (log10(_mx) - log10(_mn)) * cos (rot_rad);
00219    y0 = y1 + (log10(value) - log10(_mn)) * _size / (log10(_mx) - log10(_mn)) * sin (rot_rad);
00220 
00221    // x0 = pow(10,x0);
00222    // y0 = pow(10,y0);
00223 
00224    wdWindow(ow_xmin,ow_xmax,ow_ymin,ow_ymax);
00225    wdViewport(oc_xmin, ov_xmax, ov_ymin, ov_ymax);
00226 }
00227 
00228 void XYLogAxis::draw (void)
00229 {
00230    draw (_xmin, _ymin, _xmax, _ymax);
00231 }
00232 
00233 void XYLogAxis::draw (int xmin, int ymin, int xmax, int ymax) const
00234 {
00235    if (visible() == xyfalse) return;
00236 
00237    int mode = cdClip(CD_CLIPON);        
00238 
00239    // guarda a região de clip corrente
00240    int oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax;
00241    cdGetClipArea (&oldclip_xmin, &oldclip_xmax, &oldclip_ymin, &oldclip_ymax);
00242    // define nova região de clip
00243    cdClipArea(xmin, xmax, ymin, ymax);
00244 
00245    // ângulo de rotação em radianos
00246    double rot_rad = _rot * XY_PI / 180.0;
00247 
00248    // (x1, y1) ponto inferior esquerdo no eixo
00249    double x1, y1;
00250    position (&x1, &y1);
00251 
00252    // (x2, y2) ponto superior direito no eixo
00253    double x2 = x1 + _size * cos (rot_rad);
00254    double y2 = y1 + _size * sin (rot_rad);
00255 
00256    // controle de ponto flutuante
00257    if (mtEqual(x1, x2)) x2 = x1;
00258    if (mtEqual(y1, y2)) y2 = y1;
00259 
00260    // desenha eixo com linha sólida mais fina possível e com cor definida
00261    // pelo usuário
00262    cdLineWidth (2);
00263    cdLineStyle (continuous);
00264    cdForeground (_color);
00265 
00266    // desenha eixo
00267    wdLine (x1, y1, x2, y2);
00268 
00269    // desenha seta no eixo
00270    if (_arrow == xytrue)
00271    {
00272       cdInteriorStyle (CD_SOLID);
00273       drawArrow(x1, y1, x2, y2);
00274    }
00275 
00276    // desenha a escala se ela foi definida e se passo tem um valor válido
00277    if (_step > 0.0)
00278    {
00279       double xorigin, yorigin;
00280       position(&xorigin, &yorigin);
00281 
00282       double decade_step;
00283       for( double val = _mn; val <= _mx; val += decade_step *_step )
00284       {
00285         int current_decade = mtDecade( val );
00286         decade_step = pow( 10, current_decade );
00287         double dx, dy;
00288         mtRotate( (log10(val)-log10(_mn))*_size / (log10(_mx)-log10(_mn)), 0.0, 
00289               rot_rad, &dx, &dy);
00290 
00291         double xtick = xorigin + dx;
00292         double ytick = yorigin + dy;
00293 
00294         cdMarkType( CD_PLUS );
00295         wdMarkSize( 1.0 );
00296              wdMark(xtick, ytick);
00297              // printf( "%f %f\n", val, decade_step *_step ); fflush(stdout);
00298       }
00299       
00300       // desenha a decoração da escala
00301        if (_decor)
00302            _decor -> draw(this, 0, 0 ); // first_tick, last_tick);
00303         
00304    }
00305 
00306    // desenha título se o mesmo foi definido, indicando localização na linha,
00307    // se direita, centro ou esquerda
00308    if (_title)
00309    {
00310       // consulta área do gráfico para desenho do eixo
00311       int xmn, ymn, xmx, ymx;
00312       getViewport(xmn, xmx, ymn, ymx);
00313 
00314       // define área do gráfico para desenho do título do eixo
00315             _title -> setViewport(xmn, xmx, ymn, ymx);
00316       _title -> draw();
00317    }
00318 
00319    cdClip(mode);
00320    // restaura a região de clip anterior
00321    cdClipArea(oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax);
00322 }
00323                                                         
00324 void XYLogAxis::boundingBox (int& bxmin, int& bymin, int& bxmax, int& bymax)
00325                                          const
00326 {                                                                       
00327    // ângulo de rotação em radianos
00328    double rot_rad = _rot * XY_PI / 180.0;
00329 
00330    // (x1, y1) ponto inferior esquerdo no eixo
00331    double x1, y1;
00332    position (&x1, &y1);
00333 
00334    // (x2, y2) ponto superior direito no eixo
00335    double x2 = x1 + _size * cos (rot_rad);
00336    double y2 = y1 + _size * sin (rot_rad);
00337 
00338    // controle de ponto flutuante
00339    if (mtEqual(x1, x2))
00340       x2 = x1;
00341    if (mtEqual(y1, y2))
00342       y2 = y1;
00343 
00344    // inicializando boundinBox com coordenadas do eixo
00345    double xmin = MIN(x1, x2);
00346    double ymin = MIN(y1, y2);
00347    double xmax = MAX(x1, x2);
00348    double ymax = MAX(y1, y2);
00349 
00350    // calcula boundinBox da seta do eixo
00351    if (_arrow == xytrue)
00352    {
00353       double bx1, bx2, by1, by2;
00354       boxArrow(x1, y1, x2, y2, bx1, by1, bx2, by2);
00355 
00356       xmin = MIN(bx1, xmin);
00357       xmax = MAX(bx2, xmax);
00358       ymin = MIN(by1, ymin);
00359       ymax = MAX(by2, ymax);
00360    }
00361 
00362    // contabiliza boundingBox da escala se a mesma foi definida e se passo tem
00363    // um valor válido
00364    if (_step > 0.0)
00365    {
00366       // atualiza boundingBox com as coordenadas do primeiro tick
00367       double ex1, ey1, ex2, ey2;
00368       firstTick (ex1, ey1, ex2, ey2);
00369 
00370       xmin = MIN3 (xmin, ex1, ex2);
00371       xmax = MAX3 (xmax, ex1, ex2);
00372       ymin = MIN3 (ymin, ey1, ey2);
00373       ymax = MAX3 (ymax, ey1, ey2);
00374 
00375       int bex1, bey1, bex2, bey2;
00376 
00377       // atualiza boundingBox com as coordenadas da decoração da escala
00378       if (_decor)
00379          _decor -> boundingBox (this, bex1, bey1, bex2, bey2);
00380 
00381       wdCanvas2World (bex1, bey1, &ex1, &ey1);
00382       wdCanvas2World (bex2, bey2, &ex2, &ey2);
00383 
00384       xmin = MIN3 (xmin, ex1, ex2);
00385       xmax = MAX3 (xmax, ex1, ex2);
00386       ymin = MIN3 (ymin, ey1, ey2);
00387       ymax = MAX3 (ymax, ey1, ey2);
00388    }
00389 
00390    // boundingBox em pixels
00391    wdWorld2Canvas (xmin, ymin, &bxmin, &bymin);
00392    wdWorld2Canvas (xmax, ymax, &bxmax, &bymax);
00393 }
00394 

XY
Tecgraf / PUC-Rio - Computer Graphics Technology Group