~ubuntu-branches/ubuntu/breezy/koffice/breezy

« back to all changes in this revision

Viewing changes to kchart/kdchart/KDChartPolarPainter.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ben Burton
  • Date: 2004-05-09 11:33:00 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040509113300-vfrdadqsvjfuhn3b
Tags: 1:1.3.1-1
* New upstream bugfix release.
* Built against newer imagemagick (closes: #246623).
* Made koffice-libs/kformula recommend/depend on latex-xft-fonts, which
  provides mathematical fonts that the formula editor can use.  Also
  patched the kformula part to make these fonts the default.
* Changed kword menu hint from "WordProcessors" to "Word processors"
  (closes: #246209).
* Spellchecker configuration is now fixed (closes: #221256, #227568).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- Mode: C++ -*-
2
 
 
3
 
  $Id: KDChartPolarPainter.cpp,v 1.1.2.2 2001/12/09 23:04:57 khz Exp $
4
 
 
5
 
  KDChart - a multi-platform charting engine
6
 
 
7
 
  Copyright (C) 2001 by Klar�lvdalens Datakonsult AB
8
 
*/
9
 
 
 
2
   KDChart - a multi-platform charting engine
 
3
   */
 
4
 
 
5
/****************************************************************************
 
6
 ** Copyright (C) 2001-2003 Klar�lvdalens Datakonsult AB.  All rights reserved.
 
7
 **
 
8
 ** This file is part of the KDChart library.
 
9
 **
 
10
 ** This file may be distributed and/or modified under the terms of the
 
11
 ** GNU General Public License version 2 as published by the Free Software
 
12
 ** Foundation and appearing in the file LICENSE.GPL included in the
 
13
 ** packaging of this file.
 
14
 **
 
15
 ** Licensees holding valid commercial KDChart licenses may use this file in
 
16
 ** accordance with the KDChart Commercial License Agreement provided with
 
17
 ** the Software.
 
18
 **
 
19
 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
20
 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
21
 **
 
22
 ** See http://www.klaralvdalens-datakonsult.se/?page=products for
 
23
 **   information about KDChart Commercial License Agreements.
 
24
 **
 
25
 ** Contact info@klaralvdalens-datakonsult.se if any conditions of this
 
26
 ** licensing are not clear to you.
 
27
 **
 
28
 **********************************************************************/
10
29
#include "KDChartPolarPainter.h"
11
30
#include <KDChartParams.h>
12
31
#include <KDChartAxisParams.h>
15
34
 
16
35
#include <qpainter.h>
17
36
 
18
 
#ifdef __WINDOWS__
19
 
#include <math.h>
20
 
#else
21
 
#include <cmath>
22
 
#include <stdlib.h>
23
 
#endif
24
 
 
25
 
#if defined __WINDOWS__ || defined SUN7 || ( defined HP11_aCC && defined HP1100 )
26
 
#define std
27
 
#endif
28
 
 
29
 
/**
30
 
   \class KDChartPolarPainter KDChartPolarPainter.h
31
 
 
32
 
   \brief A chart painter implementation that can paint polar charts.
33
 
*/
34
 
 
35
 
/**
36
 
   Constructor. Sets up internal data structures as necessary.
37
 
 
38
 
   \param params the KDChartParams structure that defines the chart
39
 
   \param data the data that will be displayed as a chart
40
 
*/
41
 
KDChartPolarPainter::KDChartPolarPainter( KDChartParams* params ) :
42
 
  KDChartPainter( params )
 
37
/**
 
38
  \class KDChartPolarPainter KDChartPolarPainter.h
 
39
 
 
40
  \brief A chart painter implementation that can paint polar charts.
 
41
  */
 
42
 
 
43
/**
 
44
  Constructor. Sets up internal data structures as necessary.
 
45
 
 
46
  \param params the KDChartParams structure that defines the chart
 
47
  \param data the data that will be displayed as a chart
 
48
  */
 
49
    KDChartPolarPainter::KDChartPolarPainter( KDChartParams* params ) :
 
50
KDChartPainter( params )
43
51
{
44
52
    // This constructor intentionally left blank so far; we cannot setup the
45
53
    // geometry yet since we do not know the size of the painter.
47
55
 
48
56
 
49
57
/**
50
 
   Destructor.
51
 
*/
 
58
  Destructor.
 
59
  */
52
60
KDChartPolarPainter::~KDChartPolarPainter()
53
61
{
54
62
    // intentionally left blank
56
64
 
57
65
 
58
66
/**
59
 
   Paints the actual data area. Data regions will only be added if \a
60
 
   regions is not 0 and the chart is configured to be drawn with
61
 
   markers.
 
67
  Paints the actual data area. Data regions will only be added if \a
 
68
  regions is not 0 and the chart is configured to be drawn with
 
69
  markers.
62
70
 
63
 
   \param painter the QPainter onto which the chart should be painted
64
 
   \param data the data that will be displayed as a chart
65
 
   \param paint2nd specifies whether the main chart or the additional chart is to be drawn now
66
 
   \param regions a pointer to a list of regions that will be filled
67
 
   with regions representing the data segments, if not null
68
 
*/
 
71
  \param painter the QPainter onto which the chart should be painted
 
72
  \param data the data that will be displayed as a chart
 
73
  \param paint2nd specifies whether the main chart or the additional chart is to be drawn now
 
74
  \param regions a pointer to a list of regions that will be filled
 
75
  with regions representing the data segments, if not null
 
76
  */
69
77
void KDChartPolarPainter::paintData( QPainter* painter,
70
 
                                     KDChartTableData* data,
71
 
                                     bool paint2nd,
72
 
                                     KDChartDataRegionList* regions )
 
78
        KDChartTableDataBase* data,
 
79
        bool paint2nd,
 
80
        KDChartDataRegionList* regions )
73
81
{
74
82
    uint chart = paint2nd ? 1 : 0;
75
83
 
82
90
    //
83
91
 
84
92
    const QWMatrix & world = painter->worldMatrix();
85
 
    ourClipRect.moveBy( static_cast < int > ( world.dx() ),
86
 
                        static_cast < int > ( world.dy() ) );
 
93
    ourClipRect =
 
94
#if COMPAT_QT_VERSION >= 0x030000
 
95
        world.mapRect( ourClipRect );
 
96
#else
 
97
    world.map( ourClipRect );
 
98
#endif
87
99
 
88
100
    painter->setClipRect( ourClipRect );
89
101
 
90
102
 
91
103
    uint datasetStart, datasetEnd;
92
104
    if(    params()->neverUsedSetChartSourceMode()
93
 
        || !params()->findDataset( KDChartParams::DataEntry,
94
 
                                   datasetStart,
95
 
                                   datasetEnd,
96
 
                                   chart ) ) {
97
 
        uint maxRow, maxRowMinus1;
 
105
            || !params()->findDataset( KDChartParams::DataEntry,
 
106
                datasetStart,
 
107
                datasetEnd,
 
108
                chart ) ) {
 
109
        int maxRow, maxRowMinus1;
98
110
        switch ( data->usedRows() ) {
99
 
        case 0:
100
 
            return ;
101
 
        case 1:
102
 
            maxRow = 0;
103
 
            maxRowMinus1 = 0;
104
 
            break;
105
 
        default:
106
 
            maxRow = data->usedRows() - 1;
107
 
            maxRowMinus1 = maxRow - 1;
 
111
            case 0:
 
112
                return ;
 
113
            case 1:
 
114
                maxRow = 0;
 
115
                maxRowMinus1 = 0;
 
116
                break;
 
117
            default:
 
118
                maxRow = data->usedRows() - 1;
 
119
                maxRowMinus1 = maxRow - 1;
108
120
        }
109
121
        datasetStart = paint2nd ? maxRow
110
 
                       : 0;
 
122
            : 0;
111
123
        datasetEnd = paint2nd ? maxRow
112
 
                     : ( ( KDChartParams::NoType
113
 
                           == params()->additionalChartType() )
114
 
                         ? maxRow
115
 
                         : maxRowMinus1 );
 
124
            : ( ( KDChartParams::NoType
 
125
                        == params()->additionalChartType() )
 
126
                    ? maxRow
 
127
                    : maxRowMinus1 );
116
128
    }
117
129
 
118
130
 
137
149
    QRect position( x, y, size, size );
138
150
 
139
151
    QPoint center( position.width() / 2 + position.x(),
140
 
                   position.height() / 2 + position.y() );
 
152
            position.height() / 2 + position.y() );
141
153
 
142
154
 
143
155
    double maxValue;
144
156
    switch ( params()->polarChartSubType() ) {
145
 
    case KDChartParams::PolarNormal:
146
 
        maxValue = data->maxValue();
147
 
        break;
148
 
    case KDChartParams::PolarPercent:
149
 
        maxValue = 100.0;
150
 
        break;
151
 
    default:
152
 
        maxValue = QMAX( data->maxColSum(), 0.0 );
 
157
        case KDChartParams::PolarNormal:
 
158
            maxValue = data->maxValue();
 
159
            break;
 
160
        case KDChartParams::PolarPercent:
 
161
            maxValue = 100.0;
 
162
            break;
 
163
        default:
 
164
            maxValue = QMAX( data->maxColSum(), 0.0 );
153
165
    }
154
166
 
155
167
    double pixelsPerUnit = 0.0;
159
171
 
160
172
    QMap < int, double > currentValueSums;
161
173
    if (    params()->polarChartSubType() == KDChartParams::PolarStacked
162
 
         || params()->polarChartSubType() == KDChartParams::PolarPercent )
 
174
            || params()->polarChartSubType() == KDChartParams::PolarPercent )
163
175
        // this array is only used for stacked and percent polar
164
176
        // charts, no need to waste time initializing it for normal
165
177
        // ones
169
181
 
170
182
 
171
183
    /*
172
 
        axes schema: use AxisPosSaggital for saggital 'axis' lines
173
 
                     use AxisPosCircular for circular 'axis'
174
 
    */
175
 
    const KDChartAxisParams & paraSaggital = params()->axisParams( KDChartAxisParams::AxisPosSaggital );
 
184
       axes schema: use AxisPosSagittal for sagittal 'axis' lines
 
185
       use AxisPosCircular for circular 'axis'
 
186
       */
 
187
    const KDChartAxisParams & paraSagittal = params()->axisParams( KDChartAxisParams::AxisPosSagittal );
176
188
    const KDChartAxisParams & paraCircular = params()->axisParams( KDChartAxisParams::AxisPosCircular );
177
189
 
178
 
    uint saggitalLineWidth = 0 <= paraSaggital.axisLineWidth()
179
 
                         ? paraSaggital.axisLineWidth()
180
 
                         : -1 * static_cast < int > (   paraSaggital.axisLineWidth()
181
 
                                                      * minSizeP1000 );
182
 
    ( ( KDChartAxisParams& ) paraSaggital ).setAxisTrueLineWidth( saggitalLineWidth );
183
 
    uint saggitalGridLineWidth
 
190
    int sagittalLineWidth = 0 <= paraSagittal.axisLineWidth()
 
191
        ? paraSagittal.axisLineWidth()
 
192
        : -1 * static_cast < int > (   paraSagittal.axisLineWidth()
 
193
                * minSizeP1000 );
 
194
    ( ( KDChartAxisParams& ) paraSagittal ).setAxisTrueLineWidth( sagittalLineWidth );
 
195
    int sagittalGridLineWidth
184
196
        = (    KDChartAxisParams::AXIS_GRID_AUTO_LINEWIDTH
185
 
            == paraSaggital.axisGridLineWidth() )
186
 
        ? saggitalLineWidth
187
 
        : (   ( 0 <= paraSaggital.axisGridLineWidth() )
188
 
            ? paraSaggital.axisGridLineWidth()
189
 
            : -1 * static_cast < int > (   paraSaggital.axisGridLineWidth()
190
 
                                         * minSizeP1000 ) );
 
197
                == paraSagittal.axisGridLineWidth() )
 
198
        ? sagittalLineWidth
 
199
        : (   ( 0 <= paraSagittal.axisGridLineWidth() )
 
200
                ? paraSagittal.axisGridLineWidth()
 
201
                : -1 * static_cast < int > (   paraSagittal.axisGridLineWidth()
 
202
                    * minSizeP1000 ) );
191
203
 
192
 
    uint circularLineWidth = 0 <= paraCircular.axisLineWidth()
193
 
                           ? paraCircular.axisLineWidth()
194
 
                           : -1 * static_cast < int > (   paraCircular.axisLineWidth()
195
 
                                                        * minSizeP1000 );
 
204
    int circularLineWidth = 0 <= paraCircular.axisLineWidth()
 
205
        ? paraCircular.axisLineWidth()
 
206
        : -1 * static_cast < int > (   paraCircular.axisLineWidth()
 
207
                * minSizeP1000 );
196
208
    ( ( KDChartAxisParams& ) paraCircular ).setAxisTrueLineWidth( circularLineWidth );
197
 
    uint circularGridLineWidth
 
209
    int circularGridLineWidth
198
210
        = (    KDChartAxisParams::AXIS_GRID_AUTO_LINEWIDTH
199
 
            == paraCircular.axisGridLineWidth() )
 
211
                == paraCircular.axisGridLineWidth() )
200
212
        ? circularLineWidth
201
213
        : (   ( 0 <= paraCircular.axisGridLineWidth() )
202
 
            ? paraCircular.axisGridLineWidth()
203
 
            : -1 * static_cast < int > (   paraCircular.axisGridLineWidth()
204
 
                                         * minSizeP1000 ) );
 
214
                ? paraCircular.axisGridLineWidth()
 
215
                : -1 * static_cast < int > (   paraCircular.axisGridLineWidth()
 
216
                    * minSizeP1000 ) );
