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

xygrid.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /* Módulo: xygrid.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 tipo    */
00007 /* especial de eixo que desenha linhas perpendiculares ao ângulo de rotação  */
00008 /* em toda a região de desenho das máscaras do gráfico (mask area), começan  */
00009 /* do numa posição específica com intervalo entre as linhas definido pelo    */
00010 /* usuário.                                                                  */
00011 /*****************************************************************************/
00012 
00013 #include <stdlib.h>
00014 #include <math.h>
00015 #include <stdio.h>
00016 
00017 #include "xygrid.h"
00018 
00019 const char* xy_id_xygrid_cpp="$Id: xygrid.cpp,v 1.16 1999/12/09 21:47:46 rborges Exp $";
00020                                                                 
00021 XYGrid::XYGrid (double mn,
00022                       double mx,
00023                       double p,
00024                       long color,
00025                       double rot,
00026                       double step,
00027                       xybool visible)
00028                       : XYAxis(mn, mx, 0., 0., color, 1.0, rot, step, xyfalse, visible),
00029                               _limit(0.),
00030                                     _style(continuous)
00031 {
00032    referenceTick(p);
00033 }
00034 
00035 XYGrid::XYGrid (double mn,
00036                       double mx,
00037                       double p,
00038                       long color,
00039                 int style,
00040                       double rot,
00041                       double step,
00042                       xybool visible)
00043                       : XYAxis(mn, mx, 0., 0., color, 1.0, rot, step, xyfalse, visible),
00044                               _limit(0.),
00045                                     _style(style)
00046 {
00047    referenceTick(p);
00048 }
00049 
00050 void XYGrid::limit (double h)
00051 {
00052    _limit = h;
00053 }
00054 
00055 double XYGrid::limit (void) const
00056 {
00057    return _limit;
00058 }
00059 
00060 void XYGrid::style (int s)
00061 {
00062    _style = s;
00063 }
00064 
00065 int XYGrid::style (void) const
00066 {
00067    return _style;
00068 }
00069 
00070 xybool XYGrid::pointInGrid (int px, int py, int x0, int y0, int x1, int y1)
00071 {
00072    if ((x0 == x1) && (x1 == px))
00073       if ((y0 <= py) && (py <= y1))
00074                return xytrue;
00075 
00076    if ((y0 == y1) && (y1 == py))
00077       if ((x0 <= px) && (px <= x1))
00078                return xytrue;
00079 
00080    return xyfalse;
00081 }
00082 
00083 xybool XYGrid::pick (int px, int py)
00084 {
00085    if (visible() == xyfalse)    // invisível!!!
00086       return xyfalse;
00087 
00088    // ângulo de rotação em radianos
00089    double rot_rad = _rot * XY_PI / 180.0;
00090 
00091    // primeira posição normalizada na grade em relação ao canvas
00092    double f = (first() - _mn) * _size / (_mx - _mn);
00093 
00094    // passo normalizado na grade em relação ao canvas
00095    double s = _step * _size / (_mx - _mn);
00096 
00097    // intervalo de deslocamento em relação as direções x e y
00098    double dx;
00099    double dy;
00100    mtRotate (s, 0, rot_rad, &dx, &dy);
00101 
00102    // (x0, y0) ponto inferior esquerdo da grade em relação ao canvas
00103    double x0, y0;
00104    position (&x0, &y0);
00105 
00106    // (x1, y1) ponto inferior esquerdo da primeira linha da grade, 
00107    // em coordenadas normalizadas
00108    double x1 = x0 + f * cos (rot_rad);
00109    double y1 = y0 + f * sin (rot_rad);
00110 
00111    // (x2, y2) ponto superior direito da primeira linha da grade, 
00112    // em coordenadas normalizadas
00113    double x2 = x1 + limit() * sin (rot_rad);
00114    double y2 = y1 + limit() * cos (rot_rad);
00115 
00116    // posição no eixo da primeira linha da grade
00117    double first = this -> first();
00118 
00119    // posição no eixo da última linha da grade
00120    double q = _mx;                                              
00121 
00122    int px1, py1, px2, py2;
00123 
00124    for (double p = first; p <= q; p += _step)
00125    {
00126       // controle de ponto flutuante
00127       if (mtEqual(x1, x2))
00128          x2 = x1;
00129       if (mtEqual(y1, y2))
00130          y2 = y1;
00131 
00132       // converte coordenadas do mundo para coordenadas em pixels
00133       wdWorld2Canvas (x1, y1, &px1, &py1);
00134       wdWorld2Canvas (x2, y2, &px2, &py2);
00135 
00136       // verifica se o ponto está sobre uma linha da grade
00137       if (pointInGrid(px, py, px1, py1, px2, py2))
00138          return xytrue;
00139 
00140       // próxima linha da grade
00141       x1 += dx;
00142       x2 += dx;
00143       y1 += dy;
00144       y2 += dy;
00145    }
00146 
00147    return xyfalse;
00148 }
00149 
00150 int XYGrid::worldSize2PixelSize (double w) const
00151 {
00152    // ângulo de rotação em radianos
00153    double rot_rad = _rot * XY_PI / 180.0;
00154 
00155    w = (transform(w) - transform(_mn)) * _size
00156      / (transform(_mx) - transform(_mn));
00157 
00158    // intervalo de deslocamento em relação as direções x e y
00159    double dx;
00160    double dy;
00161    mtRotate (w, 0, rot_rad, &dx, &dy);
00162 
00163    // calcula o passo, em pixels
00164    int pdx,pdy;
00165    wdWorld2Canvas (dx, dy, &pdx, &pdy);
00166 
00167    return (int) mtDistance(pdx, 0, 0, pdy);
00168 }
00169 
00170 void XYGrid::draw (void)
00171 {
00172    draw (_xmin, _ymin, _xmax, _ymax);
00173 }
00174 
00175 void XYGrid::draw (int xmin, int ymin, int xmax, int ymax) const
00176 {
00177    if (visible() == xyfalse)    // invisível!!!
00178       return;
00179 
00180    // ângulo de rotação em radianos
00181    double rot_rad = _rot * XY_PI / 180.0;
00182 
00183    // primeira posição normalizada na grade em relação ao canvas
00184    double f = (first() - _mn) * _size / (_mx - _mn);
00185 
00186    // passo normalizado na grade em relação ao canvas
00187    double s = _step * _size / (_mx - _mn);
00188 
00189    // verifica se a grade é muito compacta
00190    if (s <= 0.01)
00191       return;
00192 
00193    int mode = cdClip(CD_CLIPON);
00194 
00195    // guarda a região de clip corrente
00196    int oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax;
00197    cdGetClipArea (&oldclip_xmin, &oldclip_xmax, &oldclip_ymin, &oldclip_ymax);
00198 
00199    // define nova região de clip
00200    cdClipArea(xmin, xmax, ymin, ymax);
00201 
00202    // intervalo de deslocamento em relação as direções x e y
00203    double dx;
00204    double dy;
00205    mtRotate (s, 0, rot_rad, &dx, &dy);
00206 
00207    // (x0, y0) ponto inferior esquerdo da grade em relação ao canvas
00208    double x0, y0;
00209    position (&x0, &y0);
00210 
00211    // (x1, y1) ponto inferior esquerdo da primeira linha da grade,
00212    // em coordenadas normalizadas 
00213    double x1 = x0 + f * cos (rot_rad);
00214    double y1 = y0 + f * sin (rot_rad);
00215 
00216    // (x2, y2) ponto superior direito da primeira linha da grade,
00217    // em coordenadas normalizadas
00218    double x2 = x1 + limit() * sin (rot_rad);
00219    double y2 = y1 + limit() * cos (rot_rad);
00220 
00221    // posição no eixo da primeira linha da grade
00222    double first = this -> first();
00223 
00224    // posição no eixo da última linha da grade
00225    double mx;
00226 
00227    // normalizando a área de desenho
00228    double pxmin = (double) (xmin - _xmin) / (_xmax - _xmin);
00229    double pymin = (double) (ymin - _ymin) / (_ymax - _ymin);
00230    double pxmax = (double) (xmax - _xmin) / (_xmax - _xmin);
00231    double pymax = (double) (ymax - _ymin) / (_ymax - _ymin);
00232 
00233    // se x2 igual a x1 calcula novos limites para otimizar o desenho na área
00234    // definida por (pxmin, pymin) e (pxmax, pymax)
00235    if (mtEqual(x1, x2))
00236    {
00237       // calcula posição da primeira linha a ser desenhada com sendo 
00238       // a primeira linha que aparece na área definida por (pxmin, pymin)
00239       // e (pxmax, pymax)
00240       while (x1 < pxmin)
00241       {
00242          // coordenada normalizada
00243          x1 += dx;
00244 
00245          // coordenada no eixo
00246                first += _step;
00247       }
00248 
00249       // faz x2 acompanhar o valor de x1
00250       x2 = x1;
00251 
00252       // calcula posição da última linha a ser desenhada com sendo a última
00253       // linha que aparece na área definida por (pxmin, pymin) e 
00254       // (pxmax, pymax)
00255 
00256       // coordenada no eixo
00257       mx = first;
00258       
00259       while ((x1 < pxmax) && (mx < _mx) && !mtEqual(_mx, mx))
00260       {
00261          // coordenada normalizada
00262          x1 += dx;
00263 
00264          // coordenada no eixo
00265                mx += _step;
00266       }
00267 
00268       // faz x1 voltar ao valor de coordenada da primeira linha da grade
00269       x1 = x2;
00270         
00271       // clipa coordenadas y da linha contra a área definida por (pxmin, pymin)
00272       // e (pxmax, pymax)
00273       if (y1 < pymin)
00274          y1 = pymin;
00275 
00276       if (y2 > pymax)
00277          y2 = pymax;
00278    }
00279    // se y2 igual a y1 calcula novos limites para otimizar o desenho na área
00280    // definida por (pxmin, pymin) e (pxmax, pymax)
00281    else if (mtEqual(y1, y2))
00282    {
00283       // calcula posição da primeira linha a ser desenhada com sendo 
00284       // a primeira linha que aparece na área definida por (pxmin, pymin)
00285       // e (pxmax, pymax)
00286       while (y1 < pymin)
00287       {
00288          // coordenada normalizada
00289          y1 += dy;
00290 
00291          // coordenada no eixo
00292                first += _step;
00293       }
00294 
00295       // faz y2 acompanhar o valor de y1
00296       y2 = y1;
00297 
00298       // redefine última linha a ser desenhada com sendo a última linha que
00299       // aparece na área definida por (pxmin, pymin) e (pxmax, pymax)
00300 
00301       // coordenada no eixo
00302       mx = first;
00303       
00304       while ((y1 < pymax) && (mx < _mx) && !mtEqual(_mx, mx))
00305       {
00306          // coordenada normalizada
00307          y1 += dy;
00308 
00309          // coordenada no eixo
00310                mx += _step;
00311       }
00312 
00313       // faz y1 voltar ao valor de coordenada da primeira linha da grade
00314       y1 = y2;
00315 
00316       // clipa coordenadas x da linha contra a área definida por (pxmin, pymin)
00317       // e (pxmax, pymax)
00318       if (x1 < pxmin)
00319          x1 = pxmin;
00320 
00321       if (x2 > pxmax)
00322          x2 = pxmax;
00323    }
00324 
00325    // desenha grade cor e estilo de linha definidos pelo usuário e com linha 
00326    // sólida mais fina possível
00327    cdLineWidth  (1);
00328    cdLineStyle  (_style);
00329    cdForeground (_color);
00330 
00331    // desenho da grade
00332    //for (double p = first; p <= _mx; p += _step)  // isLessEqual(p, mx)
00333    for (double p = first; mtLessEqual(p, _mx); p += _step)  // isLessEqual(p, mx)
00334    {
00335       // desenha linha da grade
00336       wdLine(x1, y1, x2, y2);
00337 
00338       // próxima linha da grade
00339       x1 += dx;
00340       x2 += dx;
00341       y1 += dy;
00342       y2 += dy;
00343    }
00344 
00345    cdClip(mode);
00346    
00347    // restaura a região de clip anterior
00348    cdClipArea(oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax);
00349 }
00350 
00351 void XYGrid::boundingBox (int& xmin, int& ymin, int& xmax, int& ymax) const
00352 {
00353    if (visible() == xyfalse)    // invisível!!!
00354       return;
00355 
00356    // ângulo de rotação em radianos
00357    double rot_rad = _rot * XY_PI / 180.0;
00358 
00359    // primeira posição normalizada na grade em relação ao canvas
00360    double f = (first() - _mn) * _size / (_mx - _mn);
00361 
00362    // passo normalizado na grade em relação ao canvas
00363    double s = _step * _size / (_mx - _mn);
00364 
00365    // verifica se a grade é muito compacta
00366    if (s <= 0.01)
00367       return;
00368 
00369    // intervalo de deslocamento em relação as direções x e y
00370    double dx;
00371    double dy;
00372    mtRotate (s, 0, rot_rad, &dx, &dy);
00373 
00374    // (x0, y0) ponto inferior esquerdo da grade em relação ao canvas
00375    double x0, y0;
00376    position (&x0, &y0);
00377 
00378    // (x1, y1) ponto inferior esquerdo da primeira linha da grade,
00379    // em coordenadas normalizadas
00380    double x1 = x0 + f * cos (rot_rad);
00381    double y1 = y0 + f * sin (rot_rad);
00382 
00383    // (x2, y2) ponto superior direito da primeira linha da grade,
00384    // em coordenadas normalizadas
00385    double x2 = x1 + limit() * sin (rot_rad);
00386    double y2 = y1 + limit() * cos (rot_rad);
00387 
00388    int bx1, by1, bx2, by2;
00389 
00390    // transforma valores de coordenadas do mundo em pixel
00391    wdWorld2Canvas (x1, y1, &bx1, &by1);
00392    wdWorld2Canvas (x2, y2, &bx2, &by2);
00393 
00394    // inicializa boundingBox
00395    xmin = MIN(bx1, bx2);
00396    ymin = MIN(by1, by2);
00397    xmax = MAX(bx1, bx2);
00398    ymax = MAX(by1, by2);
00399 
00400    // calcula boundingBox
00401    for (double p = first(); p < _mx; p += _step)
00402    {
00403       // próxima linha da grade
00404       x1 += dx;
00405       x2 += dx;
00406       y1 += dy;
00407       y2 += dy;
00408 
00409       // transforma valores de coordenadas do mundo em pixel
00410       wdWorld2Canvas (x1, y1, &bx1, &by1);
00411       wdWorld2Canvas (x2, y2, &bx2, &by2);
00412 
00413       // boundingBox da grade
00414       xmin = MIN3(bx1, bx2, xmin);
00415       ymin = MIN3(by1, by2, ymin);
00416       xmax = MAX3(bx1, bx2, xmax);
00417       ymax = MAX3(by1, by2, ymax);
00418    }
00419 }
00420 

XY
Tecgraf / PUC-Rio - Computer Graphics Technology Group