1
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
3
* Copyright (C) 1997 Josef Wilgen
4
* Copyright (C) 2002 Uwe Rathmann
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the Qwt License, Version 1.0
8
*****************************************************************************/
15
#include <qfontmetrics.h>
16
#include "qwt_painter.h"
17
#include "qwt_scale_div.h"
18
#include "qwt_scale_map.h"
19
#include "qwt_round_scale_draw.h"
21
class QwtRoundScaleDraw::PrivateData
27
startAngle(-135 * 16),
42
The range of the scale is initialized to [0, 100],
43
The center is set to (50, 50) with a radius of 50.
44
The angle range is set to [-135, 135].
46
QwtRoundScaleDraw::QwtRoundScaleDraw()
48
d_data = new QwtRoundScaleDraw::PrivateData;
51
scaleMap().setPaintInterval(d_data->startAngle, d_data->endAngle);
55
QwtRoundScaleDraw::QwtRoundScaleDraw(const QwtRoundScaleDraw &other):
56
QwtAbstractScaleDraw(other)
58
d_data = new QwtRoundScaleDraw::PrivateData(*other.d_data);
63
QwtRoundScaleDraw::~QwtRoundScaleDraw()
68
//! Assignment operator
69
QwtRoundScaleDraw &QwtRoundScaleDraw::operator=(const QwtRoundScaleDraw &other)
71
*(QwtAbstractScaleDraw*)this = (const QwtAbstractScaleDraw &)other;
72
*d_data = *other.d_data;
77
Change of radius the scale
79
Radius is the radius of the backbone without ticks and labels.
81
\param radius New Radius
84
void QwtRoundScaleDraw::setRadius(int radius)
86
d_data->radius = radius;
92
Radius is the radius of the backbone without ticks and labels.
94
\sa setRadius(), extent()
96
int QwtRoundScaleDraw::radius() const
98
return d_data->radius;
102
Move the center of the scale draw, leaving the radius unchanged
104
\param center New center
107
void QwtRoundScaleDraw::moveCenter(const QPoint ¢er)
109
d_data->center = center;
112
//! Get the center of the scale
113
QPoint QwtRoundScaleDraw::center() const
115
return d_data->center;
119
\brief Adjust the baseline circle segment for round scales.
121
The baseline will be drawn from min(angle1,angle2) to max(angle1, angle2).
122
The default setting is [ -135, 135 ].
123
An angle of 0 degrees corresponds to the 12 o'clock position,
124
and positive angles count in a clockwise direction.
126
\param angle2 boundaries of the angle interval in degrees.
128
<li>The angle range is limited to [-360, 360] degrees. Angles exceeding
129
this range will be clipped.
130
<li>For angles more than 359 degrees above or below min(angle1, angle2),
131
scale marks will not be drawn.
132
<li>If you need a counterclockwise scale, use QwtScaleDiv::setRange
135
void QwtRoundScaleDraw::setAngleRange(double angle1, double angle2)
137
angle1 = qwtLim(angle1, -360.0, 360.0);
138
angle2 = qwtLim(angle2, -360.0, 360.0);
140
d_data->startAngle = qRound(angle1 * 16.0);
141
d_data->endAngle = qRound(angle2 * 16.0);
143
if (d_data->startAngle == d_data->endAngle)
145
d_data->startAngle -= 1;
146
d_data->endAngle += 1;
149
scaleMap().setPaintInterval(d_data->startAngle, d_data->endAngle);
153
Draws the label for a major scale tick
155
\param painter Painter
158
\sa drawTick(), drawBackbone()
160
void QwtRoundScaleDraw::drawLabel(QPainter *painter, double value) const
162
const QwtText label = tickLabel(painter->font(), value);
163
if ( label.isEmpty() )
166
const int tval = map().transform(value);
167
if ((tval > d_data->startAngle + 359 * 16)
168
|| (tval < d_data->startAngle - 359 * 16))
173
double radius = d_data->radius;
174
if ( hasComponent(QwtAbstractScaleDraw::Ticks) ||
175
hasComponent(QwtAbstractScaleDraw::Backbone) )
180
if ( hasComponent(QwtAbstractScaleDraw::Ticks) )
181
radius += majTickLength();
183
const QSize sz = label.textSize(painter->font());
184
const double arc = tval / 16.0 / 360.0 * 2 * M_PI;
186
const int x = d_data->center.x() +
187
qRound((radius + sz.width() / 2.0) * sin(arc));
188
const int y = d_data->center.y() -
189
qRound( (radius + sz.height() / 2.0) * cos(arc));
191
const QRect r(x - sz.width() / 2, y - sz.height() / 2,
192
sz.width(), sz.height() );
193
label.draw(painter, r);
199
\param painter Painter
200
\param value Value of the tick
201
\param len Lenght of the tick
203
\sa drawBackbone(), drawLabel()
205
void QwtRoundScaleDraw::drawTick(QPainter *painter, double value, int len) const
210
const int tval = map().transform(value);
212
const int cx = d_data->center.x();
213
const int cy = d_data->center.y();
214
const int radius = d_data->radius;
216
if ((tval <= d_data->startAngle + 359 * 16)
217
|| (tval >= d_data->startAngle - 359 * 16))
219
const double arc = double(tval) / 16.0 * M_PI / 180.0;
221
const double sinArc = sin(arc);
222
const double cosArc = cos(arc);
224
const int x1 = qRound( cx + radius * sinArc );
225
const int x2 = qRound( cx + (radius + len) * sinArc );
226
const int y1 = qRound( cy - radius * cosArc );
227
const int y2 = qRound( cy - (radius + len) * cosArc );
229
QwtPainter::drawLine(painter, x1, y1, x2, y2);
234
Draws the baseline of the scale
235
\param painter Painter
237
\sa drawTick(), drawLabel()
239
void QwtRoundScaleDraw::drawBackbone(QPainter *painter) const
241
const int a1 = qRound(qwtMin(map().p1(), map().p2()) - 90 * 16);
242
const int a2 = qRound(qwtMax(map().p1(), map().p2()) - 90 * 16);
244
const int radius = d_data->radius;
245
const int x = d_data->center.x() - radius;
246
const int y = d_data->center.y() - radius;
248
painter->drawArc(x, y, 2 * radius, 2 * radius,
249
-a2, a2 - a1 + 1); // counterclockwise
253
Calculate the extent of the scale
255
The extent is the distcance between the baseline to the outermost
256
pixel of the scale draw. radius() + extent() is an upper limit
257
for the radius of the bounding circle.
259
\param pen Pen that is used for painting backbone and ticks
260
\param font Font used for painting the labels
262
\sa setMinimumExtent(), minimumExtent()
263
\warning The implemented algo is not too smart and
264
calculates only an upper limit, that might be a
267
int QwtRoundScaleDraw::extent(const QPen &pen, const QFont &font) const
271
if ( hasComponent(QwtAbstractScaleDraw::Labels) )
273
const QwtScaleDiv &sd = scaleDiv();
274
const QwtValueList &ticks = sd.ticks(QwtScaleDiv::MajorTick);
275
for (uint i = 0; i < (uint)ticks.count(); i++)
277
const double value = ticks[i];
278
if ( !sd.contains(value) )
281
const QwtText label = tickLabel(font, value);
282
if ( label.isEmpty() )
285
const int tval = map().transform(value);
286
if ((tval < d_data->startAngle + 360 * 16)
287
&& (tval > d_data->startAngle - 360 * 16))
289
const double arc = tval / 16.0 / 360.0 * 2 * M_PI;
291
const QSize sz = label.textSize(font);
292
const double off = qwtMax(sz.width(), sz.height());
294
double x = off * sin(arc);
295
double y = off * cos(arc);
297
const int dist = (int)ceil(sqrt(x * x + y * y) + 1 );
304
if ( hasComponent(QwtAbstractScaleDraw::Ticks) )
306
d += majTickLength();
309
if ( hasComponent(QwtAbstractScaleDraw::Backbone) )
311
const int pw = qwtMax( 1, pen.width() ); // penwidth can be zero
315
if ( hasComponent(QwtAbstractScaleDraw::Labels) &&
316
( hasComponent(QwtAbstractScaleDraw::Ticks) ||
317
hasComponent(QwtAbstractScaleDraw::Backbone) ) )
322
d = qwtMax(d, minimumExtent());