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

xygra.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /* Módulo: xygra.cpp                                                          */
00003 /* Autores: Carlos Henrique Levy e Jaudênia Cavalcante                       */
00004 /* Data: 26 fev 96                                                           */
00005 /* Comentário:                                                               */
00006 /*    Implementação de métodos da classe abstrata que manipula de forma única*/
00007 /* um conjunto de eixos, (XYAxis), marcadores (XYMarker), regiões (XYSlice), */
00008 /* curvas (XYMask), legenda (XYLegend) e títulos (XYText) numa área de um can*/
00009 /* vas do CD. O layout básico de um gráfico é os títulos, um embaixo do outro*/
00010 /* começando pelo topo da área gerenciada pelo gráfico, a legenda e os eixos */
00011 /* limitando uma região (mask area) onde curvas, marcadores e regiões são de */
00012 /* senhados.                                                                 */
00013 /*****************************************************************************/
00014 
00015 #include <stdlib.h>
00016 
00017 #include "xygra.h"
00018 #include "cdps.h"
00019 
00020 const char* xy_id_xygr_cpp="$Id: xygra.cpp,v 1.36 2002/01/23 16:12:49 clinio Exp $";
00021                                                                 
00022 #ifndef NOIUP
00023 XYGraph::XYGraph (Ihandle* canvas,
00024                   XYCoordinate x,
00025                   XYCoordinate y,
00026                   double width,
00027                   double height,
00028                         xybool visible)
00029                       : XYObject(x, y, visible),
00030                         _canvas(canvas),
00031                         _cdcanvas(NULL),
00032                         _cvimage(NULL),
00033                         _image(NULL),
00034                         _image_w(0),
00035                         _image_h(0),
00036                         _legend(NULL),
00037                         _color(XY_GRAY),
00038                         _ma_color(XY_WHITE),
00039                         _width(width),
00040                         _height(height),
00041                         _ma_xmin(0.0),
00042                         _ma_xmax(1.0),
00043                         _ma_ymin(0.0),
00044                         _ma_ymax(1.0),
00045                         _distortion(xytrue),
00046                         _doublebuffering(xyfalse),
00047                     _dont_destroy_cdcanvas( xyfalse )
00048 {
00049    activateCanvas();
00050    setWindow();
00051    defineViewport();
00052    propagateViewport();
00053 }
00054 #endif
00055 
00056 XYGraph::XYGraph (cdCanvas* cdcanvas,
00057                   XYCoordinate x,
00058                   XYCoordinate y,
00059                   double width,
00060                   double height,
00061                         xybool visible)
00062                       : XYObject(x, y, visible),
00063                         _canvas(NULL),
00064                                             _cdcanvas(cdcanvas),
00065                       _cvimage(NULL),
00066                       _image(NULL),
00067                           _image_w(0),
00068                         _image_h(0),
00069                         _legend(NULL),
00070                         _color(XY_GRAY),
00071                         _ma_color(XY_WHITE),
00072                         _width(width),
00073                                 _height(height),
00074                                                   _ma_xmin(0.0),
00075                                                   _ma_xmax(1.0),
00076                     _ma_ymin(0.0),
00077                     _ma_ymax(1.0),
00078                     _distortion(xytrue),
00079                         _doublebuffering(xyfalse),
00080                     _dont_destroy_cdcanvas( xytrue )
00081 {
00082    activateCanvas();
00083    setWindow();
00084    defineViewport();
00085    propagateViewport();
00086 }
00087 
00088 XYGraph::~XYGraph (void)
00089 {
00090    // Libera imagem 
00091    if (_cvimage)
00092      cdKillCanvas (_cvimage);
00093    if (_image)
00094      cdKillImage (_image);
00095 
00096    // libera o canvas CD usado, se existir canvas IUP
00097    if (_cdcanvas && _dont_destroy_cdcanvas == xyfalse )
00098       cdKillCanvas (_cdcanvas);
00099 }
00100 
00101 void XYGraph::position (double x, double y)
00102 {
00103    XYObject::position(x, y);
00104    defineViewport();
00105 }
00106 
00107 void XYGraph::position (int xp, int yp)
00108 {
00109    XYObject::position(xp, yp);
00110    defineViewport();
00111 }
00112 
00113 void XYGraph::position (double* x, double* y) const
00114 {
00115    int    w, h;      // tamanho do canvas em pixel
00116    cdGetCanvasSize(&w, &h, NULL, NULL);
00117    XYGraph* g = (XYGraph*) this;
00118 
00119    // posicao do grafico deve ser calculada em relacao ao canvas inteiro, 
00120    // sendo o unico objeto XY que sofre esta restricao 
00121    int x1, y1, x2, y2;
00122    g->getViewport (x1, x2, y1, y2); // salva viewport atual
00123    g->setViewport (0, w-1, 0, h-1);   // canvas inteiro
00124    XYObject::position(x, y);
00125    g->setViewport (x1, x2, y1, y2); // retorna ao original
00126 }
00127 
00128 void XYGraph::position (int* xp, int* yp) const
00129 {
00130    int    w, h;      // tamanho do canvas em pixel
00131    cdGetCanvasSize(&w, &h, NULL, NULL);
00132    XYGraph* g = (XYGraph*) this;
00133 
00134    // posicao do grafico deve ser calculada em relacao ao canvas inteiro, 
00135    // sendo o unico objeto XY que sofre esta restricao 
00136    int x1, y1, x2, y2;
00137    g->getViewport (x1, x2, y1, y2); // salva viewport atual
00138    g->setViewport (0, w-1, 0, h-1);   // canvas inteiro
00139    XYObject::position(xp, yp);
00140    g->setViewport (x1, x2, y1, y2); // retorna ao original
00141 }
00142 
00143 XYCoordinate* XYGraph::position (void)
00144 {
00145    return XYObject::position();
00146 }
00147 
00148 void XYGraph::setCdCanvas (cdCanvas* c)
00149 {
00150    _cdcanvas = c;
00151 }
00152 
00153 cdCanvas* XYGraph::getCdCanvas (void) const
00154 {
00155    return _cdcanvas;
00156 }
00157 
00158 cdCanvas* XYGraph::canvasImage (cdCanvas* cvimage)
00159 {
00160    cdCanvas* old = _cvimage;
00161    _cvimage = cvimage;
00162    return old;
00163 }
00164 
00165 cdCanvas* XYGraph::canvasImage (void)
00166 {
00167    return _cvimage;
00168 }
00169 
00170 void XYGraph::createImage (int w, int h)
00171 {
00172    _image_w = w;
00173    _image_h = h;
00174    _image   = cdCreateImage (_image_w, _image_h);
00175 }
00176 
00177 void XYGraph::insert (XYText* text)
00178 {
00179    text -> insertAction((XYGraph *)this);
00180    _titles.insert(text);
00181 }
00182 
00183 void XYGraph::insert (XYAxis* axis)
00184 {
00185    axis -> insertAction((XYGraph *)this);
00186    _axes.insert(axis);
00187 }
00188 
00189 void XYGraph::insert (XYMask* mask)
00190 {
00191    mask -> insertAction((XYGraph *)this);
00192    _masks.insert(mask);
00193 }
00194 
00195 void XYGraph::insert (XYMarker* marker)
00196 {
00197    marker -> insertAction((XYGraph *)this);
00198    _markers.insert(marker);
00199 }
00200 
00201 void XYGraph::insert (XYSlice* slice)
00202 {
00203    slice -> insertAction((XYGraph *)this);
00204    _slices.insertEnd(slice);
00205 }
00206 
00207 void XYGraph::insert (XYArea* area)
00208 {
00209    area -> insertAction((XYGraph *)this);
00210    _areas.insertEnd(area);
00211 }
00212 
00213 void XYGraph::insert (XYObject* decorator)
00214 {
00215    _decorators.insertEnd(decorator);
00216 }
00217 
00218 void XYGraph::remove (XYText* text)
00219 {
00220    text -> removeAction((XYGraph *)this);
00221    _titles.remove(text);
00222 }
00223 
00224 void XYGraph::remove (XYAxis* axis)
00225 {
00226    axis -> removeAction((XYGraph *)this);
00227    _axes.remove(axis);
00228 }
00229 
00230 void XYGraph::remove (XYMask* mask)
00231 {
00232    mask -> removeAction((XYGraph *)this);
00233    _masks.remove(mask);
00234 }
00235 
00236 void XYGraph::remove (XYMarker* marker)
00237 {
00238    marker -> removeAction((XYGraph *)this);
00239    _markers.remove(marker);
00240 }
00241 
00242 void XYGraph::remove (XYArea* area)
00243 {
00244    area -> removeAction((XYGraph *)this);
00245    _areas.remove(area);
00246 }
00247 
00248 void XYGraph::remove (XYSlice* slice)
00249 {
00250    slice -> removeAction((XYGraph *)this);
00251    _slices.remove(slice);
00252 }
00253 
00254 void XYGraph::remove (XYObject* decorator)
00255 {
00256    _decorators.remove(decorator);
00257 }
00258 
00259 XYList<XYText>& XYGraph::text (void)
00260 {
00261    return _titles;
00262 }
00263 
00264 XYList<XYAxis>& XYGraph::axis (void)
00265 {
00266    return _axes;
00267 }
00268 
00269 XYList<XYMask>& XYGraph::mask (void)
00270 {
00271    return _masks;
00272 }
00273 
00274 XYList<XYMarker>& XYGraph::marker (void)
00275 {
00276    return _markers;
00277 }
00278 
00279 XYList<XYArea>& XYGraph::area (void)
00280 {
00281    return _areas;
00282 }
00283 
00284 XYList<XYSlice>& XYGraph::slice (void)
00285 {
00286    return _slices;
00287 }
00288 
00289 XYList<XYObject>& XYGraph::decorator (void)
00290 {
00291    return _decorators;
00292 }
00293 
00294 void XYGraph::legend (XYLegend* leg)
00295 {
00296    // Compartilha mesma lista de mascaras
00297    leg -> mask(&_masks); 
00298    
00299    _legend = leg;
00300 }
00301 
00302 XYLegend* XYGraph::legend (void) const
00303 {
00304    return _legend;
00305 }
00306 
00307 void XYGraph::backgroundColor (long color)
00308 {
00309    _color = color;
00310 }
00311 
00312 long XYGraph::backgroundColor (void) const
00313 {
00314    return _color;
00315 }
00316 
00317 void XYGraph::maskAreaColor (long color)
00318 {
00319    _ma_color = color;
00320 }
00321 
00322 long XYGraph::maskAreaColor (void) const
00323 {
00324    return _ma_color;
00325 }
00326 
00327 void XYGraph::width (double w)
00328 {
00329    _width = w;
00330    defineViewport();
00331 }
00332 
00333 double XYGraph::width (void) const
00334 {
00335    return _width;
00336 }
00337 
00338 void XYGraph::height (double h)
00339 {
00340    _height = h;
00341    defineViewport();
00342 }
00343 
00344 double XYGraph::height (void) const
00345 {
00346    return _height;
00347 }
00348 
00349 void XYGraph::setMaskArea (double xmin, double ymin, double xmax,
00350                                              double ymax)
00351 {
00352    _ma_xmin = xmin;
00353    _ma_ymin = ymin;
00354    _ma_xmax = xmax;
00355    _ma_ymax = ymax;
00356 }
00357 
00358 void XYGraph::getMaskArea (double& xmn, double& ymn, double& xmx,
00359                                              double& ymx) const
00360 {
00361    xmn = _ma_xmin;
00362    ymn = _ma_ymin;
00363    xmx = _ma_xmax;
00364    ymx = _ma_ymax;
00365 }
00366 
00367 void XYGraph::distortion (xybool d)
00368 {
00369    _distortion = d;
00370 }
00371 
00372 xybool XYGraph::distortion (void) const
00373 {
00374    return _distortion;
00375 }
00376                 
00377 xybool XYGraph::doubleBuffering (xybool on)
00378 {
00379    xybool old = _doublebuffering;
00380    _doublebuffering = on;
00381 
00382    return old;
00383 }
00384 
00385 xybool XYGraph::doubleBuffering (void) const
00386 {
00387    return _doublebuffering;
00388 }
00389 
00390 void XYGraph::defineViewport (void)
00391 {
00392    int w, h;         // tamanho do canvas em pixel
00393    double wmm, hmm;  // tamanho do canvas em milímetros
00394    cdGetCanvasSize(&w, &h, &wmm, &hmm);
00395 
00396    double xd, yd;
00397    position (&xd, &yd);
00398 
00399    int x1, x2, y1, y2;  // coordenadas da viewport
00400 
00401    if (_distortion)
00402    {
00403       // canto inferior esquerdo no canvas
00404       x1 = (int) (xd * (w - 1));
00405       y1 = (int) (yd * (h - 1));
00406 
00407       // canto superior direito no canvas( + 0.5 : round )
00408       x2 = (int) (x1 + (_width  * (w - 1)  + (double)0.5));
00409       y2 = (int) (y1 + (_height * (h - 1)  + (double)0.5));
00410    }
00411    else
00412    {
00413       // tamanho da viewport quadrada em milímetros
00414       double square = wmm > hmm ? hmm : wmm;
00415 
00416       double xppm = w / wmm;             // pixel por milímetro em x
00417       double yppm = h / hmm;             // pixel por milímetro em y
00418 
00419       int xpix = (int) (square * xppm);  // tamanho em pixel, em x
00420       int ypix = (int) (square * yppm);  // tamanho em pixel, em y
00421 
00422       // centraliza viewport no canvas
00423       x1 = (int) ((w - xpix) / 2.);
00424       x2 = x1 + xpix;
00425 
00426       y1 = (int) ((h - ypix) / 2.);
00427       y2 = y1 + ypix;
00428    }
00429 
00430    XYGraph* graph = (XYGraph *) this;
00431    graph -> setViewport (x1, x2, y1, y2);
00432 }
00433 
00434 int XYGraph::activateCanvas (void) const
00435 {
00436 #ifndef NOIUP
00437    // define um canvas CD, se ele ainda não existe
00438    if (_cdcanvas == NULL)
00439    {
00440       XYGraph* t = (XYGraph*) this;
00441       t -> setCdCanvas(cdCreateCanvas (CD_IUP, _canvas));
00442    }
00443 #endif
00444 
00445    if (_cdcanvas != NULL)
00446    {
00447       // ativa canvas CD
00448       int rc = wdActivate(_cdcanvas);
00449 
00450       // se não conseguir ativar o canvas CD, retorna mensagem de erro
00451       if (rc == CD_ERROR)
00452          return rc;
00453 
00454       cdBackground(_color);
00455       setViewport();
00456       setWindow ();
00457 
00458       // se double-buffering cria imagem (caso não exista) e a define como o
00459       // canvas CD corrente
00460       if (_doublebuffering)
00461       {
00462          // se não existe canvas CD para imagem, então cria
00463          if (_cvimage == NULL)
00464          {
00465             int w, h;
00466             cdGetCanvasSize (&w, &h, NULL, NULL);
00467 
00468             XYGraph* g = (XYGraph*) this;
00469 
00470                 // cria uma imagem, se ela tiver um tamanho diferente da imagem que
00471                   // já existe
00472                   if ((w != _image_w) || (_image_h != h))
00473             {
00474                    if (_image)
00475                   cdKillImage (_image);
00476                 
00477                g -> createImage (w, h);
00478 
00479                if (_image == NULL)
00480                  return CD_ERROR;
00481             }
00482 
00483                   // Cria/Ativa canvas p/ imagem 
00484                               g -> canvasImage (cdCreateCanvas (CD_IMAGE, _image));
00485                         rc = wdActivate(_cvimage);
00486 
00487                   // se não conseguir ativar o canvas CD, retorna mensagem de erro
00488             if (rc == CD_ERROR)
00489                return rc;
00490                        
00491             // N limpa com cor de fundo p/ ficar consistente com o modo sem doublebuffer
00492             cdClear();
00493                }
00494                  
00495          if (_cvimage != NULL)
00496          {
00497             // define canvas CD da imagem como corrente
00498             rc = wdActivate(_cvimage);
00499 
00500             // se não conseguir ativar o canvas da imagem, retorna mensagem
00501             // de erro
00502             if (rc == CD_ERROR)
00503                return rc;
00504 
00505             cdBackground(_color);
00506             setViewport();
00507             setWindow ();
00508          }
00509          else
00510            return CD_ERROR;
00511       }
00512 
00513       return CD_OK;
00514    }
00515              
00516    return CD_ERROR;
00517 }
00518 
00519 void XYGraph::getMaskArea (int& xmn, int& ymn, int& xmx, int& ymx) const
00520 {
00521    int x1, y1, x2, y2;
00522    getViewport(x1, x2, y1, y2);
00523 
00524    // define região de desenho das máscaras
00525    xmn = (int) (x1 + _ma_xmin * (x2 - x1));
00526    ymn = (int) (y1 + _ma_ymin * (y2 - y1) - 1);
00527    xmx = (int) (x1 + _ma_xmax * (x2 - x1) + 1);
00528    ymx = (int) (y1 + _ma_ymax * (y2 - y1));
00529 }
00530 
00531 void XYGraph::flush (void) const
00532 {
00533    // ativa canvas CD
00534    wdActivate(_cdcanvas);
00535 
00536    if (_cvimage)
00537    {
00538       XYGraph* g = (XYGraph*) this;
00539 
00540       // consulta posição do gráfico
00541       int x, y;
00542       g -> position(&x, &y);
00543 
00544       // consulta região ocupada pelo gráfico no canvas
00545       int x1, y1, x2, y2;
00546       g -> getViewport(x1, x2, y1, y2);
00547 
00548       // copia o pedaço da imagem que contém o gráfico para o canvas CD
00549       cdPutImageRect (_image, x, y, x1, x2, y1, y2);
00550       
00551       // OBS : Destroi o _cvimage a cada novo draw -> Nao eh muito eficiente
00552       // define o canvas da imagem como sendo nulo
00553       cdKillCanvas (_cvimage);
00554       g -> canvasImage(0);
00555    }
00556    // comentado para resolver o problema da impressao de varios
00557    // graficos num mesmo canvas. o cdflush faz pular de pagina.
00558    //else
00559    //   cdFlush();
00560 }
00561 
00562 XYMask& XYGraph::mask(unsigned m)
00563 {
00564    XYMask *temp = NULL, *nothing = NULL;
00565    XYListIterator<XYMask> im(&_masks);
00566 
00567    for (unsigned i = 0; i < m-1; i++)
00568    {
00569       if (im.End())
00570       return *nothing;
00571 
00572       temp = im.Next();
00573    }
00574 
00575    return *temp;
00576 }
00577 
00578 void XYGraph::scroll (int dx, int dy)
00579 {
00580    activateCanvas();
00581 
00582    int ua_x1, ua_y1, ua_x2, ua_y2;
00583    getMaskArea (ua_x1, ua_y1, ua_x2, ua_y2);
00584 
00585    // faz deslocamento da região selecionada
00586    int mode = cdClip(CD_CLIPON);
00587 
00588    // guarda a região de clip corrente
00589    int oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax;
00590    cdGetClipArea (&oldclip_xmin, &oldclip_xmax, &oldclip_ymin, &oldclip_ymax);
00591    // define nova região de clip
00592    cdClipArea(ua_x1 + 1, ua_x2, ua_y1, ua_y2);
00593         
00594    cdScrollImage(ua_x1, ua_x2, ua_y1, ua_y2, -dx, -dy);
00595 
00596    // limpa região horizontal não deslocada
00597    if (dy != 0)
00598    {
00599       cdForeground(CD_WHITE);
00600       cdInteriorStyle(CD_SOLID);
00601 
00602       if (dy > 0)
00603       {
00604          cdClipArea(ua_x1, ua_x2, ua_y2 - dy, ua_y2);   
00605          cdBox(ua_x1, ua_x2, ua_y2 - dy, ua_y2);
00606          drawMaskArea(ua_x1, ua_y2 - dy, ua_x2, ua_y2);
00607       }
00608       else
00609       {
00610          cdClipArea(ua_x1, ua_x2, ua_y1, ua_y1 - dy);   
00611          cdBox(ua_x1, ua_x2, ua_y1, ua_y1 - dy);
00612          drawMaskArea(ua_x1, ua_y1, ua_x2, ua_y1 - dy);
00613       }
00614    }
00615 
00616    // limpa região vertical não deslocada
00617    if (dx != 0)
00618    {
00619       cdForeground(CD_WHITE);
00620       cdInteriorStyle(CD_SOLID);
00621 
00622       if (dx > 0)
00623       {
00624          cdClipArea(ua_x2 - dx, ua_x2, ua_y1, ua_y2);
00625          cdBox(ua_x2 - dx, ua_x2, ua_y1, ua_y2);
00626          drawMaskArea (ua_x2 - dx, ua_y1, ua_x2, ua_y2);
00627       }
00628       else
00629       {
00630          cdClipArea(ua_x1, ua_x1 - dx + 1, ua_y1, ua_y2);
00631          cdBox(ua_x1, ua_x1 - dx + 1, ua_y1, ua_y2);
00632          drawMaskArea (ua_x1, ua_y1, ua_x1 - dx + 1, ua_y2);
00633       }
00634    }
00635 
00636    cdClip(mode);
00637    // restaura a região de clip anterior
00638    cdClipArea(oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax);
00639 }
00640 
00641 xybool XYGraph::contains(const XYObject* obj)
00642 {
00643    // testa lista de marcadores
00644    XYListIterator<XYMarker> imk(&_markers);
00645    if (imk.Contains((XYMarker*)obj) == xytrue)
00646      return xytrue;        
00647 
00648    // testa lista de máscaras
00649    XYListIterator<XYMask> im(&_masks);
00650    if (im.Contains((XYMask*)obj) == xytrue)
00651      return xytrue;
00652 
00653    // testa lista de "slices"
00654    XYListIterator<XYSlice> is(&_slices);
00655    if (is.Contains((XYSlice*)obj) == xytrue)
00656      return xytrue;
00657     
00658    // testa lista de "areas"
00659    XYListIterator<XYArea> ia(&_areas);
00660    if (ia.Contains((XYArea*)obj) == xytrue)
00661      return xytrue;
00662     
00663    // testa lista de "decoradores"
00664    XYListIterator<XYObject> id(&_decorators);
00665    if (id.Contains((XYObject*)obj) == xytrue)
00666      return xytrue;
00667     
00668    // testa legenda, se houver
00669    if (_legend)
00670       // se objeto é uma legenda...
00671       if (_legend == obj)
00672          return xytrue;
00673 
00674    // testa lista de textos
00675    XYListIterator<XYText> it(&_titles);
00676    if (it.Contains((XYText*)obj) == xytrue)
00677      return xytrue;
00678       
00679    // testa lista de eixos
00680    XYListIterator<XYAxis> in(&_axes);
00681    if (in.Contains((XYAxis*)obj) == xytrue)
00682      return xytrue;
00683     
00684    return xyfalse;
00685 }
00686 
00687 XYObject* XYGraph::pick (int px, int py)
00688 {
00689    activateCanvas();
00690 
00691    // testa lista de marcadores
00692    XYListIterator<XYMarker> ic(&_markers);
00693    XYMarker* kcont;
00694 
00695    while (!ic.End())
00696    {
00697       kcont = ic.Next();
00698 
00699       // decide pick
00700       if (kcont -> pick(px, py))
00701          return kcont;
00702    }
00703 
00704    // testa lista de máscaras
00705    XYListIterator<XYMask> im(&_masks);
00706    XYMask *mcont, *sel=NULL;
00707 
00708    while (!im.End())
00709    {
00710       mcont = im.Next();
00711 
00712       // decide pick
00713       if (mcont -> pick(px, py))
00714        sel = mcont;
00715    }
00716    if (sel!=NULL) return sel;
00717 
00718    // define window para [0.0, 1.0] x [0.0, 1.0]
00719    setWindow();
00720    setViewport();
00721 
00722    // antes de testar "slices" para pick é necessário inverter a ordem
00723    // na lista que os contém porque eles foram inseridos no final dela
00724    // e isso faz com que sejam desenhados na ordem correta mas o pick
00725    // precisa pesquisar na ordem inversa
00726 
00727    XYListIterator<XYSlice> iu(&_aux_slices);  // lista auxiliar de "slices"
00728    XYListIterator<XYSlice> is(&_slices);      // lista original de "slices"
00729    XYSlice* xcont;
00730    XYSlice* scont;
00731 
00732    // limpa lista auxiliar caso ela possua algum elemento
00733    while (!iu.End())
00734    {
00735       xcont = iu.Next();
00736       _aux_slices.remove(xcont);
00737    }
00738 
00739    // inverte ordem da lista original numa lista auxiliar
00740    while (!is.End())
00741    {
00742       scont = is.Next();
00743       _aux_slices.insert(scont);
00744    }
00745 
00746    iu.Reset();
00747 
00748    // testa lista invertida de "slices" para pick
00749    while (!iu.End())
00750    {
00751       scont = iu.Next();
00752 
00753       // decide pick
00754       if (scont -> pick(px, py))
00755          return scont;
00756    }
00757 
00758    // testa legenda para pick, se houver
00759    if (_legend)
00760       if (_legend -> pick(px, py))
00761          return _legend;
00762 
00763    // testa lista de textos
00764    XYListIterator<XYText> it(&_titles);
00765    XYText* tcont;
00766 
00767    while (!it.End())
00768    {
00769       tcont = it.Next();
00770 
00771       // decide pick
00772       if (tcont -> pick(px, py))
00773          return tcont;
00774    }
00775 
00776    // testa lista de eixos
00777    XYListIterator<XYAxis> in(&_axes);
00778    XYAxis* acont;
00779 
00780    while (!in.End())
00781    {
00782       acont = in.Next();
00783 
00784       // decide pick
00785       if (acont -> pick(px, py))
00786          return acont;
00787    }
00788 
00789    return NULL;
00790 }
00791 
00792 XYAxis* XYGraph::pickAxis (int x, int y)
00793 {
00794    activateCanvas();
00795 
00796    // testa lista de eixos
00797    XYListIterator<XYAxis> in(&_axes);
00798    XYAxis* cont;
00799 
00800    while (!in.End())
00801    {
00802       cont = in.Next();
00803 
00804       // decide pick
00805       if (cont -> pick(x, y))
00806          return cont;
00807    }
00808 
00809    return 0;
00810 }
00811 
00812 XYArea* XYGraph::pickArea (int x, int y)
00813 {
00814    activateCanvas();
00815 
00816    XYListIterator<XYArea> is(&_areas); 
00817    XYArea* acont;
00818 
00819    while (!is.End())
00820    { acont = is.Next();
00821      if (acont->pick(x, y)) return acont;
00822    }
00823 
00824    return 0;
00825 }
00826 
00827 XYSlice* XYGraph::pickSlice (int x, int y)
00828 {
00829    activateCanvas();
00830 
00831    // antes de testar "slices" para pick é necessário inverter a ordem
00832    // na lista que os contém porque eles foram inseridos no final dela
00833    // e isso faz com que sejam desenhados na ordem correta mas o pick
00834    // precisa pesquisar na ordem inversa
00835 
00836    XYListIterator<XYSlice> iu(&_aux_slices);  // lista auxiliar de "slices"
00837    XYListIterator<XYSlice> is(&_slices);      // lista original de "slices"
00838    XYSlice* xcont;
00839    XYSlice* scont;
00840 
00841    // limpa lista auxiliar caso ela possua algum elemento
00842    while (!iu.End())
00843    {
00844       xcont = iu.Next();
00845       _aux_slices.remove(xcont);
00846    }
00847 
00848    // inverte ordem da lista original na lista auxiliar
00849    while (!is.End())
00850    {
00851       scont = is.Next();
00852       _aux_slices.insert(scont);
00853    }
00854 
00855    iu.Reset();
00856 
00857    // testa lista invertida de "slices" para pick
00858    while (!iu.End())
00859    {
00860       scont = iu.Next();
00861 
00862       // decide pick
00863       if (scont -> pick(x, y))
00864          return scont;
00865    }
00866 
00867    return 0;
00868 }
00869 
00870 XYMarker* XYGraph::pickMarker (int x, int y)
00871 {
00872    activateCanvas();
00873 
00874    // testa lista de marcadores
00875    XYListIterator<XYMarker> ic(&_markers);
00876    XYMarker* cont;
00877 
00878    while (!ic.End())
00879    {
00880       cont = ic.Next();
00881 
00882       // decide pick
00883       if (cont -> pick(x, y))
00884          return cont;
00885    }
00886 
00887    return 0;
00888 }
00889 
00890 XYMask* XYGraph::pickMask (int x, int y)
00891 {
00892    activateCanvas();
00893 
00894    // testa lista de máscaras
00895    XYListIterator<XYMask> im(&_masks);
00896    XYMask *cont, *sel=NULL;
00897 
00898    while (!im.End())
00899    {
00900       cont = im.Next();
00901 
00902       // decide pick
00903       if (cont -> pick(x, y))
00904        sel = cont;
00905    }
00906 
00907    return sel;
00908 }
00909 
00910 XYLegend* XYGraph::pickLegend (int x, int y)
00911 {
00912    activateCanvas();
00913 
00914    // decide pick para a legenda
00915    if (_legend)
00916       if (_legend -> pick(x, y))
00917          return _legend;
00918 
00919    return 0;
00920 }
00921 
00922 XYText* XYGraph::pickText (int x, int y)
00923 {
00924    activateCanvas();
00925 
00926    // testa lista de textos
00927    XYListIterator<XYText> it(&_titles);
00928    XYText* cont;
00929 
00930    while (!it.End())
00931    {
00932       cont = it.Next();
00933 
00934       // decide pick
00935       if (cont -> pick(x, y))
00936          return cont;
00937    }
00938 
00939    return 0;
00940 }
00941 
00942 XYList<XYObject>* XYGraph::fence (int x0, int y0, int x1, int y1)
00943 {
00944    activateCanvas();
00945 
00946    XYList<XYObject>* obj = new XYList<XYObject>;
00947 
00948    // verifica lista de marcadores para "fence"
00949    XYListIterator<XYMarker> ic(&_markers);
00950    XYMarker* kcont;
00951 
00952    while (!ic.End())
00953    {
00954       kcont = ic.Next();
00955 
00956       // decide "fence"
00957       if (kcont -> fence(x0, y0, x1, y1))
00958          obj -> insert(kcont);
00959    }
00960 
00961    // verifica lista de máscaras para "fence"
00962    XYListIterator<XYMask> im(&_masks);
00963    XYMask* mcont;
00964 
00965    while (!im.End())
00966    {
00967       mcont = im.Next();
00968 
00969       // decide "fence"
00970       if (mcont -> fence(x0, y0, x1, y1))
00971          obj -> insert(mcont);
00972    }
00973 
00974    // define window para [0.0, 1.0] x [0.0, 1.0]
00975    setWindow();
00976    setViewport();
00977 
00978    // verifica lista de "slices" para "fence"
00979    XYListIterator<XYSlice> is(&_slices);
00980    XYSlice* scont;
00981 
00982    while (!is.End())
00983    {
00984       scont = is.Next();
00985 
00986       // decide "fence"
00987       if (scont -> fence(x0, y0, x1, y1))
00988          obj -> insert(scont);
00989    }
00990 
00991    // verifica lista de "areas" para "fence"
00992    XYListIterator<XYArea> ir(&_areas);
00993    XYArea* rcont;
00994    while (!ir.End())
00995    { rcont = ir.Next();
00996      if (rcont->fence(x0, y0, x1, y1)) obj -> insert(rcont);
00997    }
00998 
00999    // testa lista de eixos para "fence"
01000    XYListIterator<XYAxis> in(&_axes);
01001    XYAxis* acont;
01002 
01003    while (!in.End())
01004    {
01005       acont = in.Next();
01006 
01007       // decide "fence"
01008       if (acont -> fence(x0, y0, x1, y1))
01009          obj -> insert(acont);
01010    }
01011 
01012    // verifica lista de textos para "fence"
01013    XYListIterator<XYText> it(&_titles);
01014    XYText* tcont;
01015 
01016    while (!it.End())
01017    {
01018       tcont = it.Next();
01019 
01020       // decide "fence"
01021       if (tcont -> fence(x0, y0, x1, y1))
01022          obj -> insert(tcont);
01023    }
01024 
01025    // testa legenda para "fence", se houver
01026    if (_legend)
01027       if (_legend -> fence(x0, y0, x1, y1))
01028          obj -> insert(_legend);
01029 
01030    return obj;
01031 }
01032 
01033 void XYGraph::print (void)
01034 {
01035    cdCanvas *oldcanvas = _cdcanvas;
01036    _cdcanvas = cdCreateCanvas (CD_PS, (void *) "imagem");
01037 
01038    draw();
01039    cdKillCanvas (_cdcanvas);
01040    _cdcanvas = oldcanvas;
01041    activateCanvas();
01042 }
01043 
01044 void XYGraph::clear (void)
01045 {
01046    activateCanvas();
01047    defineViewport();
01048 
01049    int mode = cdClip(CD_CLIPOFF);
01050 
01051    // preenche o fundo da região do gráfico com a cor definida pelo usuário
01052    cdForeground(_color);
01053    cdInteriorStyle(CD_SOLID);
01054 
01055    int x1, y1, x2, y2;
01056    getViewport (x1, x2, y1, y2);
01057    cdBox(x1, x2, y1, y2);
01058 
01059    cdClip(mode);
01060 }
01061 
01062 void XYGraph::clear (int xmin, int ymin, int xmax, int ymax) const
01063 {
01064    activateCanvas ();
01065    int mode = cdClip(CD_CLIPON);
01066 
01067    // guarda a região de clip corrente
01068    int oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax;
01069    cdGetClipArea (&oldclip_xmin, &oldclip_xmax, &oldclip_ymin, &oldclip_ymax);
01070    // define nova região de clip
01071    cdClipArea(xmin, xmax, ymin, ymax);
01072 
01073    // preenche o fundo da região do gráfico com a cor definida pelo usuário
01074    cdForeground(_color);
01075    cdInteriorStyle(CD_SOLID);
01076 
01077    cdBox(xmin, xmax, ymin, ymax);
01078 
01079    cdClip(mode);
01080    // restaura a região de clip anterior
01081    cdClipArea(oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax);
01082 }
01083 
01084 void XYGraph::maskAreaClear (void) const
01085 {
01086    int x1, y1, x2, y2;
01087    getMaskArea(x1, y1, x2, y2);
01088 
01089    int mode = cdClip(CD_CLIPON);
01090 
01091    // guarda a região de clip corrente
01092    int oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax;
01093    cdGetClipArea (&oldclip_xmin, &oldclip_xmax, &oldclip_ymin, &oldclip_ymax);
01094    // define nova região de clip
01095    cdClipArea(x1, x2, y1, y2);
01096 
01097    // preenche a região de desenho das máscaras do gráfico com a cor
01098    // definida pelo usuário
01099    cdForeground(_ma_color);
01100    cdInteriorStyle(CD_SOLID);
01101 
01102    cdBox(x1, x2, y1, y2);
01103 
01104    cdClip(mode);
01105    // restaura a região de clip anterior
01106    cdClipArea(oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax);
01107 }
01108 
01109 void XYGraph::propagateViewport (void) const
01110 {
01111    int x1, y1, x2, y2;
01112    getViewport(x1, x2, y1, y2);
01113 
01114    XYListIterator<XYText> it(&_titles);
01115    XYText* tcont;
01116 
01117    // define área no gráfico para todos os textos
01118    while (!it.End())
01119    {
01120       tcont = it.Next();
01121       tcont -> setViewport(x1, x2, y1, y2);
01122    }
01123 
01124    XYListIterator<XYAxis> in(&_axes);
01125    XYAxis* acont;
01126 
01127    // define área no gráfico para todos os eixos
01128    while (!in.End())
01129    {
01130       acont = in.Next();
01131       acont -> setViewport(x1, x2, y1, y2);
01132    }
01133 
01134    XYListIterator<XYSlice> is(&_slices);
01135    XYMarker* bcont;
01136    XYMarker* fcont;
01137    XYSlice* scont;
01138    const XYAxis* ncont;
01139 
01140    int sx1, sx2, sy1, sy2;
01141    getMaskArea(sx1, sy1, sx2, sy2);
01142 
01143    // define área no gráfico para todos os "slices"
01144    while (!is.End())
01145    {
01146       scont = is.Next();
01147       scont -> setViewport(sx1, sx2, sy1, sy2);
01148 
01149       ncont = scont -> axis();
01150         
01151       bcont = scont -> beginMarker();
01152       bcont -> setViewport(sx1, sx2, sy1, sy2);
01153         
01154       fcont = scont -> endMarker();
01155       fcont -> setViewport(sx1, sx2, sy1, sy2);
01156 
01157       if (ncont -> rotation() == 0.0)
01158             {
01159          bcont -> limit(_ma_ymax - _ma_ymin);
01160          fcont -> limit(_ma_ymax - _ma_ymin);
01161             }
01162       else
01163             {
01164          bcont -> limit(_ma_xmax - _ma_xmin);
01165          fcont -> limit(_ma_xmax - _ma_xmin);
01166             }
01167    }
01168 
01169    XYListIterator<XYMarker> ic(&_markers);
01170    XYMarker* ccont;
01171 
01172    // define área no gráfico para todos os marcadores
01173    while (!ic.End())
01174    {
01175       ccont = ic.Next();
01176       ccont -> setViewport(sx1, sx2, sy1, sy2);
01177 
01178       ncont = ccont -> axis();
01179 
01180       if (ncont -> rotation() == 0.0)
01181          ccont -> limit(_ma_ymax - _ma_ymin);
01182       else
01183          ccont -> limit(_ma_xmax - _ma_xmin);
01184    }
01185 
01186    XYListIterator<XYMask> im(&_masks);
01187 
01188    if (!im.End())
01189    {
01190       XYMask* cont;
01191 
01192       // define área no gráfico para todas as máscaras
01193       while (!im.End())
01194       {
01195          cont = im.Next();
01196          cont -> setViewport(sx1, sx2 - 1, sy1 + 1, sy2);
01197       }
01198    }
01199 
01200    // define área no gráfico para legenda
01201    if (_legend != NULL)
01202       _legend -> setViewport(x1, x2, y1, y2);
01203 }
01204 
01205 void XYGraph::draw (void)
01206 {
01207    if (visible() == xyfalse)    // invisível!!!
01208       return;
01209 
01210    activateCanvas();
01211 
01212    int x1, y1, x2, y2;
01213    getViewport(x1, x2, y1, y2);
01214 
01215    draw(x1, y1, x2, y2);
01216 }
01217 
01218 void XYGraph::draw (int xmin, int ymin, int xmax, int ymax) const
01219 {
01220    if (visible() == xyfalse) return;
01221 
01222    activateCanvas();
01223 
01224    int mode = cdClip(CD_CLIPON);
01225 
01226    // guarda a região de clip corrente
01227    int oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax;
01228    cdGetClipArea (&oldclip_xmin, &oldclip_xmax, &oldclip_ymin, &oldclip_ymax);
01229    // define nova região de clip
01230    cdClipArea(xmin, xmax, ymin, ymax);
01231 
01232    // desenha lista de decorators
01233    XYListIterator<XYObject> id(&_decorators);
01234    XYObject* dcont;
01235 
01236    while (!id.End())
01237    {
01238       dcont = id.Next();
01239       dcont -> draw(xmin, ymin, xmax, ymax);
01240    }
01241 
01242    // desenha lista de textos
01243    XYListIterator<XYText> it(&_titles);
01244    XYText* tcont;
01245 
01246    while (!it.End())
01247    {
01248       tcont = it.Next();
01249       tcont -> draw(xmin, ymin, xmax, ymax);
01250    }
01251 
01252    // desenha lista de eixos
01253    XYListIterator<XYAxis> in(&_axes);
01254    XYAxis* acont;
01255 
01256    while (!in.End())
01257    {
01258       acont = in.Next();
01259       acont -> draw(xmin, ymin, xmax, ymax);
01260    }
01261 
01262    // desenha todas as máscaras
01263    XYListIterator<XYMask> im(&_masks);
01264    XYMask* mcont;
01265 
01266    while (!im.End())
01267    {
01268       mcont = im.Next();
01269       mcont -> draw(xmin, ymin, xmax, ymax);
01270    }
01271 
01272    // redefine window e viewport porque as máscaras possuem transformações
01273    // próprias
01274    setWindow();
01275    setViewport();
01276 
01277    im.Reset();
01278 
01279    // desenha todos os marcadores
01280    XYListIterator<XYMarker> ic(&_markers);
01281    XYMarker* ccont;
01282    while (!ic.End())
01283    { ccont = ic.Next();
01284      ccont->draw(xmin, ymin, xmax, ymax);
01285    }
01286 
01287 
01288    // desenha legenda para as máscaras, se existir
01289    if (_legend != NULL) _legend -> draw(xmin, ymin, xmax, ymax);
01290 
01291    cdClip(mode);
01292    // restaura a região de clip anterior
01293    cdClipArea(oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax);
01294 }
01295 
01296 void XYGraph::drawMaskArea (int xmin, int ymin, int xmax, int ymax) const
01297 {
01298    int mode = cdClip(CD_CLIPON);
01299 
01300    // guarda a região de clip corrente
01301    int oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax;
01302    cdGetClipArea (&oldclip_xmin, &oldclip_xmax, &oldclip_ymin, &oldclip_ymax);
01303    // define nova região de clip
01304    cdClipArea(xmin, xmax, ymin, ymax);
01305 
01306    XYListIterator<XYAxis> in(&_axes);
01307    XYAxis* acont;
01308 
01309    double x1, y1, x2, y2;
01310    double rot_rad;
01311 
01312    // desenha eixo com linha sólida mais fina possível e com cor definida
01313    // pelo usuário, se ele estiver dentro da área útil
01314    while (!in.End())
01315    {
01316       acont = in.Next();
01317 
01318       // consulta posição do eixo
01319       acont -> position(&x1, &y1);
01320 
01321       // ângulo de rotação em radianos
01322       rot_rad = acont -> rotation() * XY_PI / 180.0;
01323 
01324       // (x2, y2) ponto superior direito no eixo
01325       x2 = x1 + acont -> size() * cos (rot_rad);
01326       y2 = y1 + acont -> size() * sin (rot_rad);
01327 
01328       // controle de ponto flutuante
01329       if (mtEqual(x1, x2))
01330          x2 = x1;
01331       if (mtEqual(y1, y2))
01332          y2 = y1;
01333 
01334       if ((x1 >= _ma_xmin) && (y1 >= _ma_ymin) && (x2 <= _ma_xmax)
01335           && (y2 <= _ma_ymax))
01336          // desenha eixo
01337          acont -> draw();
01338    }
01339 
01340    // desenha todas as máscaras
01341    XYListIterator<XYMask> im(&_masks);
01342    XYMask* cont;
01343 
01344    while (!im.End())
01345    {
01346       cont = im.Next();
01347       cont -> draw(xmin, ymin, xmax, ymax);
01348    }
01349 
01350    // redefine window e viewport porque as máscaras possuem transformações
01351    // próprias
01352    setWindow();
01353    setViewport();
01354 
01355    // desenha todos os marcadores
01356    XYListIterator<XYMarker> ic(&_markers);
01357    XYMarker* ccont;
01358    while (!ic.End())
01359    { ccont = ic.Next();
01360      ccont -> draw(xmin, ymin, xmax, ymax);
01361    }
01362 
01363    cdClip(mode);
01364    // restaura a região de clip anterior
01365    cdClipArea(oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax);
01366 }
01367 

XY
Tecgraf / PUC-Rio - Computer Graphics Technology Group