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 *****************************************************************************/
10 #include "qwt_round_scale_draw.h"
11 #include "qwt_painter.h"
12 #include "qwt_scale_div.h"
13 #include "qwt_scale_map.h"
17 #include <qfontmetrics.h>
20 class QwtRoundScaleDraw::PrivateData
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].
45 QwtRoundScaleDraw::QwtRoundScaleDraw()
47 d_data
= new QwtRoundScaleDraw::PrivateData
;
50 scaleMap().setPaintInterval( d_data
->startAngle
, d_data
->endAngle
);
54 QwtRoundScaleDraw::~QwtRoundScaleDraw()
60 Change of radius the scale
62 Radius is the radius of the backbone without ticks and labels.
64 \param radius New Radius
67 void QwtRoundScaleDraw::setRadius( double radius
)
69 d_data
->radius
= radius
;
75 Radius is the radius of the backbone without ticks and labels.
77 \return Radius of the scale
78 \sa setRadius(), extent()
80 double QwtRoundScaleDraw::radius() const
82 return d_data
->radius
;
86 Move the center of the scale draw, leaving the radius unchanged
88 \param center New center
91 void QwtRoundScaleDraw::moveCenter( const QPointF
¢er
)
93 d_data
->center
= center
;
96 //! Get the center of the scale
97 QPointF
QwtRoundScaleDraw::center() const
99 return d_data
->center
;
103 \brief Adjust the baseline circle segment for round scales.
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.
110 \param angle2 boundaries of the angle interval in degrees.
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()
119 void QwtRoundScaleDraw::setAngleRange( double angle1
, double angle2
)
122 angle1
= qBound( -360.0, angle1
, 360.0 );
123 angle2
= qBound( -360.0, angle2
, 360.0 );
126 d_data
->startAngle
= angle1
;
127 d_data
->endAngle
= angle2
;
129 if ( d_data
->startAngle
== d_data
->endAngle
)
131 d_data
->startAngle
-= 1;
132 d_data
->endAngle
+= 1;
135 scaleMap().setPaintInterval( d_data
->startAngle
, d_data
->endAngle
);
139 Draws the label for a major scale tick
141 \param painter Painter
144 \sa drawTick(), drawBackbone()
146 void QwtRoundScaleDraw::drawLabel( QPainter
*painter
, double value
) const
148 const double tval
= scaleMap().transform( value
);
149 if ( ( tval
>= d_data
->startAngle
+ 360.0 )
150 || ( tval
<= d_data
->startAngle
- 360.0 ) )
155 const QwtText label
= tickLabel( painter
->font(), value
);
156 if ( label
.isEmpty() )
159 double radius
= d_data
->radius
;
160 if ( hasComponent( QwtAbstractScaleDraw::Ticks
) ||
161 hasComponent( QwtAbstractScaleDraw::Backbone
) )
166 if ( hasComponent( QwtAbstractScaleDraw::Ticks
) )
167 radius
+= tickLength( QwtScaleDiv::MajorTick
);
169 const QSizeF sz
= label
.textSize( painter
->font() );
170 const double arc
= qwtRadians( tval
);
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
);
177 const QRectF
r( x
- sz
.width() / 2, y
- sz
.height() / 2,
178 sz
.width(), sz
.height() );
179 label
.draw( painter
, r
);
185 \param painter Painter
186 \param value Value of the tick
187 \param len Lenght of the tick
189 \sa drawBackbone(), drawLabel()
191 void QwtRoundScaleDraw::drawTick( QPainter
*painter
, double value
, double len
) const
196 const double tval
= scaleMap().transform( value
);
198 const double cx
= d_data
->center
.x();
199 const double cy
= d_data
->center
.y();
200 const double radius
= d_data
->radius
;
202 if ( ( tval
< d_data
->startAngle
+ 360.0 )
203 && ( tval
> d_data
->startAngle
- 360.0 ) )
205 const double arc
= qwtRadians( tval
);
207 const double sinArc
= qSin( arc
);
208 const double cosArc
= qCos( arc
);
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
;
215 QwtPainter::drawLine( painter
, x1
, y1
, x2
, y2
);
220 Draws the baseline of the scale
221 \param painter Painter
223 \sa drawTick(), drawLabel()
225 void QwtRoundScaleDraw::drawBackbone( QPainter
*painter
) const
227 const double deg1
= scaleMap().p1();
228 const double deg2
= scaleMap().p2();
230 const int a1
= qRound( qMin( deg1
, deg2
) - 90 );
231 const int a2
= qRound( qMax( deg1
, deg2
) - 90 );
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
;
237 painter
->drawArc( QRectF( x
, y
, 2 * radius
, 2 * radius
),
238 -a2
* 16, ( a2
- a1
+ 1 ) * 16 ); // counterclockwise
242 Calculate the extent of the scale
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.
248 \param font Font used for painting the labels
249 \return Calculated extent
251 \sa setMinimumExtent(), minimumExtent()
252 \warning The implemented algorithm is not too smart and
253 calculates only an upper limit, that might be a
256 double QwtRoundScaleDraw::extent( const QFont
&font
) const
260 if ( hasComponent( QwtAbstractScaleDraw::Labels
) )
262 const QwtScaleDiv
&sd
= scaleDiv();
263 const QList
<double> &ticks
= sd
.ticks( QwtScaleDiv::MajorTick
);
264 for ( int i
= 0; i
< ticks
.count(); i
++ )
266 const double value
= ticks
[i
];
267 if ( !sd
.contains( value
) )
270 const double tval
= scaleMap().transform( value
);
271 if ( ( tval
< d_data
->startAngle
+ 360 )
272 && ( tval
> d_data
->startAngle
- 360 ) )
274 const QwtText label
= tickLabel( font
, value
);
275 if ( label
.isEmpty() )
278 const double arc
= qwtRadians( tval
);
280 const QSizeF sz
= label
.textSize( font
);
281 const double off
= qMax( sz
.width(), sz
.height() );
283 double x
= off
* qSin( arc
);
284 double y
= off
* qCos( arc
);
286 const double dist
= qSqrt( x
* x
+ y
* y
);
293 if ( hasComponent( QwtAbstractScaleDraw::Ticks
) )
295 d
+= maxTickLength();
298 if ( hasComponent( QwtAbstractScaleDraw::Backbone
) )
300 const double pw
= qMax( 1, penWidth() ); // pen width can be zero
304 if ( hasComponent( QwtAbstractScaleDraw::Labels
) &&
305 ( hasComponent( QwtAbstractScaleDraw::Ticks
) ||
306 hasComponent( QwtAbstractScaleDraw::Backbone
) ) )
311 d
= qMax( d
, minimumExtent() );