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         startAngle(-135 * 16),
00028         endAngle(135 * 16)
00029     {
00030     }
00031 
00032     QPoint center;
00033     int radius; 
00034 
00035     int startAngle;
00036     int endAngle;
00037 };
00038 
00046 QwtRoundScaleDraw::QwtRoundScaleDraw()
00047 {
00048     d_data = new QwtRoundScaleDraw::PrivateData;
00049 
00050     setRadius(50);
00051     scaleMap().setPaintInterval(d_data->startAngle, d_data->endAngle);
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     d_data->startAngle = qRound(angle1 * 16.0);
00141     d_data->endAngle = qRound(angle2 * 16.0); 
00142  
00143     if (d_data->startAngle == d_data->endAngle)
00144     {
00145         d_data->startAngle -= 1;
00146         d_data->endAngle += 1;
00147     }
00148  
00149     scaleMap().setPaintInterval(d_data->startAngle, d_data->endAngle);
00150 }
00151 
00160 void QwtRoundScaleDraw::drawLabel(QPainter *painter, double value) const
00161 {
00162     const QwtText label = tickLabel(painter->font(), value);
00163     if ( label.isEmpty() )
00164         return; 
00165 
00166     const int tval = map().transform(value);
00167     if ((tval > d_data->startAngle + 359 * 16)
00168         || (tval < d_data->startAngle - 359 * 16))
00169     {
00170        return; 
00171     }
00172 
00173     double radius = d_data->radius;
00174     if ( hasComponent(QwtAbstractScaleDraw::Ticks) ||
00175         hasComponent(QwtAbstractScaleDraw::Backbone) )
00176     {
00177         radius += spacing();
00178     }
00179 
00180     if ( hasComponent(QwtAbstractScaleDraw::Ticks) )
00181         radius += majTickLength();
00182 
00183     const QSize sz = label.textSize(painter->font());
00184     const double arc = tval / 16.0 / 360.0 * 2 * M_PI;
00185 
00186     const int x = d_data->center.x() +
00187         qRound((radius + sz.width() / 2.0) * sin(arc));
00188     const int y = d_data->center.y() -
00189         qRound( (radius + sz.height() / 2.0) * cos(arc));
00190 
00191     const QRect r(x - sz.width() / 2, y - sz.height() / 2,
00192         sz.width(), sz.height() );
00193     label.draw(painter, r);
00194 }
00195 
00205 void QwtRoundScaleDraw::drawTick(QPainter *painter, double value, int len) const
00206 {
00207     if ( len <= 0 )
00208         return;
00209 
00210     const int tval = map().transform(value);
00211 
00212     const int cx = d_data->center.x();
00213     const int cy = d_data->center.y();
00214     const int radius = d_data->radius;
00215 
00216     if ((tval <= d_data->startAngle + 359 * 16)
00217         || (tval >= d_data->startAngle - 359 * 16))
00218     {
00219         const double arc = double(tval) / 16.0 * M_PI / 180.0;
00220 
00221         const double sinArc = sin(arc);
00222         const double cosArc = cos(arc);
00223 
00224         const int x1 = qRound( cx + radius * sinArc );
00225         const int x2 = qRound( cx + (radius + len) * sinArc );
00226         const int y1 = qRound( cy - radius * cosArc );
00227         const int y2 = qRound( cy - (radius + len) * cosArc );
00228 
00229         QwtPainter::drawLine(painter, x1, y1, x2, y2);
00230     }
00231 }
00232 
00239 void QwtRoundScaleDraw::drawBackbone(QPainter *painter) const
00240 {
00241     const int a1 = qRound(qwtMin(map().p1(), map().p2()) - 90 * 16);
00242     const int a2 = qRound(qwtMax(map().p1(), map().p2()) - 90 * 16);
00243 
00244     const int radius = d_data->radius;
00245     const int x = d_data->center.x() - radius;
00246     const int y = d_data->center.y() - radius;
00247 
00248     painter->drawArc(x, y, 2 * radius, 2 * radius,
00249         -a2, a2 - a1 + 1);           // counterclockwise
00250 }
00251 
00267 int QwtRoundScaleDraw::extent(const QPen &pen, const QFont &font) const
00268 {
00269     int d = 0;
00270 
00271     if ( hasComponent(QwtAbstractScaleDraw::Labels) )
00272     {
00273         const QwtScaleDiv &sd = scaleDiv();
00274         const QwtValueList &ticks = sd.ticks(QwtScaleDiv::MajorTick);
00275         for (uint i = 0; i < (uint)ticks.count(); i++)
00276         {
00277             const double value = ticks[i];
00278             if ( !sd.contains(value) )
00279                 continue;
00280 
00281             const QwtText label = tickLabel(font, value);
00282             if ( label.isEmpty() )
00283                 continue;
00284                 
00285             const int tval = map().transform(value);
00286             if ((tval < d_data->startAngle + 360 * 16)
00287                 && (tval > d_data->startAngle - 360 * 16))
00288             {
00289                 const double arc = tval / 16.0 / 360.0 * 2 * M_PI;
00290 
00291                 const QSize sz = label.textSize(font);
00292                 const double off = qwtMax(sz.width(), sz.height());
00293 
00294                 double x = off * sin(arc);
00295                 double y = off * cos(arc);
00296 
00297                 const int dist = (int)ceil(sqrt(x * x + y * y) + 1 );
00298                 if ( dist > d )
00299                     d = dist;
00300             }
00301         }
00302     }
00303 
00304     if ( hasComponent(QwtAbstractScaleDraw::Ticks) )
00305     {
00306         d += majTickLength();
00307     }
00308 
00309     if ( hasComponent(QwtAbstractScaleDraw::Backbone) )
00310     {
00311         const int pw = qwtMax( 1, pen.width() );  // penwidth can be zero
00312         d += pw;
00313     }
00314 
00315     if ( hasComponent(QwtAbstractScaleDraw::Labels) &&
00316         ( hasComponent(QwtAbstractScaleDraw::Ticks) || 
00317             hasComponent(QwtAbstractScaleDraw::Backbone) ) )
00318     {
00319         d += spacing();
00320     }
00321 
00322     d = qwtMax(d, minimumExtent());
00323 
00324     return d;
00325 }

Generated on Sat May 24 18:47:40 2008 for Qwt User's Guide by  doxygen 1.5.0