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

xysdnm.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /* Módulo: xysdnm.cpp                                                        */
00003 /* Autor: Camilo da Fonseca Freire                                           */
00004 /* Data: 05 jul 96                                                           */
00005 /* Comentário:                                                                                                                                                         */
00006 /*    Implementação de métodos da classe especializada onde decorações numé- */
00007 /* ricas são formatadas, ou seja, a numeração é desenhada usando-se os valo- */
00008 /* res inicial e final dados no eixo ao qual está relacionada, seguindo a in */
00009 /* crementação também indicada no formato definido pelo usuário.             */
00010 /*****************************************************************************/
00011 
00012 #include "xymath.h"
00013 #include "xysdnm.h"
00014 #include "xyaxln.h"
00015 
00016 const char* xy_id_xyscdtnm_cpp="$Id: xysdnm.cpp,v 1.16 2001/05/15 18:36:24 camilo Exp $";
00017                                                                 
00018 XYNumericalScaleDecorator::XYNumericalScaleDecorator (char *format,
00019                                                       XYRasterText* scale)
00020                                                                                           : _format(strdup(format)),
00021                                                                                             _scale(scale),
00022                                                         _exp(1.)
00023 {
00024 }
00025 
00026 XYNumericalScaleDecorator::XYNumericalScaleDecorator (char *format,
00027                                                       double exp,
00028                                                       XYRasterText* scale)
00029                                                                                           : _format(strdup(format)),
00030                                                                                             _scale(scale),
00031                                                         _exp(exp)
00032 {
00033 }
00034 
00035 XYNumericalScaleDecorator::~XYNumericalScaleDecorator (void)
00036 {
00037 }
00038 
00039 void XYNumericalScaleDecorator::exp (double e)
00040 {
00041    _exp = e;
00042 }
00043 
00044 double XYNumericalScaleDecorator::exp (void) const
00045 {
00046    return _exp;
00047 }
00048 
00049 void XYNumericalScaleDecorator::format (char* f)
00050 {
00051    _format = strdup(f);
00052 }
00053 
00054 char* XYNumericalScaleDecorator::format (void) const
00055 {
00056    return _format;
00057 }
00058 
00059 void XYNumericalScaleDecorator::scale (XYRasterText* s)
00060 {
00061    _scale = s;
00062 }
00063 
00064 XYRasterText* XYNumericalScaleDecorator::scale (void) const
00065 {
00066    return _scale;
00067 }
00068 
00069 void XYNumericalScaleDecorator::draw (const XYAxis *axis, int /* first_tick */,
00070                                       int /* last_tick */) const
00071 {
00072    // intervalos de deslocamento em relação as direções x e y
00073    double dx, dy;
00074    double rot_rad = axis -> rotation() * XY_PI / 180.0;
00075 
00076    mtRotate ((axis -> step() * axis -> size()) / (axis -> max()
00077              - axis -> min()), 0.0, rot_rad, &dx, &dy);
00078 
00079    double ex1, ey1, ex2, ey2;
00080    axis -> firstTick (ex1, ey1, ex2, ey2);
00081 
00082    // consulta área do gráfico para o eixo
00083    int xmn, ymn, xmx, ymx;
00084    axis -> getViewport(xmn, xmx, ymn, ymx);
00085 
00086    // decide área no gráfico para a escala
00087    _scale -> setViewport(xmn, xmx, ymn, ymx);
00088 
00089    double tex2 = ex2;
00090    double tey2 = ey2;
00091 
00092    int ftx1, ftx2, fty1, fty2;
00093    int ltx1, ltx2, lty1, lty2;
00094 
00095    // calcula ticks que receberão labels para não haver sobreposição de labels,
00096    // o método é calcular boundindBox do maior label em ticks consecutivos e
00097    // verificar quando deixa de ocorrer sobreposição
00098 
00099    // consulta o boundingBox do primeiro texto na escala
00100    char c[80];
00101    sprintf (c, _format, axis -> first()/_exp);
00102 
00103    _scale -> text (c);
00104    _scale -> position (tex2, tey2);
00105    _scale -> boundingBox(ftx1, fty1, ftx2, fty2);
00106 
00107    // quantidade total de ticks
00108    int total = (int) floor ((axis -> max() - axis -> first()) / axis -> step());
00109 
00110    // consulta o boundingBox do último texto na escala
00111    sprintf (c, _format, axis -> max()/_exp);
00112 
00113    _scale -> text (c);
00114    _scale -> position (tex2 + dx * total, tey2 + dy * total);
00115    _scale -> boundingBox(ltx1, lty1, ltx2, lty2);
00116 
00117    // determina qual é o maior boundingBox, se o do primeiro ou o do último
00118    // texto na escala
00119    double mor = ((ltx2 - ltx1) > (ftx2 - ftx1)) ? axis -> max()
00120               : axis -> first();
00121 
00122    // maior texto na escala colocado no primeiro tick
00123    sprintf (c, _format, mor/_exp);
00124 
00125    _scale -> text (c);
00126    _scale -> position (tex2, tey2);
00127    _scale -> boundingBox(ftx1, fty1, ftx2, fty2);
00128 
00129    // próximo tick
00130    tex2 += dx;
00131    tey2 += dy;
00132                 
00133    // maior texto na escala colocado no segundo tick
00134    sprintf (c, _format, mor/_exp);
00135 
00136    _scale -> text (c);
00137    _scale -> position (tex2, tey2);
00138    _scale -> boundingBox(ltx1, lty1, ltx2, lty2);
00139 
00140    // guarda quantidade de ticks sem texto
00141    int test_intercept = 1;
00142         
00143    // maior texto na escala colocado nos demais ticks até que não haja
00144    // interseção do seu boundingBox no tick anterior com o tick atual
00145    while (mtIntercept (ftx1, fty1, ftx2, fty2, ltx1, lty1, ltx2, lty2) != 0)
00146    {
00147       ++test_intercept;
00148 
00149       // próximo tick
00150       tex2 += dx;
00151       tey2 += dy;
00152                 
00153       // maior texto na escala colocado nos demais ticks
00154       sprintf (c, _format, mor/_exp);
00155 
00156       _scale -> text (c);
00157       _scale -> position (tex2, tey2);
00158       _scale -> boundingBox(ltx1, lty1, ltx2, lty2);
00159    }
00160 
00161    // quantidade de ticks no eixo
00162    int ntick = 0;
00163 
00164    for (double tick = axis -> first();
00165         mtLessEqual ( tick, axis -> max() );
00166         tick += axis -> step())
00167    {
00168       // formata texto
00169       sprintf (c, _format, tick/_exp);
00170 
00171             // define o texto
00172       _scale -> text (c);
00173       _scale -> position (ex2, ey2);
00174 
00175       if (ntick % test_intercept == 0)
00176          // desenha a escala
00177          _scale -> draw (xmn, ymn, xmx, ymx);
00178 
00179       // próximo tick
00180       ex2 += dx;
00181       ey2 += dy;
00182 
00183       ++ntick;
00184    }
00185 }
00186 
00187 void XYNumericalScaleDecorator::boundingBox (const XYAxis *axis, int& bxmin,
00188                                                                int& bymin, int& bxmax,
00189                                                                            int& bymax) const
00190 {
00191    // intervalos de deslocamento em relação as direções x e y
00192    double dx, dy;
00193    double rot_rad = axis -> rotation() * XY_PI / 180.0;
00194 
00195    mtRotate ((axis -> step() * axis -> size()) / (axis -> max()
00196              - axis -> min()), 0, rot_rad, &dx, &dy);
00197 
00198    double ex1, ey1, ex2, ey2;
00199    axis -> firstTick (ex1, ey1, ex2, ey2);
00200 
00201    // consulta área do gráfico para o eixo
00202    int xmn, ymn, xmx, ymx;
00203    axis -> getViewport(xmn, xmx, ymn, ymx);
00204 
00205    // decide área no gráfico para a escala
00206    _scale -> setViewport(xmn, xmx, ymn, ymx);
00207 
00208    double tex2 = ex2;
00209    double tey2 = ey2;
00210 
00211    int ftx1, ftx2, fty1, fty2;
00212    int ltx1, ltx2, lty1, lty2;
00213 
00214    // calcula ticks que receberão labels para não haver sobreposição de labels,
00215    // o metodo é calcular boundindBox do maior label em ticks consecutivos e
00216    // verificar quando deixa de ocorrer sobreposição
00217 
00218    // consulta o boundingBox do primeiro texto na escala
00219    char c[80];
00220    sprintf (c, _format, axis -> first()/_exp);
00221 
00222    _scale -> text (c);
00223    _scale -> position (tex2, tey2);
00224    _scale -> boundingBox(ftx1, fty1, ftx2, fty2);
00225 
00226    // quantidade total de ticks
00227    int total = (int) floor ((axis -> max() - axis -> first())
00228              / axis -> step());
00229 
00230    // consulta o boundingBox do último texto na escala
00231    sprintf (c, _format, axis -> max()/_exp);
00232 
00233    _scale -> text (c);
00234    _scale -> position (tex2 + dx * total, tey2 + dy * total);
00235    _scale -> boundingBox(ltx1, lty1, ltx2, lty2);
00236 
00237    // determina qual é o maior boundingBox, se o do primeiro ou o do último
00238    // texto na escala
00239    double mor = ((ltx2 - ltx1) > (ftx2 - ftx1)) ? axis -> max()
00240               : axis -> first();
00241 
00242    // maior texto na escala colocado no primeiro tick
00243    sprintf (c, _format, mor/_exp);
00244 
00245    _scale -> text (c);
00246    _scale -> position (tex2, tey2);
00247    _scale -> boundingBox(ftx1, fty1, ftx2, fty2);
00248 
00249    // próximo tick
00250    tex2 += dx;
00251    tey2 += dy;
00252 
00253    // maior texto na escala colocado no segundo tick
00254    sprintf (c, _format, mor/_exp);
00255 
00256    _scale -> text (c);
00257    _scale -> position (tex2, tey2);
00258    _scale -> boundingBox(ltx1, lty1, ltx2, lty2);
00259 
00260    // guarda quantidade de ticks sem texto
00261    int test_intercept = 1;
00262 
00263    // maior texto na escala colocado nos demais ticks até que não haja
00264    // interseção do seu boundingBox no tick anterior com o tick atual
00265    while (mtIntercept (ftx1, fty1, ftx2, fty2, ltx1, lty1, ltx2, lty2) != 0)
00266    {
00267       ++test_intercept;
00268 
00269       // próximo tick
00270       tex2 += dx;
00271       tey2 += dy;
00272 
00273       // maior texto na escala colocado nos demais ticks
00274       sprintf (c, _format, mor/_exp);
00275 
00276       _scale -> text (c);
00277       _scale -> position (tex2, tey2);
00278       _scale -> boundingBox(ltx1, lty1, ltx2, lty2);
00279    }
00280 
00281    // inicializa boundingBox com posição de referência do primeiro texto
00282    double xmin = ex2;
00283    double xmax = ex2;
00284    double ymin = ey2;
00285    double ymax = ey2;
00286 
00287    int x1, x2, y1, y2;
00288    double wx1, wy1, wx2, wy2;
00289 
00290    // quantidade de ticks no eixo
00291    int ntick = 0;
00292 
00293    for (double tick = axis -> first();
00294         tick <= axis -> max();
00295         tick += axis -> step())
00296    {
00297       // formata texto
00298       sprintf (c, _format, tick/_exp);
00299 
00300             // define o texto
00301           _scale -> text (c);
00302       _scale -> position (ex2, ey2);
00303 
00304       if ((ntick % test_intercept) == 0)
00305       {
00306                // calcula boundingBox do texto
00307          _scale -> boundingBox (x1, y1, x2, y2);
00308 
00309              wdCanvas2World (x1, y1, &wx1, &wy1);
00310              wdCanvas2World (x2, y2, &wx2, &wy2);
00311 
00312            // atualiza boundingBox total
00313            xmin = MIN3 (xmin, wx1, wx2);
00314            xmax = MAX3 (xmax, wx1, wx2);
00315              ymin = MIN3 (ymin, wy1, wy2);
00316            ymax = MAX3 (ymax, wy1, wy2);
00317       }
00318 
00319       // próximo tick
00320       ex2 += dx;
00321       ey2 += dy;
00322 
00323       ++ntick;
00324    }
00325 
00326    wdWorld2Canvas (xmin, ymin, &bxmin, &bymin);
00327    wdWorld2Canvas (xmax, ymax, &bxmax, &bymax);
00328 }

XY
Tecgraf / PUC-Rio - Computer Graphics Technology Group