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

xyaxpl.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /* Módulo: xyaxpl.cpp                                                        */
00003 /* Autor: Camilo da Foseca Freire                                            */
00004 /* Data: 06 jul 96                                                           */
00005 /* Comentário:                                                               */
00006 /*    Implementação de métodos da classe especializada que define um eixo    */
00007 /* polar.                                                                    */
00008 /*****************************************************************************/
00009 
00010 #include <stdlib.h>
00011 #include <math.h>
00012 #include <stdio.h>
00013 
00014 #include "xyaxpl.h"
00015 #include "xysdnm.h"
00016                                                                 
00017 const char* xy_id_xyaxpl_cpp="$Id: xyaxpl.cpp,v 1.19 1999/12/09 21:47:46 rborges Exp $";
00018                                                                 
00019 XYPolarAxis::XYPolarAxis (double radius,
00020                           XYCoordinate x,
00021                           XYCoordinate y,
00022                                 long color,
00023                                 double size,
00024                                             double rot,
00025                                       double step,
00026                                 XYScaleDecorator* decor,
00027                                 XYText* title,
00028                                 xybool arrow,
00029                                 xybool visible)
00030                                 : XYAxis (0., radius, x, y, color, size, rot, step,
00031                                                   decor, title, arrow, visible)
00032 {
00033 }
00034 
00035 XYPolarAxis::XYPolarAxis (double radius,
00036                           XYCoordinate x,
00037                           XYCoordinate y,
00038                                           long color,
00039                                             double size,
00040                                             double rot,
00041                                             xybool arrow,
00042                                             xybool visible)
00043                                             : XYAxis (0., radius, x, y, color, size, rot,
00044                                                       arrow, visible)
00045 {
00046 }
00047 
00048 void XYPolarAxis::polar2cart (double radius, double alpha, double& x,
00049                               double & y ) const
00050 {
00051    x = radius * cos (alpha * XY_PI / 180.);
00052    y = radius * sin (alpha * XY_PI / 180.);
00053 }
00054 
00055 void XYPolarAxis::firstTick (double& tx1, double& ty1, double& tx2,
00056                              double& ty2) const
00057 {
00058    double tick_size = 0.01;
00059 
00060    // ângulo de rotação em radianos
00061    double rot_rad = _rot * XY_PI / 180.0;
00062 
00063    // (x1, y1) ponto inferior esquerdo no eixo
00064    double x1, y1;
00065    position (&x1, &y1);
00066 
00067    // (x2, y2) ponto superior direito no eixo
00068    double x2 = x1 + _size * cos (rot_rad);
00069    double y2 = y1 + _size * sin (rot_rad);
00070 
00071    // controle de ponto flutuante
00072    if (mtEqual(x1, x2))
00073       x2 = x1;
00074    if (mtEqual(y1, y2))
00075       y2 = y1;
00076 
00077    // (tx1, ty1) coordenadas sobre o eixo
00078    tx1 = x1;
00079    ty1 = y1;
00080 
00081    if (rot_rad > 0 && rot_rad <= XY_PI)
00082       mtRotate(tick_size, 0, rot_rad + XY_PI / 2.0, &tx2, &ty2);
00083    else
00084       mtRotate(tick_size, 0, rot_rad - XY_PI / 2.0, &tx2, &ty2);
00085 
00086    tx2 += x1;
00087    ty2 += y1;
00088 
00089    // controle de ponto flutuante
00090    if (mtEqual(tx1, tx2))
00091       tx2 = tx1;
00092    if (mtEqual(ty1, ty2))
00093       ty2 = ty1;
00094 }
00095 
00096 void XYPolarAxis::draw (void)
00097 {
00098    draw (_xmin, _ymin, _xmax, _ymax);
00099 }
00100 
00101 void XYPolarAxis::draw (int xmin, int ymin, int xmax, int ymax) const
00102 {
00103    if (visible() == xyfalse)    // invisível!!!
00104       return;
00105 
00106    int mode = cdClip(CD_CLIPON);
00107 
00108    // guarda a região de clip corrente
00109    int oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax;
00110    cdGetClipArea (&oldclip_xmin, &oldclip_xmax, &oldclip_ymin, &oldclip_ymax);
00111    // define nova região de clip
00112    cdClipArea(xmin, xmax, ymin, ymax);
00113 
00114    // ângulo de rotação em radianos
00115    double rot_rad = _rot * XY_PI / 180.0;
00116 
00117    // (x1, y1) ponto inferior esquerdo no eixo
00118    double x1, y1;
00119    position (&x1, &y1);
00120 
00121    // (x2, y2) ponto superior direito no eixo
00122    double x2 = x1 + _size * cos (rot_rad);
00123    double y2 = y1 + _size * sin (rot_rad);
00124 
00125    // controle de ponto flutuante
00126    if (mtEqual(x1, x2))
00127       x2 = x1;
00128    if (mtEqual(y1, y2))
00129       y2 = y1;
00130 
00131    // desenha eixo com linha sólida mais fina possível e com cor definida
00132    // pelo usuário
00133    cdLineWidth (1);
00134    cdLineStyle (continuous);
00135    cdForeground (_color);
00136 
00137    // desenha eixo
00138    wdLine (x1, y1, x2, y2);
00139 
00140    // desenha seta no eixo
00141    if (_arrow == xytrue)
00142    {
00143       cdInteriorStyle (CD_SOLID);
00144       drawArrow(x1, y1, x2, y2);
00145    }
00146 
00147    // desenha a escala se ela foi definida e se o passo tem um valor válido
00148    if (_step > 0.0)
00149    {
00150       // calcula coordenadas do primeiro tick
00151       double ex1, ey1, ex2, ey2;
00152       firstTick (ex1, ey1, ex2, ey2);
00153 
00154       // intervalos de deslocamento em relação as direções x e y
00155       double dx, dy;
00156       mtRotate (_step * _size / _mx, 0.0, rot_rad, &dx, &dy);
00157 
00158       // calcula qual é o último tick a ser desenhado, o método é verificar,
00159       // a partir do último, qual é o primeiro tick que está dentro da área
00160       // a ser redesenhada
00161       int last_tick = (int) floor  (_mx / _step);
00162 
00163       // inicializa com posição do último tick
00164       double tex1 = ex1 + dx * last_tick;
00165       double tey1 = ey1 + dy * last_tick;
00166       double tex2 = ex2 + dx * last_tick;
00167       double tey2 = ey2 + dy * last_tick;
00168 
00169       // normalizando a área de desenho
00170       double pxmin = (double) (xmin - _xmin) / (_xmax - _xmin);
00171       double pymin = (double) (ymin - _ymin) / (_ymax - _ymin);
00172       double pxmax = (double) (xmax - _xmin) / (_xmax - _xmin);
00173       double pymax = (double) (ymax - _ymin) / (_ymax - _ymin);
00174 
00175       // verifica se tick está dentro da área a ser redesenhada
00176       while ((mtPointInRect(tex1, tey1, pxmin, pymin, pxmax, pymax) != xytrue)
00177              && (last_tick >=0))
00178       {
00179          // próximo tick
00180          tex1 -= dx;
00181          tex2 -= dx;
00182          tey1 -= dy;
00183          tey2 -= dy;
00184 
00185          // atualiza número do último tick
00186          last_tick--;
00187       }
00188 
00189       // retorna, se não há tick para ser desenhado
00190       if (last_tick < 0)
00191             {
00192         cdClip(mode);
00193         // restaura a região de clip anterior
00194         cdClipArea(oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax);
00195                     return;
00196             }
00197 
00198       // calcula qual é o primeiro tick a ser desenhado, o método é verificar,
00199       // a partir do primeiro, qual é o primeiro tick que está dentro da área
00200       // a ser redesenhada
00201       int first_tick = 0;
00202 
00203       // verifica se tick está dentro da área a ser redesenhada
00204       while ((mtPointInRect(ex1, ey1, pxmin, pymin, pxmax, pymax) != xytrue)
00205              && (first_tick < last_tick))
00206       {
00207          // próximo tick
00208          ex1 += dx;
00209          ex2 += dx;
00210          ey1 += dy;
00211          ey2 += dy;
00212 
00213          // atualiza número do primeiro tick
00214          first_tick++;
00215       }
00216         
00217       for (int ntick = first_tick; ntick <= last_tick; ++ntick)
00218       {
00219          // desenha tick
00220          wdLine(ex1, ey1, ex2, ey2);
00221 
00222          // próximo tick
00223                ex1 += dx;
00224                ex2 += dx;
00225                ey1 += dy;
00226                ey2 += dy;
00227       }
00228 
00229       // desenha os labels da escala
00230       if (_decor)
00231          _decor -> draw (this, first_tick, last_tick);
00232    }
00233 
00234    // desenha título se o mesmo foi definido, indicando localização na linha,
00235    // se direita, centro ou esquerda
00236    if (_title)
00237    {
00238       // consulta área do gráfico para desenho do eixo
00239       int xmn, ymn, xmx, ymx;
00240       getViewport(xmn, xmx, ymn, ymx);
00241 
00242       // define área do gráfico para desenho do título do eixo
00243       _title -> setViewport(xmn, xmx, ymn, ymx);
00244       _title -> draw();
00245    }
00246 
00247    cdClip(mode);
00248    // restaura região de clip anterior
00249    cdClipArea(oldclip_xmin, oldclip_xmax, oldclip_ymin, oldclip_ymax);
00250 }
00251 
00252 void XYPolarAxis::boundingBox (int& bxmin, int& bymin, int& bxmax, int& bymax)
00253                                      const
00254 {
00255    // ângulo de rotação em radianos
00256    double rot_rad = _rot * XY_PI / 180.0;
00257 
00258    // (x1, y1) ponto inferior esquerdo no eixo
00259    double x1, y1;
00260    position (&x1, &y1);
00261 
00262    // (x2, y2) ponto superior direito no eixo
00263    double x2 = x1 + _size * cos (rot_rad);
00264    double y2 = y1 + _size * sin (rot_rad);
00265 
00266    // controle de ponto flutuante
00267    if (mtEqual(x1, x2))
00268       x2 = x1;
00269    if (mtEqual(y1, y2))
00270       y2 = y1;
00271 
00272    // inicializando boundingBox com coordenadas do eixo
00273    double xmin = MIN(x1, x2);
00274    double ymin = MIN(y1, y2);
00275    double xmax = MAX(x1, x2);
00276    double ymax = MAX(y1, y2);
00277 
00278    // calcula boundingBox da seta do eixo
00279    if (_arrow == xytrue)
00280    {
00281       double bx1, bx2, by1, by2;
00282       boxArrow(x1, y1, x2, y2, bx1, by1, bx2, by2);
00283 
00284       xmin = MIN(bx1, xmin);
00285       xmax = MAX(bx2, xmax);
00286       ymin = MIN(by1, ymin);
00287       ymax = MAX(by2, ymax);
00288    }
00289 
00290    // contabiliza boundingBox da escala se a mesma foi definida e se passo tem
00291    // um valor válido
00292    if (_step > 0.0)
00293    {
00294       // atualiza boundingBox com as coordenadas do primeiro tick
00295       double ex1, ey1, ex2, ey2;
00296       firstTick (ex1, ey1, ex2, ey2);
00297 
00298       xmin = MIN3 (xmin, ex1, ex2);
00299       xmax = MAX3 (xmax, ex1, ex2);
00300       ymin = MIN3 (ymin, ey1, ey2);
00301       ymax = MAX3 (ymax, ey1, ey2);
00302 
00303       int bex1, bey1, bex2, bey2;
00304 
00305       // atualiza boundingBox com as coordenadas dos labels
00306       if (_decor)
00307          _decor -> boundingBox (this, bex1, bey1, bex2, bey2);
00308 
00309       wdCanvas2World (bex1, bey1, &ex1, &ey1);
00310       wdCanvas2World (bex2, bey2, &ex2, &ey2);
00311 
00312       // boundingBox em pixels
00313       xmin = MIN3 (xmin, ex1, ex2);
00314       xmax = MAX3 (xmax, ex1, ex2);
00315       ymin = MIN3 (ymin, ey1, ey2);
00316       ymax = MAX3 (ymax, ey1, ey2);
00317    }
00318 
00319    // boundingBox em pixels
00320    wdWorld2Canvas (xmin, ymin, &bxmin, &bymin);
00321    wdWorld2Canvas (xmax, ymax, &bxmax, &bymax);
00322 }
00323 

XY
Tecgraf / PUC-Rio - Computer Graphics Technology Group