205
217
 
206
218
    QFont actFont;
207
219
    int labels = 0;
209
221
 
210
222
    // draw the "axis" circles
211
223
    if( paraCircular.axisShowGrid()
212
 
        || paraCircular.axisVisible()
213
 
        || paraCircular.axisLabelsVisible() ) {
 
224
            || paraCircular.axisVisible()
 
225
            || paraCircular.axisLabelsVisible() ) {
214
226
 
215
227
        double radiusPPU = maxValue * pixelsPerUnit;
216
228
        double pDelimDelta = 0.0;
218
230
        // calculate label texts
219
231
        QStringList* labelTexts = 0;
220
232
        ((KDChartParams*)params())->setAxisArea( KDChartAxisParams::AxisPosCircular,
221
 
                            QRect( 0,
222
 
                                0,
223
 
                                radiusPPU,
224
 
                                radiusPPU ) );
 
233
                                                 QRect( 0,
 
234
                                                     0,
 
235
                                                     static_cast<int>( radiusPPU ),
 
236
                                                     static_cast<int>( radiusPPU ) ) );
225
237
 
226
238
        double delimLen = 20.0 * minSizeP1000; // per mille of area
227
239
        KDChartAxisParams::AxisPos basicPos;
228
240
        QPoint orig, dest;
229
 
        KDChartAxesPainter::findInfos( minSizeP1000,
230
 
                                    paraCircular,
231
 
                                    KDChartAxisParams::AxisPosCircular,
232
 
                                    basicPos,
233
 
                                    orig,
234
 
                                    dest );
 
241
        double dDummy;
235
242
        double nSubDelimFactor = 0.0;
236
243
        double nTxtHeight = 0.0;
237
244
        double pTextsX = 0.0;
239
246
        double pTextsW = 0.0;
240
247
        double pTextsH = 0.0;
241
248
        int textAlign = Qt::AlignHCenter | Qt::AlignVCenter;
242
 
        KDChartAxesPainter::calculateLabelTexts( *painter,
243
 
                                                *data,
244
 
                                                *params(),
245
 
                                                KDChartAxisParams::AxisPosCircular,
246
 
                                                minSizeP1000,
247
 
                                                basicPos,
248
 
                                                orig,
249
 
                                                delimLen,
250
 
                                                // start of reference parameters
251
 
                                                nSubDelimFactor,
252
 
                                                pDelimDelta,
253
 
                                                nTxtHeight,
254
 
                                                pTextsX,
255
 
                                                pTextsY,
256
 
                                                pTextsW,
257
 
                                                pTextsH,
258
 
                                                textAlign );
259
 
        labelTexts = ( QStringList* ) paraCircular.axisLabelTexts();
260
 
        if( paraCircular.axisLabelsVisible() ) {
261
 
            // calculate font size
262
 
            actFont = paraCircular.axisLabelsFont();
263
 
            if ( paraCircular.axisLabelsFontUseRelSize() ) {
264
 
                actFont.setPointSizeFloat( nTxtHeight );
265
 
            }
266
 
            QFontMetrics fm( actFont );
267
 
            QString strMax;
268
 
            int maxLabelsWidth = 0;
269
 
            for ( QStringList::Iterator it = labelTexts->begin();
270
 
                    it != labelTexts->end();
271
 
                    ++it ) {
272
 
                if ( fm.width( *it ) > maxLabelsWidth ) {
273
 
                    maxLabelsWidth = fm.width( *it );
274
 
                    strMax = *it;
275
 
                }
276
 
            }
277
 
            while ( fm.width( strMax ) > pTextsW
278
 
                    && 6.0 < nTxtHeight ) {
279
 
                nTxtHeight -= 0.5;
280
 
                actFont.setPointSizeFloat( nTxtHeight );
281
 
                fm = QFontMetrics( actFont );
282
 
            }
283
 
            painter->setFont( actFont );
284
 
        }
285
 
 
286
 
        double radiusDelta = pDelimDelta;
287
 
 
288
 
        labels = labelTexts
289
 
               ? labelTexts->count()
290
 
               : 0;
291
 
        if( labels )
292
 
            currentRadiusPPU = -radiusDelta;
