qwt_round_scale_draw.cpp

00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
00002  * Qwt Widget Library
00003  * Copyright (C) 1997   Josef Wilgen
00004  * Copyright (C) 2002   Uwe Rathmann
00005  * 
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the Qwt License, Version 1.0
00008  *****************************************************************************/
00009 
00010 // vim: expandtab
00011 
00012 #include <math.h>
00013 #include <qpen.h>
00014 #include <qpainter.h>
00015 #include <qfontmetrics.h>
00016 #include "qwt_painter.h"
00017 #include "qwt_scale_div.h"
00018 #include "qwt_scale_map.h"
00019 #include "qwt_round_scale_draw.h"
00020 
00021 class QwtRoundScaleDraw::PrivateData
00022 {
00023 public:
00024     PrivateData():
00025         center(50, 50),
00026         radius(50),
00027         minAngle(-135 * 16),
00028         maxAngle(135 * 16)
00029     {
00030     }
00031 
00032     QPoint center;
00033     int radius; 
00034 
00035     int minAngle;
00036     int maxAngle;
00037 };
00038 
00046 QwtRoundScaleDraw::QwtRoundScaleDraw()
00047 {
00048     d_data = new QwtRoundScaleDraw::PrivateData;
00049 
00050     setRadius(50);
00051     scaleMap().setPaintInterval(d_data->minAngle, d_data->maxAngle);
00052 }
00053 
00055 QwtRoundScaleDraw::QwtRoundScaleDraw(const QwtRoundScaleDraw &other):
00056     QwtAbstractScaleDraw(other)
00057 {
00058     d_data = new QwtRoundScaleDraw::PrivateData(*other.d_data);
00059 }
00060 
00061 
00063 QwtRoundScaleDraw::~QwtRoundScaleDraw()
00064 {
00065     delete d_data;
00066 }
00067 
00069 QwtRoundScaleDraw &QwtRoundScaleDraw::operator=(const QwtRoundScaleDraw &other)
00070 {
00071     *(QwtAbstractScaleDraw*)this = (const QwtAbstractScaleDraw &)other;
00072     *d_data = *other.d_data;
00073     return *this;
00074 }
00075 
00084 void QwtRoundScaleDraw::setRadius(int radius)
00085 {
00086     d_data->radius = radius;
00087 }
00088 
00096 int QwtRoundScaleDraw::radius() const
00097 {
00098     return d_data->radius;
00099 }
00100 
00107 void QwtRoundScaleDraw::moveCenter(const QPoint &center)
00108 {
00109     d_data->center = center;
00110 }
00111 
00113 QPoint QwtRoundScaleDraw::center() const
00114 {
00115     return d_data->center;
00116 }
00117 
00135 void QwtRoundScaleDraw::setAngleRange(double angle1, double angle2)
00136 {
00137     angle1 = qwtLim(angle1, -360.0, 360.0);
00138     angle2 = qwtLim(angle2, -360.0, 360.0);
00139 
00140     int amin = qRound(qwtMin(angle1, angle2) * 16.0);
00141     int amax = qRound(qwtMax(angle1, angle2) * 16.0); 
00142  
00143     if (amin == amax)
00144     {
00145         amin -= 1;
00146         amax += 1;
00147     }
00148  
00149     d_data->minAngle = amin;
00150     d_data->maxAngle = amax;
00151     scaleMap().setPaintInterval(d_data->minAngle, d_data->maxAngle);
00152 }
00153 
00162 void QwtRoundScaleDraw::drawLabel(QPainter *painter, double value) const
00163 {
00164     const QwtText label = tickLabel(painter->font(), value);
00165     if ( label.isEmpty() )
00166         return; 
00167 
00168     const int tval = map().transform(value);
00169     if ((tval > d_data->minAngle + 359 * 16)
00170         || (tval < d_data->minAngle - 359 * 16))
00171     {
00172        return; 
00173     }
00174 
00175     double radius = d_data->radius;
00176     if ( hasComponent(QwtAbstractScaleDraw::Ticks) ||
00177         hasComponent(QwtAbstractScaleDraw::Backbone) )
00178     {
00179         radius += spacing();
00180     }
00181 
00182     if ( hasComponent(QwtAbstractScaleDraw::Ticks) )
00183         radius += majTickLength();
00184 
00185     const QSize sz = label.textSize(painter->font());
00186     const double arc = tval / 16.0 / 360.0 * 2 * M_PI;
00187 
00188     const int x = d_data->center.x() +
00189         qRound((radius + sz.width() / 2.0) * sin(arc));
00190     const int y = d_data->center.y() -
00191         qRound( (radius + sz.height() / 2.0) * cos(arc));
00192 
00193     const QRect r(x - sz.width() / 2, y - sz.height() / 2,
00194         sz.width(), sz.height() );
00195     label.draw(painter, r);
00196 }
00197 
00207 void QwtRoundScaleDraw::drawTick(QPainter *painter, double value, int len) const
00208 {
00209     if ( len <= 0 )
00210         return;
00211 
00212     const int tval = map().transform(value);
00213 
00214     const int cx = d_data->center.x();
00215     const int cy = d_data->center.y();
00216     const int radius = d_data->radius;
00217 
00218     if ((tval <= d_data->minAngle + 359 * 16)
00219         || (tval >= d_data->minAngle - 359 * 16))
00220     {
00221         const double arc = double(tval) / 16.0 * M_PI / 180.0;
00222 
00223         const double sinArc = sin(arc);
00224         const double cosArc = cos(arc);
00225 
00226         const int x1 = qRound( cx + radius * sinArc );
00227         const int x2 = qRound( cx + (radius + len) * sinArc );
00228         const int y1 = qRound( cy - radius * cosArc );
00229         const int y2 = qRound( cy - (radius + len) * cosArc );
00230 
00231         QwtPainter::drawLine(painter, x1, y1, x2, y2);
00232     }
00233 }
00234 
00241 void QwtRoundScaleDraw::drawBackbone(QPainter *painter) const
00242 {
00243     const int a1 = qRound(qwtMin(map().p1(), map().p2()) - 90 * 16);
00244     const int a2 = qRound(qwtMax(map().p1(), map().p2()) - 90 * 16);
00245 
00246     const int radius = d_data->radius;
00247     const int x = d_data->center.x() - radius;
00248     const int y = d_data->center.y() - radius;
00249 
00250     painter->drawArc(x, y, 2 * radius, 2 * radius,
00251         -a2, a2 - a1 + 1);           // counterclockwise
00252 }
00253 
00269 int QwtRoundScaleDraw::extent(const QPen &pen, const QFont &font) const
00270 {
00271     int d = 0;
00272 
00273     if ( hasComponent(QwtAbstractScaleDraw::Labels) )
00274     {
00275         const QwtScaleDiv &sd = scaleDiv();
00276         const QwtValueList &ticks = sd.ticks(QwtScaleDiv::MajorTick);
00277         for (uint i = 0; i < (uint)ticks.count(); i++)
00278         {
00279             const double value = ticks[i];
00280             if ( !sd.contains(value) )
00281                 continue;
00282 
00283             const QwtText label = tickLabel(font, value);
00284             if ( label.isEmpty() )
00285                 continue;
00286                 
00287             const int tval = map().transform(value);
00288             if ((tval < d_data->minAngle + 360 * 16)
00289                 && (tval > d_data->minAngle - 360 * 16))
00290             {
00291                 const double arc = tval / 16.0 / 360.0 * 2 * M_PI;
00292 
00293                 const QSize sz = label.textSize(font);
00294                 const double off = qwtMax(sz.width(), sz.height());
00295 
00296                 double x = off * sin(arc);
00297                 double y = off * cos(arc);
00298 
00299                 const int dist = (int)ceil(sqrt(x * x + y * y) + 1 );
00300                 if ( dist > d )
00301                     d = dist;
00302             }
00303         }
00304     }
00305 
00306     if ( hasComponent(QwtAbstractScaleDraw::Ticks) )
00307     {
00308         d += majTickLength();
00309     }
00310 
00311     if ( hasComponent(QwtAbstractScaleDraw::Backbone) )
00312     {
00313         const int pw = qwtMax( 1, pen.width() );  // penwidth can be zero
00314         d += pw;
00315     }
00316 
00317     if ( hasComponent(QwtAbstractScaleDraw::Labels) &&
00318         ( hasComponent(QwtAbstractScaleDraw::Ticks) || 
00319             hasComponent(QwtAbstractScaleDraw::Backbone) ) )
00320     {
00321         d += spacing();
00322     }
00323 
00324     d = qwtMax(d, minimumExtent());
00325 
00326     return d;
00327 }

Generated on Mon Feb 26 21:22:38 2007 for Qwt User's Guide by  doxygen 1.4.6