qwt_compass_rose.cpp 7.04 KB
Newer Older
pixhawk's avatar
pixhawk committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 * Qwt Widget Library
 * Copyright (C) 1997   Josef Wilgen
 * Copyright (C) 2002   Uwe Rathmann
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the Qwt License, Version 1.0
 *****************************************************************************/

#include <math.h>
#include <qpainter.h>
#include "qwt_math.h"
#include "qwt_painter.h"
#include "qwt_compass_rose.h"

static QPoint cutPoint(QPoint p11, QPoint p12, QPoint p21, QPoint p22)
{
    double dx1 = p12.x() - p11.x();
    double dy1 = p12.y() - p11.y();
    double dx2 = p22.x() - p21.x();
    double dy2 = p22.y() - p21.y();

    if ( dx1 == 0.0 && dx2 == 0.0 )
        return QPoint();

26
    if ( dx1 == 0.0 ) {
pixhawk's avatar
pixhawk committed
27 28 29 30 31
        const double m = dy2 / dx2;
        const double t = p21.y() - m * p21.x();
        return QPoint(p11.x(), qRound(m * p11.x() + t));
    }

32
    if ( dx2 == 0 ) {
pixhawk's avatar
pixhawk committed
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
        const double m = dy1 / dx1;
        const double t = p11.y() - m * p11.x();
        return QPoint(p21.x(), qRound(m * p21.x() + t));
    }

    const double m1 = dy1 / dx1;
    const double t1 = p11.y() - m1 * p11.x();

    const double m2 = dy2 / dx2;
    const double t2 = p21.y() - m2 * p21.x();

    if ( m1 == m2 )
        return QPoint();

    const double x = ( t2 - t1 ) / ( m1 - m2 );
    const double y = t1 + m1 * x;

    return QPoint(qRound(x), qRound(y));
}

/*!
   Constructor

   \param numThorns Number of thorns
   \param numThornLevels Number of thorn levels
*/
QwtSimpleCompassRose::QwtSimpleCompassRose(int numThorns, int numThornLevels):
    d_width(0.2),
    d_numThorns(numThorns),
    d_numThornLevels(numThornLevels),
    d_shrinkFactor(0.9)
{
    const QColor dark(128,128,255);
    const QColor light(192,255,255);
67

pixhawk's avatar
pixhawk committed
68
    QPalette palette;
69
    for ( int i = 0; i < QPalette::NColorGroups; i++ ) {
pixhawk's avatar
pixhawk committed
70 71
#if QT_VERSION < 0x040000
        palette.setColor((QPalette::ColorGroup)i,
72
                         QColorGroup::Dark, dark);
pixhawk's avatar
pixhawk committed
73
        palette.setColor((QPalette::ColorGroup)i,
74
                         QColorGroup::Light, light);
pixhawk's avatar
pixhawk committed
75 76
#else
        palette.setColor((QPalette::ColorGroup)i,
77
                         QPalette::Dark, dark);
pixhawk's avatar
pixhawk committed
78
        palette.setColor((QPalette::ColorGroup)i,
79
                         QPalette::Light, light);
pixhawk's avatar
pixhawk committed
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
#endif
    }

    setPalette(palette);
}

/*!
   Draw the rose

   \param painter Painter
   \param center Center point
   \param radius Radius of the rose
   \param north Position
   \param cg Color group
*/
95 96
void QwtSimpleCompassRose::draw(QPainter *painter, const QPoint &center,
                                int radius, double north, QPalette::ColorGroup cg) const
pixhawk's avatar
pixhawk committed
97 98 99
{
#if QT_VERSION < 0x040000
    QColorGroup colorGroup;
100 101 102 103 104 105 106
    switch(cg) {
    case QPalette::Disabled:
        colorGroup = palette().disabled();
    case QPalette::Inactive:
        colorGroup = palette().inactive();
    default:
        colorGroup = palette().active();
pixhawk's avatar
pixhawk committed
107 108
    }

109 110
    drawRose(painter, colorGroup, center, radius, north, d_width,
             d_numThorns, d_numThornLevels, d_shrinkFactor);
pixhawk's avatar
pixhawk committed
111 112 113
#else
    QPalette pal = palette();
    pal.setCurrentColorGroup(cg);
114 115
    drawRose(painter, pal, center, radius, north, d_width,
             d_numThorns, d_numThornLevels, d_shrinkFactor);
pixhawk's avatar
pixhawk committed
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
#endif
}