293
 
        for( int iLabel = 0; iLabel < labels; ++iLabel ) {
294
 
//while( currentRadius < maxValue ) {
295
 
//double currentRadiusPPU = currentRadius;
296
 
            currentRadiusPPU += radiusDelta;
297
 
            double currentRadiusPPU2 = currentRadiusPPU * 2;
298
 
            int circularAxisAngle = static_cast < int > (4.0 * radiusPPU / currentRadiusPPU);
299
 
            if( paraCircular.axisShowGrid() ) {
300
 
                painter->setPen( QPen( paraCircular.axisGridColor(),
301
 
                                       circularGridLineWidth ) );
302
 
                painter->drawEllipse( center.x() - currentRadiusPPU,
303
 
                            center.y() - currentRadiusPPU,
304
 
                            currentRadiusPPU2, currentRadiusPPU2 );
305
 
            }
306
 
            if( paraCircular.axisVisible() ) {
307
 
                painter->setPen( QPen( paraCircular.axisLineColor(),
308
 
                                       circularLineWidth ) );
309
 
                if( params()->polarDelimAtPos( KDChartEnums::PosTopCenter ) )
310
 
                    painter->drawArc( center.x() - currentRadiusPPU,
311
 
                                      center.y() - currentRadiusPPU,
312
 
                                      currentRadiusPPU2, currentRadiusPPU2,
313
 
                                      (90 - circularAxisAngle/2) * 16,
314
 
                                      circularAxisAngle * 16 );
315
 
                if( params()->polarDelimAtPos( KDChartEnums::PosBottomCenter ) )
316
 
                    painter->drawArc( center.x() - currentRadiusPPU,
317
 
                                      center.y() - currentRadiusPPU,
318
 
                                      currentRadiusPPU2, currentRadiusPPU2,
319
 
                                      (270 - circularAxisAngle/2) * 16,
320
 
                                      circularAxisAngle * 16 );
321
 
 
322
 
                if( params()->polarDelimAtPos( KDChartEnums::PosCenterRight ) )
323
 
                    painter->drawArc( center.x() - currentRadiusPPU,
324
 
                                      center.y() - currentRadiusPPU,
325
 
                                      currentRadiusPPU2, currentRadiusPPU2,
326
 
                                      (0 - circularAxisAngle/2) * 16,
327
 
                                      circularAxisAngle * 16 );
328
 
                if( params()->polarDelimAtPos( KDChartEnums::PosCenterLeft ) )
329
 
                    painter->drawArc( center.x() - currentRadiusPPU,
330
 
                                      center.y() - currentRadiusPPU,
331
 
                                      currentRadiusPPU2, currentRadiusPPU2,
332
 
                                      (180 - circularAxisAngle/2) * 16,
333
 
                                      circularAxisAngle * 16 );
334
 
 
335
 
                if( params()->polarDelimAtPos( KDChartEnums::PosTopRight ) )
336
 
                    painter->drawArc( center.x() - currentRadiusPPU,
337
 
                                      center.y() - currentRadiusPPU,
338
 
                                      currentRadiusPPU2, currentRadiusPPU2,
339
 
                                      (45 - circularAxisAngle/2) * 16,
340
 
                                      circularAxisAngle * 16 );
341
 
                if( params()->polarDelimAtPos( KDChartEnums::PosBottomLeft ) )
342
 
                    painter->drawArc( center.x() - currentRadiusPPU,
343
 
                                      center.y() - currentRadiusPPU,
344
 
                                      currentRadiusPPU2, currentRadiusPPU2,
345
 
                                      (225 - circularAxisAngle/2) * 16,
346
 
                                      circularAxisAngle * 16 );
347
 
 
348
 
                if( params()->polarDelimAtPos( KDChartEnums::PosBottomRight ) )
349
 
                    painter->drawArc( center.x() - currentRadiusPPU,
350
 
                                      center.y() - currentRadiusPPU,
351
 
                                      currentRadiusPPU2, currentRadiusPPU2,
352
 
                                      (315 - circularAxisAngle/2) * 16,
353
 
                                      circularAxisAngle * 16 );
354
 
                if( params()->polarDelimAtPos( KDChartEnums::PosTopLeft ) )
355
 
                    painter->drawArc( center.x() - currentRadiusPPU,
356
 
                                      center.y() - currentRadiusPPU,
357
 
                                      currentRadiusPPU2, currentRadiusPPU2,
358
 
                                      (135 - circularAxisAngle/2) * 16,
359
 
                                      circularAxisAngle * 16 );
360
 
            }
361
 
            if( paraCircular.axisLabelsVisible() ) {
362
 
                const bool rotate = params()->polarRotateCircularLabels();
363
 
                QPoint shiftCenter = center + _dataRect.topLeft();
364
 
                painter->setPen( QPen( paraCircular.axisLabelsColor(),
365
 
                                       circularLineWidth ) );
366
 
                const QString& txt = (*labelTexts)[ iLabel ];
367
 
                if( params()->polarLabelsAtPos( KDChartEnums::PosTopCenter ) )
368
 
                    paintCircularAxisLabel( painter, rotate, 90, shiftCenter, currentRadiusPPU, txt,
369
 
                                            Qt::AlignBottom | Qt::AlignHCenter, iLabel );
370
 
 
371
 
                if( params()->polarLabelsAtPos( KDChartEnums::PosBottomCenter ) )
372
 
                    paintCircularAxisLabel( painter, rotate, 270, shiftCenter, currentRadiusPPU, txt,
373
 
                                            Qt::AlignTop | Qt::AlignHCenter, iLabel );
374
 
 
375
 
                if( params()->polarLabelsAtPos( KDChartEnums::PosCenterRight ) )
376
 
                    paintCircularAxisLabel( painter, rotate,   0, shiftCenter, currentRadiusPPU, txt,
377
 
                                            Qt::AlignVCenter | Qt::AlignRight, iLabel );
378
 
 
379
 
                if( params()->polarLabelsAtPos( KDChartEnums::PosCenterLeft ) )
380
 
                    paintCircularAxisLabel( painter, rotate, 180, shiftCenter, currentRadiusPPU, txt,
381
 
                                            Qt::AlignVCenter | Qt::AlignLeft, iLabel );
382
 
 
383
 
                if( params()->polarLabelsAtPos( KDChartEnums::PosTopRight ) )
384
 
                    paintCircularAxisLabel( painter, rotate,  45, shiftCenter, currentRadiusPPU, txt,
385
 
                                            Qt::AlignBottom | Qt::AlignRight, iLabel );
386
 
 
387
 
                if( params()->polarLabelsAtPos( KDChartEnums::PosBottomLeft ) )
388
 
                    paintCircularAxisLabel( painter, rotate, 225, shiftCenter, currentRadiusPPU, txt,
389
 
                                            Qt::AlignTop | Qt::AlignLeft, iLabel );
390
 
 
391
 
                if( params()->polarLabelsAtPos( KDChartEnums::PosBottomRight ) )
392
 
                    paintCircularAxisLabel( painter, rotate, 315, shiftCenter, currentRadiusPPU, txt,
393
 
                                            Qt::AlignTop | Qt::AlignRight, iLabel );
394
 
 
395
 
                if( params()->polarLabelsAtPos( KDChartEnums::PosTopLeft ) )
396
 
                    paintCircularAxisLabel( painter, rotate, 135, shiftCenter, currentRadiusPPU, txt,
397
 
                                            Qt::AlignBottom | Qt::AlignLeft, iLabel );
398
 
            }
399
 
        }
400
 
    }
401
 
 
402
 
 
403
 
    double circularSpan = params()->polarChartSubType() == KDChartParams::PolarPercent
404
 
                        ? 100.0
405
 
                        : paraCircular.trueAxisHigh() - paraCircular.trueAxisLow();
406
 
    double radius = currentRadiusPPU;
407
 
    if(    !labels
408
 
        || params()->polarChartSubType() == KDChartParams::PolarPercent )
409
 
        radius = (position.width() / 2.0) * 1000.0 / 1250.0;
410
 
 
411
 
    if( params()->polarChartSubType() != KDChartParams::PolarPercent )
412
 
        pixelsPerUnit = labels ? currentRadiusPPU / circularSpan
413
 
                               : (position.height() / maxValue / 2.0) * 1000.0 / 1250.0;
414
 
    else
415
 
        pixelsPerUnit = (position.height() / 100.0 / 2.0) * 1000.0 / 1250.0;
416
 
 
417
 
    // draw the saggital grid and axis lines
