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

xymcast.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /* Módulo: xymcast.cpp                                                       */
00003 /* Autores: Carlos Henrique Levy e Jaudênia Cavalcante                       */
00004 /* Data: 26 ago 96                                                           */
00005 /* Comentário:                                                               */
00006 /*    Implementação de métodos da classe especializada que representa através*/
00007 /* de segmentos de retas conectados (de modo a dar um aspecto escada) um con */
00008 /* junto de dados num gráfico cartesiano.                                    */
00009 /*****************************************************************************/
00010 
00011 #include "xymcast.h"
00012 
00013 const char* xy_id_xymcarg_cpp="$Id: xymcast.cpp,v 1.12 2003/01/03 17:35:41 clinio Exp $";
00014                                                                 
00015 XYCartesianStepMask::XYCartesianStepMask (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 XYCartesianStepMask::XYCartesianStepMask (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 XYCartesianStepMask::width (int w)
00047 {
00048    _width = w;
00049 }
00050 
00051 int XYCartesianStepMask::width (void) const
00052 {
00053    return _width;
00054 }
00055 
00056 void XYCartesianStepMask::style (XYMask::LineStyle s)
00057 {
00058    _style = s;
00059 }
00060 
00061 int XYCartesianStepMask::style (void) const
00062 {
00063    return _style;
00064 }
00065 
00066 void XYCartesianStepMask::draw (void)
00067 {
00068    draw(_xmin, _ymin, _xmax, _ymax);
00069 }
00070 
00071 xybool XYCartesianStepMask::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 o atual modo de clipping
00089    int mode = cdClip(CD_CLIPON);
00090 
00091    // guarda a região de clip corrente
00092    int oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax;
00093    cdGetClipArea (&oldclip_xmin, &oldclip_xmax, &oldclip_ymin, &oldclip_ymax);
00094    // define nova região de clip
00095    cdClipArea(_xmin, _xmax, _ymin, _ymax);
00096 
00097    // converte coordenadas (x, y) em pixels para coordenadas do mundo
00098    double px, py;
00099    wdCanvas2World (x, y, &px, &py);
00100 
00101    double xt, yt;
00102 
00103    int    ifirst=0;
00104    while (!(s->point(ifirst, xt, yt)) && ifirst < npoints) ifirst++;
00105    if (ifirst >= npoints) return xyfalse;
00106 
00107 
00108    double x1 = _x_axis -> transform(xt);
00109    double y1 = _y_axis -> transform(yt);
00110 
00111    // define tolerância para 1.5 milimetros 
00112    int tol_dx,tol_dy;
00113    wdMM2Pixel(1.5, 1.5, &tol_dx, &tol_dy); 
00114    double yaxis_min = _y_axis -> transform(_y_axis -> min()); 
00115    double yaxis_max = _y_axis -> transform(_y_axis -> max()); 
00116    double tol_y = tol_dy * ( yaxis_max - yaxis_min) / (_ymax - _ymin + 1);
00117    double xaxis_min = _x_axis -> transform(_x_axis -> min());
00118    double xaxis_max = _x_axis -> transform(_x_axis -> max());
00119    double tol_x = tol_dx * ( xaxis_max - xaxis_min) / (_xmax - _xmin + 1);
00120    double oldtol = mtTolerance(tol_y);
00121           
00122    double x2, y2;
00123 
00124    // verifica uma série nos dois segmentos do degrau
00125    int    iprevious = ifirst;
00126    for (int i = (ifirst+1); i < npoints; ++i)
00127    {
00128       if (s -> point(i, xt, yt))
00129       {
00130         x2 = _x_axis -> transform(xt);
00131         y2 = _y_axis -> transform(yt);
00132 
00133         mtTolerance(tol_y);
00134         xybool r1 = mtPointInLine(px, py, x1, y1, x2, y1);
00135         mtTolerance(tol_x);
00136         xybool r2 = mtPointInLine (py, px, y1, x2, y2, x2); // Inverte x e y
00137 
00138         if ( ( r1 || r2 ) && (i == (iprevious+1)) )
00139         {
00140            cdClip(mode);
00141            // restaura a região de clip anterior
00142            cdClipArea(oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax);
00143           
00144            mtTolerance(oldtol);
00145            return xytrue;
00146         }
00147 
00148         x1 = x2;
00149         y1 = y2;
00150         iprevious = i;
00151      }
00152    }
00153 
00154    cdClip(mode);
00155    // restaura a região de clip anterior
00156    cdClipArea(oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax);
00157 
00158    mtTolerance(oldtol);
00159    return xyfalse;
00160 }
00161 
00162 xybool XYCartesianStepMask::fence (int x2, int y2, int x3, int y3)
00163 {
00164    if (visible() == xyfalse)           // invisível!!!
00165       return xyfalse;
00166 
00167    // limites da menor caixa que contém uma máscara
00168    int x0, y0, x1, y1;
00169    boundingBox (x0, y0, x1, y1);
00170 
00171    return mtInclude (x0, y0, x1, y1, x2, y2, x3, y3);
00172 }
00173 
00174 void XYCartesianStepMask::drawIcon (int xmin, int ymin, int xmax, int ymax)
00175                                                 const
00176 {
00177    int d = 2;
00178    int avg = (ymax+ymin)/2;
00179    int xmid = (int)((double)(xmax + xmin) / 2);
00180 
00181    // ativa estilo, largura e cor da linha usada para desenhar a série
00182    cdLineStyle(_style);
00183    cdLineWidth(_width);
00184    cdForeground(_color);
00185 
00186    cdLine (xmin, avg-d, xmid, avg-d);
00187    cdLine (xmid, avg-d, xmid, avg+d);
00188    cdLine (xmid, avg+d, xmax, avg+d);
00189 }
00190 
00191 void XYCartesianStepMask::draw (int xmin, int ymin, int xmax, int ymax) const
00192 {
00193    if (visible() == xyfalse)  // invisível!!!
00194       return;
00195 
00196    XYSeries* s = (XYSeries *) _series;
00197 
00198    // define domínio da série nos limites da área a ser desenhada:
00199 
00200    // domínio original da série
00201    double old_begin, old_end;
00202    s -> domain(&old_begin, &old_end);
00203 
00204    // novo domínio
00205    double begin, end;
00206 
00207    // define os parâmetros de visualização para o domínio dos eixos na
00208    // região de desenho das máscaras. Isto é necessário para se poder
00209    // calcular os novos limites do eixo X em coordenadas do mundo
00210    setMacWindow();
00211    setViewport();
00212 
00213    // calcula os novos limites no eixo X, em coordenadas do mundo
00214    wdCanvas2World (xmin, 0, &begin, 0);
00215    wdCanvas2World (xmax, 0, &end, 0);
00216 
00217    // calcula o novo domínio para a série que é o domínio que está dentro
00218    // da região que vai ser desenhada. Agora, se a área não intercepta o
00219    // domínio, então retorna porque não há nada para ser desenhado
00220    if ((begin > old_end) || (end < old_begin))
00221       return;
00222 
00223    // clipa dentro do grafico
00224    if (begin < old_begin)
00225      begin = old_begin;
00226    if (end > old_end)
00227      end = old_end;
00228         
00229    // define o novo domínio
00230    s -> domain(begin, end);
00231 
00232    // número de pontos na série
00233    int npoints = s -> numPoints();
00234 
00235    // teste de inconsistência
00236    if (npoints <= 1)
00237    {
00238       // restaura valores originais do domínio da série
00239       s -> domain(old_begin, old_end);
00240       return;
00241    }
00242 
00243    // começa a desenhar:
00244 
00245    // transforma coordenadas máximas e mínimas de acordo com o tipo dos eixos
00246    // ativos e usa esses valores para a nova window
00247    setMacWindow();
00248    setViewport();
00249 
00250    // ativa estilo, largura e cor da linha usada para desenhar a série
00251    cdLineStyle(_style);
00252    cdLineWidth(_width);
00253    cdForeground(_color);
00254 
00255    // guarda o atual modo de clipping
00256    int mode = cdClip(CD_CLIPON);
00257 
00258    // guarda a região de clip corrente
00259    int oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax;
00260    cdGetClipArea (&oldclip_xmin, &oldclip_xmax, &oldclip_ymin, &oldclip_ymax);
00261    // define nova região de clip
00262    cdClipArea(_xmin, _xmax, _ymin, _ymax);
00263 
00264    cdWriteMode(CD_REPLACE);
00265 
00266    // obtem primeiro ponto 
00267    double xt, yt;
00268 
00269    int    ifirst=0;
00270    while (!(s -> point(ifirst, xt, yt)) && ifirst < npoints) ifirst++;    
00271    if (ifirst >= npoints) return;
00272 
00273    double x1 = _x_axis -> transform(xt);
00274    double y1 = _y_axis -> transform(yt);
00275 
00276    double x2, y2;
00277    int    iprevious=ifirst;
00278 
00279    // desenha uma série com aparência de degrau
00280    for (int i = (ifirst+1); i < npoints; ++i)
00281    {
00282       if ( s -> point(i, xt, yt) )
00283       { x2 = _x_axis -> transform(xt);
00284         y2 = _y_axis -> transform(yt);
00285 
00286         // desenha traço da série       como sendo um degrau de escada
00287         if (i == (iprevious+1))
00288         { wdLine (x1, y1, x2, y1);
00289           wdLine (x2, y1, x2, y2);
00290         }
00291 
00292         x1 = x2;
00293         y1 = y2;
00294         iprevious = i;
00295       }
00296    }
00297 
00298    // restaura o atual modo de clipping
00299    cdClipArea(xmin, xmax, ymin, ymax);
00300 
00301    // restaura valores originais do domínio da série
00302    s -> domain(old_begin, old_end);
00303 
00304    cdClip(mode);
00305    // restaura a região de clip anterior
00306    cdClipArea(oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax);
00307 }
00308 
00309 void XYCartesianStepMask::boundingBox (int& bxmin, int& bymin, int& bxmax,
00310                                        int& bymax) const
00311 {
00312    if (visible() == xyfalse)  // invisível!!!
00313       return;
00314 
00315    XYSeries* s = (XYSeries *) _series;
00316 
00317    // número de pontos na série
00318    int npoints = s -> numPoints();
00319 
00320    double xt, yt;
00321 
00322    s -> point(0, xt, yt);
00323    double x1 = _x_axis -> transform(xt);
00324    double y1 = _y_axis -> transform(yt);
00325 
00326    s -> point(1, xt, yt);
00327    double x2 = _x_axis -> transform(xt);
00328    double y2 = _y_axis -> transform(yt);
00329 
00330    // controle de ponto flutuante
00331    //if (mtEqual(x1, x2))
00332    //   x2 = x1;
00333    //if (mtEqual(y1, y2))
00334    //   y2 = y1;
00335 
00336    // inicializa boundingBox
00337    double txmin = MIN(x1, x2);
00338    double tymin = MIN(y1, y2);
00339    double txmax = MAX(x1, x2);
00340    double tymax = MAX(y1, y2);
00341 
00342    // verifica uma série com aparência de degrau
00343    for (int i = 2; i < npoints; ++i)
00344    {
00345       x1 = x2;
00346       y1 = y2;
00347 
00348       s -> point(i, xt, yt);
00349       x2 = _x_axis -> transform(xt);
00350       y2 = _y_axis -> transform(yt);
00351 
00352       // controle de ponto flutuante
00353       //if (mtEqual(x1, x2))
00354       //   x2 = x1;
00355       //if (mtEqual(y1, y2))
00356       //   y2 = y1;
00357 
00358       txmin = MIN(x2, txmin);
00359       tymin = MIN(y2, tymin);
00360       txmax = MAX(x2, txmax);
00361       tymax = MAX(y2, tymax);
00362    }
00363 
00364    wdWorld2Canvas(txmin, tymin, &bxmin, &bymin);
00365    wdWorld2Canvas(txmax, tymax, &bxmax, &bymax);
00366 
00367    // restringe a boundingBox a área de desenho da máscara,
00368    // caso ela a ultrapasse
00369 
00370    if (bxmin > _xmin)
00371       bxmin = _xmin;
00372 
00373    if (bxmax > _xmax)
00374       bxmax = _xmax;
00375 
00376    if (bymin > _ymin)
00377       bymin = _ymin;
00378 
00379    if (bymax > _ymax)
00380       bymax =_ymax;
00381 }
00382 

XY
Tecgraf / PUC-Rio - Computer Graphics Technology Group