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

xysdlg.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /* Módulo: xysdlog.cpp                                                      */
00003 /* Autores: Carlos Henrique Levy e Jaudênia Cavalcante                       */
00004 /* Data: 08 jul 96                                                           */
00005 /* Comentário:                                                                                                                                                         */
00006 /*    Implementação de métodos da classe especializada onde decorações loga  */
00007 /* rítmicas são formatadas, ou seja, a numeração aparece como resultado de   */
00008 /* potências de 10, onde os índices estão de acordo com o eixo logaritmico   */
00009 /* definido pelo usuário.                                                    */
00010 /*****************************************************************************/
00011 
00012 #include "xysdlg.h"
00013 #include "xyaxlg.h"
00014 
00015 const char* xy_id_xyscdtlg_cpp="$Id: xysdlg.cpp,v 1.11 2002/01/23 16:13:05 clinio Exp $";
00016                                                                 
00017 XYLogScaleDecorator::XYLogScaleDecorator (char *format, 
00018                                                       XYText* scale)
00019                                                                       : _format(format),
00020                                                                     _scale(scale)
00021 {
00022 }
00023 
00024 XYLogScaleDecorator::~XYLogScaleDecorator (void)
00025 {
00026 }
00027 
00028 void XYLogScaleDecorator::format (char* f)
00029 {
00030    _format = f;
00031 }
00032 
00033 char* XYLogScaleDecorator::format (void) const
00034 {
00035    return _format;
00036 }
00037 
00038 void XYLogScaleDecorator::draw (const XYAxis *axis, int first_tick,
00039                                 int last_tick) const
00040 {
00041    XYLogAxis* lgax = (XYLogAxis*) axis;
00042    int last_bxmin = -9, last_bymin = -9, last_bxmax = -9, last_bymax = -9;
00043    int bxmin = -5, bymin = -5, bxmax = -5, bymax = -5;
00044 
00045    // consulta área do gráfico para o eixo
00046    int xmn, ymn, xmx, ymx;
00047    axis -> getViewport(xmn, xmx, ymn, ymx);
00048    
00049    // decide área no gráfico para a escala
00050    _scale -> setViewport(xmn, xmx, ymn, ymx);
00051    
00052    double mn   = lgax->min();
00053    double mx   = lgax->max();
00054    double step = lgax->step();
00055    double size = lgax->size();
00056 
00057    // intervalos de deslocamento em relação as direções x e y
00058    double rot_rad = lgax -> rotation() * XY_PI / 180.0;
00059 
00060    if (step > 0.0)
00061    {
00062       double xorigin, yorigin; 
00063       lgax->position(&xorigin, &yorigin);
00064 
00065       double decade_step;
00066       for( double val = mn; val <= mx; val += decade_step )// *step )
00067       {
00068         int current_decade = mtDecade(val);
00069         decade_step = pow( 10, current_decade );
00070         double dx, dy;
00071         mtRotate( (log10(val)-log10(mn))*size / (log10(mx)-log10(mn)), 0.0,
00072                 rot_rad, &dx, &dy);
00073 
00074         double xtick = xorigin + dx;
00075         double ytick = yorigin + dy;
00076 
00077         static char c[80];
00078         sprintf (c, _format, val);
00079        
00080         _scale->text (c);
00081         _scale->position(xtick, ytick);
00082         _scale->boundingBox(bxmin,bymin,bxmax,bymax);
00083         if ( !mtIntercept(bxmin,bymin,bxmax,bymax,
00084               last_bxmin,last_bymin,last_bxmax,last_bymax) ) {
00085            _scale->draw(xmn, ymn, xmx, ymx);
00086            int dx = (bxmax-bxmin)/10;
00087            int dy = (bymax-bymin)/10;
00088            last_bxmin = bxmin-dx; last_bxmax = bxmax+dx;
00089            last_bymin = bymin-dy; last_bymax = bymax+dy;
00090         }
00091      }
00092   }
00093 }
00094 
00095 void XYLogScaleDecorator::boundingBox (const XYAxis *axis, int& bxmin,
00096                                                                int& bymin, int& bxmax,
00097                                                                int& bymax) const
00098 {
00099    XYLogAxis* eixo = (XYLogAxis*) axis;
00100 
00101    // intervalos de deslocamento em relação as direções x e y
00102    double dx, dy;
00103    double rot_rad = eixo -> rotation() * XY_PI / 180.0;
00104 
00105    mtRotate ((eixo -> step() * eixo -> size()) / (eixo -> max()
00106              - eixo -> min()), 0.0, rot_rad, &dx, &dy);
00107 
00108    double ex1, ey1, ex2, ey2;
00109    eixo -> firstTick (ex1, ey1, ex2, ey2);
00110 
00111    // consulta área do gráfico para o eixo
00112    int xmn, ymn, xmx, ymx;
00113    eixo -> getViewport(xmn, xmx, ymn, ymx);
00114 
00115    // decide área no gráfico para a escala
00116    _scale -> setViewport(xmn, xmx, ymn, ymx);
00117 
00118    double tex2 = ex2;
00119    double tey2 = ey2;
00120 
00121    int ftx1, ftx2, fty1, fty2;
00122    int ltx1, ltx2, lty1, lty2;
00123 
00124    // calcula ticks que receberão labels para não haver sobreposição de labels,
00125    // o metodo é calcular boundindBox do maior label em ticks consecutivos e
00126    // verificar quando deixa de ocorrer sobreposição
00127 
00128    // consulta o boundingBox do primeiro texto na escala
00129    char c[80];
00130    sprintf (c, _format, (int)(eixo -> min() + pow (10, 0)));
00131 
00132    _scale -> text (c);
00133    _scale -> position (tex2, tey2);
00134    _scale -> boundingBox(ftx1, fty1, ftx2, fty2);
00135 
00136    // quantidade total de ticks
00137    int total = (int) log10 (eixo -> max() - eixo -> min());
00138 
00139    // consulta o boundingBox do último texto na escala
00140    sprintf (c, _format, (int)(eixo -> min() + pow (10, total)));
00141 
00142    _scale -> text (c);
00143    _scale -> position (tex2 + dx * total, tey2 + dy * total);
00144    _scale -> boundingBox(ltx1, lty1, ltx2, lty2);
00145 
00146    // determina qual é o maior boundingBox, se o do primeiro ou o do último
00147    // texto na escala
00148    double mor = ((ltx2 - ltx1) > (ftx2 - ftx1)) ? eixo -> min()
00149                   + pow (10, total) : eixo -> min() + pow (10, 0);
00150 
00151    // maior texto na escala colocado no primeiro tick
00152    sprintf (c, _format, (int) mor);
00153 
00154    _scale -> text (c);
00155    _scale -> position (tex2, tey2);
00156    _scale -> boundingBox(ftx1, fty1, ftx2, fty2);
00157 
00158    // próximo tick
00159    tex2 += dx;
00160    tey2 += dy;
00161 
00162    // maior texto na escala colocado no segundo tick
00163    sprintf (c, _format, (int) mor);
00164 
00165    _scale -> text (c);
00166    _scale -> position (tex2, tey2);
00167    _scale -> boundingBox(ltx1, lty1, ltx2, lty2);
00168 
00169    // guarda quantidade de ticks sem texto
00170    int test_intercept = 1;
00171 
00172    // maior texto na escala colocado nos demais ticks até que não haja
00173    // interseção do seu boundingBox no tick anterior com o tick atual
00174    while (mtIntercept (ftx1, fty1, ftx2, fty2, ltx1, lty1, ltx2, lty2) != 0)
00175    {
00176       ++test_intercept;
00177 
00178       // próximo tick
00179       tex2 += dx;
00180       tey2 += dy;
00181 
00182       // maior texto na escala colocado nos demais ticks
00183       sprintf (c, _format, (int) mor);
00184 
00185       _scale -> text (c);
00186       _scale -> position (tex2, tey2);
00187       _scale -> boundingBox(ltx1, lty1, ltx2, lty2);
00188    }
00189 
00190    // inicializa boundingBox com posição de referência do primeiro texto
00191    double xmin = ex2;
00192    double xmax = ex2;
00193    double ymin = ey2;
00194    double ymax = ey2;
00195 
00196    int x1, x2, y1, y2;
00197    double wx1, wy1, wx2, wy2;
00198 
00199    for (int ntick = 0; ntick <= total; ++ntick)
00200    {
00201       if ((ntick % test_intercept) == 0)
00202       {
00203          // formata o  texto
00204          sprintf (c, _format, (int)(eixo -> min() + pow (10, ntick)));
00205 
00206                // define o texto
00207                _scale -> text (c);
00208          _scale -> position (ex2, ey2);
00209 
00210                // calcula boundingBox do texto
00211            _scale -> boundingBox (x1, y1, x2, y2);
00212 
00213                wdCanvas2World (x1, y1, &wx1, &wy1);
00214                wdCanvas2World (x2, y2, &wx2, &wy2);
00215 
00216            // atualiza boundingBox total
00217            xmin = MIN3 (xmin, wx1, wx2);
00218            xmax = MAX3 (xmax, wx1, wx2);
00219                ymin = MIN3 (ymin, wy1, wy2);
00220            ymax = MAX3 (ymax, wy1, wy2);
00221       }
00222 
00223       // próximo tick
00224       ex2 += dx;
00225       ey2 += dy;
00226    }
00227 
00228    wdWorld2Canvas (xmin, ymin, &bxmin, &bymin);
00229    wdWorld2Canvas (xmax, ymax, &bxmax, &bymax);
00230 }
00231 

XY
Tecgraf / PUC-Rio - Computer Graphics Technology Group