/*!
   Draw the rose

   \param painter Painter
   \param palette Palette
   \param center Center of the rose
   \param radius Radius of the rose
   \param north Position pointing to north
   \param width Width of the rose
   \param numThorns Number of thorns
   \param numThornLevels Number of thorn levels
   \param shrinkFactor Factor to shrink the thorns with each level
*/
void QwtSimpleCompassRose::drawRose(
133
    QPainter *painter,
pixhawk's avatar
pixhawk committed
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
#if QT_VERSION < 0x040000
    const QColorGroup &cg,
#else
    const QPalette &palette,
#endif
    const QPoint &center, int radius, double north, double width,
    int numThorns, int numThornLevels, double shrinkFactor)
{
    if ( numThorns < 4 )
        numThorns = 4;

    if ( numThorns % 4 )
        numThorns += 4 - numThorns % 4;

    if ( numThornLevels <= 0 )
        numThornLevels = numThorns / 4;

    if ( shrinkFactor >= 1.0 )
        shrinkFactor = 1.0;

    if ( shrinkFactor <= 0.5 )
        shrinkFactor = 0.5;

    painter->save();

    painter->setPen(Qt::NoPen);

161
    for ( int j = 1; j <= numThornLevels; j++ ) {
pixhawk's avatar
pixhawk committed
162 163 164 165 166
        double step =  pow(2.0, j) * M_PI / (double)numThorns;
        if ( step > M_PI_2 )
            break;

        double r = radius;
167
        for ( int k = 0; k < 3; k++ ) {
pixhawk's avatar
pixhawk committed
168 169 170 171 172 173 174 175 176
            if ( j + k < numThornLevels )
                r *= shrinkFactor;
        }

        double leafWidth = r * width;
        if ( 2.0 * M_PI / step > 32 )
            leafWidth = 16;

        const double origin = north / 180.0 * M_PI;
177 178
        for ( double angle = origin;
                angle < 2.0 * M_PI + origin; angle += step) {
pixhawk's avatar
pixhawk committed
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
            const QPoint p = qwtPolar2Pos(center, r, angle);
            QPoint p1 = qwtPolar2Pos(center, leafWidth, angle + M_PI_2);
            QPoint p2 = qwtPolar2Pos(center, leafWidth, angle - M_PI_2);

            QwtPolygon pa(3);
            pa.setPoint(0, center);
            pa.setPoint(1, p);

            QPoint p3 = qwtPolar2Pos(center, r, angle + step / 2.0);
            p1 = cutPoint(center, p3, p1, p);
            pa.setPoint(2, p1);
#if QT_VERSION < 0x040000
            painter->setBrush(cg.brush(QColorGroup::Dark));
#else
            painter->setBrush(palette.brush(QPalette::Dark));
#endif
            painter->drawPolygon(pa);

            QPoint p4 = qwtPolar2Pos(center, r, angle - step / 2.0);
            p2 = cutPoint(center, p4, p2, p);

            pa.setPoint(2, p2);
#if QT_VERSION < 0x040000
            painter->setBrush(cg.brush(QColorGroup::Light));
#else
            painter->setBrush(palette.brush(QPalette::Light));
#endif
            painter->drawPolygon(pa);
        }
    }
    painter->restore();
}

/*!
   Set the width of the rose heads. Lower value make thinner heads.
   The range is limited from 0.03 to 0.4.

   \param width Width
*/

219
void QwtSimpleCompassRose::setWidth(double width)
pixhawk's avatar
pixhawk committed
220
{
221 222
    d_width = width;
    if (d_width < 0.03)
pixhawk's avatar
pixhawk committed
223 224
        d_width = 0.03;

225
    if (d_width > 0.4)
pixhawk's avatar
pixhawk committed
226 227 228 229 230
        d_width = 0.4;
}

/*!
  Set the number of thorns on one level
231
  The number is aligned to a multiple of 4, with a minimum of 4
pixhawk's avatar
pixhawk committed
232 233 234 235

  \param numThorns Number of thorns
  \sa numThorns(), setNumThornLevels()
*/
236
void QwtSimpleCompassRose::setNumThorns(int numThorns)
pixhawk's avatar
pixhawk committed
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
{
    if ( numThorns < 4 )
        numThorns = 4;

    if ( numThorns % 4 )
        numThorns += 4 - numThorns % 4;

    d_numThorns = numThorns;
}

/*!
   \return Number of thorns
   \sa setNumThorns(), setNumThornLevels()
*/
int QwtSimpleCompassRose::numThorns() const
{
253
    return d_numThorns;
pixhawk's avatar
pixhawk committed
254 255 256 257 258 259 260 261
}

/*!
  Set the of thorns levels

  \param numThornLevels Number of thorns levels
  \sa setNumThorns(), numThornLevels()
*/
262
void QwtSimpleCompassRose::setNumThornLevels(int numThornLevels)
pixhawk's avatar
pixhawk committed
263 264 265 266 267 268 269 270 271 272 273 274
{
    d_numThornLevels = numThornLevels;
}

/*!
   \return Number of thorn levels
   \sa setNumThorns(), setNumThornLevels()
*/
int QwtSimpleCompassRose::numThornLevels() const
{
    return d_numThornLevels;
}