418
 
    if(    paraSaggital.axisShowGrid()
419
 
        || paraSaggital.axisVisible()
420
 
        || paraSaggital.axisLabelsVisible() ) {
421
 
 
422
 
        // calculate label texts
423
 
        QStringList* labelTexts = 0;
424
 
        bool onlyDefaultLabels = true;
425
 
        if( paraSaggital.axisLabelsVisible() ) {
426
 
            ((KDChartParams*)params())->setAxisArea( KDChartAxisParams::AxisPosSaggital,
427
 
                                                     QRect( 0,
428
 
                                                            0,
429
 
                                                            static_cast < int > ( 2.0 * M_PI * radius ),
430
 
                                                            static_cast < int > ( 0.5 * radius ) ) );
431
 
            double delimLen = 20.0 * minSizeP1000; // per mille of area
432
 
            KDChartAxisParams::AxisPos basicPos;
433
 
            QPoint orig, dest;
434
 
            KDChartAxesPainter::findInfos( minSizeP1000,
435
 
                                           paraSaggital,
436
 
                                           KDChartAxisParams::AxisPosSaggital,
437
 
                                           basicPos,
438
 
                                           orig,
439
 
                                           dest );
440
 
            double nSubDelimFactor = 0.0;
441
 
            double pDelimDelta = 0.0;
442
 
            double nTxtHeight = 0.0;
443
 
            double pTextsX = 0.0;
444
 
            double pTextsY = 0.0;
445
 
            double pTextsW = 0.0;
446
 
            double pTextsH = 0.0;
447
 
            int textAlign = Qt::AlignCenter;
448
 
            KDChartAxesPainter::calculateLabelTexts( *painter,
449
 
                                                    *data,
450
 
                                                    *params(),
451
 
                                                    KDChartAxisParams::AxisPosSaggital,
452
 
                                                    minSizeP1000,
453
 
                                                    basicPos,
454
 
                                                    orig,
455
 
                                                    delimLen,
456
 
                                                    // start of reference parameters
457
 
                                                    nSubDelimFactor,
458
 
                                                    pDelimDelta,
459
 
                                                    nTxtHeight,
460
 
                                                    pTextsX,
461
 
                                                    pTextsY,
462
 
                                                    pTextsW,
463
 
                                                    pTextsH,
464
 
                                                    textAlign );
465
 
            labelTexts = ( QStringList* ) paraSaggital.axisLabelTexts();
466
 
            // calculate font size
467
 
            actFont = paraSaggital.axisLabelsFont();
468
 
            if ( paraSaggital.axisLabelsFontUseRelSize() ) {
469
 
                actFont.setPointSizeFloat( nTxtHeight );
470
 
            }
471
 
            QFontMetrics fm( actFont );
472
 
            QString strMax;
473
 
            int maxLabelsWidth = 0;
474
 
            for ( QStringList::Iterator it = labelTexts->begin();
475
 
                    it != labelTexts->end();
476
 
                    ++it ) {
477
 
                if ( fm.width( *it ) > maxLabelsWidth ) {
478
 
                    maxLabelsWidth = fm.width( *it );
479
 
                    strMax = *it;
480
 
                }
481
 
                if ( !(*it).startsWith( "Item ") )
482
 
                    onlyDefaultLabels = false;
483
 
            }
484
 
            while ( fm.width( strMax ) > pTextsW && 6.0 < nTxtHeight ) {
485
 
                nTxtHeight -= 0.5;
486
 
                actFont.setPointSizeFloat( nTxtHeight );
487
 
                fm = QFontMetrics( actFont );
488
 
            }
489
 
            painter->setFont( actFont );
490
 
        }
491
 
 
492
 
        int currentAngle = params()->polarZeroDegreePos();
493
 
        if(    -360 > currentAngle
494
 
            ||  360 < currentAngle )
495
 
            currentAngle = 0;
496
 
        if( 0 > currentAngle )
497
 
            currentAngle += 360;
498
 
        int r1 = static_cast < int > ( radius * 1050 / 1000 );
499
 
        int r2 = static_cast < int > ( radius * 1100 / 1000 );
500
 
        int r3 = static_cast < int > ( radius * 1175 / 1000 );
501
 
        QPoint pt1, pt2, pt3;
502
 
        uint nLabels = labelTexts->count();
503
 
        int angleBetweenRays = 360 / nLabels;
504
 
        for( uint value = 0; value < nLabels; ++value ) {
505
 
            pt1 = center + polarToXY( r1, currentAngle );
506
 
            pt2 = center + polarToXY( r2, currentAngle );
507
 
            pt3 = center + polarToXY( r3, currentAngle );
508
 
            if( paraSaggital.axisShowGrid() ) {
509
 
                painter->setPen( QPen( paraSaggital.axisGridColor(),
510
 
                                       saggitalGridLineWidth ) );
511
 
                painter->drawLine( center, pt1 );
512
 
            }
513
 
            if( paraSaggital.axisVisible() ) {
514
 
                painter->setPen( QPen( paraSaggital.axisLineColor(),
515
 
                                       saggitalLineWidth ) );
516
 
                painter->drawLine( pt1, pt2 );
517
 
            }
518
 
            if(    paraSaggital.axisLabelsVisible()
519
 
                && labelTexts
520
 
                && labelTexts->count() > value ) {
521
 
                painter->setPen( QPen( paraSaggital.axisLabelsColor(),
522
 
                                       saggitalLineWidth ) );
523
 
                QString label(   onlyDefaultLabels
524
 
                               ? QString::number( currentAngle )
525
 
                               : (*labelTexts)[ value ] );
526
 
 
527
 
                KDDrawText::drawRotatedText( painter,
528
 
                                             currentAngle+90,
529
 
                                             pt3 + _dataRect.topLeft(),
530
 
                                             label,
531
 
                                             0,
532
 
                                             Qt::AlignCenter );
533
 
            }
534
 
            currentAngle += angleBetweenRays;
535
 
        }
536
 
    }
537
 
 
538
 
 
539
 
    // Now draw the data
540
 
    int dataLinesWidth = 0 <= params()->polarLineWidth()
541
 
                         ? params()->polarLineWidth()
542
 
                         : -1 * static_cast < int > (   params()->polarLineWidth()
543
 
                                                      * minSizeP1000 );
544
 
    painter->setBrush( Qt::NoBrush );
