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

xysdstr.cpp

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

XY
Tecgraf / PUC-Rio - Computer Graphics Technology Group