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

xymcaar.cpp

Go to the documentation of this file.
00001 /*
00002 Módulo: xymcaar.cpp
00003 Autores: André Luiz Clinio
00004 Data: 11 mai 2000
00005 Comentário:
00006 */
00007 
00008 /* -------------------------------------------------------------------- */
00009 
00010 #include "xymcaar.h"
00011 
00012 /* -------------------------------------------------------------------- */
00013 
00014 #define XCROSSLINE(x1,y1, x2,y2, x)  ((((x-x1)*(y2-y1))/(x2-x1))+y1)
00015 
00016 /* -------------------------------------------------------------------- */
00017 
00018 const char* xy_id_xymcaar_cpp="$Id: xymcaar.cpp,v 1.2 2000/09/18 17:42:15 clinio Exp $";
00019         
00020 /* -------------------------------------------------------------------- */
00021 
00022 XYCartesianAreaMask::XYCartesianAreaMask (
00023       XYText* name,
00024       XYSeries* series,
00025       const XYAxis* x_axis,
00026       const XYAxis* y_axis,
00027       long color,
00028       xybool  visible, double value ) : 
00029 XYCartesianMask( name, series, x_axis, y_axis, color, visible ), _value(value)
00030 {
00031 }
00032 
00033 /* .................................................................... */
00034 
00035 XYCartesianAreaMask::XYCartesianAreaMask(
00036       XYSeries* series,
00037       const XYAxis* x_axis,
00038       const XYAxis* y_axis,
00039       long color,
00040       xybool  visible, double value ) : 
00041 XYCartesianMask( series, x_axis, y_axis, color, visible), _value(value)
00042 {
00043 }
00044 
00045 /* .................................................................... */
00046 
00047 void XYCartesianAreaMask::draw( void )
00048 {
00049    draw(_xmin, _ymin, _xmax, _ymax);
00050 }
00051 
00052 /* .................................................................... */
00053 
00054 xybool XYCartesianAreaMask::pick (int x, int y)
00055 {
00056    if (visible() == xyfalse) return xyfalse;
00057 
00058    XYSeries* s = (XYSeries *) _series;
00059    int npoints = s -> numPoints();
00060 
00061    // teste de inconsistência
00062    if ( (npoints <= 1) || (x < _xmin) || 
00063         (_xmax < x) || (y < _ymin) || (_ymax < y))
00064         return xyfalse;
00065 
00066    setWindow (_x_axis -> transform(_x_axis -> min()),
00067               _x_axis -> transform(_x_axis -> max()),
00068               _y_axis -> transform(_y_axis -> min()),
00069               _y_axis -> transform(_y_axis -> max()));
00070    setViewport();
00071 
00072    // guarda estado do clipping
00073    int oldmode = cdClip(CD_CLIPON);
00074    int oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax;
00075    cdGetClipArea (&oldclip_xmin, &oldclip_xmax, &oldclip_ymin, &oldclip_ymax);
00076    
00077    // define nova região de clip
00078    cdClipArea(_xmin, _xmax, _ymin, _ymax);
00079 
00080    // converte coordenadas (x, y) em pixels para coordenadas do mundo
00081    double px, py;
00082    wdCanvas2World (x, y, &px, &py);
00083 
00084    double xt, yt;
00085 
00086    int    ifirst=0;                                    
00087    while (!(s -> point(ifirst, xt, yt))) ifirst++;    
00088 
00089    double x1 = _x_axis -> transform(xt);
00090    double y1 = _y_axis -> transform(yt);
00091    int px1,py1;
00092    wdWorld2Canvas(x1, y1, &px1, &py1);
00093     
00094    // define tolerância para 2.0 milimetros  
00095    int tol_dx,tol_dy;
00096    cdMM2Pixel(2.0, 2.0, &tol_dx, &tol_dy); 
00097    double oldtol = mtTolerance((double)tol_dy);
00098    
00099    // verifica uma série
00100    xybool hit = xyfalse;
00101    int  iprevious = ifirst;
00102    for (int i = (ifirst+1); i < npoints; ++i)
00103    {
00104       int px2,py2,yint;
00105      
00106       if (s -> point(i, xt, yt))
00107       {
00108         double x2 = _x_axis -> transform(xt);
00109         double y2 = _y_axis -> transform(yt);
00110         wdWorld2Canvas(x2, y2, &px2, &py2);
00111         yint = XCROSSLINE( px1, py1, px2, py2, x );
00112 
00113         if ( x >= px1 && x <= px2 && y <= yint && (i==(iprevious+1)))
00114         {
00115           hit = xytrue; // acertou pick !
00116           break;
00117         }
00118    
00119         px1 = px2;
00120         py1 = py2;
00121         iprevious = i;
00122       }
00123    }
00124 
00125    // restaura ao modo anterior
00126    cdClip(oldmode);
00127    cdClipArea(oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax);
00128    mtTolerance(oldtol);
00129  
00130    return hit;
00131 }
00132 
00133 /* .................................................................... */
00134 
00135 xybool XYCartesianAreaMask::fence (int x2, int y2, int x3, int y3)
00136 {
00137    if (visible() == xyfalse)  return xyfalse;
00138 
00139    // limites da menor caixa que contém uma máscara
00140    int x0, y0, x1, y1;
00141    boundingBox (x0, y0, x1, y1);
00142 
00143    return mtInclude (x0, y0, x1, y1, x2, y2, x3, y3);
00144 }
00145 
00146 /* .................................................................... */
00147 
00148 void XYCartesianAreaMask::drawIcon (int xmin, int ymin, int xmax, int ymax)
00149                                   const
00150 {
00151    // ativa estilo, largura e cor da linha usada para desenhar a série
00152    cdForeground(_color);
00153 
00154    cdBox(xmin, ymin, xmax, ymax);
00155 }
00156 
00157 /* .................................................................... */
00158 
00159 void XYCartesianAreaMask::draw (int xmin, int /* ymin */, int xmax, int /* ymax */) const
00160 {
00161    if (visible() == xyfalse)  return;
00162 
00163    XYSeries* s = (XYSeries *) _series;
00164 
00165    // define domínio da série nos limites da área a ser desenhada:
00166    // domínio original da série
00167    double old_begin, old_end;
00168    s -> domain(&old_begin, &old_end);
00169    double old_xf, old_xl, old_yf, old_yl;
00170    s -> point(0, old_xf, old_yf);
00171    s -> point(s -> numPoints()-1, old_xl, old_yl);
00172 
00173    // novo domínio
00174    double begin, end;
00175 
00176    // define os parâmetros de visualização para o domínio do eixos na
00177    // região de desenho das máscaras. Isto é necessário para se poder
00178    // calcular os novos limites do eixo X em coordenadas do mundo
00179    double wxmin = _x_axis -> transform(_x_axis -> min());
00180    double wymin = _y_axis -> transform(_y_axis -> min());
00181    double wxmax = _x_axis -> transform(_x_axis -> max());
00182    double wymax = _y_axis -> transform(_y_axis -> max());
00183 
00184    setWindow (wxmin, wxmax, wymin, wymax);
00185    setViewport();
00186 
00187    // calcula os novos limites no eixo X, em coordenadas do mundo
00188    wdCanvas2World (xmin, 0, &begin, 0);
00189    wdCanvas2World (xmax, 0, &end, 0);
00190 
00191    // calcula o novo domínio para a série que é o domínio que está dentro
00192    // da região que vai ser desenhada. Agora, se a área não intercepta o
00193    // domínio, então retorna porque não há nada para ser desenhado
00194    if ((begin > old_end) || (end < old_begin))
00195       return;
00196 
00197    if (begin < old_begin) begin = old_begin;
00198    if (end > old_end) end = old_end;
00199  
00200    // define o novo domínio
00201    s -> domain(begin, end);
00202 
00203    // número de pontos na série
00204    int npoints = s -> numPoints();
00205 
00206    // começa a desenhar:
00207 
00208    // ativa estilo, largura e cor da linha usada para desenhar a série
00209    cdForeground(_color);
00210    cdWriteMode(CD_REPLACE);
00211 
00212    // guarda o atual modo de clipping
00213    int mode = cdClip(CD_CLIPON);
00214 
00215    // guarda a região de clip corrente
00216    int oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax;
00217    cdGetClipArea (&oldclip_xmin, &oldclip_xmax, &oldclip_ymin, &oldclip_ymax);
00218    // define nova região de clip
00219    cdClipArea(_xmin, _xmax, _ymin, _ymax);
00220    
00221    double xt, yt;
00222    int    ifirst=0;
00223    int    iprevious=ifirst;
00224    while (!(s -> point(ifirst, xt, yt))) ifirst++;
00225 
00226    double x1 = _x_axis -> transform(xt);
00227    double y1 = _y_axis -> transform(yt);
00228 
00229    double x2, y2, yz;
00230 
00231    if (old_xf < begin || old_xf > end ) 
00232    {
00233       if (s -> point((unsigned)-1, xt, yt))
00234       {
00235         x2 = _x_axis -> transform(xt);
00236         y2 = _y_axis -> transform(yt);
00237 
00238 
00239         x2 = _x_axis -> transform(xt);
00240         y2 = _y_axis -> transform(yt);
00241         yz = _y_axis -> transform(_value);
00242 
00243         // desenha traço da série
00244         wdBegin( CD_FILL );
00245         wdVertex( x1, yz );
00246         wdVertex( x2, yz );
00247         wdVertex( x2, y2 );
00248         wdVertex( x1, y1 );
00249         wdEnd();
00250       }
00251    }
00252 
00253    // desenha uma série
00254    int i = 0;
00255    for (i = (ifirst+1); i < npoints; ++i)
00256    {
00257        if (s -> point(i, xt, yt))
00258        {
00259          x2 = _x_axis -> transform(xt);
00260          y2 = _y_axis -> transform(yt);
00261          yz = _y_axis -> transform(_value);
00262 
00263          // desenha tra\147o da s\151rie
00264          // caso os dois pontos sejam consecutivos
00265          if (i == (iprevious+1)) 
00266          { wdBegin( CD_FILL );
00267            wdVertex( x1, yz );
00268            wdVertex( x2, yz );
00269            wdVertex( x2, y2 );
00270            wdVertex( x1, y1 );
00271            wdEnd();
00272          }
00273 
00274          x1 = x2;
00275          y1 = y2;
00276          iprevious = i;
00277        }
00278    }
00279 
00280    if ( old_xl < begin || old_xl > end )
00281    {
00282        if (s -> point(i, xt, yt))
00283        {
00284          x2 = _x_axis -> transform(xt);
00285          y2 = _y_axis -> transform(yt);
00286 
00287          // desenha tra\147o da s\151rie
00288          yz = _y_axis -> transform(_value);
00289          wdBegin( CD_FILL );
00290          wdVertex( x1, yz );
00291          wdVertex( x2, yz );
00292          wdVertex( x2, y2 );
00293          wdVertex( x1, y1 );
00294          wdEnd();
00295        }
00296    }
00297 
00298    // restaura valores originais do domínio da série
00299    s -> domain(old_begin, old_end);
00300 
00301    cdClip(mode);
00302    // restaura a região de clip anterior
00303    cdClipArea(oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax);
00304 }
00305 
00306 /* .................................................................... */
00307 
00308 void XYCartesianAreaMask::boundingBox (int& bxmin, int& bymin, int& bxmax,
00309                                        int& bymax) const
00310 {
00311    if (visible() == xyfalse) return;
00312 
00313    XYSeries* s = (XYSeries *) _series;
00314 
00315    // número de pontos na série
00316    int npoints = s -> numPoints();
00317 
00318    double xt, yt;
00319 
00320    s -> point(0, xt, yt);
00321    double x1 = _x_axis -> transform(xt);
00322    double y1 = _y_axis -> transform(yt);
00323 
00324    s -> point(1, xt, yt);
00325    double x2 = _x_axis -> transform(xt);
00326    double y2 = _y_axis -> transform(yt);
00327 
00328    // controle de ponto flutuante
00329    if (mtEqual(x1, x2)) x2 = x1;
00330    if (mtEqual(y1, y2)) y2 = y1;
00331 
00332    // inicializa boundingBox
00333    double txmin = MIN(x1, x2);
00334    double tymin = MIN(y1, y2);
00335    double txmax = MAX(x1, x2);
00336    double tymax = MAX(y1, y2);
00337 
00338    // verifica uma série
00339    for (int i = 2; i < npoints; ++i)
00340    { x1 = x2;
00341      y1 = y2;
00342 
00343      s -> point(i, xt, yt);
00344      x2 = _x_axis -> transform(xt);
00345      y2 = _y_axis -> transform(yt);
00346 
00347      // controle de ponto flutuante
00348      if (mtEqual(x1, x2)) x2 = x1;
00349      if (mtEqual(y1, y2)) y2 = y1;
00350 
00351      txmin = MIN(x2, txmin);
00352      tymin = MIN(y2, tymin);
00353      txmax = MAX(x2, txmax);
00354      tymax = MAX(y2, tymax);
00355    }
00356    // acrescentando os pontos do eixo x 
00357    tymin = MIN(_y_axis->min(), tymin);
00358    tymax = MAX(_y_axis->min(), tymax);
00359 
00360    wdWorld2Canvas(txmin, tymin, &bxmin, &bymin);
00361    wdWorld2Canvas(txmax, tymax, &bxmax, &bymax);
00362 
00363    // restringe a boundingBox a área de desenho da máscara,
00364    // caso ela a ultrapasse
00365    if (bxmin > _xmin) bxmin = _xmin;
00366    if (bxmax > _xmax) bxmax = _xmax;
00367    if (bymin > _ymin) bymin = _ymin;
00368    if (bymax > _ymax) bymax =_ymax;
00369 }
00370 
00371 /* .................................................................... */
00372 /* .................................................................... */
00373 /* .................................................................... */
00374 

XY
Tecgraf / PUC-Rio - Computer Graphics Technology Group