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.4 KiB
315 lines
8.4 KiB
15 years ago
|
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
|
||
|
* Qwt Widget Library
|
||
|
* Copyright (C) 1997 Josef Wilgen
|
||
|
* Copyright (C) 2002 Uwe Rathmann
|
||
14 years ago
|
*
|
||
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
|
||
|
*****************************************************************************/
|
||
|
|
||
|
// vim: expandtab
|
||
|
|
||
|
#include <math.h>
|
||
|
#include <qpen.h>
|
||
|
#include <qpainter.h>
|
||
|
#include <qfontmetrics.h>
|
||
|
#include "qwt_painter.h"
|
||
|
#include "qwt_scale_div.h"
|
||
|
#include "qwt_scale_map.h"
|
||
|
#include "qwt_round_scale_draw.h"
|
||
|
|
||
|
class QwtRoundScaleDraw::PrivateData
|
||
|
{
|
||
|
public:
|
||
|
PrivateData():
|
||
|
center(50, 50),
|
||
|
radius(50),
|
||
|
startAngle(-135 * 16),
|
||
14 years ago
|
endAngle(135 * 16) {
|
||
15 years ago
|
}
|
||
|
|
||
|
QPoint center;
|
||
14 years ago
|
int radius;
|
||
15 years ago
|
|
||
|
int startAngle;
|
||
|
int endAngle;
|
||
|
};
|
||
|
|
||
|
/*!
|
||
|
\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);
|
||
|
}
|
||
|
|
||
|
//! Copy constructor
|
||
|
QwtRoundScaleDraw::QwtRoundScaleDraw(const QwtRoundScaleDraw &other):
|
||
|
QwtAbstractScaleDraw(other)
|
||
|
{
|
||
|
d_data = new QwtRoundScaleDraw::PrivateData(*other.d_data);
|
||
|
}
|
||
|
|
||
|
|
||
|
//! Destructor
|
||
|
QwtRoundScaleDraw::~QwtRoundScaleDraw()
|
||
|
{
|
||
|
delete d_data;
|
||
|
}
|
||
|
|
||
|
//! Assignment operator
|
||
|
QwtRoundScaleDraw &QwtRoundScaleDraw::operator=(const QwtRoundScaleDraw &other)
|
||
|
{
|
||
|
*(QwtAbstractScaleDraw*)this = (const QwtAbstractScaleDraw &)other;
|
||
|
*d_data = *other.d_data;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
Change of radius the scale
|
||
|
|
||
|
Radius is the radius of the backbone without ticks and labels.
|
||
|
|
||
|
\param radius New Radius
|
||
|
\sa moveCenter
|
||
|
*/
|
||
|
void QwtRoundScaleDraw::setRadius(int radius)
|
||
|
{
|
||
|
d_data->radius = radius;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
14 years ago
|
Get the radius
|
||
15 years ago
|
|
||
|
Radius is the radius of the backbone without ticks and labels.
|
||
|
|
||
|
\sa setRadius(), extent()
|
||
|
*/
|
||
|
int QwtRoundScaleDraw::radius() const
|
||
|
{
|
||
|
return d_data->radius;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
Move the center of the scale draw, leaving the radius unchanged
|
||
|
|
||
|
\param center New center
|
||
|
\sa setRadius
|
||
|
*/
|
||
|
void QwtRoundScaleDraw::moveCenter(const QPoint ¢er)
|
||
|
{
|
||
|
d_data->center = center;
|
||
|
}
|
||
|
|
||
|
//! Get the center of the scale
|
||
|
QPoint QwtRoundScaleDraw::center() const
|
||
|
{
|
||
|
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.
|
||
14 years ago
|
\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 than 359 degrees above or below min(angle1, angle2),
|
||
|
scale marks will not be drawn.
|
||
|
<li>If you need a counterclockwise scale, use QwtScaleDiv::setRange
|
||
|
</ul>
|
||
|
*/
|
||
|
void QwtRoundScaleDraw::setAngleRange(double angle1, double angle2)
|
||
|
{
|
||
|
angle1 = qwtLim(angle1, -360.0, 360.0);
|
||
|
angle2 = qwtLim(angle2, -360.0, 360.0);
|
||
|
|
||
|
d_data->startAngle = qRound(angle1 * 16.0);
|
||
14 years ago
|
d_data->endAngle = qRound(angle2 * 16.0);
|
||
|
|
||
|
if (d_data->startAngle == d_data->endAngle) {
|
||
15 years ago
|
d_data->startAngle -= 1;
|
||
|
d_data->endAngle += 1;
|
||
|
}
|
||
14 years ago
|
|
||
15 years ago
|
scaleMap().setPaintInterval(d_data->startAngle, d_data->endAngle);
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
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
|
||
|
{
|
||
|
const QwtText label = tickLabel(painter->font(), value);
|
||
|
if ( label.isEmpty() )
|
||
14 years ago
|
return;
|
||
15 years ago
|
|
||
|
const int tval = map().transform(value);
|
||
|
if ((tval > d_data->startAngle + 359 * 16)
|
||
14 years ago
|
|| (tval < d_data->startAngle - 359 * 16)) {
|
||
|
return;
|
||
15 years ago
|
}
|
||
|
|
||
|
double radius = d_data->radius;
|
||
|
if ( hasComponent(QwtAbstractScaleDraw::Ticks) ||
|
||
14 years ago
|
hasComponent(QwtAbstractScaleDraw::Backbone) ) {
|
||
15 years ago
|
radius += spacing();
|
||
|
}
|
||
|
|
||
|
if ( hasComponent(QwtAbstractScaleDraw::Ticks) )
|
||
|
radius += majTickLength();
|
||
|
|
||
|
const QSize sz = label.textSize(painter->font());
|
||
|
const double arc = tval / 16.0 / 360.0 * 2 * M_PI;
|
||
|
|
||
|
const int x = d_data->center.x() +
|
||
14 years ago
|
qRound((radius + sz.width() / 2.0) * sin(arc));
|
||
15 years ago
|
const int y = d_data->center.y() -
|
||
14 years ago
|
qRound( (radius + sz.height() / 2.0) * cos(arc));
|
||
15 years ago
|
|
||
|
const QRect r(x - sz.width() / 2, y - sz.height() / 2,
|
||
14 years ago
|
sz.width(), sz.height() );
|
||
15 years ago
|
label.draw(painter, r);
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
Draw a tick
|
||
14 years ago
|
|
||
15 years ago
|
\param painter Painter
|
||
|
\param value Value of the tick
|
||
|
\param len Lenght of the tick
|
||
|
|
||
14 years ago
|
\sa drawBackbone(), drawLabel()
|
||
15 years ago
|
*/
|
||
|
void QwtRoundScaleDraw::drawTick(QPainter *painter, double value, int len) const
|
||
|
{
|
||
|
if ( len <= 0 )
|
||
|
return;
|
||
|
|
||
|
const int tval = map().transform(value);
|
||
|
|
||
|
const int cx = d_data->center.x();
|
||
|
const int cy = d_data->center.y();
|
||
|
const int radius = d_data->radius;
|
||
|
|
||
|
if ((tval <= d_data->startAngle + 359 * 16)
|
||
14 years ago
|
|| (tval >= d_data->startAngle - 359 * 16)) {
|
||
15 years ago
|
const double arc = double(tval) / 16.0 * M_PI / 180.0;
|
||
|
|
||
|
const double sinArc = sin(arc);
|
||
|
const double cosArc = cos(arc);
|
||
|
|
||
|
const int x1 = qRound( cx + radius * sinArc );
|
||
|
const int x2 = qRound( cx + (radius + len) * sinArc );
|
||
|
const int y1 = qRound( cy - radius * cosArc );
|
||
|
const int y2 = qRound( cy - (radius + len) * cosArc );
|
||
|
|
||
|
QwtPainter::drawLine(painter, x1, y1, x2, y2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
Draws the baseline of the scale
|
||
|
\param painter Painter
|
||
|
|
||
|
\sa drawTick(), drawLabel()
|
||
|
*/
|
||
|
void QwtRoundScaleDraw::drawBackbone(QPainter *painter) const
|
||
|
{
|
||
|
const int a1 = qRound(qwtMin(map().p1(), map().p2()) - 90 * 16);
|
||
|
const int a2 = qRound(qwtMax(map().p1(), map().p2()) - 90 * 16);
|
||
|
|
||
|
const int radius = d_data->radius;
|
||
|
const int x = d_data->center.x() - radius;
|
||
|
const int y = d_data->center.y() - radius;
|
||
|
|
||
|
painter->drawArc(x, y, 2 * radius, 2 * radius,
|
||
14 years ago
|
-a2, a2 - a1 + 1); // counterclockwise
|
||
15 years ago
|
}
|
||
|
|
||
|
/*!
|
||
|
Calculate the extent of the scale
|
||
|
|
||
|
The extent is the distcance between the baseline to the outermost
|
||
14 years ago
|
pixel of the scale draw. radius() + extent() is an upper limit
|
||
15 years ago
|
for the radius of the bounding circle.
|
||
|
|
||
|
\param pen Pen that is used for painting backbone and ticks
|
||
|
\param font Font used for painting the labels
|
||
|
|
||
|
\sa setMinimumExtent(), minimumExtent()
|
||
|
\warning The implemented algo is not too smart and
|
||
|
calculates only an upper limit, that might be a
|
||
|
few pixels too large
|
||
|
*/
|
||
|
int QwtRoundScaleDraw::extent(const QPen &pen, const QFont &font) const
|
||
|
{
|
||
|
int d = 0;
|
||
|
|
||
14 years ago
|
if ( hasComponent(QwtAbstractScaleDraw::Labels) ) {
|
||
15 years ago
|
const QwtScaleDiv &sd = scaleDiv();
|
||
|
const QwtValueList &ticks = sd.ticks(QwtScaleDiv::MajorTick);
|
||
14 years ago
|
for (uint i = 0; i < (uint)ticks.count(); i++) {
|
||
15 years ago
|
const double value = ticks[i];
|
||
|
if ( !sd.contains(value) )
|
||
|
continue;
|
||
|
|
||
|
const QwtText label = tickLabel(font, value);
|
||
|
if ( label.isEmpty() )
|
||
|
continue;
|
||
14 years ago
|
|
||
15 years ago
|
const int tval = map().transform(value);
|
||
|
if ((tval < d_data->startAngle + 360 * 16)
|
||
14 years ago
|
&& (tval > d_data->startAngle - 360 * 16)) {
|
||
15 years ago
|
const double arc = tval / 16.0 / 360.0 * 2 * M_PI;
|
||
|
|
||
|
const QSize sz = label.textSize(font);
|
||
|
const double off = qwtMax(sz.width(), sz.height());
|
||
|
|
||
|
double x = off * sin(arc);
|
||
|
double y = off * cos(arc);
|
||
|
|
||
|
const int dist = (int)ceil(sqrt(x * x + y * y) + 1 );
|
||
|
if ( dist > d )
|
||
|
d = dist;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
14 years ago
|
if ( hasComponent(QwtAbstractScaleDraw::Ticks) ) {
|
||
15 years ago
|
d += majTickLength();
|
||
|
}
|
||
|
|
||
14 years ago
|
if ( hasComponent(QwtAbstractScaleDraw::Backbone) ) {
|
||
15 years ago
|
const int pw = qwtMax( 1, pen.width() ); // penwidth can be zero
|
||
|
d += pw;
|
||
|
}
|
||
|
|
||
|
if ( hasComponent(QwtAbstractScaleDraw::Labels) &&
|
||
14 years ago
|
( hasComponent(QwtAbstractScaleDraw::Ticks) ||
|
||
|
hasComponent(QwtAbstractScaleDraw::Backbone) ) ) {
|
||
15 years ago
|
d += spacing();
|
||
|
}
|
||
|
|
||
|
d = qwtMax(d, minimumExtent());
|
||
|
|
||
|
return d;
|
||
|
}
|