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

Last change on this file since 8127 was 8127, checked in by stoecker, 2 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.