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

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

update qwt and qwtpolar, many QT5 fixes (unfinished)

File size: 8.1 KB
RevLine 
[4271]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"
[8127]14#include "qwt_math.h"
[4271]15#include <qpen.h>
16#include <qpainter.h>
17#include <qfontmetrics.h>
18#include <qmath.h>
19
20class QwtRoundScaleDraw::PrivateData
21{
22public:
23 PrivateData():
[8127]24 center( 50.0, 50.0 ),
25 radius( 50.0 ),
26 startAngle( -135.0 ),
27 endAngle( 135.0 )
[4271]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*/
[8127]67void QwtRoundScaleDraw::setRadius( double radius )
[4271]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
[8127]77 \return Radius of the scale
[4271]78 \sa setRadius(), extent()
79*/
[8127]80double QwtRoundScaleDraw::radius() const
[4271]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.
[8127]114 <li>For angles more or equal than 360 degrees above or below min(angle1, angle2),
[4271]115 scale marks will not be drawn.
[8127]116 <li>If you need a counterclockwise scale, use QwtScaleDiv::setInterval()
[4271]117 </ul>
118*/
119void QwtRoundScaleDraw::setAngleRange( double angle1, double angle2 )
120{
[8127]121#if 0
[4271]122 angle1 = qBound( -360.0, angle1, 360.0 );
123 angle2 = qBound( -360.0, angle2, 360.0 );
[8127]124#endif
[4271]125
[8127]126 d_data->startAngle = angle1;
127 d_data->endAngle = angle2;
[4271]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 );
[8127]149 if ( ( tval >= d_data->startAngle + 360.0 )
150 || ( tval <= d_data->startAngle - 360.0 ) )
[4271]151 {
152 return;
153 }
154
[8127]155 const QwtText label = tickLabel( painter->font(), value );
156 if ( label.isEmpty() )
157 return;
158
[4271]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() );
[8127]170 const double arc = qwtRadians( tval );
[4271]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() -
[8127]175 ( radius + sz.height() / 2.0 ) * qCos( arc );
[4271]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
[8127]202 if ( ( tval < d_data->startAngle + 360.0 )
203 && ( tval > d_data->startAngle - 360.0 ) )
[4271]204 {
[8127]205 const double arc = qwtRadians( tval );
[4271]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{
[8127]227 const double deg1 = scaleMap().p1();
228 const double deg2 = scaleMap().p2();
[4271]229
[8127]230 const int a1 = qRound( qMin( deg1, deg2 ) - 90 );
231 const int a2 = qRound( qMax( deg1, deg2 ) - 90 );
232
[4271]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
[8127]237 painter->drawArc( QRectF( x, y, 2 * radius, 2 * radius ),
238 -a2 * 16, ( a2 - a1 + 1 ) * 16 ); // counterclockwise
[4271]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
[8127]249 \return Calculated extent
[4271]250
251 \sa setMinimumExtent(), minimumExtent()
[8127]252 \warning The implemented algorithm is not too smart and
[4271]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 );
[8127]271 if ( ( tval < d_data->startAngle + 360 )
272 && ( tval > d_data->startAngle - 360 ) )
[4271]273 {
[8127]274 const QwtText label = tickLabel( font, value );
275 if ( label.isEmpty() )
276 continue;
[4271]277
[8127]278 const double arc = qwtRadians( tval );
279
[4271]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 {
[8127]300 const double pw = qMax( 1, penWidth() ); // pen width can be zero
[4271]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.