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

xymcastmk.cpp

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

XY
Tecgraf / PUC-Rio - Computer Graphics Technology Group