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

xyaxln.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /* Módulo: xyaxln.cpp                                                        */
00003 /* Autores: Carlos Henrique Levy e Jaudênia Cavalcante                       */
00004 /* Data: 06 mar 96                                                           */
00005 /* Comentário:                                                               */
00006 /*    Implementação de métodos da classe especializada que define um eixo    */
00007 /* linear com escala decimal.                                                */
00008 /*****************************************************************************/
00009 
00010 #include <stdlib.h>
00011 #include <math.h>
00012 #include <stdio.h>
00013 
00014 #include "xyaxln.h"
00015 #include "xysdnm.h"
00016                                                                 
00017 const char* xy_id_xyaxln_cpp="$Id: xyaxln.cpp,v 1.24 2001/06/04 21:23:48 clinio Exp $";
00018                                                                 
00019 XYLinearAxis::XYLinearAxis (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,
00032                                                         decorator, title, arrow, visible)
00033 {
00034 }
00035 
00036 XYLinearAxis::XYLinearAxis (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,
00046                                                   visible)
00047 {
00048 }
00049 
00050 double XYLinearAxis::defineMinPoint(double value, int x0, int y0) const
00051 {
00052    setWindow();
00053    setViewport();
00054 
00055    double dx0, dy0;
00056    wdCanvas2World(x0, y0, &dx0, &dy0);
00057 
00058    // ângulo de rotação em radianos
00059    double rot_rad = _rot * XY_PI / 180.0;
00060 
00061    // (x1, y1) ponto inferior esquerdo no eixo
00062    double x1, y1;
00063    position (&x1, &y1);
00064 
00065    // (x2, y2) ponto superior direito no eixo
00066    double x2 = x1 + _size * cos (rot_rad);
00067    double y2 = y1 + _size * sin (rot_rad);
00068 
00069    if (mtEqual(rot_rad, 0.0))
00070       return _mx - (_mx - value) * _size / (x2 - dx0);
00071    else
00072       return _mx - (_mx - value) * _size / (y2 - dy0);
00073 }
00074 
00075 double XYLinearAxis::defineMaxPoint(double value, int x0, int y0) const
00076 {
00077    setWindow();
00078    setViewport();
00079 
00080    double dx0, dy0;
00081    wdCanvas2World(x0, y0, &dx0, &dy0);
00082 
00083    // ângulo de rotação em radianos
00084    double rot_rad = _rot * XY_PI / 180.0;
00085 
00086    // (x1, y1) ponto inferior esquerdo no eixo
00087    double x1, y1;
00088    position (&x1, &y1);
00089 
00090    if (mtEqual(sin(rot_rad), 0.0))
00091      return _mn + (value - _mn) * size() / (dx0 - x1);
00092    else
00093      return _mn + (value - _mn) * size() / (dy0 - y1);
00094 }
00095 
00096 double XYLinearAxis::valueInPoint(int x0, int y0) const
00097 {
00098    // salva window e viewport para restaurar no final da funcao
00099    double ow_xmin,ow_xmax,ow_ymin,ow_ymax;
00100    int oc_xmin, ov_xmax, ov_ymin, ov_ymax;
00101    wdGetWindow(&ow_xmin,&ow_xmax,&ow_ymin,&ow_ymax);
00102    wdGetViewport(&oc_xmin,&ov_xmax,&ov_ymin,&ov_ymax);
00103    setWindow();
00104    setViewport();
00105 
00106    double dx0, dy0;
00107    wdCanvas2World(x0, y0, &dx0, &dy0);
00108 
00109    // ângulo de rotação em radianos
00110    double rot_rad = _rot * XY_PI / 180.0;
00111 
00112    // (x1, y1) ponto inferior esquerdo no eixo
00113    double x1, y1;
00114    position (&x1, &y1);
00115    
00116    double value;
00117    if (mtEqual(sin(rot_rad), 0.0))
00118       value = _mn + (dx0 - x1) * (_mx - _mn) / size();
00119    else
00120       value = _mn + (dy0 - y1) * (_mx - _mn) / size();
00121 
00122    wdWindow(ow_xmin,ow_xmax,ow_ymin,ow_ymax);
00123    wdViewport(oc_xmin, ov_xmax, ov_ymin, ov_ymax);
00124 
00125    return value;
00126 }
00127 
00128 double XYLinearAxis::valueInPoint(double x0, double y0) const
00129 {
00130    // salva window e viewport para restaurar no final da funcao
00131    double ow_xmin,ow_xmax,ow_ymin,ow_ymax;
00132    int oc_xmin, ov_xmax, ov_ymin, ov_ymax;
00133    wdGetWindow(&ow_xmin,&ow_xmax,&ow_ymin,&ow_ymax);
00134    wdGetViewport(&oc_xmin,&ov_xmax,&ov_ymin,&ov_ymax);
00135 
00136    // ângulo de rotação em radianos
00137    double rot_rad = _rot * XY_PI / 180.0;
00138 
00139    // (x1, y1) ponto inferior esquerdo no eixo
00140    double x1, y1;
00141    position (&x1, &y1);
00142 
00143    double value;
00144    if (mtEqual(sin(rot_rad), 0.0))
00145       value = _mn + (x0 - x1) * (_mx - _mn) / size();
00146    else
00147       value = _mn + (y0 - y1) * (_mx - _mn) / size();
00148 
00149    wdWindow(ow_xmin,ow_xmax,ow_ymin,ow_ymax);
00150    wdViewport(oc_xmin, ov_xmax, ov_ymin, ov_ymax);
00151 
00152    return value;
00153 }
00154 
00155 void XYLinearAxis::pointInValue(double value, int& x0, int& y0) const
00156 {
00157    // salva window e viewport para restaurar no final da funcao
00158    double ow_xmin,ow_xmax,ow_ymin,ow_ymax;
00159    int oc_xmin, ov_xmax, ov_ymin, ov_ymax;
00160    wdGetWindow(&ow_xmin,&ow_xmax,&ow_ymin,&ow_ymax);
00161    wdGetViewport(&oc_xmin,&ov_xmax,&ov_ymin,&ov_ymax);
00162 
00163    setWindow();
00164    setViewport();
00165 
00166    // ângulo de rotação em radianos
00167    double rot_rad = _rot * XY_PI / 180.0;
00168 
00169    // (x1, y1) ponto inferior esquerdo no eixo
00170    double x1, y1;
00171    position (&x1, &y1);
00172 
00173    // (x1, y1) ponto inicial do marcador em relação a área de desenho
00174    double dx0 = x1 + (value - _mn) * _size / (_mx - _mn) * cos (rot_rad);
00175    double dy0 = y1 + (value - _mn) * _size / (_mx - _mn) * sin (rot_rad);
00176 
00177    wdWorld2Canvas(dx0, dy0, &x0, &y0);
00178 
00179    wdWindow(ow_xmin,ow_xmax,ow_ymin,ow_ymax);
00180    wdViewport(oc_xmin, ov_xmax, ov_ymin, ov_ymax);
00181 }
00182 
00183 void XYLinearAxis::pointInValue(double value, double& x0, double& y0) const
00184 {
00185    // salva window e viewport para restaurar no final da funcao
00186    double ow_xmin,ow_xmax,ow_ymin,ow_ymax;
00187    int oc_xmin, ov_xmax, ov_ymin, ov_ymax;
00188    wdGetWindow(&ow_xmin,&ow_xmax,&ow_ymin,&ow_ymax);
00189    wdGetViewport(&oc_xmin,&ov_xmax,&ov_ymin,&ov_ymax);
00190 
00191    // ângulo de rotação em radianos
00192    double rot_rad = _rot * XY_PI / 180.0;
00193 
00194    // (x1, y1) ponto inferior esquerdo no eixo
00195    double x1, y1;
00196    position (&x1, &y1);
00197 
00198    // (x1, y1) ponto inicial do marcador em relação a área de desenho
00199    x0 = x1 + (value - _mn) * _size / (_mx - _mn) * cos (rot_rad);
00200    y0 = y1 + (value - _mn) * _size / (_mx - _mn) * sin (rot_rad);
00201 
00202    wdWindow(ow_xmin,ow_xmax,ow_ymin,ow_ymax);
00203    wdViewport(oc_xmin, ov_xmax, ov_ymin, ov_ymax);
00204 }
00205 
00206 void XYLinearAxis::draw (void)
00207 {
00208    draw (_xmin, _ymin, _xmax, _ymax);
00209 }
00210 
00211 void XYLinearAxis::draw (int xmin, int ymin, int xmax, int ymax) const
00212 {
00213    if (visible() == xyfalse)    // invisível!!!
00214       return;
00215 
00216    int mode = cdClip(CD_CLIPON);
00217 
00218    // guarda a região de clip corrente
00219    int oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax;
00220    cdGetClipArea (&oldclip_xmin, &oldclip_xmax, &oldclip_ymin, &oldclip_ymax);
00221    // define nova região de clip
00222    cdClipArea(xmin, xmax, ymin, ymax);
00223 
00224    // ângulo de rotação em radianos
00225    double rot_rad = _rot * XY_PI / 180.0;
00226 
00227    // (x1, y1) ponto inferior esquerdo no eixo
00228    double x1, y1;
00229    position (&x1, &y1);
00230 
00231    // (x2, y2) ponto superior direito no eixo
00232    double x2 = x1 + _size * cos (rot_rad);
00233    double y2 = y1 + _size * sin (rot_rad);
00234 
00235    // controle de ponto flutuante
00236    if (mtEqual(x1, x2))
00237       x2 = x1;
00238    if (mtEqual(y1, y2))
00239       y2 = y1;
00240 
00241    // desenha eixo com linha sólida e com cor definida
00242    // pelo usuário
00243    cdLineWidth (2);
00244    cdLineStyle (continuous);
00245    cdForeground (_color);
00246 
00247    // desenha eixo
00248    wdLine (x1, y1, x2, y2);
00249 
00250    // desenha seta no eixo
00251    if (_arrow == xytrue)
00252    {
00253       cdInteriorStyle (CD_SOLID);
00254       drawArrow(x1, y1, x2, y2);
00255    }
00256 
00257    // desenha a escala se ela foi definida e se passo tem um valor válido
00258    if (_step > 0.0)
00259    {
00260       // calcula coordenadas do primeiro tick
00261       double ex1, ey1, ex2, ey2;
00262       firstTick (ex1, ey1, ex2, ey2);
00263 
00264       // intervalos de deslocamento em relação as direções x e y
00265       double dx, dy;
00266       mtRotate (_step * _size / (_mx - _mn), 0.0, rot_rad, &dx, &dy);
00267 
00268       // calcula qual é o último tick a ser desenhado, o método é verificar,
00269       // a partir do último, qual é o primeiro tick que está dentro da área
00270       // a ser redesenhada
00271       int last_tick = (int) floor ((_mx - first()) / _step);
00272 
00273       // inicializa com posição do último tick
00274       double tex1 = ex1 + dx * last_tick;
00275       double tey1 = ey1 + dy * last_tick;
00276       double tex2 = ex2 + dx * last_tick;
00277       double tey2 = ey2 + dy * last_tick;
00278 
00279       // normalizando a área de desenho
00280       double pxmin = (double) (xmin - _xmin) / (_xmax - _xmin);
00281       double pymin = (double) (ymin - _ymin) / (_ymax - _ymin);
00282       double pxmax = (double) (xmax - _xmin) / (_xmax - _xmin);
00283       double pymax = (double) (ymax - _ymin) / (_ymax - _ymin);
00284 
00285       // verifica se tick está dentro da área a ser redesenhada
00286       while ((mtPointInRect(tex1, tey1, pxmin, pymin, pxmax, pymax) != xytrue)
00287              && (last_tick >= 0))
00288       {
00289          // próximo tick
00290          tex1 -= dx;
00291          tex2 -= dx;
00292          tey1 -= dy;
00293          tey2 -= dy;
00294 
00295          // atualiza número do último tick
00296          last_tick--;
00297       }
00298 
00299       // retorna, se não há tick para ser desenhado
00300       if (last_tick < 0)
00301             {
00302                cdClip(mode);
00303          // restaura a região de clip anterior
00304          cdClipArea(oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax);
00305                return;
00306             }
00307 
00308       // calcula qual é o primeiro tick a ser desenhado, o método é verificar,
00309       // a partir do primeiro, qual é o primeiro tick que está dentro da área
00310       // a ser redesenhada
00311       int first_tick = 0;
00312 
00313       // verifica se tick está dentro da área a ser redesenhada
00314       while ((mtPointInRect(ex1, ey1, pxmin, pymin, pxmax, pymax) != xytrue)
00315              && (first_tick < last_tick))
00316       {
00317          // próximo tick
00318          ex1 += dx;
00319          ex2 += dx;
00320          ey1 += dy;
00321          ey2 += dy;
00322 
00323          // atualiza número do primeiro tick
00324          first_tick++;
00325       }
00326         
00327       // desenha todos ticks presentes na area de redesenho
00328       for (int ntick = first_tick; ntick <= last_tick; ++ntick)
00329       {
00330          // desenha tick
00331          wdLine(ex1, ey1, ex2, ey2);
00332 
00333          // próximo tick
00334          ex1 += dx;
00335                ex2 += dx;
00336                ey1 += dy;
00337                ey2 += dy;
00338       }
00339 
00340       // desenha a decoração da escala
00341       if (_decor)
00342          _decor -> draw (this, first_tick, last_tick);
00343    }
00344 
00345    // desenha título se o mesmo foi definido, indicando localização na linha,
00346    // se direita, centro ou esquerda
00347    if (_title)
00348    {
00349       // consulta área do gráfico para desenho do eixo
00350       int xmn, ymn, xmx, ymx;
00351       getViewport(xmn, xmx, ymn, ymx);
00352 
00353       // define área do gráfico para desenho do título do eixo
00354       _title -> setViewport(xmn, xmx, ymn, ymx);
00355       _title -> draw();
00356    }
00357 
00358    cdClip(mode);
00359    cdClipArea(oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax);
00360 }
00361 
00362 void XYLinearAxis::boundingBox (int& bxmin, int& bymin, int& bxmax, int& bymax)
00363                                             const
00364 {
00365    // ângulo de rotação em radianos
00366    double rot_rad = _rot * XY_PI / 180.0;
00367 
00368    // (x1, y1) ponto inferior esquerdo no eixo
00369    double x1, y1;
00370    position (&x1, &y1);
00371 
00372    // (x2, y2) ponto superior direito no eixo
00373    double x2 = x1 + _size * cos (rot_rad);
00374    double y2 = y1 + _size * sin (rot_rad);
00375 
00376    // controle de ponto flutuante
00377    if (mtEqual(x1, x2))
00378       x2 = x1;
00379    if (mtEqual(y1, y2))
00380       y2 = y1;
00381 
00382    // inicializando boundingBox com coordenadas do eixo
00383    double xmin = MIN(x1, x2);
00384    double ymin = MIN(y1, y2);
00385    double xmax = MAX(x1, x2);
00386    double ymax = MAX(y1, y2);
00387 
00388    // calcula boundingBox da seta do eixo
00389    if (_arrow == xytrue)
00390    {
00391       double bx1, bx2, by1, by2;
00392       boxArrow(x1, y1, x2, y2, bx1, by1, bx2, by2);
00393 
00394       xmin = MIN(bx1, xmin);
00395       xmax = MAX(bx2, xmax);
00396       ymin = MIN(by1, ymin);
00397       ymax = MAX(by2, ymax);
00398    }
00399 
00400    // contabiliza boundingBox da escala se a mesma foi definida e se passo tem
00401    // um valor válido
00402    if (_step > 0.0)
00403    {
00404       // atualiza boundingBox com as coordenadas do primeiro tick
00405       double ex1, ey1, ex2, ey2;
00406       firstTick (ex1, ey1, ex2, ey2);
00407 
00408       xmin = MIN3 (xmin, ex1, ex2);
00409       xmax = MAX3 (xmax, ex1, ex2);
00410       ymin = MIN3 (ymin, ey1, ey2);
00411       ymax = MAX3 (ymax, ey1, ey2);
00412 
00413       int bex1, bey1, bex2, bey2;
00414 
00415       // atualiza boundingBox com as coordenadas da decoração da escala
00416       if (_decor)
00417          _decor -> boundingBox (this, bex1, bey1, bex2, bey2);
00418 
00419       wdCanvas2World (bex1, bey1, &ex1, &ey1);
00420       wdCanvas2World (bex2, bey2, &ex2, &ey2);
00421 
00422       xmin = MIN3 (xmin, ex1, ex2);
00423       xmax = MAX3 (xmax, ex1, ex2);
00424       ymin = MIN3 (ymin, ey1, ey2);
00425       ymax = MAX3 (ymax, ey1, ey2);
00426    }
00427 
00428    // boundingBox em pixels
00429    wdWorld2Canvas (xmin, ymin, &bxmin, &bymin);
00430    wdWorld2Canvas (xmax, ymax, &bxmax, &bymax);
00431 }
00432 

XY
Tecgraf / PUC-Rio - Computer Graphics Technology Group