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

xymcalnmk.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /* Módulo: xymcalnmk.cpp                                                     */
00003 /* Autores: Carlos Henrique Levy, Jaudênia Cavalcante e Camilo Freire        */
00004 /* Data: 23 mai 2000                                                         */
00005 /* Comentário:                                                               */
00006 /*    Implementação de métodos da classe especializada que representa através*/
00007 /* de segmentos de retas e marcas conectados um conjunto de dados num gráfico*/
00008 /* cartesiano.                                                               */
00009 /*****************************************************************************/
00010 
00011 #include "xymcalnmk.h"
00012 
00013 const char* xy_id_xymcalnmk_cpp="$Id: xymcalnmk.cpp,v 1.3 2000/06/14 19:11:44 camilo Exp $";
00014                                                                 
00015 XYCartesianLineMarkMask::XYCartesianLineMarkMask (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                                           int  size,
00023                                           MarkStyle mark,
00024                                           xybool  visible)
00025                                           : XYCartesianLineMask(name, series,
00026                                                                 x_axis, y_axis,
00027                                                                 color, width,
00028                                                                 style, visible),
00029                                             _size(size),
00030                                             _mark(mark)
00031 {
00032 }
00033 
00034 XYCartesianLineMarkMask::XYCartesianLineMarkMask (XYSeries* series,
00035                                           const XYAxis* x_axis,
00036                                           const XYAxis* y_axis,
00037                                           long color,
00038                                           int  width,
00039                                           LineStyle style,
00040                                           int  size,
00041                                           MarkStyle mark,
00042                                           xybool  visible)
00043                                           : XYCartesianLineMask(series, x_axis,
00044                                                                 y_axis, color,
00045                                                                 width, style,
00046                                                                 visible),
00047                                             _size(size),
00048                                             _mark(mark)
00049 {
00050 }
00051 
00052 void XYCartesianLineMarkMask::size (int s)
00053 {
00054    _size = s;
00055 }
00056 
00057 int XYCartesianLineMarkMask::size (void) const
00058 {
00059    return _size;
00060 }
00061 
00062 void XYCartesianLineMarkMask::mark (XYMask::MarkStyle m)
00063 {
00064    _mark = m;
00065 }
00066 
00067 int XYCartesianLineMarkMask::mark (void) const
00068 {
00069    return _mark;
00070 }
00071 
00072 void XYCartesianLineMarkMask::draw (void)
00073 {
00074    draw(_xmin, _ymin, _xmax, _ymax);
00075 }
00076 
00077 xybool XYCartesianLineMarkMask::pick (int x, int y)
00078 {
00079    if (visible() == xyfalse)    // invisível!!!
00080       return xyfalse;
00081 
00082    XYSeries* s = (XYSeries *) _series;
00083 
00084    int npoints = s -> numPoints();
00085 
00086    // teste de inconsistência
00087    if ((npoints <= 1) || (x < _xmin) || (_xmax < x) || (y < _ymin) ||
00088        (_ymax < y))
00089       return xyfalse;
00090 
00091    setWindow (_x_axis -> transform(_x_axis -> min()),
00092               _x_axis -> transform(_x_axis -> max()),
00093               _y_axis -> transform(_y_axis -> min()),
00094               _y_axis -> transform(_y_axis -> max()));
00095    setViewport();
00096 
00097    // guarda estado do clipping
00098    int oldmode = cdClip(CD_CLIPON);
00099    int oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax;
00100    cdGetClipArea (&oldclip_xmin, &oldclip_xmax, &oldclip_ymin, &oldclip_ymax);
00101    
00102    // define nova região de clip
00103    cdClipArea(_xmin, _xmax, _ymin, _ymax);
00104 
00105    // converte coordenadas (x, y) em pixels para coordenadas do mundo
00106    double px, py;
00107    wdCanvas2World (x, y, &px, &py);
00108 
00109    double xt, yt;
00110 
00111    int    ifirst=0;                                    
00112    while (!(s -> point(ifirst, xt, yt))) ifirst++;    
00113 
00114    double x1 = _x_axis -> transform(xt);
00115    double y1 = _y_axis -> transform(yt);
00116    int px1,py1;
00117    wdWorld2Canvas(x1, y1, &px1, &py1);
00118     
00119    // define tolerância para 2.0 milimetros  
00120    int tol_dx,tol_dy;
00121    cdMM2Pixel(2.0, 2.0, &tol_dx, &tol_dy); 
00122    tol_dy = width() > tol_dy ? width() : tol_dy; // coerente com largura da line
00123    double oldtol = mtTolerance((double)tol_dy);
00124 
00125    // tolerância considerada por causa do desenho da marca que ocupa vários
00126    // pixels da tela
00127    int tol = _size;
00128    
00129    // verifica uma série
00130    xybool hit = xyfalse;
00131    int  iprevious = ifirst;
00132    for (int i = (ifirst+1); i < npoints; ++i)
00133    {
00134       int px2,py2;
00135      
00136       if (s -> point(i, xt, yt))
00137       {
00138         double x2 = _x_axis -> transform(xt);
00139         double y2 = _y_axis -> transform(yt);
00140         wdWorld2Canvas(x2, y2, &px2, &py2);
00141 
00142         if ((mtPointInLineEx(x, y, px1, py1, px2, py2)) && (i==(iprevious+1)))
00143         {
00144           hit = xytrue; // acertou pick !
00145           break;
00146         }
00147    
00148         if (mtPointInMark(x, y, px1, py1, tol))
00149         {
00150           hit = xytrue;
00151           break;
00152         }
00153 
00154         px1 = px2;
00155         py1 = py2;
00156         iprevious = i;
00157       }
00158    }
00159 
00160    // restaura ao modo anterior
00161    cdClip(oldmode);
00162    cdClipArea(oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax);
00163    mtTolerance(oldtol);
00164  
00165    return hit;
00166 }
00167 
00168 void XYCartesianLineMarkMask::drawIcon (int xmin, int ymin, int xmax, int ymax)
00169                                                 const
00170 {
00171    int xmid = (int)((double)(xmax + xmin) / 2);
00172    int ymid = (int)((double)(ymax + ymin) / 2);
00173 
00174    // ativa estilo, largura e cor da linha usada para desenhar a série
00175    cdLineStyle(style());
00176    cdLineWidth(width());
00177    cdForeground(_color);
00178 
00179    cdLine (xmin, ymid, xmax, ymid);
00180 
00181    // ativa estilo, tamanho e cor da marca usada para desenhar a série
00182    cdMarkType(_mark);
00183    wdMarkSize(_size*.25);
00184    cdForeground(_color);
00185 
00186    cdMark (xmid, ymid);
00187 }
00188 
00189 void XYCartesianLineMarkMask::draw (int xmin, int /* ymin */, int xmax, int /* ymax */) const
00190 {
00191    if (visible() == xyfalse)  // invisível!!!
00192       return;
00193 
00194    XYSeries* s = (XYSeries *) _series;
00195 
00196    // define domínio da série nos limites da área a ser desenhada:
00197 
00198    // domínio original da série
00199    double old_begin, old_end;
00200    s -> domain(&old_begin, &old_end);
00201    double old_xf, old_xl, old_yf, old_yl;
00202    s -> point(0, old_xf, old_yf);
00203    s -> point(s -> numPoints()-1, old_xl, old_yl);
00204 
00205    // novo domínio
00206    double begin, end;
00207 
00208    // define os parâmetros de visualização para o domínio do eixos na
00209    // região de desenho das máscaras. Isto é necessário para se poder
00210    // calcular os novos limites do eixo X em coordenadas do mundo
00211    double wxmin = _x_axis -> transform(_x_axis -> min());
00212    double wymin = _y_axis -> transform(_y_axis -> min());
00213    double wxmax = _x_axis -> transform(_x_axis -> max());
00214    double wymax = _y_axis -> transform(_y_axis -> max());
00215 
00216    setWindow (wxmin, wxmax, wymin, wymax);
00217    setViewport();
00218 
00219    // calcula os novos limites no eixo X, em coordenadas do mundo
00220    wdCanvas2World (xmin, 0, &begin, 0);
00221    wdCanvas2World (xmax, 0, &end, 0);
00222 
00223    // calcula o novo domínio para a série que é o domínio que está dentro
00224    // da região que vai ser desenhada. Agora, se a área não intercepta o
00225    // domínio, então retorna porque não há nada para ser desenhado
00226    if ((begin > old_end) || (end < old_begin))
00227       return;
00228 
00229    if (begin < old_begin)
00230       begin = old_begin;
00231 
00232    if (end > old_end)
00233       end = old_end;
00234         
00235    // define o novo domínio
00236    s -> domain(begin, end);
00237 
00238    // número de pontos na série
00239    int npoints = s -> numPoints();
00240 
00241    // teste de inconsistência
00242    //if (npoints <= 1)
00243    //{
00244       // restaura valores originais do domínio da série
00245    //   s -> domain(old_begin, old_end);
00246    //   return;
00247    //}
00248 
00249    // começa a desenhar:
00250 
00251    // ativa estilo, largura e cor da linha usada para desenhar a série
00252    cdMarkType(_mark);
00253    wdMarkSize(_size*.25);
00254    cdLineStyle(style());
00255    cdLineWidth(width());
00256    cdForeground(_color);
00257 
00258    cdWriteMode(CD_REPLACE);
00259 
00260    // guarda o atual modo de clipping
00261    int mode = cdClip(CD_CLIPON);
00262 
00263    // guarda a região de clip corrente
00264    int oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax;
00265    cdGetClipArea (&oldclip_xmin, &oldclip_xmax, &oldclip_ymin, &oldclip_ymax);
00266    // define nova região de clip
00267    cdClipArea(_xmin, _xmax, _ymin, _ymax);
00268    
00269    double xt, yt;
00270    int    ifirst=0;
00271    int    iprevious=ifirst;
00272    while (!(s -> point(ifirst, xt, yt))) ifirst++;
00273 
00274    double x1 = _x_axis -> transform(xt);
00275    double y1 = _y_axis -> transform(yt);
00276 
00277    double x2, y2;
00278    int vx1, vy1;
00279 
00280    if (old_xf < begin || old_xf > end ) 
00281    {
00282       if (s -> point((unsigned)-1, xt, yt))
00283       {
00284         x2 = _x_axis -> transform(xt);
00285         y2 = _y_axis -> transform(yt);
00286 
00287 
00288         x2 = _x_axis -> transform(xt);
00289         y2 = _y_axis -> transform(yt);
00290 
00291         // desenha traço da série
00292         wdLine (x2, y2, x1, y1);
00293       }
00294    }
00295 
00296    // desenha uma série
00297    int i = 0;
00298    for (i = (ifirst+1); i < npoints; ++i)
00299    {
00300        if (s -> point(i, xt, yt))
00301        {
00302          x2 = _x_axis -> transform(xt);
00303          y2 = _y_axis -> transform(yt);
00304 
00305          // desenha tra\147o da s\151rie
00306          // caso os dois pontos sejam consecutivos
00307          if (i == (iprevious+1)) wdLine (x1, y1, x2, y2);
00308 
00309          // calcula os novos valores em coordenadas da tela
00310          wdWorld2Canvas (x1, y1, &vx1, &vy1);
00311 
00312          // desenha marca da série
00313          cdMark (vx1, vy1);
00314 
00315          x1 = x2;
00316          y1 = y2;
00317          iprevious = i;
00318        }
00319    }
00320 
00321    if ( old_xl < begin || old_xl > end )
00322    {
00323        if (s -> point(i, xt, yt))
00324        {
00325          x2 = _x_axis -> transform(xt);
00326          y2 = _y_axis -> transform(yt);
00327 
00328          // desenha tra\147o da s\151rie
00329          wdLine (x1, y1, x2, y2);
00330        }
00331    }
00332 
00333    // restaura valores originais do domínio da série
00334    s -> domain(old_begin, old_end);
00335 
00336    cdClip(mode);
00337    // restaura a região de clip anterior
00338    cdClipArea(oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax);
00339 }

XY
Tecgraf / PUC-Rio - Computer Graphics Technology Group