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

xysddt.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /* Módulo: xysddt.cpp                                                        */
00003 /* Autor: Camilo da Fonseca Freire                                           */
00004 /* Data: 8 Ago 2000                                                          */
00005 /* Comentário:                                                               */
00006 /*    Implementação de métodos da classe especializada onde decorações de    */
00007 /* datas, 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 <time.h>
00013 
00014 #include "xymath.h"
00015 #include "xysddt.h"
00016 #include "xyaxln.h"
00017 
00018 
00019 #define FORMAT_STRING "  %02d/%02d/%04d  \n%02d:%02d:%02d"
00020 
00021 
00022 const char* xy_id_xyscdtdt="$Id: xysddt.cpp,v 1.1 2003/01/03 16:08:53 clinio Exp $";
00023                                                                 
00024 XYDateScaleDecorator::XYDateScaleDecorator( XYText* scale ) : 
00025    _scale(scale)
00026 {
00027    struct tm time1; 
00028    struct tm* new_time = NULL;
00029    time_t the_time1;
00030    time_t zero_timet = (time_t) 0;
00031 
00032 
00033    time1.tm_sec = 0; time1.tm_min = 0; time1.tm_hour = 0;
00034    time1.tm_mday = 1; time1.tm_mon = 1; time1.tm_year = 1970;
00035 
00036    time1.tm_isdst = 0;
00037    time1.tm_mon -= 1;
00038    time1.tm_year -= 1900;
00039    the_time1 = mktime( &time1 );
00040    _diff = the_time1;
00041 
00042    new_time = localtime( &zero_timet );
00043    if ( new_time->tm_isdst > 0 ) _diff -= 60 * 60;
00044 
00045    this->delta(0);
00046 }
00047 
00048 XYDateScaleDecorator::~XYDateScaleDecorator (void)
00049 {
00050 }
00051 
00052 void XYDateScaleDecorator::scale (XYText* s)
00053 {
00054    _scale = s;
00055 }
00056 
00057 XYText* XYDateScaleDecorator::scale (void) const
00058 {
00059    return _scale;
00060 }
00061 
00062 void XYDateScaleDecorator::draw (const XYAxis *axis, int /* first_tick */,
00063                                       int /* last_tick */) const
00064 {
00065    // intervalos de deslocamento em relação as direções x e y
00066    double dx, dy;
00067    double rot_rad = axis -> rotation() * XY_PI / 180.0;
00068 
00069    mtRotate ((axis -> step() * axis -> size()) / (axis -> max()
00070              - axis -> min()), 0.0, rot_rad, &dx, &dy);
00071 
00072    double ex1, ey1, ex2, ey2;
00073    axis -> firstTick (ex1, ey1, ex2, ey2);
00074 
00075    // consulta área do gráfico para o eixo
00076    int xmn, ymn, xmx, ymx;
00077    axis -> getViewport(xmn, xmx, ymn, ymx);
00078 
00079    // decide área no gráfico para a escala
00080    _scale -> setViewport(xmn, xmx, ymn, ymx);
00081 
00082    double tex2 = ex2;
00083    double tey2 = ey2;
00084 
00085    int ftx1, ftx2, fty1, fty2;
00086    int ltx1, ltx2, lty1, lty2;
00087 
00088    // calcula ticks que receberão labels para não haver sobreposição de labels,
00089    // o método é calcular boundindBox do maior label em ticks consecutivos e
00090    // verificar quando deixa de ocorrer sobreposição
00091 
00092    // consulta o boundingBox do primeiro texto na escala
00093    char c[80];
00094    struct tm *lt; 
00095    time_t tm = (int) axis -> first();
00096    tm += (time_t)_delta;
00097 
00098    lt = localtime(&tm);
00099    if ( lt->tm_isdst > 0 ) tm -= 60*60;
00100 
00101    lt = localtime(&tm);
00102    lt->tm_mon += 1;
00103    lt->tm_year += 1900;
00104 
00105    sprintf (c, FORMAT_STRING, 
00106          lt->tm_mday, lt->tm_mon, lt->tm_year,
00107          lt->tm_hour, lt->tm_min, lt->tm_sec );
00108 
00109    _scale -> text (c);
00110    _scale -> position (tex2, tey2);
00111    _scale -> boundingBox(ftx1, fty1, ftx2, fty2);
00112 
00113    // quantidade total de ticks
00114    int total = (int) floor ((axis -> max() - axis -> first()) / axis -> step());
00115 
00116    // consulta o boundingBox do último texto na escala
00117    tm = (int) axis -> max();
00118    tm += (time_t)_delta;
00119    lt = localtime(&tm);
00120    if ( lt->tm_isdst > 0 ) tm -= 60*60;
00121 
00122    lt = localtime(&tm);
00123    lt->tm_mon += 1;
00124    lt->tm_year += 1900;
00125    sprintf (c, FORMAT_STRING, 
00126          lt->tm_mday, lt->tm_mon, lt->tm_year,
00127          lt->tm_hour, lt->tm_min, lt->tm_sec );
00128 
00129    _scale -> text (c);
00130    _scale -> position (tex2 + dx * total, tey2 + dy * total);
00131    _scale -> boundingBox(ltx1, lty1, ltx2, lty2);
00132 
00133    // determina qual é o maior boundingBox, se o do primeiro ou o do último
00134    // texto na escala
00135    double mor = ((ltx2 - ltx1) > (ftx2 - ftx1))
00136               ? axis -> max()
00137               : axis -> first();
00138 
00139    // maior texto na escala colocado no primeiro tick
00140    tm = (int) mor;
00141    tm += (time_t)_delta;
00142    lt = localtime(&tm);
00143    if ( lt->tm_isdst > 0 ) tm -= 60*60;
00144 
00145    lt = localtime(&tm);
00146    lt->tm_mon += 1;
00147    lt->tm_year += 1900;
00148    sprintf (c, FORMAT_STRING, 
00149          lt->tm_mday, lt->tm_mon, lt->tm_year,
00150          lt->tm_hour, lt->tm_min, lt->tm_sec );
00151 
00152    _scale -> text (c);
00153    _scale -> position (tex2, tey2);
00154    _scale -> boundingBox(ftx1, fty1, ftx2, fty2);
00155 
00156    // próximo tick
00157    tex2 += dx;
00158    tey2 += dy;
00159                 
00160    // maior texto na escala colocado no segundo tick
00161    _scale -> text (c);
00162    _scale -> position (tex2, tey2);
00163    _scale -> boundingBox(ltx1, lty1, ltx2, lty2);
00164 
00165    // guarda quantidade de ticks sem texto
00166    int test_intercept = 1;
00167         
00168    // maior texto na escala colocado nos demais ticks até que não haja
00169    // interseção do seu boundingBox no tick anterior com o tick atual
00170    while (mtIntercept (ftx1, fty1, ftx2, fty2, ltx1, lty1, ltx2, lty2) != 0)
00171    {
00172       ++test_intercept;
00173 
00174       // próximo tick
00175       tex2 += dx;
00176       tey2 += dy;
00177                 
00178       // maior texto na escala colocado nos demais ticks
00179       _scale -> text (c);
00180       _scale -> position (tex2, tey2);
00181       _scale -> boundingBox(ltx1, lty1, ltx2, lty2);
00182    }
00183 
00184    // quantidade de ticks no eixo
00185    int ntick = 0;
00186 
00187    for (double tick = axis -> first();
00188         mtLessEqual ( tick, axis -> max() );
00189         tick += axis -> step())
00190    {
00191       // formata texto
00192       tm = (int) tick;
00193       tm += (time_t)_delta;
00194    lt = localtime(&tm);
00195    if ( lt->tm_isdst > 0 ) tm -= 60*60;
00196 
00197       lt = localtime(&tm);
00198       lt->tm_mon += 1;
00199       lt->tm_year += 1900;
00200       sprintf (c, FORMAT_STRING, 
00201           lt->tm_mday, lt->tm_mon, lt->tm_year,
00202                lt->tm_hour, lt->tm_min, lt->tm_sec );
00203 
00204             // define o texto
00205       _scale -> text (c);
00206       _scale -> position (ex2, ey2);
00207 
00208       if (ntick % test_intercept == 0)
00209          // desenha a escala
00210          _scale -> draw (xmn, ymn, xmx, ymx);
00211 
00212       // próximo tick
00213       ex2 += dx;
00214       ey2 += dy;
00215 
00216       ++ntick;
00217    }
00218 }
00219 
00220 void XYDateScaleDecorator::boundingBox (const XYAxis *axis, int& bxmin,
00221                                         int& bymin, int& bxmax,
00222                                         int& bymax) const
00223 {
00224    // intervalos de deslocamento em relação as direções x e y
00225    double dx, dy;
00226    double rot_rad = axis -> rotation() * XY_PI / 180.0;
00227 
00228    mtRotate ((axis -> step() * axis -> size()) / (axis -> max()
00229              - axis -> min()), 0, rot_rad, &dx, &dy);
00230 
00231    double ex1, ey1, ex2, ey2;
00232    axis -> firstTick (ex1, ey1, ex2, ey2);
00233 
00234    // consulta área do gráfico para o eixo
00235    int xmn, ymn, xmx, ymx;
00236    axis -> getViewport(xmn, xmx, ymn, ymx);
00237 
00238    // decide área no gráfico para a escala
00239    _scale -> setViewport(xmn, xmx, ymn, ymx);
00240 
00241    double tex2 = ex2;
00242    double tey2 = ey2;
00243 
00244    int ftx1, ftx2, fty1, fty2;
00245    int ltx1, ltx2, lty1, lty2;
00246 
00247    // calcula ticks que receberão labels para não haver sobreposição de labels,
00248    // o metodo é calcular boundindBox do maior label em ticks consecutivos e
00249    // verificar quando deixa de ocorrer sobreposição
00250 
00251    // consulta o boundingBox do primeiro texto na escala
00252    char c[80];
00253    struct tm *lt; 
00254    time_t time = (int) axis -> first();
00255    time += (time_t)_delta;
00256    lt = localtime(&time);
00257    if ( lt->tm_isdst > 0 ) time -= 60*60;
00258 
00259    lt = localtime(&time);
00260    lt->tm_mon += 1;
00261    lt->tm_year += 1900;
00262 
00263    sprintf (c, FORMAT_STRING, 
00264             lt->tm_mday, lt->tm_mon, lt->tm_year,
00265             lt->tm_hour, lt->tm_min, lt->tm_sec );
00266 
00267    _scale -> text (c);
00268    _scale -> position (tex2, tey2);
00269    _scale -> boundingBox(ftx1, fty1, ftx2, fty2);
00270 
00271    // quantidade total de ticks
00272    int total = (int) floor ((axis -> max() - axis -> first())
00273              / axis -> step());
00274 
00275    // consulta o boundingBox do último texto na escala
00276    time = (int) axis -> max();
00277    time += (time_t)_delta;
00278    lt = localtime(&time);
00279    if ( lt->tm_isdst > 0 ) time -= 60*60;
00280 
00281    lt = localtime(&time);
00282    lt->tm_mon += 1;
00283    lt->tm_year += 1900;
00284 
00285    sprintf (c, FORMAT_STRING, 
00286          lt->tm_mday, lt->tm_mon, lt->tm_year,
00287          lt->tm_hour, lt->tm_min, lt->tm_sec );
00288 
00289    _scale -> text (c);
00290    _scale -> position (tex2 + dx * total, tey2 + dy * total);
00291    _scale -> boundingBox(ltx1, lty1, ltx2, lty2);
00292 
00293    // determina qual é o maior boundingBox, se o do primeiro ou o do último
00294    // texto na escala
00295    double mor = ((ltx2 - ltx1) > (ftx2 - ftx1)) ? axis -> max()
00296               : axis -> first();
00297 
00298    // maior texto na escala colocado no primeiro tick
00299    time = (int) mor;
00300    time += (time_t)_delta;
00301    lt = localtime(&time);
00302    if ( lt->tm_isdst > 0 ) time -= 60*60;
00303 
00304    lt = localtime(&time);
00305    lt->tm_mon += 1;
00306    lt->tm_year += 1900;
00307 
00308    sprintf (c, FORMAT_STRING, 
00309          lt->tm_mday, lt->tm_mon, lt->tm_year, 
00310          lt->tm_hour, lt->tm_min, lt->tm_sec );
00311 
00312    _scale -> text (c);
00313    _scale -> position (tex2, tey2);
00314    _scale -> boundingBox(ftx1, fty1, ftx2, fty2);
00315 
00316    // próximo tick
00317    tex2 += dx;
00318    tey2 += dy;
00319 
00320    // maior texto na escala colocado no segundo tick
00321 
00322    _scale -> text (c);
00323    _scale -> position (tex2, tey2);
00324    _scale -> boundingBox(ltx1, lty1, ltx2, lty2);
00325 
00326    // guarda quantidade de ticks sem texto
00327    int test_intercept = 1;
00328 
00329    // maior texto na escala colocado nos demais ticks até que não haja
00330    // interseção do seu boundingBox no tick anterior com o tick atual
00331    while (mtIntercept (ftx1, fty1, ftx2, fty2, ltx1, lty1, ltx2, lty2) != 0)
00332    {
00333       ++test_intercept;
00334 
00335       // próximo tick
00336       tex2 += dx;
00337       tey2 += dy;
00338 
00339       // maior texto na escala colocado nos demais ticks
00340 
00341       _scale -> text (c);
00342       _scale -> position (tex2, tey2);
00343       _scale -> boundingBox(ltx1, lty1, ltx2, lty2);
00344    }
00345 
00346    // inicializa boundingBox com posição de referência do primeiro texto
00347    double xmin = ex2;
00348    double xmax = ex2;
00349    double ymin = ey2;
00350    double ymax = ey2;
00351 
00352    int x1, x2, y1, y2;
00353    double wx1, wy1, wx2, wy2;
00354 
00355    // quantidade de ticks no eixo
00356    int ntick = 0;
00357 
00358    for (double tick = axis -> first();
00359         tick <= axis -> max();
00360         tick += axis -> step())
00361    {
00362       // formata texto
00363       time_t tm = (int) tick;
00364       tm += (time_t)_delta;
00365    lt = localtime(&tm);
00366    if ( lt->tm_isdst > 0 ) tm -= 60*60;
00367 
00368       lt = localtime(&tm);
00369       lt->tm_mon += 1;
00370       lt->tm_year += 1900;
00371 
00372       sprintf (c, FORMAT_STRING, 
00373           lt->tm_mday, lt->tm_mon, lt->tm_year,
00374                lt->tm_hour, lt->tm_min, lt->tm_sec );
00375 
00376             // define o texto
00377       _scale -> text (c);
00378       _scale -> position (ex2, ey2);
00379 
00380       if ((ntick % test_intercept) == 0)
00381       {
00382                // calcula boundingBox do texto
00383          _scale -> boundingBox (x1, y1, x2, y2);
00384 
00385              wdCanvas2World (x1, y1, &wx1, &wy1);
00386              wdCanvas2World (x2, y2, &wx2, &wy2);
00387 
00388            // atualiza boundingBox total
00389            xmin = MIN3 (xmin, wx1, wx2);
00390            xmax = MAX3 (xmax, wx1, wx2);
00391            ymin = MIN3 (ymin, wy1, wy2);
00392            ymax = MAX3 (ymax, wy1, wy2);
00393       }
00394 
00395       // próximo tick
00396       ex2 += dx;
00397       ey2 += dy;
00398 
00399       ++ntick;
00400    }
00401 
00402    wdWorld2Canvas (xmin, ymin, &bxmin, &bymin);
00403    wdWorld2Canvas (xmax, ymax, &bxmax, &bymax);
00404 }

XY
Tecgraf / PUC-Rio - Computer Graphics Technology Group