545
 
    for ( int dataset = datasetStart; dataset <= datasetEnd; dataset++ ) {
546
 
        painter->setPen( QPen( params()->dataColor( dataset ),
547
 
                         dataLinesWidth ) );
548
 
        QPointArray points( numValues );
549
 
        int totalPoints = 0;
550
 
        double valueTotal = 0.0; // Will only be used for Percent
551
 
        int angleBetweenRays = 360 / numValues;
552
 
        for ( uint value = 0; value < numValues; value++ ) {
553
 
            if( params()->polarChartSubType() == KDChartParams::PolarPercent )
554
 
                valueTotal = data->colAbsSum( value );
555
 
            // the value determines the angle, the dataset only the color
556
 
            if ( data->cell( dataset, value ).isDouble() ) {
557
 
                double cellValue = data->cell( dataset, value ).doubleValue();
558
 
                double drawValue;
559
 
                if ( params()->polarChartSubType() == KDChartParams::PolarStacked )
560
 
                    drawValue = ( cellValue + currentValueSums[ value ] ) * pixelsPerUnit;
561
 
                else if( params()->polarChartSubType() == KDChartParams::PolarPercent ) {
562
 
                    drawValue = (   ( cellValue + currentValueSums[ value ] )
563
 
                                    / valueTotal * static_cast<double>( radius ) );
564
 
                } else
565
 
                    drawValue = cellValue * pixelsPerUnit;
566
 
 
567
 
                // record the point for drawing the polygon later
568
 
                int drawAngle = value * angleBetweenRays;
569
 
                QPoint drawPoint( center + polarToXY( static_cast<int>( drawValue ),
570
 
                                                      drawAngle ) );
571
 
                points.setPoint( totalPoints, drawPoint );
572
 
                totalPoints++;
573
 
                QRegion region;
574
 
                // the marker can be drawn now
575
 
                if( params()->polarMarker() ) {
576
 
                    drawMarker( painter, params()->polarMarkerStyle( dataset ),
577
 
                                params()->dataColor( dataset ),
578
 
                                drawPoint,
579
 
                                dataset, value, chart, minSizeP1000, region );
 
249
        bool isLogarithmic = false; // value not used for KD Chart 1.0.0
 
250
        bool isDateTime = false;
 
251
        bool autoDtLabels = false;
 
252
        QDateTime dtLow;
 
253
        QDateTime dtHigh;
 
254
        KDChartAxisParams::ValueScale dtDeltaScale;
 
255
        KDChartAxesPainter::calculateLabelTexts( *data,
 
256
                *params(),
 
257
                KDChartAxisParams::AxisPosCircular,
 
258
                minSizeP1000,
 
259
                delimLen,
 
260
                // start of reference parameters
 
261
                basicPos,
 
262
                orig,
 
263
                dest,
 
264
                dDummy,dDummy,dDummy,dDummy,
 
265
                nSubDelimFactor,
 
266
                pDelimDelta,
 
267
                nTxtHeight,
 
268
                pTextsX,
 
269
                pTextsY,
 
270
                pTextsW,
 
271
                pTextsH,
 
272
                textAlign,
 
273
                isLogarithmic,
 
274
                isDateTime,
 
275
                autoDtLabels,
 
276
                dtLow,
 
277
                dtHigh,
 
278
                dtDeltaScale );
 
279
                labelTexts = ( QStringList* ) paraCircular.axisLabelTexts();
 
280
                if( paraCircular.axisLabelsVisible() ) {
 
281
//qDebug("\nnTxtHeight: "+QString::number(nTxtHeight));
 
282
                    // calculate font size
 
283
                    actFont = paraCircular.axisLabelsFont();
 
284
                    if ( paraCircular.axisLabelsFontUseRelSize() ) {
 
285
//qDebug("paraCircular.axisLabelsFontUseRelSize() is TRUE");
 
286
                        actFont.setPointSizeFloat( nTxtHeight );
 
287
                    }
 
288
                    QFontMetrics fm( actFont );
 
289
                    QString strMax;
 
290
                    int maxLabelsWidth = 0;
 
291
                    for ( QStringList::Iterator it = labelTexts->begin();
 
292
                            it != labelTexts->end();
 
293
                            ++it ) {
 
294
                        if ( fm.width( *it ) > maxLabelsWidth ) {
 
295
                            maxLabelsWidth = fm.width( *it );
 
296
                            strMax = *it;
 
297
                        }
 
298
                    }
 
299
                    while ( fm.width( strMax ) > pTextsW
 
300
                            && 6.0 < nTxtHeight ) {
 
301
                        nTxtHeight -= 0.5;
 
302
                        actFont.setPointSizeFloat( nTxtHeight );
 
303
                        fm = QFontMetrics( actFont );
 
304
                    }
 
305
                    painter->setFont( actFont );
 
306
                }
 
307
 
 
308
                double radiusDelta = pDelimDelta;
 
309
 
 
310
                labels = labelTexts
 
311
                    ? labelTexts->count()
 
312
                    : 0;
 
313
                if( labels )
 
314
                    currentRadiusPPU = -radiusDelta;
 
315
                for( int iLabel = 0; iLabel < labels; ++iLabel ) {
 
316
                    //while( currentRadius < maxValue ) {
 
317
                    //double currentRadiusPPU = currentRadius;
 
318
                    currentRadiusPPU += radiusDelta;
 
319
                    double currentRadiusPPU2 = currentRadiusPPU * 2;
 
320
                    int circularAxisAngle = ( currentRadiusPPU != 0.0 ) ? ( static_cast < int > (4.0 * radiusPPU / currentRadiusPPU) ) : 0;
 
321
                    if( paraCircular.axisShowGrid() ) {
 
322
                        painter->setPen( QPen( paraCircular.axisGridColor(),
 
323
                                    circularGridLineWidth ) );
 
324
                        painter->drawEllipse( static_cast<int>( center.x() - currentRadiusPPU ),
 
325
                                static_cast<int>( center.y() - currentRadiusPPU ),
 
326
                                static_cast<int>( currentRadiusPPU2 ), static_cast<int>( currentRadiusPPU2 ) );
 
327
                    }
 
328
                    if( paraCircular.axisVisible() ) {
 
329
                        painter->setPen( QPen( paraCircular.axisLineColor(),
 
330
                                    circularLineWidth ) );
 
331
                        if( params()->polarDelimAtPos( KDChartEnums::PosTopCenter ) )
 
332
                            painter->drawArc( static_cast<int>( center.x() - currentRadiusPPU ),
 
333
                                    static_cast<int>( center.y() - currentRadiusPPU ),
 
334
                                    static_cast<int>( currentRadiusPPU2 ), static_cast<int>( currentRadiusPPU2 ),
 
335
                                    (90 - circularAxisAngle/2) * 16,
 
336
                                    circularAxisAngle * 16 );
 
337
                        if( params()->polarDelimAtPos( KDChartEnums::PosBottomCenter ) )
 
338
                            painter->drawArc( static_cast<int>( center.x() - currentRadiusPPU ),
 
339
                                    static_cast<int>( center.y() - currentRadiusPPU ),
 
340
                                    static_cast<int>( currentRadiusPPU2 ), static_cast<int>( currentRadiusPPU2 ),
 
341
                                    (270 - circularAxisAngle/2) * 16,
 
342
                                    circularAxisAngle * 16 );
 
343
 
 
344
                        if( params()->polarDelimAtPos( KDChartEnums::PosCenterRight ) )
 
345
                            painter->drawArc( static_cast<int>( center.x() - currentRadiusPPU ),
 
346
                                    static_cast<int>( center.y() - currentRadiusPPU ),
 
347
                                    static_cast<int>( currentRadiusPPU2 ), static_cast<int>( currentRadiusPPU2 ),
 
348
                                    (0 - circularAxisAngle/2) * 16,
 
349
                                    circularAxisAngle * 16 );
 
350
                        if( params()->polarDelimAtPos( KDChartEnums::PosCenterLeft ) )
 
351
                            painter->drawArc( static_cast<int>( center.x() - currentRadiusPPU ),
 
352
                                    static_cast<int>( center.y() - currentRadiusPPU ),
 
353
                                    static_cast<int>( currentRadiusPPU2 ), static_cast<int>( currentRadiusPPU2 ),
 
354
                                    (180 - circularAxisAngle/2) * 16,
 
355
                                    circularAxisAngle * 16 );
 
356
 
 
357
                        if( params()->polarDelimAtPos( KDChartEnums::PosTopRight ) )
 
358
                            painter->drawArc( static_cast<int>( center.x() - currentRadiusPPU ),
 
359
                                    static_cast<int>( center.y() - currentRadiusPPU ),
 
360
                                    static_cast<int>( currentRadiusPPU2 ), static_cast<int>( currentRadiusPPU2 ),
 
361
                                    (45 - circularAxisAngle/2) * 16,
 
362
                                    circularAxisAngle * 16 );
 
363
                        if( params()->polarDelimAtPos( KDChartEnums::PosBottomLeft ) )
 
364
                            painter->drawArc( static_cast<int>( center.x() - currentRadiusPPU ),
 
365
                                    static_cast<int>( center.y() - currentRadiusPPU ),
 
366
                                    static_cast<int>( currentRadiusPPU2 ), static_cast<int>( currentRadiusPPU2 ),
 
367
                                    (225 - circularAxisAngle/2) * 16,
 
368
                                    circularAxisAngle * 16 );
 
369
 
 
370
                        if( params()->polarDelimAtPos( KDChartEnums::PosBottomRight ) )
 
371
                            painter->drawArc( static_cast<int>( center.x() - currentRadiusPPU ),
 
372
                                    static_cast<int>( center.y() - currentRadiusPPU ),
 
373
                                    static_cast<int>( currentRadiusPPU2 ), static_cast<int>( currentRadiusPPU2 ),
 
374
                                    (315 - circularAxisAngle/2) * 16,
 
375
                                    circularAxisAngle * 16 );
 
376
                        if( params()->polarDelimAtPos( KDChartEnums::PosTopLeft ) )
 
377
                            painter->drawArc( static_cast<int>( center.x() - currentRadiusPPU ),
 
378
                                    static_cast<int>( center.y() - currentRadiusPPU ),
 
379
                                    static_cast<int>( currentRadiusPPU2 ), static_cast<int>( currentRadiusPPU2 ),
 
380
                                    (135 - circularAxisAngle/2) * 16,
 
381
                                    circularAxisAngle * 16 );
 
382
                    }
 
383
                    if( paraCircular.axisLabelsVisible() ) {
 
384
                        const bool rotate = params()->polarRotateCircularLabels();
 
385
                        QPoint shiftCenter = center + _dataRect.topLeft();
 
386
                        painter->setPen( QPen( paraCircular.axisLabelsColor(),
 
387
                                    circularLineWidth ) );
 
388
                        const QString& txt = (*labelTexts)[ iLabel ];
 
389
                        if( params()->polarLabelsAtPos( KDChartEnums::PosTopCenter ) )
 
390
                            paintCircularAxisLabel( painter, rotate, 90, shiftCenter, currentRadiusPPU, txt,
 
391
                                    Qt::AlignBottom | Qt::AlignHCenter, iLabel );
 
392
 
 
393
                        if( params()->polarLabelsAtPos( KDChartEnums::PosBottomCenter ) )
 
394
                            paintCircularAxisLabel( painter, rotate, 270, shiftCenter, currentRadiusPPU, txt,
 
395
                                    Qt::AlignTop | Qt::AlignHCenter, iLabel );
 
396
 
 
397
                        if( params()->polarLabelsAtPos( KDChartEnums::PosCenterRight ) )
 
398
                            paintCircularAxisLabel( painter, rotate,   0, shiftCenter, currentRadiusPPU, txt,
 
399
                                    Qt::AlignVCenter | Qt::AlignRight, iLabel );
 
400
 
 
401
                        if( params()->polarLabelsAtPos( KDChartEnums::PosCenterLeft ) )
 
402
                            paintCircularAxisLabel( painter, rotate, 180, shiftCenter, currentRadiusPPU, txt,
 
403
                                    Qt::AlignVCenter | Qt::AlignLeft, iLabel );
 
404
 
 
405
                        if( params()->polarLabelsAtPos( KDChartEnums::PosTopRight ) )
 
406
                            paintCircularAxisLabel( painter, rotate,  45, shiftCenter, currentRadiusPPU, txt,
 
407
                                    Qt::AlignBottom | Qt::AlignRight, iLabel );
 
408
 
 
409
                        if( params()->polarLabelsAtPos( KDChartEnums::PosBottomLeft ) )
 
410
                            paintCircularAxisLabel( painter, rotate, 225, shiftCenter, currentRadiusPPU, txt,
 
411
                                    Qt::AlignTop | Qt::AlignLeft, iLabel );
 
412
 
 
413
                        if( params()->polarLabelsAtPos( KDChartEnums::PosBottomRight ) )
 
414
                            paintCircularAxisLabel( painter, rotate, 315, shiftCenter, currentRadiusPPU, txt,
 
415
                                    Qt::AlignTop | Qt::AlignRight, iLabel );
 
416
 
 
417
                        if( params()->polarLabelsAtPos( KDChartEnums::PosTopLeft ) )
 
418
                            paintCircularAxisLabel( painter, rotate, 135, shiftCenter, currentRadiusPPU, txt,
 
419
                                    Qt::AlignBottom | Qt::AlignLeft, iLabel );
 
420
                    }
 
421
                }
 
422
                }
 
423
 
 
424
 
 
425
                double circularSpan = params()->polarChartSubType() == KDChartParams::PolarPercent
 
426
                    ? 100.0
 
427
                    : paraCircular.trueAxisHigh() - paraCircular.trueAxisLow();
 
428
                double radius = currentRadiusPPU;
 
429
                if(    !labels
 
430
                        || params()->polarChartSubType() == KDChartParams::PolarPercent )
 
431
                    radius = (position.width() / 2.0) * 1000.0 / 1250.0;
 
432
 
 
433
                if( params()->polarChartSubType() != KDChartParams::PolarPercent )
 
434
                    pixelsPerUnit = labels ? currentRadiusPPU / circularSpan
 
435
                        : (position.height() / maxValue / 2.0) * 1000.0 / 1250.0;
 
436
                else
 
437
                    pixelsPerUnit = (position.height() / 100.0 / 2.0) * 1000.0 / 1250.0;
 
438
 
 
439
                // draw the sagittal grid and axis lines
 
440
                if(    paraSagittal.axisShowGrid()
 
441
                        || paraSagittal.axisVisible()
 
442
                        || paraSagittal.axisLabelsVisible() ) {
 
443
 
 
444
                    // calculate label texts
 
445
                    QStringList* labelTexts = 0;
 
446
                    bool onlyDefaultLabels = true;
 
447
                    if( paraSagittal.axisLabelsVisible() ) {
 
448
                        ((KDChartParams*)params())->setAxisArea( KDChartAxisParams::AxisPosSagittal,
 
449
                                                                 QRect( 0,
 
450
                                                                     0,
 
451
                                                                     static_cast < int > ( 2.0 * M_PI * radius ),
 
452
                                                                     static_cast < int > ( 0.5 * radius ) ) );
 
453
                        double delimLen = 20.0 * minSizeP1000; // per mille of area
 
454
                        KDChartAxisParams::AxisPos basicPos;
 
455
                        QPoint orig, dest;
 
456
                        double dDummy;
 
457
                        double nSubDelimFactor = 0.0;
 
458
                        double pDelimDelta = 0.0;
 
459
                        double nTxtHeight = 0.0;
 
460
                        double pTextsX = 0.0;
 
461
                        double pTextsY = 0.0;
 
462
                        double pTextsW = 0.0;
 
463
                        double pTextsH = 0.0;
 
464
                        int textAlign = Qt::AlignCenter;
 
465
                        bool isLogarithmic = false; // value not used for KD Chart 1.0.0
 
466
                        bool isDateTime = false;
 
467
                        bool autoDtLabels = false;
 
468
                        QDateTime dtLow;
 
469
                        QDateTime dtHigh;
 
470
                        KDChartAxisParams::ValueScale dtDeltaScale;
 
471
                        KDChartAxesPainter::calculateLabelTexts( *data,
 
472
                                *params(),
 
473
                                KDChartAxisParams::AxisPosSagittal,
 
474
                                minSizeP1000,
 
475
                                delimLen,
 
476
                                // start of reference parameters
 
477
                                basicPos,
 
478
                                orig,
 
479
                                dest,
 
480
                                dDummy,dDummy,dDummy,dDummy,
 
481
                                nSubDelimFactor,
 
482
                                pDelimDelta,
 
483
                                nTxtHeight,
 
484
                                pTextsX,
 
485
                                pTextsY,
 
486
                                pTextsW,
 
487
                                pTextsH,
 
488
                                textAlign,
 
489
                                isLogarithmic,
 
490
                                isDateTime,
 
491
                                autoDtLabels,
 
492
                                dtLow,
 
493
                                dtHigh,
 
494
                                dtDeltaScale );
 
495
                                labelTexts = ( QStringList* ) paraSagittal.axisLabelTexts();
 
496
                                // calculate font size
 
497
                                actFont = paraSagittal.axisLabelsFont();
 
498
                                if ( paraSagittal.axisLabelsFontUseRelSize() ) {
 
499
                                    actFont.setPointSizeFloat( nTxtHeight );
 
500
                                }
 
501
                                QFontMetrics fm( actFont );
 
502
                                QString strMax;
 
503
                                int maxLabelsWidth = 0;
 
504
                                for ( QStringList::Iterator it = labelTexts->begin();
 
505
                                        it != labelTexts->end();
 
506
                                        ++it ) {
 
507
                                    if ( fm.width( *it ) > maxLabelsWidth ) {
 
508
                                        maxLabelsWidth = fm.width( *it );
 
509
                                        strMax = *it;
 
510
                                    }
 
511
                                    if ( !(*it).startsWith( "Item ") )
 
512
                                        onlyDefaultLabels = false;
 
513
                                }
 
514
                                while ( fm.width( strMax ) > pTextsW && 6.0 < nTxtHeight ) {
 
515
                                    nTxtHeight -= 0.5;
 
516
                                    actFont.setPointSizeFloat( nTxtHeight );
 
517
                                    fm = QFontMetrics( actFont );
 
518
                                }
 
519
                                painter->setFont( actFont );
 
520
                    }
 
521
 
 
522
                    int currentAngle = params()->polarZeroDegreePos();
 
523
                    if(    -360 > currentAngle
 
524
                            ||  360 < currentAngle )
 
525
                        currentAngle = 0;
 
526
                    if( 0 > currentAngle )
 
527
                        currentAngle += 360;
 
528
                    int r1 = static_cast < int > ( radius * 1050 / 1000 );
 
529
                    int r2 = static_cast < int > ( radius * 1100 / 1000 );
 
530
                    int r3 = static_cast < int > ( radius * 1175 / 1000 );
 
531
                    QPoint pt1, pt2, pt3;
 
532
                    uint nLabels = labelTexts->count();
 
533
                    int angleBetweenRays = 360 / nLabels;
 
534
                    for( uint value = 0; value < nLabels; ++value ) {
 
535
                        pt1 = center + polarToXY( r1, currentAngle );
 
536
                        pt2 = center + polarToXY( r2, currentAngle );
 
537
                        pt3 = center + polarToXY( r3, currentAngle );
 
538
                        if( paraSagittal.axisShowGrid() ) {
 
539
                            painter->setPen( QPen( paraSagittal.axisGridColor(),
 
540
                                        sagittalGridLineWidth ) );
 
541
                            painter->drawLine( center, pt1 );
 
542
                        }
 
543
                        if( paraSagittal.axisVisible() ) {
 
544
                            painter->setPen( QPen( paraSagittal.axisLineColor(),
 
545
                                        sagittalLineWidth ) );
 
546
                            painter->drawLine( pt1, pt2 );
 
547
                        }
 
548
                        if(    paraSagittal.axisLabelsVisible()
 
549
                                && labelTexts
 
550
                                && labelTexts->count() > value ) {
 
551
                            painter->setPen( QPen( paraSagittal.axisLabelsColor(),
 
552
                                        sagittalLineWidth ) );
 
553
                            QString label(   onlyDefaultLabels
 
554
                                    ? QString::number( currentAngle )
 
555
                                    : (*labelTexts)[ value ] );
 
556
 
 
557
                            KDDrawText::drawRotatedText( painter,
 
558
                                    currentAngle+90,
 
559
                                    pt3 + _dataRect.topLeft(),
 
560
                                    label,
 
561
                                    0,
 
562
                                    Qt::AlignCenter );
 
563
                        }
 
564
                        currentAngle += angleBetweenRays;
 
565
                    }
 
566
                }
 
567
 
 
568
 
 
569
                // Now draw the data
 
570
                int dataLinesWidth = 0 <= params()->polarLineWidth()
 
571
                    ? params()->polarLineWidth()
 
572
                    : -1 * static_cast < int > (   params()->polarLineWidth()
 
573
                            * minSizeP1000 );
 
574
                painter->setBrush( Qt::NoBrush );
 
575
                for ( unsigned int dataset = datasetStart; dataset <= datasetEnd; dataset++ ) {
580
576
                    painter->setPen( QPen( params()->dataColor( dataset ),
581
 
                                    dataLinesWidth ) );
582
 
                }
583
 
                if ( regions ) {
584
 
                    KDChartDataRegion* datReg = new KDChartDataRegion( region,
585
 
                                                                       dataset,
586
 
                                                                       value,
587
 
                                                                       chart );
588
 
                    datReg->points[ KDChartEnums::PosTopLeft ] =
589
 
                        drawPoint + _dataRect.topLeft();
590
 
 
591
 
                    datReg->points[     KDChartEnums::PosTopCenter ]    =
592
 
                        datReg->points[ KDChartEnums::PosTopLeft ];
593
 
                    datReg->points[     KDChartEnums::PosTopRight ]     =
594
 
                        datReg->points[ KDChartEnums::PosTopLeft ];
595
 
                    datReg->points[     KDChartEnums::PosBottomLeft ]   =
596
 
                        datReg->points[ KDChartEnums::PosTopLeft ];
597
 
                    datReg->points[     KDChartEnums::PosBottomCenter ] =
598
 
                        datReg->points[ KDChartEnums::PosTopLeft ];
599
 
                    datReg->points[     KDChartEnums::PosBottomRight ]  =
600
 
                        datReg->points[ KDChartEnums::PosTopLeft ];
601
 
                    datReg->points[     KDChartEnums::PosCenterLeft ]   =
602
 
                        datReg->points[ KDChartEnums::PosTopLeft ];
603
 
                    datReg->points[     KDChartEnums::PosCenter ]       =
604
 
                        datReg->points[ KDChartEnums::PosTopLeft ];
605
 
                    datReg->points[     KDChartEnums::PosCenterRight ]  =
606
 
                        datReg->points[ KDChartEnums::PosTopLeft ];
607
 
                    /*
608
 
                    // test the center positions:
609
 
                    painter->drawEllipse( datReg->points[ KDChartEnums::PosCenterLeft ].x() - 2,
610
 
                                        datReg->points[ KDChartEnums::PosCenterLeft ].y() - 2,  5, 5);
611
 
                    */
612
 
                    datReg->startAngle = drawAngle;
613
 
                    datReg->angleLen   = drawAngle;
614
 
                    regions->append( datReg );
615
 
                }
616
 
                // calculate running sum for stacked and percent
617
 
                if ( params()->polarChartSubType() == KDChartParams::PolarStacked ||
618
 
                     params()->polarChartSubType() == KDChartParams::PolarPercent )
619
 
                    currentValueSums[ value ] += cellValue;
620
 
            }
621
 
        }
622
 
        painter->drawPolygon( points );
623
 
    }
