地面站终端 App
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

315 lines
8.1 KiB

15 years ago
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
15 years ago
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#include "qwt_round_scale_draw.h"
15 years ago
#include "qwt_painter.h"
#include "qwt_scale_div.h"
#include "qwt_scale_map.h"
#include "qwt_math.h"
#include <qpen.h>
#include <qpainter.h>
#include <qfontmetrics.h>
#include <qmath.h>
15 years ago
class QwtRoundScaleDraw::PrivateData
{
public:
PrivateData():
center( 50.0, 50.0 ),
radius( 50.0 ),
startAngle( -135.0 ),
endAngle( 135.0 )
{
15 years ago
}
QPointF center;
double radius;
15 years ago
double startAngle;
double endAngle;
15 years ago
};
/*!
\brief Constructor
The range of the scale is initialized to [0, 100],
The center is set to (50, 50) with a radius of 50.
The angle range is set to [-135, 135].
*/
QwtRoundScaleDraw::QwtRoundScaleDraw()
{
d_data = new QwtRoundScaleDraw::PrivateData;
setRadius( 50 );
scaleMap().setPaintInterval( d_data->startAngle, d_data->endAngle );
15 years ago
}
//! Destructor
QwtRoundScaleDraw::~QwtRoundScaleDraw()
{
delete d_data;
}
/*!
Change of radius the scale
Radius is the radius of the backbone without ticks and labels.
\param radius New Radius
\sa moveCenter()
15 years ago
*/
void QwtRoundScaleDraw::setRadius( double radius )
15 years ago
{
d_data->radius = radius;
}
/*!
Get the radius
15 years ago
Radius is the radius of the backbone without ticks and labels.
\return Radius of the scale
15 years ago
\sa setRadius(), extent()
*/
double QwtRoundScaleDraw::radius() const
15 years ago
{
return d_data->radius;
}
/*!
Move the center of the scale draw, leaving the radius unchanged
\param center New center
\sa setRadius()
15 years ago
*/
void QwtRoundScaleDraw::moveCenter( const QPointF &center )
15 years ago
{
d_data->center = center;
}
//! Get the center of the scale
QPointF QwtRoundScaleDraw::center() const
15 years ago
{
return d_data->center;
}
/*!
\brief Adjust the baseline circle segment for round scales.
The baseline will be drawn from min(angle1,angle2) to max(angle1, angle2).
The default setting is [ -135, 135 ].
An angle of 0 degrees corresponds to the 12 o'clock position,
and positive angles count in a clockwise direction.
\param angle1
\param angle2 boundaries of the angle interval in degrees.
\warning <ul>
15 years ago
<li>The angle range is limited to [-360, 360] degrees. Angles exceeding
this range will be clipped.
<li>For angles more or equal than 360 degrees above or below min(angle1, angle2),
15 years ago
scale marks will not be drawn.
<li>If you need a counterclockwise scale, use QwtScaleDiv::setInterval()
15 years ago
</ul>
*/
void QwtRoundScaleDraw::setAngleRange( double angle1, double angle2 )
15 years ago
{
#if 0
angle1 = qBound( -360.0, angle1, 360.0 );
angle2 = qBound( -360.0, angle2, 360.0 );
#endif
15 years ago
d_data->startAngle = angle1;
d_data->endAngle = angle2;
if ( d_data->startAngle == d_data->endAngle )
{
15 years ago
d_data->startAngle -= 1;
d_data->endAngle += 1;
}
scaleMap().setPaintInterval( d_data->startAngle, d_data->endAngle );
15 years ago
}
/*!
Draws the label for a major scale tick
\param painter Painter
\param value Value
\sa drawTick(), drawBackbone()
*/
void QwtRoundScaleDraw::drawLabel( QPainter *painter, double value ) const
15 years ago
{
const QwtText label = tickLabel( painter->font(), value );
15 years ago
if ( label.isEmpty() )
return;
15 years ago
const double tval = scaleMap().transform( value );
if ( ( tval >= d_data->startAngle + 360.0 )
|| ( tval <= d_data->startAngle - 360.0 ) )
{
return;
15 years ago
}
double radius = d_data->radius;
if ( hasComponent( QwtAbstractScaleDraw::Ticks ) ||
hasComponent( QwtAbstractScaleDraw::Backbone ) )
{
15 years ago
radius += spacing();
}
if ( hasComponent( QwtAbstractScaleDraw::Ticks ) )
radius += tickLength( QwtScaleDiv::MajorTick );
15 years ago
const QSizeF sz = label.textSize( painter->font() );
const double arc = qwtRadians( tval );
15 years ago
const double x = d_data->center.x() +
( radius + sz.width() / 2.0 ) * qSin( arc );
const double y = d_data->center.y() -
( radius + sz.height() / 2.0 ) * qCos( arc );
15 years ago
const QRectF r( x - sz.width() / 2, y - sz.height() / 2,
sz.width(), sz.height() );
label.draw( painter, r );
15 years ago
}
/*!
Draw a tick
15 years ago
\param painter Painter
\param value Value of the tick
\param len Lenght of the tick
\sa drawBackbone(), drawLabel()
15 years ago
*/
void QwtRoundScaleDraw::drawTick( QPainter *painter, double value, double len ) const
15 years ago
{
if ( len <= 0 )
return;
const double tval = scaleMap().transform( value );
15 years ago
const double cx = d_data->center.x();
const double cy = d_data->center.y();
const double radius = d_data->radius;
15 years ago
if ( ( tval < d_data->startAngle + 360.0 )
|| ( tval > d_data->startAngle - 360.0 ) )
{
const double arc = qwtRadians( tval );
15 years ago
const double sinArc = qSin( arc );
const double cosArc = qCos( arc );
15 years ago
const double x1 = cx + radius * sinArc;
const double x2 = cx + ( radius + len ) * sinArc;
const double y1 = cy - radius * cosArc;
const double y2 = cy - ( radius + len ) * cosArc;
15 years ago
QwtPainter::drawLine( painter, x1, y1, x2, y2 );
15 years ago
}
}
/*!
Draws the baseline of the scale
\param painter Painter
\sa drawTick(), drawLabel()
*/
void QwtRoundScaleDraw::drawBackbone( QPainter *painter ) const
15 years ago
{
const double deg1 = scaleMap().p1();
const double deg2 = scaleMap().p2();
const int a1 = qRound( qMin( deg1, deg2 ) - 90 );
const int a2 = qRound( qMax( deg1, deg2 ) - 90 );
15 years ago
const double radius = d_data->radius;
const double x = d_data->center.x() - radius;
const double y = d_data->center.y() - radius;
15 years ago
painter->drawArc( QRectF( x, y, 2 * radius, 2 * radius ),
-a2 * 16, ( a2 - a1 + 1 ) * 16 ); // counterclockwise
15 years ago
}
/*!
Calculate the extent of the scale
The extent is the distance between the baseline to the outermost
pixel of the scale draw. radius() + extent() is an upper limit
15 years ago
for the radius of the bounding circle.
\param font Font used for painting the labels
\return Calculated extent
15 years ago
\sa setMinimumExtent(), minimumExtent()
\warning The implemented algorithm is not too smart and
15 years ago
calculates only an upper limit, that might be a
few pixels too large
*/
double QwtRoundScaleDraw::extent( const QFont &font ) const
15 years ago
{
double d = 0.0;
15 years ago
if ( hasComponent( QwtAbstractScaleDraw::Labels ) )
{
15 years ago
const QwtScaleDiv &sd = scaleDiv();
const QList<double> &ticks = sd.ticks( QwtScaleDiv::MajorTick );
for ( int i = 0; i < ticks.count(); i++ )
{
15 years ago
const double value = ticks[i];
if ( !sd.contains( value ) )
15 years ago
continue;
const QwtText label = tickLabel( font, value );
15 years ago
if ( label.isEmpty() )
continue;
const double tval = scaleMap().transform( value );
if ( ( tval < d_data->startAngle + 360 )
&& ( tval > d_data->startAngle - 360 ) )
{
const double arc = qwtRadians( tval );
15 years ago
const QSizeF sz = label.textSize( font );
const double off = qMax( sz.width(), sz.height() );
15 years ago
double x = off * qSin( arc );
double y = off * qCos( arc );
15 years ago
const double dist = qSqrt( x * x + y * y );
15 years ago
if ( dist > d )
d = dist;
}
}
}
if ( hasComponent( QwtAbstractScaleDraw::Ticks ) )
{
d += maxTickLength();
15 years ago
}
if ( hasComponent( QwtAbstractScaleDraw::Backbone ) )
{
const double pw = qMax( 1, penWidth() ); // pen width can be zero
15 years ago
d += pw;
}
if ( hasComponent( QwtAbstractScaleDraw::Labels ) &&
( hasComponent( QwtAbstractScaleDraw::Ticks ) ||
hasComponent( QwtAbstractScaleDraw::Backbone ) ) )
{
15 years ago
d += spacing();
}
d = qMax( d, minimumExtent() );
15 years ago
return d;
}