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

Last change on this file since 7784 was 4272, checked in by mervart, 12 years ago
File size: 31.0 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 scaleDraw->setTransformation( azimuthMap.transformation()->copy() );
880 }
881 else
882 {
883 QwtScaleDraw *scaleDraw =
884 static_cast<QwtScaleDraw *>( axis.scaleDraw );
885
886 switch( axisId )
887 {
888 case QwtPolar::AxisLeft:
889 {
890 scaleDraw->move( p.x() - min, p.y() );
891 scaleDraw->setLength( -l );
892 break;
893 }
894 case QwtPolar::AxisRight:
895 {
896 scaleDraw->move( p.x() + min, p.y() );
897 scaleDraw->setLength( l );
898 break;
899 }
900 case QwtPolar::AxisTop:
901 {
902 scaleDraw->move( p.x(), p.y() - max );
903 scaleDraw->setLength( l );
904 break;
905 }
906 case QwtPolar::AxisBottom:
907 {
908 scaleDraw->move( p.x(), p.y() + max );
909 scaleDraw->setLength( -l );
910 break;
911 }
912 }
913 scaleDraw->setTransformation( radialMap.transformation()->copy() );
914 }
915 }
916}
917
918/*!
919 \brief Update the item to changes of the axes scale division
920
921 If AutoScaling is enabled the radial scale is calculated
922 from the interval, otherwise the scales are adopted to
923 the plot scales.
924
925 \param azimuthScaleDiv Scale division of the azimuth-scale
926 \param radialScaleDiv Scale division of the radius-axis
927 \param interval The interval of the radius-axis, that is
928 visible on the canvas
929
930 \sa QwtPolarPlot::setGridAttributes()
931*/
932
933void QwtPolarGrid::updateScaleDiv( const QwtScaleDiv &azimuthScaleDiv,
934 const QwtScaleDiv &radialScaleDiv, const QwtInterval &interval )
935{
936 GridData &radialGrid = d_data->gridData[QwtPolar::Radius];
937
938 const QwtPolarPlot *plt = plot();
939 if ( plt && testGridAttribute( AutoScaling ) )
940 {
941 const QwtScaleEngine *se = plt->scaleEngine( QwtPolar::Radius );
942 radialGrid.scaleDiv = se->divideScale(
943 interval.minValue(), interval.maxValue(),
944 plt->scaleMaxMajor( QwtPolar::Radius ),
945 plt->scaleMaxMinor( QwtPolar::Radius ), 0 );
946 }
947 else
948 {
949 if ( radialGrid.scaleDiv != radialScaleDiv )
950 radialGrid.scaleDiv = radialScaleDiv;
951 }
952
953 GridData &azimuthGrid = d_data->gridData[QwtPolar::Azimuth];
954 if ( azimuthGrid.scaleDiv != azimuthScaleDiv )
955 {
956 azimuthGrid.scaleDiv = azimuthScaleDiv;
957 }
958
959 bool hasOrigin = false;
960 for ( int axisId = 0; axisId < QwtPolar::AxesCount; axisId++ )
961 {
962 AxisData &axis = d_data->axisData[axisId];
963 if ( axis.isVisible && axis.scaleDraw )
964 {
965 if ( axisId == QwtPolar::AxisAzimuth )
966 {
967 axis.scaleDraw->setScaleDiv( azimuthGrid.scaleDiv );
968 if ( testDisplayFlag( SmartScaleDraw ) )
969 {
970 axis.scaleDraw->enableComponent(
971 QwtAbstractScaleDraw::Ticks, !azimuthGrid.isVisible );
972 }
973 }
974 else
975 {
976 QwtScaleDiv sd = radialGrid.scaleDiv;
977
978 QList<double> &ticks =
979 const_cast<QList<double> &>( sd.ticks( QwtScaleDiv::MajorTick ) );
980
981 if ( testDisplayFlag( SmartOriginLabel ) )
982 {
983 bool skipOrigin = hasOrigin;
984 if ( !skipOrigin )
985 {
986 if ( axisId == QwtPolar::AxisLeft
987 || axisId == QwtPolar::AxisRight )
988 {
989 if ( d_data->axisData[QwtPolar::AxisBottom].isVisible )
990 skipOrigin = true;
991 }
992 else
993 {
994 if ( d_data->axisData[QwtPolar::AxisLeft].isVisible )
995 skipOrigin = true;
996 }
997 }
998 if ( ticks.size() > 0 && ticks.first() == sd.lowerBound() )
999 {
1000 if ( skipOrigin )
1001 ticks.removeFirst();
1002 else
1003 hasOrigin = true;
1004 }
1005 }
1006
1007 if ( testDisplayFlag( HideMaxRadiusLabel ) )
1008 {
1009 if ( ticks.size() > 0 && ticks.last() == sd.upperBound() )
1010 ticks.removeLast();
1011 }
1012
1013 axis.scaleDraw->setScaleDiv( sd );
1014
1015 if ( testDisplayFlag( SmartScaleDraw ) )
1016 {
1017 axis.scaleDraw->enableComponent(
1018 QwtAbstractScaleDraw::Ticks, !radialGrid.isVisible );
1019 }
1020
1021 }
1022 }
1023 }
1024}
1025
1026/*!
1027 \return Number of pixels, that are necessary to paint the azimuth scale
1028 \sa QwtRoundScaleDraw::extent()
1029*/
1030int QwtPolarGrid::marginHint() const
1031{
1032 const AxisData &axis = d_data->axisData[QwtPolar::AxisAzimuth];
1033 if ( axis.isVisible )
1034 {
1035 const int extent = axis.scaleDraw->extent( axis.font );
1036 return extent;
1037 }
1038
1039 return 0;
1040}
1041
1042/*!
1043 Returns the scale draw of a specified axis
1044
1045 \param axisId axis index ( QwtPolar::AxisLeft <= axisId <= QwtPolar::AxisBottom)
1046 \return specified scaleDraw for axis, or NULL if axis is invalid.
1047 \sa azimuthScaleDraw()
1048*/
1049const QwtScaleDraw *QwtPolarGrid::scaleDraw( int axisId ) const
1050{
1051 if ( axisId >= QwtPolar::AxisLeft || axisId <= QwtPolar::AxisBottom )
1052 return static_cast<QwtScaleDraw *>( d_data->axisData[axisId].scaleDraw );
1053
1054 return NULL;
1055}
1056
1057/*!
1058 Returns the scale draw of a specified axis
1059
1060 \param axisId axis index ( QwtPolar::AxisLeft <= axisId <= QwtPolar::AxisBottom)
1061 \return specified scaleDraw for axis, or NULL if axis is invalid.
1062 \sa setScaleDraw(), azimuthScaleDraw()
1063*/
1064QwtScaleDraw *QwtPolarGrid::scaleDraw( int axisId )
1065{
1066 if ( axisId >= QwtPolar::AxisLeft || axisId <= QwtPolar::AxisBottom )
1067 return static_cast<QwtScaleDraw *>( d_data->axisData[axisId].scaleDraw );
1068
1069 return NULL;
1070}
1071
1072/*!
1073 \brief Set a scale draw
1074
1075 \param axisId axis index ( QwtPolar::AxisLeft <= axisId <= QwtPolar::AxisBottom)
1076 \param scaleDraw object responsible for drawing scales.
1077
1078 \sa scaleDraw(), setAzimuthScaleDraw()
1079*/
1080void QwtPolarGrid::setScaleDraw( int axisId, QwtScaleDraw *scaleDraw )
1081{
1082 if ( axisId < QwtPolar::AxisLeft || axisId > QwtPolar::AxisBottom )
1083 return;
1084
1085 AxisData &axisData = d_data->axisData[axisId];
1086 if ( axisData.scaleDraw != scaleDraw )
1087 {
1088 delete axisData.scaleDraw;
1089 axisData.scaleDraw = scaleDraw;
1090 itemChanged();
1091 }
1092}
1093
1094/*!
1095 \return Scale draw for the azimuth scale
1096 \sa setAzimuthScaleDraw(), scaleDraw()
1097*/
1098const QwtRoundScaleDraw *QwtPolarGrid::azimuthScaleDraw() const
1099{
1100 return static_cast<QwtRoundScaleDraw *>(
1101 d_data->axisData[QwtPolar::AxisAzimuth].scaleDraw );
1102}
1103
1104/*!
1105 \return Scale draw for the azimuth scale
1106 \sa setAzimuthScaleDraw(), scaleDraw()
1107*/
1108QwtRoundScaleDraw *QwtPolarGrid::azimuthScaleDraw()
1109{
1110 return static_cast<QwtRoundScaleDraw *>(
1111 d_data->axisData[QwtPolar::AxisAzimuth].scaleDraw );
1112}
1113
1114/*!
1115 \brief Set a scale draw for the azimuth scale
1116
1117 \param scaleDraw object responsible for drawing scales.
1118 \sa azimuthScaleDraw(), setScaleDraw()
1119*/
1120void QwtPolarGrid::setAzimuthScaleDraw( QwtRoundScaleDraw *scaleDraw )
1121{
1122 AxisData &axisData = d_data->axisData[QwtPolar::AxisAzimuth];
1123 if ( axisData.scaleDraw != scaleDraw )
1124 {
1125 delete axisData.scaleDraw;
1126 axisData.scaleDraw = scaleDraw;
1127 itemChanged();
1128 }
1129}
Note: See TracBrowser for help on using the repository browser.