# qwt_compass_rose.cpp

    00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
    00002  * Qwt Widget Library
    00003  * Copyright (C) 1997   Josef Wilgen
    00004  * Copyright (C) 2002   Uwe Rathmann
    00005  *
    00006  * This library is free software; you can redistribute it and/or
    00007  * modify it under the terms of the Qwt License, Version 1.0
    00008  *****************************************************************************/
    00009
    00010 #include <math.h>
    00011 #include <qpainter.h>
    00012 #include "qwt_math.h"
    00013 #include "qwt_painter.h"
    00014 #include "qwt_compass_rose.h"
    00015
    00016 static QPoint cutPoint(QPoint p11, QPoint p12, QPoint p21, QPoint p22)
    00017 {
    00018     double dx1 = p12.x() - p11.x();
    00019     double dy1 = p12.y() - p11.y();
    00020     double dx2 = p22.x() - p21.x();
    00021     double dy2 = p22.y() - p21.y();
    00022
    00023     if ( dx1 == 0.0 && dx2 == 0.0 )
    00024         return QPoint();
    00025
    00026     if ( dx1 == 0.0 )
    00027     {
    00028         const double m = dy2 / dx2;
    00029         const double t = p21.y() - m * p21.x();
    00030         return QPoint(p11.x(), qRound(m * p11.x() + t));
    00031     }
    00032
    00033     if ( dx2 == 0 )
    00034     {
    00035         const double m = dy1 / dx1;
    00036         const double t = p11.y() - m * p11.x();
    00037         return QPoint(p21.x(), qRound(m * p21.x() + t));
    00038     }
    00039
    00040     const double m1 = dy1 / dx1;
    00041     const double t1 = p11.y() - m1 * p11.x();
    00042
    00043     const double m2 = dy2 / dx2;
    00044     const double t2 = p21.y() - m2 * p21.x();
    00045
    00046     if ( m1 == m2 )
    00047         return QPoint();
    00048
    00049     const double x = ( t2 - t1 ) / ( m1 - m2 );
    00050     const double y = t1 + m1 * x;
    00051
    00052     return QPoint(qRound(x), qRound(y));
    00053 }
    00054
    00061 QwtSimpleCompassRose::QwtSimpleCompassRose(int numThorns, int numThornLevels):
    00062     d_width(0.2),
    00063     d_numThorns(numThorns),
    00064     d_numThornLevels(numThornLevels),
    00065     d_shrinkFactor(0.9)
    00066 {
    00067     const QColor dark(128,128,255);
    00068     const QColor light(192,255,255);
    00069
    00070     QPalette palette;
    00071     for ( int i = 0; i < QPalette::NColorGroups; i++ )
    00072     {
    00073 #if QT_VERSION < 0x040000
    00074         palette.setColor((QPalette::ColorGroup)i,
    00075             QColorGroup::Dark, dark);
    00076         palette.setColor((QPalette::ColorGroup)i,
    00077             QColorGroup::Light, light);
    00078 #else
    00079         palette.setColor((QPalette::ColorGroup)i,
    00080             QPalette::Dark, dark);
    00081         palette.setColor((QPalette::ColorGroup)i,
    00082             QPalette::Light, light);
    00083 #endif
    00084     }
    00085
    00086     setPalette(palette);
    00087 }
    00088
    00098 void QwtSimpleCompassRose::draw(QPainter *painter, const QPoint &center,
    00099     int radius, double north, QPalette::ColorGroup cg) const
    00100 {
    00101 #if QT_VERSION < 0x040000
    00102     QColorGroup colorGroup;
    00103     switch(cg)
    00104     {
    00105         case QPalette::Disabled:
    00106             colorGroup = palette().disabled();
    00107         case QPalette::Inactive:
    00108             colorGroup = palette().inactive();
    00109         default:
    00110             colorGroup = palette().active();
    00111     }
    00112
    00113     drawRose(painter, colorGroup, center, radius, north, d_width,
    00114         d_numThorns, d_numThornLevels, d_shrinkFactor);
    00115 #else
    00116     QPalette pal = palette();
    00117     pal.setCurrentColorGroup(cg);
    00118     drawRose(painter, pal, center, radius, north, d_width,
    00119         d_numThorns, d_numThornLevels, d_shrinkFactor);
    00120 #endif
    00121 }
    00122
    00136 void QwtSimpleCompassRose::drawRose(
    00137     QPainter *painter,
    00138 #if QT_VERSION < 0x040000
    00139     const QColorGroup &cg,
    00140 #else
    00141     const QPalette &palette,
    00142 #endif
    00143     const QPoint &center, int radius, double north, double width,
    00144     int numThorns, int numThornLevels, double shrinkFactor)
    00145 {
    00146     if ( numThorns < 4 )
    00147         numThorns = 4;
    00148
    00149     if ( numThorns % 4 )
    00150         numThorns += 4 - numThorns % 4;
    00151
    00152     if ( numThornLevels <= 0 )
    00153         numThornLevels = numThorns / 4;
    00154
    00155     if ( shrinkFactor >= 1.0 )
    00156         shrinkFactor = 1.0;
    00157
    00158     if ( shrinkFactor <= 0.5 )
    00159         shrinkFactor = 0.5;
    00160
    00161     painter->save();
    00162
    00163     painter->setPen(Qt::NoPen);
    00164
    00165     for ( int j = 1; j <= numThornLevels; j++ )
    00166     {
    00167         double step =  pow(2.0, j) * M_PI / (double)numThorns;
    00168         if ( step > M_PI_2 )
    00169             break;
    00170
    00171         double r = radius;
    00172         for ( int k = 0; k < 3; k++ )
    00173         {
    00174             if ( j + k < numThornLevels )
    00175                 r *= shrinkFactor;
    00176         }
    00177
    00178         double leafWidth = r * width;
    00179         if ( 2.0 * M_PI / step > 32 )
    00180             leafWidth = 16;
    00181
    00182         const double origin = north / 180.0 * M_PI;
    00183         for ( double angle = origin;
    00184             angle < 2.0 * M_PI + origin; angle += step)
    00185         {
    00186             const QPoint p = qwtPolar2Pos(center, r, angle);
    00187             QPoint p1 = qwtPolar2Pos(center, leafWidth, angle + M_PI_2);
    00188             QPoint p2 = qwtPolar2Pos(center, leafWidth, angle - M_PI_2);
    00189
    00190             QwtPolygon pa(3);
    00191             pa.setPoint(0, center);
    00192             pa.setPoint(1, p);
    00193
    00194             QPoint p3 = qwtPolar2Pos(center, r, angle + step / 2.0);
    00195             p1 = cutPoint(center, p3, p1, p);
    00196             pa.setPoint(2, p1);
    00197 #if QT_VERSION < 0x040000
    00198             painter->setBrush(cg.brush(QColorGroup::Dark));
    00199 #else
    00200             painter->setBrush(palette.brush(QPalette::Dark));
    00201 #endif
    00202             painter->drawPolygon(pa);
    00203
    00204             QPoint p4 = qwtPolar2Pos(center, r, angle - step / 2.0);
    00205             p2 = cutPoint(center, p4, p2, p);
    00206
    00207             pa.setPoint(2, p2);
    00208 #if QT_VERSION < 0x040000
    00209             painter->setBrush(cg.brush(QColorGroup::Light));
    00210 #else
    00211             painter->setBrush(palette.brush(QPalette::Light));
    00212 #endif
    00213             painter->drawPolygon(pa);
    00214         }
    00215     }
    00216     painter->restore();
    00217 }
    00218
    00226 void QwtSimpleCompassRose::setWidth(double width)
    00227 {
    00228    d_width = width;
    00229    if (d_width < 0.03)
    00230         d_width = 0.03;
    00231
    00232    if (d_width > 0.4)
    00233         d_width = 0.4;
    00234 }
    00235
    00243 void QwtSimpleCompassRose::setNumThorns(int numThorns)
    00244 {
    00245     if ( numThorns < 4 )
    00246         numThorns = 4;
    00247
    00248     if ( numThorns % 4 )
    00249         numThorns += 4 - numThorns % 4;
    00250
    00251     d_numThorns = numThorns;
    00252 }
    00253
    00258 int QwtSimpleCompassRose::numThorns() const
    00259 {
    00260    return d_numThorns;
    00261 }
    00262
    00269 void QwtSimpleCompassRose::setNumThornLevels(int numThornLevels)
    00270 {
    00271     d_numThornLevels = numThornLevels;
    00272 }
    00273
    00278 int QwtSimpleCompassRose::numThornLevels() const
    00279 {
    00280     return d_numThornLevels;
    00281 }