source: ntrip/trunk/BNC/qwtpolar/qwt_polar_grid.cpp@ 10518

Last change on this file since 10518 was 8127, checked in by stoecker, 8 years ago

update qwt and qwtpolar, many QT5 fixes (unfinished)

File size: 31.4 KB
Line 
1/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
2 * QwtPolar Widget Library
3 * Copyright (C) 2008 Uwe Rathmann
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the Qwt License, Version 1.0
7 *****************************************************************************/
8
9#include "qwt_polar_grid.h"
10#include <qwt_painter.h>
11#include <qwt_text.h>
12#include <qwt_clipper.h>
13#include <qwt_scale_map.h>
14#include <qwt_scale_engine.h>
15#include <qwt_scale_div.h>
16#include <qwt_scale_draw.h>
17#include <qwt_round_scale_draw.h>
18#include <qpainter.h>
19#include <qpen.h>
20#include <float.h>
21
22static inline bool isClose( double value1, double value2 )
23{
24 return qAbs( value1 - value2 ) < DBL_EPSILON;
25}
26
27class QwtPolarGrid::AxisData
28{
29public:
30 AxisData():
31 isVisible( false ),
32 scaleDraw( NULL )
33 {
34 }
35 ~AxisData()
36 {
37 delete scaleDraw;
38 }
39
40 bool isVisible;
41 mutable QwtAbstractScaleDraw *scaleDraw;
42 QPen pen;
43 QFont font;
44};
45
46class QwtPolarGrid::GridData
47{
48public:
49 GridData():
50 isVisible( true ),
51 isMinorVisible( false )
52 {
53 }
54
55 bool isVisible;
56 bool isMinorVisible;
57 QwtScaleDiv scaleDiv;
58
59 QPen majorPen;
60 QPen minorPen;
61};
62
63class QwtPolarGrid::PrivateData
64{
65public:
66 GridData gridData[QwtPolar::ScaleCount];
67 AxisData axisData[QwtPolar::AxesCount];
68 QwtPolarGrid::DisplayFlags displayFlags;
69 QwtPolarGrid::GridAttributes attributes;
70};
71
72/*!
73 \brief Constructor
74
75 Enables major and disables minor grid lines.
76 The azimuth and right radial axis are visible. all other axes
77 are hidden. Autoscaling is enabled.
78*/
79QwtPolarGrid::QwtPolarGrid():
80 QwtPolarItem( QwtText( "Grid" ) )
81{
82 d_data = new PrivateData;
83
84 for ( int axisId = 0; axisId < QwtPolar::AxesCount; axisId++ )
85 {
86 AxisData &axis = d_data->axisData[axisId];
87 switch( axisId )
88 {
89 case QwtPolar::AxisAzimuth:
90 {
91 axis.scaleDraw = new QwtRoundScaleDraw;
92 axis.scaleDraw->setTickLength( QwtScaleDiv::MinorTick, 2 );
93 axis.scaleDraw->setTickLength( QwtScaleDiv::MediumTick, 2 );
94 axis.scaleDraw->setTickLength( QwtScaleDiv::MajorTick, 4 );
95 axis.isVisible = true;
96 break;
97 }
98 case QwtPolar::AxisLeft:
99 {
100 QwtScaleDraw *scaleDraw = new QwtScaleDraw;
101 scaleDraw->setAlignment( QwtScaleDraw::BottomScale );
102
103 axis.scaleDraw = scaleDraw;
104 axis.isVisible = false;
105 break;
106 }
107 case QwtPolar::AxisRight:
108 {
109 QwtScaleDraw *scaleDraw = new QwtScaleDraw;
110 scaleDraw->setAlignment( QwtScaleDraw::BottomScale );
111
112 axis.scaleDraw = scaleDraw;
113 axis.isVisible = true;
114 break;
115 }
116 case QwtPolar::AxisTop:
117 {
118 QwtScaleDraw *scaleDraw = new QwtScaleDraw;
119 scaleDraw->setAlignment( QwtScaleDraw::LeftScale );
120
121 axis.scaleDraw = scaleDraw;
122 axis.isVisible = false;
123 break;
124 }
125 case QwtPolar::AxisBottom:
126 {
127 QwtScaleDraw *scaleDraw = new QwtScaleDraw;
128 scaleDraw->setAlignment( QwtScaleDraw::LeftScale );
129
130 axis.scaleDraw = scaleDraw;
131 axis.isVisible = true;
132 break;
133 }
134 default:;
135 }
136 }
137
138 d_data->attributes = AutoScaling;
139
140 d_data->displayFlags = 0;
141 d_data->displayFlags |= SmartOriginLabel;
142 d_data->displayFlags |= HideMaxRadiusLabel;
143 d_data->displayFlags |= ClipAxisBackground;
144 d_data->displayFlags |= SmartScaleDraw;
145 d_data->displayFlags |= ClipGridLines;
146
147 setZ( 10.0 );
148 setRenderHint( RenderAntialiased, true );
149}
150
151//! Destructor
152QwtPolarGrid::~QwtPolarGrid()
153{
154 delete d_data;
155}
156
157//! \return QwtPlotItem::Rtti_PolarGrid
158int QwtPolarGrid::rtti() const
159{
160 return QwtPolarItem::Rtti_PolarGrid;
161}
162
163/*!
164 Change the display flags
165
166 \param flag See DisplayFlag
167 \param on true/false
168*/
169void QwtPolarGrid::setDisplayFlag( DisplayFlag flag, bool on )
170{
171 if ( ( ( d_data->displayFlags & flag ) != 0 ) != on )
172 {
173 if ( on )
174 d_data->displayFlags |= flag;
175 else
176 d_data->displayFlags &= ~flag;
177
178 itemChanged();
179 }
180}
181
182/*!
183 \return true, if flag is enabled
184 \param flag See DisplayFlag
185*/
186bool QwtPolarGrid::testDisplayFlag( DisplayFlag flag ) const
187{
188 return ( d_data->displayFlags & flag );
189}
190
191/*!
192 \brief Specify an attribute for the grid
193
194 \param attribute Grid attribute
195 \param on On/Off
196
197 /sa GridAttribute, testGridAttribute(), updateScaleDiv(),
198 QwtPolarPlot::zoom(), QwtPolarPlot::scaleDiv()
199*/
200void QwtPolarGrid::setGridAttribute( GridAttribute attribute, bool on )
201{
202 if ( bool( d_data->attributes & attribute ) == on )
203 return;
204
205 if ( on )
206 d_data->attributes |= attribute;
207 else
208 d_data->attributes &= ~attribute;
209
210 itemChanged();
211}
212
213/*!
214 \return true, if attribute is enabled
215 \sa GridAttribute, setGridAttribute()
216*/
217bool QwtPolarGrid::testGridAttribute( GridAttribute attribute ) const
218{
219 return d_data->attributes & attribute;
220}
221
222/*!
223 Assign a pen for painting an axis
224
225 \param axisId Axis id (QwtPolar::Axis)
226 \param pen Pen
227
228 \sa axisPen()
229*/
230void QwtPolarGrid::setAxisPen( int axisId, const QPen &pen )
231{
232 if ( axisId < 0 || axisId >= QwtPolar::AxesCount )
233 return;
234
235 AxisData &axisData = d_data->axisData[axisId];
236 if ( axisData.pen != pen )
237 {
238 axisData.pen = pen;
239 itemChanged();
240 }
241}
242
243/*!
244 Show/Hide grid lines for a scale
245
246 \param scaleId Scale id ( QwtPolar::Scale )
247 \param show true/false
248*/
249void QwtPolarGrid::showGrid( int scaleId, bool show )
250{
251 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
252 return;
253
254 GridData &grid = d_data->gridData[scaleId];
255 if ( grid.isVisible != show )
256 {
257 grid.isVisible = show;
258 itemChanged();
259 }
260}
261
262/*!
263 \return true if grid lines are enabled
264 \param scaleId Scale id ( QwtPolar::Scale )
265 \sa QwtPolar::Scale, showGrid()
266*/
267bool QwtPolarGrid::isGridVisible( int scaleId ) const
268{
269 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
270 return false;
271
272 return d_data->gridData[scaleId].isVisible;
273}
274
275/*!
276 Show/Hide minor grid lines for a scale
277
278 To display minor grid lines. showGrid() needs to be enabled too.
279
280 \param scaleId Scale id ( QwtPolar::Scale )
281 \param show true/false
282
283 \sa showGrid
284*/
285void QwtPolarGrid::showMinorGrid( int scaleId, bool show )
286{
287 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
288 return;
289
290 GridData &grid = d_data->gridData[scaleId];
291 if ( grid.isMinorVisible != show )
292 {
293 grid.isMinorVisible = show;
294 itemChanged();
295 }
296}
297
298/*!
299 \return true if minor grid lines are enabled
300 \param scaleId Scale id ( QwtPolar::Scale )
301 \sa showMinorGrid()
302*/
303bool QwtPolarGrid::isMinorGridVisible( int scaleId ) const
304{
305 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
306 return false;
307
308 return d_data->gridData[scaleId].isMinorVisible;
309}
310
311/*!
312 Show/Hide an axis
313
314 \param axisId Axis id (QwtPolar::Axis)
315 \param show true/false
316
317 \sa isAxisVisible()
318*/
319void QwtPolarGrid::showAxis( int axisId, bool show )
320{
321 if ( axisId < 0 || axisId >= QwtPolar::AxesCount )
322 return;
323
324 AxisData &axisData = d_data->axisData[axisId];
325 if ( axisData.isVisible != show )
326 {
327 axisData.isVisible = show;
328 itemChanged();
329 }
330}
331
332/*!
333 \return true if the axis is visible
334 \param axisId Axis id (QwtPolar::Axis)
335
336 \sa showAxis()
337*/
338bool QwtPolarGrid::isAxisVisible( int axisId ) const
339{
340 if ( axisId < 0 || axisId >= QwtPolar::AxesCount )
341 return false;
342
343 return d_data->axisData[axisId].isVisible;
344}
345
346/*!
347 Assign a pen for all axes and grid lines
348
349 \param pen Pen
350 \sa setMajorGridPen(), setMinorGridPen(), setAxisPen()
351*/
352void QwtPolarGrid::setPen( const QPen &pen )
353{
354 bool isChanged = false;
355
356 for ( int scaleId = 0; scaleId < QwtPolar::ScaleCount; scaleId++ )
357 {
358 GridData &grid = d_data->gridData[scaleId];
359 if ( grid.majorPen != pen || grid.minorPen != pen )
360 {
361 grid.majorPen = pen;
362 grid.minorPen = pen;
363 isChanged = true;
364 }
365 }
366 for ( int axisId = 0; axisId < QwtPolar::AxesCount; axisId++ )
367 {
368 AxisData &axis = d_data->axisData[axisId];
369 if ( axis.pen != pen )
370 {
371 axis.pen = pen;
372 isChanged = true;
373 }
374 }
375 if ( isChanged )
376 itemChanged();
377}
378
379/*!
380 Assign a font for all scale tick labels
381
382 \param font Font
383 \sa setAxisFont()
384*/
385void QwtPolarGrid::setFont( const QFont &font )
386{
387 bool isChanged = false;
388 for ( int axisId = 0; axisId < QwtPolar::AxesCount; axisId++ )
389 {
390 AxisData &axis = d_data->axisData[axisId];
391 if ( axis.font != font )
392 {
393 axis.font = font;
394 isChanged = true;
395 }
396 }
397 if ( isChanged )
398 itemChanged();
399}
400
401/*!
402 Assign a pen for the major grid lines
403
404 \param pen Pen
405 \sa setPen(), setMinorGridPen(), majorGridPen
406*/
407void QwtPolarGrid::setMajorGridPen( const QPen &pen )
408{
409 bool isChanged = false;
410
411 for ( int scaleId = 0; scaleId < QwtPolar::ScaleCount; scaleId++ )
412 {
413 GridData &grid = d_data->gridData[scaleId];
414 if ( grid.majorPen != pen )
415 {
416 grid.majorPen = pen;
417 isChanged = true;
418 }
419 }
420 if ( isChanged )
421 itemChanged();
422}
423
424/*!
425 Assign a pen for the major grid lines of a specific scale
426
427 \param scaleId Scale id ( QwtPolar::Scale )
428 \param pen Pen
429 \sa setPen(), setMinorGridPen(), majorGridPen
430*/
431void QwtPolarGrid::setMajorGridPen( int scaleId, const QPen &pen )
432{
433 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
434 return;
435
436 GridData &grid = d_data->gridData[scaleId];
437 if ( grid.majorPen != pen )
438 {
439 grid.majorPen = pen;
440 itemChanged();
441 }
442}
443
444/*!
445 \return Pen for painting the major grid lines of a specific scale
446 \param scaleId Scale id ( QwtPolar::Scale )
447 \sa setMajorGridPen(), minorGridPen()
448*/
449QPen QwtPolarGrid::majorGridPen( int scaleId ) const
450{
451 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
452 return QPen();
453
454 const GridData &grid = d_data->gridData[scaleId];
455 return grid.majorPen;
456}
457
458/*!
459 Assign a pen for the minor grid lines
460
461 \param pen Pen
462 \sa setPen(), setMajorGridPen(), minorGridPen()
463*/
464void QwtPolarGrid::setMinorGridPen( const QPen &pen )
465{
466 bool isChanged = false;
467
468 for ( int scaleId = 0; scaleId < QwtPolar::ScaleCount; scaleId++ )
469 {
470 GridData &grid = d_data->gridData[scaleId];
471 if ( grid.minorPen != pen )
472 {
473 grid.minorPen = pen;
474 isChanged = true;
475 }
476 }
477 if ( isChanged )
478 itemChanged();
479}
480
481/*!
482 Assign a pen for the minor grid lines of a specific scale
483
484 \param scaleId Scale id ( QwtPolar::Scale )
485 \param pen Pen
486 \sa setPen(), setMajorGridPen(), minorGridPen
487*/
488void QwtPolarGrid::setMinorGridPen( int scaleId, const QPen &pen )
489{
490 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
491 return;
492
493 GridData &grid = d_data->gridData[scaleId];
494 if ( grid.minorPen != pen )
495 {
496 grid.minorPen = pen;
497 itemChanged();
498 }
499}
500
501/*!
502 \return Pen for painting the minor grid lines of a specific scale
503 \param scaleId Scale id ( QwtPolar::Scale )
504*/
505QPen QwtPolarGrid::minorGridPen( int scaleId ) const
506{
507 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
508 return QPen();
509
510 const GridData &grid = d_data->gridData[scaleId];
511 return grid.minorPen;
512}
513
514/*!
515 \return Pen for painting a specific axis
516
517 \param axisId Axis id (QwtPolar::Axis)
518 \sa setAxisPen()
519*/
520QPen QwtPolarGrid::axisPen( int axisId ) const
521{
522 if ( axisId < 0 || axisId >= QwtPolar::AxesCount )
523 return QPen();
524
525 return d_data->axisData[axisId].pen;
526}
527
528/*!
529 Assign a font for the tick labels of a specific axis
530
531 \param axisId Axis id (QwtPolar::Axis)
532 \param font new Font
533*/
534void QwtPolarGrid::setAxisFont( int axisId, const QFont &font )
535{
536 if ( axisId < 0 || axisId >= QwtPolar::AxesCount )
537 return;
538
539 AxisData &axisData = d_data->axisData[axisId];
540 if ( axisData.font != font )
541 {
542 axisData.font = font;
543 itemChanged();
544 }
545}
546
547/*!
548 \return Font for the tick labels of a specific axis
549 \param axisId Axis id (QwtPolar::Axis)
550*/
551QFont QwtPolarGrid::axisFont( int axisId ) const
552{
553 if ( axisId < 0 || axisId >= QwtPolar::AxesCount )
554 return QFont();
555
556 return d_data->axisData[axisId].font;
557}
558
559/*!
560 Draw the grid and axes
561
562 \param painter Painter
563 \param azimuthMap Maps azimuth values to values related to 0.0, M_2PI
564 \param radialMap Maps radius values into painter coordinates.
565 \param pole Position of the pole in painter coordinates
566 \param radius Radius of the complete plot area in painter coordinates
567 \param canvasRect Contents rect of the canvas in painter coordinates
568*/
569void QwtPolarGrid::draw( QPainter *painter,
570 const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap,
571 const QPointF &pole, double radius,
572 const QRectF &canvasRect ) const
573{
574 updateScaleDraws( azimuthMap, radialMap, pole, radius );
575
576 painter->save();
577
578 if ( testDisplayFlag( ClipAxisBackground ) )
579 {
580 QRegion clipRegion( canvasRect.toRect() );
581 for ( int axisId = 0; axisId < QwtPolar::AxesCount; axisId++ )
582 {
583 const AxisData &axis = d_data->axisData[axisId];
584 if ( axisId != QwtPolar::AxisAzimuth && axis.isVisible )
585 {
586 QwtScaleDraw *scaleDraw = static_cast<QwtScaleDraw *>( axis.scaleDraw );
587 if ( scaleDraw->hasComponent( QwtScaleDraw::Labels ) )
588 {
589 const QList<double> &ticks =
590 scaleDraw->scaleDiv().ticks( QwtScaleDiv::MajorTick );
591 for ( int i = 0; i < int( ticks.size() ); i++ )
592 {
593 if ( !scaleDraw->scaleDiv().contains( ticks[i] ) )
594 continue;
595
596 QRect labelRect =
597 scaleDraw->boundingLabelRect( axis.font, ticks[i] );
598
599 const int margin = 2;
600 labelRect.adjust( -margin, -margin, margin, margin );
601
602 if ( labelRect.isValid() )
603 clipRegion -= QRegion( labelRect );
604 }
605 }
606 }
607 }
608 painter->setClipRegion( clipRegion );
609 }
610
611 // draw radial grid
612
613 const GridData &radialGrid = d_data->gridData[QwtPolar::Radius];
614 if ( radialGrid.isVisible && radialGrid.isMinorVisible )
615 {
616 painter->setPen( radialGrid.minorPen );
617
618 drawCircles( painter, canvasRect, pole, radialMap,
619 radialGrid.scaleDiv.ticks( QwtScaleDiv::MinorTick ) );
620 drawCircles( painter, canvasRect, pole, radialMap,
621 radialGrid.scaleDiv.ticks( QwtScaleDiv::MediumTick ) );
622 }
623 if ( radialGrid.isVisible )
624 {
625 painter->setPen( radialGrid.majorPen );
626
627 drawCircles( painter, canvasRect, pole, radialMap,
628 radialGrid.scaleDiv.ticks( QwtScaleDiv::MajorTick ) );
629 }
630
631 // draw azimuth grid
632
633 const GridData &azimuthGrid =
634 d_data->gridData[QwtPolar::Azimuth];
635
636 if ( azimuthGrid.isVisible && azimuthGrid.isMinorVisible )
637 {
638 painter->setPen( azimuthGrid.minorPen );
639
640 drawRays( painter, canvasRect, pole, radius, azimuthMap,
641 azimuthGrid.scaleDiv.ticks( QwtScaleDiv::MinorTick ) );
642 drawRays( painter, canvasRect, pole, radius, azimuthMap,
643 azimuthGrid.scaleDiv.ticks( QwtScaleDiv::MediumTick ) );
644 }
645 if ( azimuthGrid.isVisible )
646 {
647 painter->setPen( azimuthGrid.majorPen );
648
649 drawRays( painter, canvasRect, pole, radius, azimuthMap,
650 azimuthGrid.scaleDiv.ticks( QwtScaleDiv::MajorTick ) );
651 }
652 painter->restore();
653
654 for ( int axisId = 0; axisId < QwtPolar::AxesCount; axisId++ )
655 {
656 const AxisData &axis = d_data->axisData[axisId];
657 if ( axis.isVisible )
658 {
659 painter->save();
660 drawAxis( painter, axisId );
661 painter->restore();
662 }
663 }
664}
665
666/*!
667 Draw lines from the pole
668
669 \param painter Painter
670 \param canvasRect Contents rect of the canvas in painter coordinates
671 \param pole Position of the pole in painter coordinates
672 \param radius Length of the lines in painter coordinates
673 \param azimuthMap Maps azimuth values to values related to 0.0, M_2PI
674 \param values Azimuth values, indicating the direction of the lines
675*/
676void QwtPolarGrid::drawRays(
677 QPainter *painter, const QRectF &canvasRect,
678 const QPointF &pole, double radius,
679 const QwtScaleMap &azimuthMap, const QList<double> &values ) const
680{
681 for ( int i = 0; i < int( values.size() ); i++ )
682 {
683 double azimuth = azimuthMap.transform( values[i] );
684 azimuth = ::fmod( azimuth, 2 * M_PI );
685
686 bool skipLine = false;
687 if ( testDisplayFlag( SmartScaleDraw ) )
688 {
689 const QwtAbstractScaleDraw::ScaleComponent bone =
690 QwtAbstractScaleDraw::Backbone;
691 if ( isClose( azimuth, 0.0 ) )
692 {
693 const AxisData &axis = d_data->axisData[QwtPolar::AxisRight];
694 if ( axis.isVisible && axis.scaleDraw->hasComponent( bone ) )
695 skipLine = true;
696 }
697 else if ( isClose( azimuth, M_PI / 2 ) )
698 {
699 const AxisData &axis = d_data->axisData[QwtPolar::AxisTop];
700 if ( axis.isVisible && axis.scaleDraw->hasComponent( bone ) )
701 skipLine = true;
702 }
703 else if ( isClose( azimuth, M_PI ) )
704 {
705 const AxisData &axis = d_data->axisData[QwtPolar::AxisLeft];
706 if ( axis.isVisible && axis.scaleDraw->hasComponent( bone ) )
707 skipLine = true;
708 }
709 else if ( isClose( azimuth, 3 * M_PI / 2.0 ) )
710 {
711 const AxisData &axis = d_data->axisData[QwtPolar::AxisBottom];
712 if ( axis.isVisible && axis.scaleDraw->hasComponent( bone ) )
713 skipLine = true;
714 }
715 }
716 if ( !skipLine )
717 {
718 const QPointF pos = qwtPolar2Pos( pole, radius, azimuth );
719
720 /*
721 Qt4 is horrible slow, when painting primitives,
722 with coordinates far outside the visible area.
723 */
724
725 QPolygonF polygon( 2 );
726 polygon[0] = pole.toPoint();
727 polygon[1] = pos.toPoint();
728
729 if ( testDisplayFlag( ClipGridLines ) )
730 polygon = QwtClipper::clipPolygonF( canvasRect, polygon );
731
732 QwtPainter::drawPolyline( painter, polygon );
733 }
734 }
735}
736
737/*!
738 Draw circles
739
740 \param painter Painter
741 \param canvasRect Contents rect of the canvas in painter coordinates
742 \param pole Position of the pole in painter coordinates
743 \param radialMap Maps radius values into painter coordinates.
744 \param values Radial values, indicating the distances from the pole
745*/
746void QwtPolarGrid::drawCircles(
747 QPainter *painter, const QRectF &canvasRect,
748 const QPointF &pole, const QwtScaleMap &radialMap,
749 const QList<double> &values ) const
750{
751 for ( int i = 0; i < int( values.size() ); i++ )
752 {
753 const double val = values[i];
754
755 const GridData &gridData =
756 d_data->gridData[QwtPolar::Radius];
757
758 bool skipLine = false;
759 if ( testDisplayFlag( SmartScaleDraw ) )
760 {
761 const AxisData &axis = d_data->axisData[QwtPolar::AxisAzimuth];
762 if ( axis.isVisible &&
763 axis.scaleDraw->hasComponent( QwtAbstractScaleDraw::Backbone ) )
764 {
765 if ( isClose( val, gridData.scaleDiv.upperBound() ) )
766 skipLine = true;
767 }
768 }
769
770 if ( isClose( val, gridData.scaleDiv.lowerBound() ) )
771 skipLine = true;
772
773 if ( !skipLine )
774 {
775 const double radius = radialMap.transform( val );
776
777 QRectF outerRect( 0, 0, 2 * radius, 2 * radius );
778 outerRect.moveCenter( pole );
779
780 if ( testDisplayFlag( ClipGridLines ) )
781 {
782 /*
783 Qt4 is horrible slow, when painting primitives,
784 with coordinates far outside the visible area.
785 We need to clip.
786 */
787
788 const QVector<QwtInterval> angles =
789 QwtClipper::clipCircle( canvasRect, pole, radius );
790 for ( int i = 0; i < angles.size(); i++ )
791 {
792 const QwtInterval intv = angles[i];
793 if ( intv.minValue() == 0 && intv.maxValue() == 2 * M_PI )
794 QwtPainter::drawEllipse( painter, outerRect );
795 else
796 {
797 const double from = intv.minValue() / M_PI * 180;
798 const double to = intv.maxValue() / M_PI * 180;
799 double span = to - from;
800 if ( span < 0.0 )
801 span += 360.0;
802
803 painter->drawArc( outerRect,
804 qRound( from * 16 ), qRound( span * 16 ) );
805 }
806 }
807 }
808 else
809 {
810 QwtPainter::drawEllipse( painter, outerRect );
811 }
812 }
813 }
814}
815
816/*!
817 Paint an axis
818
819 \param painter Painter
820 \param axisId Axis id (QwtPolar::Axis)
821*/
822void QwtPolarGrid::drawAxis( QPainter *painter, int axisId ) const
823{
824 if ( axisId < 0 || axisId >= QwtPolar::AxesCount )
825 return;
826
827 AxisData &axis = d_data->axisData[axisId];
828
829 painter->setPen( axis.pen );
830 painter->setFont( axis.font );
831
832 QPalette pal;
833 pal.setColor( QPalette::Foreground, axis.pen.color() );
834 pal.setColor( QPalette::Text, axis.pen.color() );
835
836 axis.scaleDraw->draw( painter, pal );
837}
838
839/*!
840 Update the axis scale draw geometries
841
842 \param azimuthMap Maps azimuth values to values related to 0.0, M_2PI
843 \param radialMap Maps radius values into painter coordinates.
844 \param pole Position of the pole in painter coordinates
845 \param radius Radius of the complete plot area in painter coordinates
846
847 \sa updateScaleDiv()
848*/
849void QwtPolarGrid::updateScaleDraws(
850 const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap,
851 const QPointF &pole, double radius ) const
852{
853 const QPoint p = pole.toPoint();
854
855 const QwtInterval interval =
856 d_data->gridData[QwtPolar::ScaleRadius].scaleDiv.interval();
857
858 const int min = radialMap.transform( interval.minValue() );
859 const int max = radialMap.transform( interval.maxValue() );
860 const int l = max - min;
861
862 for ( int axisId = 0; axisId < QwtPolar::AxesCount; axisId++ )
863 {
864 AxisData &axis = d_data->axisData[axisId];
865
866 if ( axisId == QwtPolar::AxisAzimuth )
867 {
868 QwtRoundScaleDraw *scaleDraw =
869 static_cast<QwtRoundScaleDraw *>( axis.scaleDraw );
870
871 scaleDraw->setRadius( qRound( radius ) );
872 scaleDraw->moveCenter( p );
873
874 double from = ::fmod( 90.0 - azimuthMap.p1() * 180.0 / M_PI, 360.0 );
875 if ( from < 0.0 )
876 from += 360.0;
877
878 scaleDraw->setAngleRange( from, from - 360.0 );
879
880 const QwtTransform *transform = azimuthMap.transformation();
881 if ( transform )
882 scaleDraw->setTransformation( transform->copy() );
883 else
884 scaleDraw->setTransformation( NULL );
885 }
886 else
887 {
888 QwtScaleDraw *scaleDraw =
889 static_cast<QwtScaleDraw *>( axis.scaleDraw );
890
891 switch( axisId )
892 {
893 case QwtPolar::AxisLeft:
894 {
895 scaleDraw->move( p.x() - min, p.y() );
896 scaleDraw->setLength( -l );
897 break;
898 }
899 case QwtPolar::AxisRight:
900 {
901 scaleDraw->move( p.x() + min, p.y() );
902 scaleDraw->setLength( l );
903 break;
904 }
905 case QwtPolar::AxisTop:
906 {
907 scaleDraw->move( p.x(), p.y() - max );
908 scaleDraw->setLength( l );
909 break;
910 }
911 case QwtPolar::AxisBottom:
912 {
913 scaleDraw->move( p.x(), p.y() + max );
914 scaleDraw->setLength( -l );
915 break;
916 }
917 }
918 const QwtTransform *transform = radialMap.transformation();
919 if ( transform )
920 scaleDraw->setTransformation( transform->copy() );
921 else
922 scaleDraw->setTransformation( NULL );
923 }
924 }
925}
926
927/*!
928 \brief Update the item to changes of the axes scale division
929
930 If AutoScaling is enabled the radial scale is calculated
931 from the interval, otherwise the scales are adopted to
932 the plot scales.
933
934 \param azimuthScaleDiv Scale division of the azimuth-scale
935 \param radialScaleDiv Scale division of the radius-axis
936 \param interval The interval of the radius-axis, that is
937 visible on the canvas
938
939 \sa QwtPolarPlot::setGridAttributes()
940*/
941
942void QwtPolarGrid::updateScaleDiv( const QwtScaleDiv &azimuthScaleDiv,
943 const QwtScaleDiv &radialScaleDiv, const QwtInterval &interval )
944{
945 GridData &radialGrid = d_data->gridData[QwtPolar::Radius];
946
947 const QwtPolarPlot *plt = plot();
948 if ( plt && testGridAttribute( AutoScaling ) )
949 {
950 const QwtScaleEngine *se = plt->scaleEngine( QwtPolar::Radius );
951 radialGrid.scaleDiv = se->divideScale(
952 interval.minValue(), interval.maxValue(),
953 plt->scaleMaxMajor( QwtPolar::Radius ),
954 plt->scaleMaxMinor( QwtPolar::Radius ), 0 );
955 }
956 else
957 {
958 if ( radialGrid.scaleDiv != radialScaleDiv )
959 radialGrid.scaleDiv = radialScaleDiv;
960 }
961
962 GridData &azimuthGrid = d_data->gridData[QwtPolar::Azimuth];
963 if ( azimuthGrid.scaleDiv != azimuthScaleDiv )
964 {
965 azimuthGrid.scaleDiv = azimuthScaleDiv;
966 }
967
968 bool hasOrigin = false;
969 for ( int axisId = 0; axisId < QwtPolar::AxesCount; axisId++ )
970 {
971 AxisData &axis = d_data->axisData[axisId];
972 if ( axis.isVisible && axis.scaleDraw )
973 {
974 if ( axisId == QwtPolar::AxisAzimuth )
975 {
976 axis.scaleDraw->setScaleDiv( azimuthGrid.scaleDiv );
977 if ( testDisplayFlag( SmartScaleDraw ) )
978 {
979 axis.scaleDraw->enableComponent(
980 QwtAbstractScaleDraw::Ticks, !azimuthGrid.isVisible );
981 }
982 }
983 else
984 {
985 QwtScaleDiv sd = radialGrid.scaleDiv;
986
987 QList<double> ticks = sd.ticks( QwtScaleDiv::MajorTick );
988
989 if ( testDisplayFlag( SmartOriginLabel ) )
990 {
991 bool skipOrigin = hasOrigin;
992 if ( !skipOrigin )
993 {
994 if ( axisId == QwtPolar::AxisLeft
995 || axisId == QwtPolar::AxisRight )
996 {
997 if ( d_data->axisData[QwtPolar::AxisBottom].isVisible )
998 skipOrigin = true;
999 }
1000 else
1001 {
1002 if ( d_data->axisData[QwtPolar::AxisLeft].isVisible )
1003 skipOrigin = true;
1004 }
1005 }
1006 if ( ticks.size() > 0 && ticks.first() == sd.lowerBound() )
1007 {
1008 if ( skipOrigin )
1009 ticks.removeFirst();
1010 else
1011 hasOrigin = true;
1012 }
1013 }
1014
1015 if ( testDisplayFlag( HideMaxRadiusLabel ) )
1016 {
1017 if ( ticks.size() > 0 && ticks.last() == sd.upperBound() )
1018 ticks.removeLast();
1019 }
1020
1021 sd.setTicks( QwtScaleDiv::MajorTick, ticks );
1022 axis.scaleDraw->setScaleDiv( sd );
1023
1024 if ( testDisplayFlag( SmartScaleDraw ) )
1025 {
1026 axis.scaleDraw->enableComponent(
1027 QwtAbstractScaleDraw::Ticks, !radialGrid.isVisible );
1028 }
1029
1030 }
1031 }
1032 }
1033}
1034
1035/*!
1036 \return Number of pixels, that are necessary to paint the azimuth scale
1037 \sa QwtRoundScaleDraw::extent()
1038*/
1039int QwtPolarGrid::marginHint() const
1040{
1041 const AxisData &axis = d_data->axisData[QwtPolar::AxisAzimuth];
1042 if ( axis.isVisible )
1043 {
1044 const int extent = axis.scaleDraw->extent( axis.font );
1045 return extent;
1046 }
1047
1048 return 0;
1049}
1050
1051/*!
1052 Returns the scale draw of a specified axis
1053
1054 \param axisId axis index ( QwtPolar::AxisLeft <= axisId <= QwtPolar::AxisBottom)
1055 \return specified scaleDraw for axis, or NULL if axis is invalid.
1056 \sa azimuthScaleDraw()
1057*/
1058const QwtScaleDraw *QwtPolarGrid::scaleDraw( int axisId ) const
1059{
1060 if ( axisId >= QwtPolar::AxisLeft && axisId <= QwtPolar::AxisBottom )
1061 return static_cast<QwtScaleDraw *>( d_data->axisData[axisId].scaleDraw );
1062
1063 return NULL;
1064}
1065
1066/*!
1067 Returns the scale draw of a specified axis
1068
1069 \param axisId axis index ( QwtPolar::AxisLeft <= axisId <= QwtPolar::AxisBottom)
1070 \return specified scaleDraw for axis, or NULL if axis is invalid.
1071 \sa setScaleDraw(), azimuthScaleDraw()
1072*/
1073QwtScaleDraw *QwtPolarGrid::scaleDraw( int axisId )
1074{
1075 if ( axisId >= QwtPolar::AxisLeft && axisId <= QwtPolar::AxisBottom )
1076 return static_cast<QwtScaleDraw *>( d_data->axisData[axisId].scaleDraw );
1077
1078 return NULL;
1079}
1080
1081/*!
1082 \brief Set a scale draw
1083
1084 \param axisId axis index ( QwtPolar::AxisLeft <= axisId <= QwtPolar::AxisBottom)
1085 \param scaleDraw object responsible for drawing scales.
1086
1087 \sa scaleDraw(), setAzimuthScaleDraw()
1088*/
1089void QwtPolarGrid::setScaleDraw( int axisId, QwtScaleDraw *scaleDraw )
1090{
1091 if ( axisId < QwtPolar::AxisLeft || axisId > QwtPolar::AxisBottom )
1092 return;
1093
1094 AxisData &axisData = d_data->axisData[axisId];
1095 if ( axisData.scaleDraw != scaleDraw )
1096 {
1097 delete axisData.scaleDraw;
1098 axisData.scaleDraw = scaleDraw;
1099 itemChanged();
1100 }
1101}
1102
1103/*!
1104 \return Scale draw for the azimuth scale
1105 \sa setAzimuthScaleDraw(), scaleDraw()
1106*/
1107const QwtRoundScaleDraw *QwtPolarGrid::azimuthScaleDraw() const
1108{
1109 return static_cast<QwtRoundScaleDraw *>(
1110 d_data->axisData[QwtPolar::AxisAzimuth].scaleDraw );
1111}
1112
1113/*!
1114 \return Scale draw for the azimuth scale
1115 \sa setAzimuthScaleDraw(), scaleDraw()
1116*/
1117QwtRoundScaleDraw *QwtPolarGrid::azimuthScaleDraw()
1118{
1119 return static_cast<QwtRoundScaleDraw *>(
1120 d_data->axisData[QwtPolar::AxisAzimuth].scaleDraw );
1121}
1122
1123/*!
1124 \brief Set a scale draw for the azimuth scale
1125
1126 \param scaleDraw object responsible for drawing scales.
1127 \sa azimuthScaleDraw(), setScaleDraw()
1128*/
1129void QwtPolarGrid::setAzimuthScaleDraw( QwtRoundScaleDraw *scaleDraw )
1130{
1131 AxisData &axisData = d_data->axisData[QwtPolar::AxisAzimuth];
1132 if ( axisData.scaleDraw != scaleDraw )
1133 {
1134 delete axisData.scaleDraw;
1135 axisData.scaleDraw = scaleDraw;
1136 itemChanged();
1137 }
1138}
Note: See TracBrowser for help on using the repository browser.