source: ntrip/trunk/BNC/qwt/qwt_round_scale_draw.cpp@ 9045

Last change on this file since 9045 was 8127, checked in by stoecker, 8 years ago

update qwt and qwtpolar, many QT5 fixes (unfinished)

File size: 8.1 KB
Line 
1/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
2 * Qwt Widget Library
3 * Copyright (C) 1997 Josef Wilgen
4 * Copyright (C) 2002 Uwe Rathmann
5 *
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 *****************************************************************************/
9
10#include "qwt_round_scale_draw.h"
11#include "qwt_painter.h"
12#include "qwt_scale_div.h"
13#include "qwt_scale_map.h"
14#include "qwt_math.h"
15#include <qpen.h>
16#include <qpainter.h>
17#include <qfontmetrics.h>
18#include <qmath.h>
19
20class QwtRoundScaleDraw::PrivateData
21{
22public:
23 PrivateData():
24 center( 50.0, 50.0 ),
25 radius( 50.0 ),
26 startAngle( -135.0 ),
27 endAngle( 135.0 )
28 {
29 }
30
31 QPointF center;
32 double radius;
33
34 double startAngle;
35 double endAngle;
36};
37
38/*!
39 \brief Constructor
40
41 The range of the scale is initialized to [0, 100],
42 The center is set to (50, 50) with a radius of 50.
43 The angle range is set to [-135, 135].
44*/
45QwtRoundScaleDraw::QwtRoundScaleDraw()
46{
47 d_data = new QwtRoundScaleDraw::PrivateData;
48
49 setRadius( 50 );
50 scaleMap().setPaintInterval( d_data->startAngle, d_data->endAngle );
51}
52
53//! Destructor
54QwtRoundScaleDraw::~QwtRoundScaleDraw()
55{
56 delete d_data;
57}
58
59/*!
60 Change of radius the scale
61
62 Radius is the radius of the backbone without ticks and labels.
63
64 \param radius New Radius
65 \sa moveCenter()
66*/
67void QwtRoundScaleDraw::setRadius( double radius )
68{
69 d_data->radius = radius;
70}
71
72/*!
73 Get the radius
74
75 Radius is the radius of the backbone without ticks and labels.
76
77 \return Radius of the scale
78 \sa setRadius(), extent()
79*/
80double QwtRoundScaleDraw::radius() const
81{
82 return d_data->radius;
83}
84
85/*!
86 Move the center of the scale draw, leaving the radius unchanged
87
88 \param center New center
89 \sa setRadius()
90*/
91void QwtRoundScaleDraw::moveCenter( const QPointF &center )
92{
93 d_data->center = center;
94}
95
96//! Get the center of the scale
97QPointF QwtRoundScaleDraw::center() const
98{
99 return d_data->center;
100}
101
102/*!
103 \brief Adjust the baseline circle segment for round scales.
104
105 The baseline will be drawn from min(angle1,angle2) to max(angle1, angle2).
106 The default setting is [ -135, 135 ].
107 An angle of 0 degrees corresponds to the 12 o'clock position,
108 and positive angles count in a clockwise direction.
109 \param angle1
110 \param angle2 boundaries of the angle interval in degrees.
111 \warning <ul>
112 <li>The angle range is limited to [-360, 360] degrees. Angles exceeding
113 this range will be clipped.
114 <li>For angles more or equal than 360 degrees above or below min(angle1, angle2),
115 scale marks will not be drawn.
116 <li>If you need a counterclockwise scale, use QwtScaleDiv::setInterval()
117 </ul>
118*/
119void QwtRoundScaleDraw::setAngleRange( double angle1, double angle2 )
120{
121#if 0
122 angle1 = qBound( -360.0, angle1, 360.0 );
123 angle2 = qBound( -360.0, angle2, 360.0 );
124#endif
125
126 d_data->startAngle = angle1;
127 d_data->endAngle = angle2;
128
129 if ( d_data->startAngle == d_data->endAngle )
130 {
131 d_data->startAngle -= 1;
132 d_data->endAngle += 1;
133 }
134
135 scaleMap().setPaintInterval( d_data->startAngle, d_data->endAngle );
136}
137
138/*!
139 Draws the label for a major scale tick
140
141 \param painter Painter
142 \param value Value
143
144 \sa drawTick(), drawBackbone()
145*/
146void QwtRoundScaleDraw::drawLabel( QPainter *painter, double value ) const
147{
148 const double tval = scaleMap().transform( value );
149 if ( ( tval >= d_data->startAngle + 360.0 )
150 || ( tval <= d_data->startAngle - 360.0 ) )
151 {
152 return;
153 }
154
155 const QwtText label = tickLabel( painter->font(), value );
156 if ( label.isEmpty() )
157 return;
158
159 double radius = d_data->radius;
160 if ( hasComponent( QwtAbstractScaleDraw::Ticks ) ||
161 hasComponent( QwtAbstractScaleDraw::Backbone ) )
162 {
163 radius += spacing();
164 }
165
166 if ( hasComponent( QwtAbstractScaleDraw::Ticks ) )
167 radius += tickLength( QwtScaleDiv::MajorTick );
168
169 const QSizeF sz = label.textSize( painter->font() );
170 const double arc = qwtRadians( tval );
171
172 const double x = d_data->center.x() +
173 ( radius + sz.width() / 2.0 ) * qSin( arc );
174 const double y = d_data->center.y() -
175 ( radius + sz.height() / 2.0 ) * qCos( arc );
176
177 const QRectF r( x - sz.width() / 2, y - sz.height() / 2,
178 sz.width(), sz.height() );
179 label.draw( painter, r );
180}
181
182/*!
183 Draw a tick
184
185 \param painter Painter
186 \param value Value of the tick
187 \param len Lenght of the tick
188
189 \sa drawBackbone(), drawLabel()
190*/
191void QwtRoundScaleDraw::drawTick( QPainter *painter, double value, double len ) const
192{
193 if ( len <= 0 )
194 return;
195
196 const double tval = scaleMap().transform( value );
197
198 const double cx = d_data->center.x();
199 const double cy = d_data->center.y();
200 const double radius = d_data->radius;
201
202 if ( ( tval < d_data->startAngle + 360.0 )
203 && ( tval > d_data->startAngle - 360.0 ) )
204 {
205 const double arc = qwtRadians( tval );
206
207 const double sinArc = qSin( arc );
208 const double cosArc = qCos( arc );
209
210 const double x1 = cx + radius * sinArc;
211 const double x2 = cx + ( radius + len ) * sinArc;
212 const double y1 = cy - radius * cosArc;
213 const double y2 = cy - ( radius + len ) * cosArc;
214
215 QwtPainter::drawLine( painter, x1, y1, x2, y2 );
216 }
217}
218
219/*!
220 Draws the baseline of the scale
221 \param painter Painter
222
223 \sa drawTick(), drawLabel()
224*/
225void QwtRoundScaleDraw::drawBackbone( QPainter *painter ) const
226{
227 const double deg1 = scaleMap().p1();
228 const double deg2 = scaleMap().p2();
229
230 const int a1 = qRound( qMin( deg1, deg2 ) - 90 );
231 const int a2 = qRound( qMax( deg1, deg2 ) - 90 );
232
233 const double radius = d_data->radius;
234 const double x = d_data->center.x() - radius;
235 const double y = d_data->center.y() - radius;
236
237 painter->drawArc( QRectF( x, y, 2 * radius, 2 * radius ),
238 -a2 * 16, ( a2 - a1 + 1 ) * 16 ); // counterclockwise
239}
240
241/*!
242 Calculate the extent of the scale
243
244 The extent is the distance between the baseline to the outermost
245 pixel of the scale draw. radius() + extent() is an upper limit
246 for the radius of the bounding circle.
247
248 \param font Font used for painting the labels
249 \return Calculated extent
250
251 \sa setMinimumExtent(), minimumExtent()
252 \warning The implemented algorithm is not too smart and
253 calculates only an upper limit, that might be a
254 few pixels too large
255*/
256double QwtRoundScaleDraw::extent( const QFont &font ) const
257{
258 double d = 0.0;
259
260 if ( hasComponent( QwtAbstractScaleDraw::Labels ) )
261 {
262 const QwtScaleDiv &sd = scaleDiv();
263 const QList<double> &ticks = sd.ticks( QwtScaleDiv::MajorTick );
264 for ( int i = 0; i < ticks.count(); i++ )
265 {
266 const double value = ticks[i];
267 if ( !sd.contains( value ) )
268 continue;
269
270 const double tval = scaleMap().transform( value );
271 if ( ( tval < d_data->startAngle + 360 )
272 && ( tval > d_data->startAngle - 360 ) )
273 {
274 const QwtText label = tickLabel( font, value );
275 if ( label.isEmpty() )
276 continue;
277
278 const double arc = qwtRadians( tval );
279
280 const QSizeF sz = label.textSize( font );
281 const double off = qMax( sz.width(), sz.height() );
282
283 double x = off * qSin( arc );
284 double y = off * qCos( arc );
285
286 const double dist = qSqrt( x * x + y * y );
287 if ( dist > d )
288 d = dist;
289 }
290 }
291 }
292
293 if ( hasComponent( QwtAbstractScaleDraw::Ticks ) )
294 {
295 d += maxTickLength();
296 }
297
298 if ( hasComponent( QwtAbstractScaleDraw::Backbone ) )
299 {
300 const double pw = qMax( 1, penWidth() ); // pen width can be zero
301 d += pw;
302 }
303
304 if ( hasComponent( QwtAbstractScaleDraw::Labels ) &&
305 ( hasComponent( QwtAbstractScaleDraw::Ticks ) ||
306 hasComponent( QwtAbstractScaleDraw::Backbone ) ) )
307 {
308 d += spacing();
309 }
310
311 d = qMax( d, minimumExtent() );
312
313 return d;
314}
Note: See TracBrowser for help on using the repository browser.