00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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 ¢er)
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);
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() );
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 }