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

xymcaln.cpp

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

XY
Tecgraf / PUC-Rio - Computer Graphics Technology Group