624
 
 
625
 
    painter->translate( -_dataRect.x(), -_dataRect.y() );
626
 
}
627
 
 
628
 
 
629
 
/*
630
 
  Helper methode being called by KDChartPolarPainter::paintData()
631
 
*/
632
 
void KDChartPolarPainter::paintCircularAxisLabel( QPainter* painter,
633
 
                                                  bool rotate,
634
 
                                                  int txtAngle,
635
 
                                                  QPoint center,
636
 
                                                  double currentRadiusPPU,
637
 
                                                  const QString& txt,
638
 
                                                  int align,
639
 
                                                  int step )
640
 
{
641
 
    if( !rotate && (0 != (align & (Qt::AlignLeft | Qt::AlignRight) ) ) )
642
 
        currentRadiusPPU += center.x()*0.01;
643
 
    KDDrawText::drawRotatedText(
644
 
        painter,
645
 
        rotate ? txtAngle - 90 : 0,
646
 
        step ? center - polarToXY( currentRadiusPPU, txtAngle )
647
 
             : center,
648
 
        txt,
649
 
        0,
650
 
        step ? (rotate ? Qt::AlignBottom | Qt::AlignHCenter : align)
651
 
             : Qt::AlignCenter );
652
 
}
653
 
 
654
 
 
655
 
/*!
656
 
  Draws the marker for one data point according to the specified style.
657
 
 
658
 
  \param painter the painter to draw on
659
 
  \param style what kind of marker is drawn (square, diamond or circle)
660
 
  \param color the color in which to draw the marker
661
 
  \param p the center of the marker
662
 
  \param dataset the dataset which this marker represents
663
 
  \param value the value which this marker represents
664
 
  \param regions a list of regions for data points, a new region for the new
665
 
  marker will be appended to this list if it is not 0
666
 
*/
667
 
void KDChartPolarPainter::drawMarker( QPainter* painter,
668
 
                                      KDChartParams::PolarMarkerStyle style,
669
 
                                      const QColor& color, const QPoint& p,
670
 
                                      uint dataset, uint value, uint chart,
671
 
                                      double minSizeP1000,
672
 
                                      QRegion& region )
673
 
{
674
 
    int xsize = params()->polarMarkerSize().width();
675
 
    if ( 0 > xsize )
676
 
        xsize = -1 * static_cast < int > ( xsize * minSizeP1000 );
677
 
    int ysize = params()->polarMarkerSize().height();
678
 
    if ( 0 > ysize )
679
 
        ysize = -1 * static_cast < int > ( ysize * minSizeP1000 );
680
 
    int xsize2 = xsize / 2;
681
 
    int ysize2 = ysize / 2;
682
 
    painter->setPen( color );
683
 
    switch ( style ) {
684
 
    case KDChartParams::PolarMarkerSquare: {
685
 
            painter->save();
686
 
            painter->setBrush( color );
687
 
            QRect rect( QPoint( p.x() - xsize2, p.y() - ysize2 ), QPoint( p.x() + xsize2, p.y() + ysize2 ) );
688
 
            painter->drawRect( rect );
689
 
            // Don't use rect for drawing after this!
690
 
            rect.moveBy( _dataRect.x(), _dataRect.y() );
691
 
            region = QRegion( rect );
692
 
            painter->restore();
693
 
            break;
694
 
        }
695
 
    case KDChartParams::PolarMarkerDiamond: {
696
 
            painter->save();
697
 
            painter->setBrush( color );
698
 
            QPointArray points( 4 );
699
 
            points.setPoint( 0, p.x() - xsize2, p.y() );
700
 
            points.setPoint( 1, p.x(), p.y() - ysize2 );
701
 
            points.setPoint( 2, p.x() + xsize2, p.y() );
702
 
            points.setPoint( 3, p.x(), p.y() + ysize2 );
703
 
            painter->drawPolygon( points );
704
 
            // Don't use points for drawing after this!
705
 
            points.translate( _dataRect.x(), _dataRect.y() );
706
 
            region = QRegion( points );
707
 
            painter->restore();
708
 
            break;
709
 
        }
710
 
    case KDChartParams::PolarMarkerCircle:
711
 
    default: {
712
 
            painter->save();
713
 
            painter->setBrush( color );
714
 
            painter->drawEllipse( p.x() - xsize2, p.y() - ysize2, xsize, ysize );
715
 
            QPointArray points;
716
 
            points.makeEllipse( p.x() - xsize2, p.y() - ysize2, xsize, ysize );
717
 
            // Don't use points for drawing after this!
718
 
            points.translate( _dataRect.x(), _dataRect.y() );
719
 
            if( points.size() > 0 )
720
 
                region = QRegion( points );
721
 
            else
722
 
                region = QRegion();
723
 
            painter->restore();
724
 
        }
725
 
    };
726
 
}
 
577
                                dataLinesWidth ) );
 
578
                    QPointArray points( numValues );
 
579
                    int totalPoints = 0;
 
580
                    double valueTotal = 0.0; // Will only be used for Percent
 
581
                    int angleBetweenRays = 360 / numValues;
 
582
                    for ( int value = 0; value < numValues; value++ ) {
 
583
                        if( params()->polarChartSubType() == KDChartParams::PolarPercent )
 
584
                            valueTotal = data->colAbsSum( value );
 
585
                        // the value determines the angle, the dataset only the color
 
586
                        if ( data->cell( dataset, value ).isDouble() ) {
 
587
                            double cellValue = data->cell( dataset, value ).doubleValue();
 
588
                            double drawValue;
 
589
                            if ( params()->polarChartSubType() == KDChartParams::PolarStacked )
 
590
                                drawValue = ( cellValue + currentValueSums[ value ] ) * pixelsPerUnit;
 
591
                            else if( params()->polarChartSubType() == KDChartParams::PolarPercent ) {
 
592
                                drawValue = (   ( cellValue + currentValueSums[ value ] )
 
593
                                        / valueTotal * static_cast<double>( radius ) );
 
594
                            } else
 
595
                                drawValue = cellValue * pixelsPerUnit;
 
596
 
 
597
                            // record the point for drawing the polygon later
 
598
                            int drawAngle = value * angleBetweenRays;
 
599
                            QPoint drawPoint( center + polarToXY( static_cast<int>( drawValue ),
 
600
                                        drawAngle ) );
 
601
                            points.setPoint( totalPoints, drawPoint );
 
602
                            totalPoints++;
 
603
                            QRegion region;
 
604
                            // the marker can be drawn now
 
605
                            if( params()->polarMarker() ) {
 
606
                                drawMarker( painter, params()->polarMarkerStyle( dataset ),
 
607
                                        params()->dataColor( dataset ),
 
608
                                        drawPoint,
 
609
                                        dataset, value, chart, minSizeP1000, region );
 
610
                                painter->setPen( QPen( params()->dataColor( dataset ),
 
611
                                            dataLinesWidth ) );
 
612
                            }
 
613
                            if ( regions ) {
 
614
                                KDChartDataRegion* datReg = new KDChartDataRegion( region,
 
615
                                        dataset,
 
616
                                        value,
 
617
                                        chart );
 
618
                                datReg->points[ KDChartEnums::PosTopLeft ] =
 
619
                                    drawPoint + _dataRect.topLeft();
 
620
 
 
621
                                datReg->points[     KDChartEnums::PosTopCenter ]    =
 
622
                                    datReg->points[ KDChartEnums::PosTopLeft ];
 
623
                                datReg->points[     KDChartEnums::PosTopRight ]     =
 
624
                                    datReg->points[ KDChartEnums::PosTopLeft ];
 
625
                                datReg->points[     KDChartEnums::PosBottomLeft ]   =
 
626
                                    datReg->points[ KDChartEnums::PosTopLeft ];
 
627
                                datReg->points[     KDChartEnums::PosBottomCenter ] =
 
628
                                    datReg->points[ KDChartEnums::PosTopLeft ];
 
629
                                datReg->points[     KDChartEnums::PosBottomRight ]  =
 
630
                                    datReg->points[ KDChartEnums::PosTopLeft ];
 
631
                                datReg->points[     KDChartEnums::PosCenterLeft ]   =
 
632
                                    datReg->points[ KDChartEnums::PosTopLeft ];
 
633
                                datReg->points[     KDChartEnums::PosCenter ]       =
 
634
                                    datReg->points[ KDChartEnums::PosTopLeft ];
 
635
                                datReg->points[     KDChartEnums::PosCenterRight ]  =
 
636
                                    datReg->points[ KDChartEnums::PosTopLeft ];
 
637
                                /*
 
638
                                // test the center positions:
 
639
                                painter->drawEllipse( datReg->points[ KDChartEnums::PosCenterLeft ].x() - 2,
 
640
                                datReg->points[ KDChartEnums::PosCenterLeft ].y() - 2,  5, 5);
 
641
                                */
 
642
                                datReg->startAngle = drawAngle;
 
643
                                datReg->angleLen   = drawAngle;
 
644
                                regions->append( datReg );
 
645
                            }
 
646
                            // calculate running sum for stacked and percent
 
647
                            if ( params()->polarChartSubType() == KDChartParams::PolarStacked ||
 
648
                                    params()->polarChartSubType() == KDChartParams::PolarPercent )
 
649
                                currentValueSums[ value ] += cellValue;
 
650
                        }
 
651
                    }
 
652
                    painter->drawPolygon( points );
 
653
                }
 
654
 
 
655
                painter->translate( -_dataRect.x(), -_dataRect.y() );
 
656
    }
 
657
 
 
658
 
 
659
    /*
 
660
       Helper methode being called by KDChartPolarPainter::paintData()
 
661
       */
 
662
    void KDChartPolarPainter::paintCircularAxisLabel( QPainter* painter,
 
663
            bool rotate,
 
664
            int txtAngle,
 
665
            QPoint center,
 
666
            double currentRadiusPPU,
 
667
            const QString& txt,
 
668
            int align,
 
669
            int step )
 
670
    {
 
671
        if( !rotate && (0 != (align & (Qt::AlignLeft | Qt::AlignRight) ) ) )
 
672
            currentRadiusPPU += center.x()*0.01;
 
673
        KDDrawText::drawRotatedText(
 
674
                painter,
 
675
                rotate ? txtAngle - 90 : 0,
 
676
                step ? center - polarToXY( static_cast<int>( currentRadiusPPU ), txtAngle )
 
677
                : center,
 
678
                txt,
 
679
                0,
 
680
                step ? (rotate ? Qt::AlignBottom | Qt::AlignHCenter : align)
 
681
                : Qt::AlignCenter );
 
682
    }
 
683
 
 
684
 
 
685
    /*!
 
686
      Draws the marker for one data point according to the specified style.
 
687
 
 
688
      \param painter the painter to draw on
 
689
      \param style what kind of marker is drawn (square, diamond or circle)
 
690
      \param color the color in which to draw the marker
 
691
      \param p the center of the marker
 
692
      \param dataset the dataset which this marker represents
 
693
      \param value the value which this marker represents
 
694
      \param regions a list of regions for data points, a new region for the new
 
695
      marker will be appended to this list if it is not 0
 
696
      */
 
697
    void KDChartPolarPainter::drawMarker( QPainter* painter,
 
698
            KDChartParams::PolarMarkerStyle style,
 
699
            const QColor& color, const QPoint& p,
 
700
            uint /*dataset*/, uint /*value*/, uint /*chart*/,
 
701
            double minSizeP1000,
 
702
            QRegion& region )
 
703
    {
 
704
        int xsize = params()->polarMarkerSize().width();
 
705
        if ( 0 > xsize )
 
706
            xsize = -1 * static_cast < int > ( xsize * minSizeP1000 );
 
707
        int ysize = params()->polarMarkerSize().height();
 
708
        if ( 0 > ysize )
 
709
            ysize = -1 * static_cast < int > ( ysize * minSizeP1000 );
 
710
        int xsize2 = xsize / 2;
 
711
        int ysize2 = ysize / 2;
 
712
        painter->setPen( color );
 
713
        switch ( style ) {
 
714
            case KDChartParams::PolarMarkerSquare: {
 
715
                                                       painter->save();
 
716
                                                       painter->setBrush( color );
 
717
                                                       QRect rect( QPoint( p.x() - xsize2, p.y() - ysize2 ), QPoint( p.x() + xsize2, p.y() + ysize2 ) );
 
718
                                                       painter->drawRect( rect );
 
719
                                                       // Don't use rect for drawing after this!
 
720
                                                       rect.moveBy( _dataRect.x(), _dataRect.y() );
 
721
                                                       region = QRegion( rect );
 
722
                                                       painter->restore();
 
723
                                                       break;
 
724
                                                   }
 
725
            case KDChartParams::PolarMarkerDiamond: {
 
726
                                                        painter->save();
 
727
                                                        painter->setBrush( color );
 
728
                                                        QPointArray points( 4 );
 
729
                                                        points.setPoint( 0, p.x() - xsize2, p.y() );
 
730
                                                        points.setPoint( 1, p.x(), p.y() - ysize2 );
 
731
                                                        points.setPoint( 2, p.x() + xsize2, p.y() );
 
732
                                                        points.setPoint( 3, p.x(), p.y() + ysize2 );
 
733
                                                        painter->drawPolygon( points );
 
734
                                                        // Don't use points for drawing after this!
 
735
                                                        points.translate( _dataRect.x(), _dataRect.y() );
 
736
                                                        region = QRegion( points );
 
737
                                                        painter->restore();
 
738
                                                        break;
 
739
                                                    }
 
740
            case KDChartParams::PolarMarkerCircle:
 
741
            default: {
 
742
                         painter->save();
 
743
                         painter->setBrush( color );
 
744
                         painter->drawEllipse( p.x() - xsize2, p.y() - ysize2, xsize, ysize );
 
745
                         QPointArray points;
 
746
                         points.makeEllipse( p.x() - xsize2, p.y() - ysize2, xsize, ysize );
 
747
                         // Don't use points for drawing after this!
 
748
                         points.translate( _dataRect.x(), _dataRect.y() );
 
749
                         if( points.size() > 0 )
 
750
                             region = QRegion( points );
 
751
                         else
 
752
                             region = QRegion();
 
753
                         painter->restore();
 
754
                     }
 
755
        };
 
756
    }
727
757
 
728
758
#define DEGTORAD(d) (d)*M_PI/180
729
759
 
730
 
QPoint KDChartPolarPainter::polarToXY( int radius, int angle )
731
 
{
732
 
  double anglerad = DEGTORAD( static_cast<double>( angle ) );
733
 
  QPoint ret( cos( anglerad ) * radius,
734
 
              sin( anglerad ) * radius );
735
 
  return ret;
736
 
}
737
 
 
738
 
 
739
 
/**
740
 
   This method is a specialization that returns a fallback legend text
741
 
   appropriate for polar charts where the fallbacks should come from
742
 
   the values, not from the datasets.
743
 
 
744
 
   This method is only used when automatic legends are used, because
745
 
   manual and first-column legends do not need fallback texts.
746
 
 
747
 
   \param uint dataset the dataset number for which to generate a
748
 
   fallback text
749
 
   \return the fallback text to use for describing the specified
750
 
   dataset in the legend
751
 
*/
752
 
QString KDChartPolarPainter::fallbackLegendText( uint dataset ) const
753
 
{
754
 
    return QObject::tr( "Series " ) + QString::number( dataset + 1 );
755
 
}
756
 
 
757
 
 
758
 
/**
759
 
   This methods returns the number of elements to be shown in the
760
 
   legend in case fallback texts are used.
761
 
 
762
 
   This method is only used when automatic legends are used, because
763
 
   manual and first-column legends do not need fallback texts.
764
 
 
765
 
   \return the number of fallback texts to use
766
 
*/
767
 
uint KDChartPolarPainter::numLegendFallbackTexts( KDChartTableData* data ) const
768
 
{
769
 
    return data->usedRows();
770
 
}
 
760
    QPoint KDChartPolarPainter::polarToXY( int radius, int angle )
 
761
    {
 
762
        double anglerad = DEGTORAD( static_cast<double>( angle ) );
 
763
        QPoint ret( static_cast<int>( cos( anglerad ) * radius ),
 
764
                static_cast<int>( sin( anglerad ) * radius ) );
 
765
        return ret;
 
766
    }
 
767
 
 
768
 
 
769
    /**
 
770
      This method is a specialization that returns a fallback legend text
 
771
      appropriate for polar charts where the fallbacks should come from
 
772
      the values, not from the datasets.
 
773
 
 
774
      This method is only used when automatic legends are used, because
 
775
      manual and first-column legends do not need fallback texts.
 
776
 
 
777
      \param uint dataset the dataset number for which to generate a
 
778
      fallback text
 
779
      \return the fallback text to use for describing the specified
 
780
      dataset in the legend
 
781
      */
 
782
    QString KDChartPolarPainter::fallbackLegendText( uint dataset ) const
 
783
    {
 
784
        return QObject::tr( "Series " ) + QString::number( dataset + 1 );
 
785
    }
 
786
 
 
787
 
 
788
    /**
 
789
      This methods returns the number of elements to be shown in the
 
790
      legend in case fallback texts are used.
 
791
 
 
792
      This method is only used when automatic legends are used, because
 
793
      manual and first-column legends do not need fallback texts.
 
794
 
 
795
      \return the number of fallback texts to use
 
796
      */
 
797
    uint KDChartPolarPainter::numLegendFallbackTexts( KDChartTableDataBase* data ) const
 
798
    {
 
799
        return data->usedRows();
 
800
    }