Qwt User's Guide: qwt_polar_plot.cpp Source File

Qwt User's Guide 6.2.0

qwt_polar_plot.cpp
1 /******************************************************************************
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_plot.h"
10 #include "qwt_polar_canvas.h"
11 #include "qwt_polar_layout.h"
12 #include "qwt_painter.h"
13 #include "qwt_scale_engine.h"
14 #include "qwt_scale_div.h"
15 #include "qwt_text_label.h"
16 #include "qwt_round_scale_draw.h"
17 #include "qwt_legend.h"
18 #include "qwt_dyngrid_layout.h"
19
20 #include <qpointer.h>
21 #include <qpaintengine.h>
22 #include <qpainter.h>
23 #include <qevent.h>
24
25 static inline double qwtDistance(
26 const QPointF& p1, const QPointF& p2 )
27 {
28 double dx = p2.x() - p1.x();
29 double dy = p2.y() - p1.y();
30 return qSqrt( dx * dx + dy * dy );
31 }
32
33 namespace
34 {
35 class ScaleData
36 {
37 public:
38 ScaleData()
39 : isValid( false )
40 , scaleEngine( NULL )
41 {
42 }
43
44 ~ScaleData()
45 {
46 delete scaleEngine;
47 }
48
49 bool doAutoScale;
50
51 double minValue;
52 double maxValue;
53 double stepSize;
54
55 int maxMajor;
56 int maxMinor;
57
58 bool isValid;
59
60 QwtScaleDiv scaleDiv;
61 QwtScaleEngine* scaleEngine;
62 };
63 }
64
65 class QwtPolarPlot::PrivateData
66 {
67 public:
68 QBrush canvasBrush;
69
70 bool autoReplot;
71
72 QwtPointPolar zoomPos;
73 double zoomFactor;
74
75 ScaleData scaleData[QwtPolar::ScaleCount];
76 QPointer< QwtTextLabel > titleLabel;
77 QPointer< QwtPolarCanvas > canvas;
78 QPointer< QwtAbstractLegend > legend;
79 double azimuthOrigin;
80
81 QwtPolarLayout* layout;
82 };
83
88 QwtPolarPlot::QwtPolarPlot( QWidget* parent )
89 : QFrame( parent )
90 {
91 initPlot( QwtText() );
92 }
93
99 QwtPolarPlot::QwtPolarPlot( const QwtText& title, QWidget* parent )
100 : QFrame( parent )
101 {
102 initPlot( title );
103 }
104
106 QwtPolarPlot::~QwtPolarPlot()
107 {
108 detachItems( QwtPolarItem::Rtti_PolarItem, autoDelete() );
109
110 delete m_data->layout;
111 delete m_data;
112 }
113
118 void QwtPolarPlot::setTitle( const QString& title )
119 {
120 if ( title != m_data->titleLabel->text().text() )
121 {
122 m_data->titleLabel->setText( title );
123 if ( !title.isEmpty() )
124 m_data->titleLabel->show();
125 else
126 m_data->titleLabel->hide();
127 }
128 }
129
134 void QwtPolarPlot::setTitle( const QwtText& title )
135 {
136 if ( title != m_data->titleLabel->text() )
137 {
138 m_data->titleLabel->setText( title );
139 if ( !title.isEmpty() )
140 m_data->titleLabel->show();
141 else
142 m_data->titleLabel->hide();
143 }
144 }
145
147 QwtText QwtPolarPlot::title() const
148 {
149 return m_data->titleLabel->text();
150 }
151
153 QwtTextLabel* QwtPolarPlot::titleLabel()
154 {
155 return m_data->titleLabel;
156 }
157
159 const QwtTextLabel* QwtPolarPlot::titleLabel() const
160 {
161 return m_data->titleLabel;
162 }
163
191 void QwtPolarPlot::insertLegend( QwtAbstractLegend* legend,
192 QwtPolarPlot::LegendPosition pos, double ratio )
193 {
194 m_data->layout->setLegendPosition( pos, ratio );
195
196 if ( legend != m_data->legend )
197 {
198 if ( m_data->legend && m_data->legend->parent() == this )
199 delete m_data->legend;
200
201 m_data->legend = legend;
202
203 if ( m_data->legend )
204 {
205 connect( this,
206 SIGNAL(legendDataChanged(
207 const QVariant&,const QList<QwtLegendData>&)),
208 m_data->legend,
209 SLOT(updateLegend(
210 const QVariant&,const QList<QwtLegendData>&))
211 );
212
213 if ( m_data->legend->parent() != this )
214 m_data->legend->setParent( this );
215
216 updateLegend();
217
218 QwtLegend* lgd = qobject_cast< QwtLegend* >( legend );
219 if ( lgd )
220 {
221 switch ( m_data->layout->legendPosition() )
222 {
223 case LeftLegend:
224 case RightLegend:
225 {
226 if ( lgd->maxColumns() == 0 )
227 lgd->setMaxColumns( 1 ); // 1 column: align vertical
228 break;
229 }
230 case TopLegend:
231 case BottomLegend:
232 {
233 lgd->setMaxColumns( 0 ); // unlimited
234 break;
235 }
236 default:
237 break;
238 }
239 }
240
241 }
242 }
243
244 updateLayout();
245 }
246
252 void QwtPolarPlot::updateLegend()
253 {
254 const QwtPolarItemList& itmList = itemList();
255 for ( QwtPolarItemIterator it = itmList.begin();
256 it != itmList.end(); ++it )
257 {
258 updateLegend( *it );
259 }
260 }
261
268 void QwtPolarPlot::updateLegend( const QwtPolarItem* plotItem )
269 {
270 if ( plotItem == NULL )
271 return;
272
273 QList< QwtLegendData > legendData;
274
275 if ( plotItem->testItemAttribute( QwtPolarItem::Legend ) )
276 legendData = plotItem->legendData();
277
278 const QVariant itemInfo = itemToInfo( const_cast< QwtPolarItem* >( plotItem ) );
279 Q_EMIT legendDataChanged( itemInfo, legendData );
280 }
281
286 QwtAbstractLegend* QwtPolarPlot::legend()
287 {
288 return m_data->legend;
289 }
290
295 const QwtAbstractLegend* QwtPolarPlot::legend() const
296 {
297 return m_data->legend;
298 }
299
309 void QwtPolarPlot::setPlotBackground( const QBrush& brush )
310 {
311 if ( brush != m_data->canvasBrush )
312 {
313 m_data->canvasBrush = brush;
314 autoRefresh();
315 }
316 }
317
322 const QBrush& QwtPolarPlot::plotBackground() const
323 {
324 return m_data->canvasBrush;
325 }
326
342 void QwtPolarPlot::setAutoReplot( bool enable )
343 {
344 m_data->autoReplot = enable;
345 }
346
348 bool QwtPolarPlot::autoReplot() const
349 {
350 return m_data->autoReplot;
351 }
352
368 void QwtPolarPlot::setAutoScale( int scaleId )
369 {
370 if ( scaleId != QwtPolar::ScaleRadius )
371 return;
372
373 ScaleData& scaleData = m_data->scaleData[scaleId];
374 if ( !scaleData.doAutoScale )
375 {
376 scaleData.doAutoScale = true;
377 autoRefresh();
378 }
379 }
380
386 bool QwtPolarPlot::hasAutoScale( int scaleId ) const
387 {
388 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
389 return false;
390
391 return m_data->scaleData[scaleId].doAutoScale;
392 }
393
401 void QwtPolarPlot::setScaleMaxMinor( int scaleId, int maxMinor )
402 {
403 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
404 return;
405
406 maxMinor = qBound( 0, maxMinor, 100 );
407
408 ScaleData& scaleData = m_data->scaleData[scaleId];
409
410 if ( maxMinor != scaleData.maxMinor )
411 {
412 scaleData.maxMinor = maxMinor;
413 scaleData.isValid = false;
414 autoRefresh();
415 }
416 }
417
423 int QwtPolarPlot::scaleMaxMinor( int scaleId ) const
424 {
425 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
426 return 0;
427
428 return m_data->scaleData[scaleId].maxMinor;
429 }
430
438 void QwtPolarPlot::setScaleMaxMajor( int scaleId, int maxMajor )
439 {
440 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
441 return;
442
443 maxMajor = qBound( 1, maxMajor, 10000 );
444
445 ScaleData& scaleData = m_data->scaleData[scaleId];
446 if ( maxMajor != scaleData.maxMinor )
447 {
448 scaleData.maxMajor = maxMajor;
449 scaleData.isValid = false;
450 autoRefresh();
451 }
452 }
453
460 int QwtPolarPlot::scaleMaxMajor( int scaleId ) const
461 {
462 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
463 return 0;
464
465 return m_data->scaleData[scaleId].maxMajor;
466 }
467
476 void QwtPolarPlot::setScaleEngine( int scaleId, QwtScaleEngine* scaleEngine )
477 {
478 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
479 return;
480
481 ScaleData& scaleData = m_data->scaleData[scaleId];
482 if ( scaleEngine == NULL || scaleEngine == scaleData.scaleEngine )
483 return;
484
485 delete scaleData.scaleEngine;
486 scaleData.scaleEngine = scaleEngine;
487
488 scaleData.isValid = false;
489
490 autoRefresh();
491 }
492
499 QwtScaleEngine* QwtPolarPlot::scaleEngine( int scaleId )
500 {
501 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
502 return NULL;
503
504 return m_data->scaleData[scaleId].scaleEngine;
505 }
506
513 const QwtScaleEngine* QwtPolarPlot::scaleEngine( int scaleId ) const
514 {
515 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
516 return NULL;
517
518 return m_data->scaleData[scaleId].scaleEngine;
519 }
520
530 void QwtPolarPlot::setScale( int scaleId,
531 double min, double max, double stepSize )
532 {
533 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
534 return;
535
536 ScaleData& scaleData = m_data->scaleData[scaleId];
537
538 scaleData.isValid = false;
539
540 scaleData.minValue = min;
541 scaleData.maxValue = max;
542 scaleData.stepSize = stepSize;
543 scaleData.doAutoScale = false;
544
545 autoRefresh();
546 }
547
554 void QwtPolarPlot::setScaleDiv( int scaleId, const QwtScaleDiv& scaleDiv )
555 {
556 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
557 return;
558
559 ScaleData& scaleData = m_data->scaleData[scaleId];
560
561 scaleData.scaleDiv = scaleDiv;
562 scaleData.isValid = true;
563 scaleData.doAutoScale = false;
564
565 autoRefresh();
566 }
567
579 const QwtScaleDiv* QwtPolarPlot::scaleDiv( int scaleId ) const
580 {
581 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
582 return NULL;
583
584 return &m_data->scaleData[scaleId].scaleDiv;
585 }
586
598 QwtScaleDiv* QwtPolarPlot::scaleDiv( int scaleId )
599 {
600 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
601 return NULL;
602
603 return &m_data->scaleData[scaleId].scaleDiv;
604 }
605
615 void QwtPolarPlot::setAzimuthOrigin( double origin )
616 {
617 origin = ::fmod( origin, 2 * M_PI );
618 if ( origin != m_data->azimuthOrigin )
619 {
620 m_data->azimuthOrigin = origin;
621 autoRefresh();
622 }
623 }
624
632 double QwtPolarPlot::azimuthOrigin() const
633 {
634 return m_data->azimuthOrigin;
635 }
636
651 void QwtPolarPlot::zoom( const QwtPointPolar& zoomPos, double zoomFactor )
652 {
653 zoomFactor = qAbs( zoomFactor );
654 if ( zoomPos != m_data->zoomPos ||
655 zoomFactor != m_data->zoomFactor )
656 {
657 m_data->zoomPos = zoomPos;
658 m_data->zoomFactor = zoomFactor;
659 updateLayout();
660 autoRefresh();
661 }
662 }
663
668 void QwtPolarPlot::unzoom()
669 {
670 if ( m_data->zoomFactor != 1.0 || m_data->zoomPos.isValid() )
671 {
672 m_data->zoomFactor = 1.0;
673 m_data->zoomPos = QwtPointPolar();
674 autoRefresh();
675 }
676 }
677
682 QwtPointPolar QwtPolarPlot::zoomPos() const
683 {
684 return m_data->zoomPos;
685 }
686
691 double QwtPolarPlot::zoomFactor() const
692 {
693 return m_data->zoomFactor;
694 }
695
710 QwtScaleMap QwtPolarPlot::scaleMap( int scaleId ) const
711 {
712 const QRectF pr = plotRect();
713 return scaleMap( scaleId, pr.width() / 2.0 );
714 }
715
730 QwtScaleMap QwtPolarPlot::scaleMap( int scaleId, const double radius ) const
731 {
732 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
733 return QwtScaleMap();
734
735 QwtScaleMap map;
736 map.setTransformation( scaleEngine( scaleId )->transformation() );
737
738 const QwtScaleDiv* sd = scaleDiv( scaleId );
739 map.setScaleInterval( sd->lowerBound(), sd->upperBound() );
740
741 if ( scaleId == QwtPolar::Azimuth )
742 {
743 map.setPaintInterval( m_data->azimuthOrigin,
744 m_data->azimuthOrigin + 2 * M_PI );
745 }
746 else
747 {
748 map.setPaintInterval( 0.0, radius );
749 }
750
751 return map;
752 }
753
762 bool QwtPolarPlot::event( QEvent* e )
763 {
764 bool ok = QWidget::event( e );
765 switch( e->type() )
766 {
767 case QEvent::LayoutRequest:
768 {
769 updateLayout();
770 break;
771 }
772 case QEvent::PolishRequest:
773 {
774 updateLayout();
775 replot();
776 break;
777 }
778 default:;
779 }
780 return ok;
781 }
782
784 void QwtPolarPlot::resizeEvent( QResizeEvent* e )
785 {
786 QFrame::resizeEvent( e );
787 updateLayout();
788 }
789
790 void QwtPolarPlot::initPlot( const QwtText& title )
791 {
792 m_data = new PrivateData;
793 m_data->layout = new QwtPolarLayout;
794
795 QwtText text( title );
796 text.setRenderFlags( Qt::AlignCenter | Qt::TextWordWrap );
797
798 m_data->titleLabel = new QwtTextLabel( text, this );
799 m_data->titleLabel->setFont( QFont( fontInfo().family(), 14, QFont::Bold ) );
800 if ( !text.isEmpty() )
801 m_data->titleLabel->show();
802 else
803 m_data->titleLabel->hide();
804
805 m_data->canvas = new QwtPolarCanvas( this );
806
807 m_data->autoReplot = false;
808 m_data->canvasBrush = QBrush( Qt::white );
809
810 for ( int scaleId = 0; scaleId < QwtPolar::ScaleCount; scaleId++ )
811 {
812 ScaleData& scaleData = m_data->scaleData[scaleId];
813
814 if ( scaleId == QwtPolar::Azimuth )
815 {
816 scaleData.minValue = 0.0;
817 scaleData.maxValue = 360.0;
818 scaleData.stepSize = 30.0;
819 }
820 else
821 {
822 scaleData.minValue = 0.0;
823 scaleData.maxValue = 1000.0;
824 scaleData.stepSize = 0.0;
825 }
826
827 scaleData.doAutoScale = true;
828
829 scaleData.maxMinor = 5;
830 scaleData.maxMajor = 8;
831
832 scaleData.isValid = false;
833
834 scaleData.scaleEngine = new QwtLinearScaleEngine;
835 }
836 m_data->zoomFactor = 1.0;
837 m_data->azimuthOrigin = 0.0;
838
839 setSizePolicy( QSizePolicy::MinimumExpanding,
840 QSizePolicy::MinimumExpanding );
841
842 for ( int scaleId = 0; scaleId < QwtPolar::ScaleCount; scaleId++ )
843 updateScale( scaleId );
844 }
845
847 void QwtPolarPlot::autoRefresh()
848 {
849 if ( m_data->autoReplot )
850 replot();
851 }
852
854 void QwtPolarPlot::updateLayout()
855 {
856 m_data->layout->activate( this, contentsRect() );
857
858 // resize and show the visible widgets
859 if ( m_data->titleLabel )
860 {
861 if ( !m_data->titleLabel->text().isEmpty() )
862 {
863 m_data->titleLabel->setGeometry( m_data->layout->titleRect().toRect() );
864 if ( !m_data->titleLabel->isVisible() )
865 m_data->titleLabel->show();
866 }
867 else
868 m_data->titleLabel->hide();
869 }
870
871 if ( m_data->legend )
872 {
873 if ( m_data->legend->isEmpty() )
874 {
875 m_data->legend->hide();
876 }
877 else
878 {
879 const QRectF legendRect = m_data->layout->legendRect();
880 m_data->legend->setGeometry( legendRect.toRect() );
881 m_data->legend->show();
882 }
883 }
884
885 m_data->canvas->setGeometry( m_data->layout->canvasRect().toRect() );
886 Q_EMIT layoutChanged();
887 }
888
899 void QwtPolarPlot::replot()
900 {
901 bool doAutoReplot = autoReplot();
902 setAutoReplot( false );
903
904 for ( int scaleId = 0; scaleId < QwtPolar::ScaleCount; scaleId++ )
905 updateScale( scaleId );
906
907 m_data->canvas->invalidateBackingStore();
908 m_data->canvas->repaint();
909
910 setAutoReplot( doAutoReplot );
911 }
912
914 QwtPolarCanvas* QwtPolarPlot::canvas()
915 {
916 return m_data->canvas;
917 }
918
920 const QwtPolarCanvas* QwtPolarPlot::canvas() const
921 {
922 return m_data->canvas;
923 }
924
930 void QwtPolarPlot::drawCanvas( QPainter* painter,
931 const QRectF& canvasRect ) const
932 {
933 const QRectF cr = canvasRect;
934 const QRectF pr = plotRect( cr );
935
936 const double radius = pr.width() / 2.0;
937
938 if ( m_data->canvasBrush.style() != Qt::NoBrush )
939 {
940 painter->save();
941 painter->setPen( Qt::NoPen );
942 painter->setBrush( m_data->canvasBrush );
943
944 if ( qwtDistance( pr.center(), cr.topLeft() ) < radius &&
945 qwtDistance( pr.center(), cr.topRight() ) < radius &&
946 qwtDistance( pr.center(), cr.bottomRight() ) < radius &&
947 qwtDistance( pr.center(), cr.bottomLeft() ) < radius )
948 {
949 QwtPainter::drawRect( painter, cr );
950 }
951 else
952 {
953 painter->setRenderHint( QPainter::Antialiasing, true );
954 QwtPainter::drawEllipse( painter, pr );
955 }
956 painter->restore();
957 }
958
959 drawItems( painter,
960 scaleMap( QwtPolar::Azimuth, radius ),
961 scaleMap( QwtPolar::Radius, radius ),
962 pr.center(), radius, canvasRect );
963 }
964
975 void QwtPolarPlot::drawItems( QPainter* painter,
976 const QwtScaleMap& azimuthMap, const QwtScaleMap& radialMap,
977 const QPointF& pole, double radius,
978 const QRectF& canvasRect ) const
979 {
980 const QRectF pr = plotRect( canvasRect );
981
982 const QwtPolarItemList& itmList = itemList();
983 for ( QwtPolarItemIterator it = itmList.begin();
984 it != itmList.end(); ++it )
985 {
986 QwtPolarItem* item = *it;
987 if ( item && item->isVisible() )
988 {
989 painter->save();
990
991 // Unfortunately circular clipping slows down
992 // painting a lot. So we better try to avoid it.
993
994 bool doClipping = false;
995 if ( item->rtti() != QwtPolarItem::Rtti_PolarGrid )
996 {
997 const QwtInterval intv =
998 item->boundingInterval( QwtPolar::Radius );
999
1000 if ( !intv.isValid() )
1001 doClipping = true;
1002 else
1003 {
1004 if ( radialMap.s1() < radialMap.s2() )
1005 doClipping = intv.maxValue() > radialMap.s2();
1006 else
1007 doClipping = intv.minValue() < radialMap.s2();
1008 }
1009 }
1010
1011 if ( doClipping )
1012 {
1013 const int margin = item->marginHint();
1014
1015 const QRectF clipRect = pr.adjusted(
1016 -margin, -margin, margin, margin );
1017 if ( !clipRect.contains( canvasRect ) )
1018 {
1019 QRegion clipRegion( clipRect.toRect(), QRegion::Ellipse );
1020 painter->setClipRegion( clipRegion, Qt::IntersectClip );
1021 }
1022 }
1023
1024 painter->setRenderHint( QPainter::Antialiasing,
1025 item->testRenderHint( QwtPolarItem::RenderAntialiased ) );
1026
1027 item->draw( painter, azimuthMap, radialMap,
1028 pole, radius, canvasRect );
1029
1030 painter->restore();
1031 }
1032 }
1033 }
1034
1040 void QwtPolarPlot::updateScale( int scaleId )
1041 {
1042 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
1043 return;
1044
1045 ScaleData& d = m_data->scaleData[scaleId];
1046
1047 double minValue = d.minValue;
1048 double maxValue = d.maxValue;
1049 double stepSize = d.stepSize;
1050
1051 if ( scaleId == QwtPolar::ScaleRadius && d.doAutoScale )
1052 {
1053 QwtInterval interval;
1054
1055 const QwtPolarItemList& itmList = itemList();
1056 for ( QwtPolarItemIterator it = itmList.begin();
1057 it != itmList.end(); ++it )
1058 {
1059 const QwtPolarItem* item = *it;
1060 if ( item->testItemAttribute( QwtPolarItem::AutoScale ) )
1061 interval |= item->boundingInterval( scaleId );
1062 }
1063
1064 minValue = interval.minValue();
1065 maxValue = interval.maxValue();
1066
1067 d.scaleEngine->autoScale( d.maxMajor,
1068 minValue, maxValue, stepSize );
1069 d.isValid = false;
1070 }
1071
1072 if ( !d.isValid )
1073 {
1074 d.scaleDiv = d.scaleEngine->divideScale(
1075 minValue, maxValue, d.maxMajor, d.maxMinor, stepSize );
1076 d.isValid = true;
1077 }
1078
1079 const QwtInterval interval = visibleInterval();
1080
1081 const QwtPolarItemList& itmList = itemList();
1082 for ( QwtPolarItemIterator it = itmList.begin();
1083 it != itmList.end(); ++it )
1084 {
1085 QwtPolarItem* item = *it;
1086 item->updateScaleDiv( *scaleDiv( QwtPolar::Azimuth ),
1087 *scaleDiv( QwtPolar::Radius ), interval );
1088 }
1089 }
1090
1095 int QwtPolarPlot::plotMarginHint() const
1096 {
1097 int margin = 0;
1098 const QwtPolarItemList& itmList = itemList();
1099 for ( QwtPolarItemIterator it = itmList.begin();
1100 it != itmList.end(); ++it )
1101 {
1102 QwtPolarItem* item = *it;
1103 if ( item && item->isVisible() )
1104 {
1105 const int hint = item->marginHint();
1106 if ( hint > margin )
1107 margin = hint;
1108 }
1109 }
1110 return margin;
1111 }
1112
1120 QRectF QwtPolarPlot::plotRect() const
1121 {
1122 return plotRect( canvas()->contentsRect() );
1123 }
1124
1133 QRectF QwtPolarPlot::plotRect( const QRectF& canvasRect ) const
1134 {
1135 const QwtScaleDiv* sd = scaleDiv( QwtPolar::Radius );
1136 const QwtScaleEngine* se = scaleEngine( QwtPolar::Radius );
1137
1138 const int margin = plotMarginHint();
1139 const QRectF cr = canvasRect;
1140 const int radius = qMin( cr.width(), cr.height() ) / 2 - margin;
1141
1142 QwtScaleMap map;
1143 map.setTransformation( se->transformation() );
1144 map.setPaintInterval( 0.0, radius / m_data->zoomFactor );
1145 map.setScaleInterval( sd->lowerBound(), sd->upperBound() );
1146
1147 double v = map.s1();
1148 if ( map.s1() <= map.s2() )
1149 v += m_data->zoomPos.radius();
1150 else
1151 v -= m_data->zoomPos.radius();
1152 v = map.transform( v );
1153
1154 const QPointF off =
1155 QwtPointPolar( m_data->zoomPos.azimuth(), v ).toPoint();
1156
1157 QPointF center( cr.center().x(), cr.top() + margin + radius );
1158 center -= QPointF( off.x(), -off.y() );
1159
1160 QRectF rect( 0, 0, 2 * map.p2(), 2 * map.p2() );
1161 rect.moveCenter( center );
1162
1163 return rect;
1164 }
1165
1170 QwtInterval QwtPolarPlot::visibleInterval() const
1171 {
1172 const QwtScaleDiv* sd = scaleDiv( QwtPolar::Radius );
1173
1174 const QRectF cRect = canvas()->contentsRect();
1175 const QRectF pRect = plotRect( cRect );
1176 if ( cRect.contains( pRect ) || !cRect.intersects( pRect ) )
1177 {
1178 return QwtInterval( sd->lowerBound(), sd->upperBound() );
1179 }
1180
1181 const QPointF pole = pRect.center();
1182 const QRectF scaleRect = pRect & cRect;
1183
1184 const QwtScaleMap map = scaleMap( QwtPolar::Radius );
1185
1186 double dmin = 0.0;
1187 double dmax = 0.0;
1188 if ( scaleRect.contains( pole ) )
1189 {
1190 dmin = 0.0;
1191
1192 QPointF corners[4];
1193 corners[0] = scaleRect.bottomRight();
1194 corners[1] = scaleRect.topRight();
1195 corners[2] = scaleRect.topLeft();
1196 corners[3] = scaleRect.bottomLeft();
1197
1198 dmax = 0.0;
1199 for ( int i = 0; i < 4; i++ )
1200 {
1201 const double dist = qwtDistance( pole, corners[i] );
1202 if ( dist > dmax )
1203 dmax = dist;
1204 }
1205 }
1206 else
1207 {
1208 if ( pole.x() < scaleRect.left() )
1209 {
1210 if ( pole.y() < scaleRect.top() )
1211 {
1212 dmin = qwtDistance( pole, scaleRect.topLeft() );
1213 dmax = qwtDistance( pole, scaleRect.bottomRight() );
1214 }
1215 else if ( pole.y() > scaleRect.bottom() )
1216 {
1217 dmin = qwtDistance( pole, scaleRect.bottomLeft() );
1218 dmax = qwtDistance( pole, scaleRect.topRight() );
1219 }
1220 else
1221 {
1222 dmin = scaleRect.left() - pole.x();
1223 dmax = qMax( qwtDistance( pole, scaleRect.bottomRight() ),
1224 qwtDistance( pole, scaleRect.topRight() ) );
1225 }
1226 }
1227 else if ( pole.x() > scaleRect.right() )
1228 {
1229 if ( pole.y() < scaleRect.top() )
1230 {
1231 dmin = qwtDistance( pole, scaleRect.topRight() );
1232 dmax = qwtDistance( pole, scaleRect.bottomLeft() );
1233 }
1234 else if ( pole.y() > scaleRect.bottom() )
1235 {
1236 dmin = qwtDistance( pole, scaleRect.bottomRight() );
1237 dmax = qwtDistance( pole, scaleRect.topLeft() );
1238 }
1239 else
1240 {
1241 dmin = pole.x() - scaleRect.right();
1242 dmax = qMax( qwtDistance( pole, scaleRect.bottomLeft() ),
1243 qwtDistance( pole, scaleRect.topLeft() ) );
1244 }
1245 }
1246 else if ( pole.y() < scaleRect.top() )
1247 {
1248 dmin = scaleRect.top() - pole.y();
1249 dmax = qMax( qwtDistance( pole, scaleRect.bottomLeft() ),
1250 qwtDistance( pole, scaleRect.bottomRight() ) );
1251 }
1252 else if ( pole.y() > scaleRect.bottom() )
1253 {
1254 dmin = pole.y() - scaleRect.bottom();
1255 dmax = qMax( qwtDistance( pole, scaleRect.topLeft() ),
1256 qwtDistance( pole, scaleRect.topRight() ) );
1257 }
1258 }
1259
1260 const double radius = pRect.width() / 2.0;
1261 if ( dmax > radius )
1262 dmax = radius;
1263
1264 QwtInterval interval;
1265 interval.setMinValue( map.invTransform( dmin ) );
1266 interval.setMaxValue( map.invTransform( dmax ) );
1267
1268 return interval;
1269 }
1270
1274 QwtPolarLayout* QwtPolarPlot::plotLayout()
1275 {
1276 return m_data->layout;
1277 }
1278
1282 const QwtPolarLayout* QwtPolarPlot::plotLayout() const
1283 {
1284 return m_data->layout;
1285 }
1286
1293 void QwtPolarPlot::attachItem( QwtPolarItem* plotItem, bool on )
1294 {
1295 if ( on )
1296 insertItem( plotItem );
1297 else
1298 removeItem( plotItem );
1299
1300 Q_EMIT itemAttached( plotItem, on );
1301
1302 if ( plotItem->testItemAttribute( QwtPolarItem::Legend ) )
1303 {
1304 // the item wants to be represented on the legend
1305
1306 if ( on )
1307 {
1308 updateLegend( plotItem );
1309 }
1310 else
1311 {
1312 const QVariant itemInfo = itemToInfo( plotItem );
1313 Q_EMIT legendDataChanged( itemInfo, QList< QwtLegendData >() );
1314 }
1315 }
1316
1317 if ( autoReplot() )
1318 update();
1319 }
1320
1337 QVariant QwtPolarPlot::itemToInfo( QwtPolarItem* plotItem ) const
1338 {
1339 return QVariant::fromValue( plotItem );
1340 }
1341
1357 QwtPolarItem* QwtPolarPlot::infoToItem( const QVariant& itemInfo ) const
1358 {
1359 if ( itemInfo.canConvert< QwtPolarItem* >() )
1360 return qvariant_cast< QwtPolarItem* >( itemInfo );
1361
1362 return NULL;
1363 }
1364
1365 #if QWT_MOC_INCLUDE
1366 #include "moc_qwt_polar_plot.cpp"
1367 #endif
QList
Definition: qwt_abstract_legend.h:17
QwtAbstractLegend
Abstract base class for legend widgets.
Definition: qwt_abstract_legend.h:35
QwtInterval
A class representing an interval.
Definition: qwt_interval.h:23
QwtInterval::minValue
double minValue() const
Definition: qwt_interval.h:192
QwtInterval::setMaxValue
void setMaxValue(double)
Definition: qwt_interval.h:186
QwtInterval::maxValue
double maxValue() const
Definition: qwt_interval.h:198
QwtInterval::setMinValue
void setMinValue(double)
Definition: qwt_interval.h:176
QwtInterval::isValid
bool isValid() const
Definition: qwt_interval.h:210
QwtLegend
The legend widget.
Definition: qwt_legend.h:32
QwtLegend::maxColumns
uint maxColumns() const
Definition: qwt_legend.cpp:310
QwtLegend::setMaxColumns
void setMaxColumns(uint numColums)
Set the maximum number of entries in a row.
Definition: qwt_legend.cpp:296
QwtLinearScaleEngine
A scale engine for linear scales.
Definition: qwt_scale_engine.h:152
QwtPainter::drawEllipse
static void drawEllipse(QPainter *, const QRectF &)
Wrapper for QPainter::drawEllipse()
Definition: qwt_painter.cpp:426
QwtPainter::drawRect
static void drawRect(QPainter *, qreal x, qreal y, qreal w, qreal h)
Wrapper for QPainter::drawRect()
Definition: qwt_painter.cpp:347
QwtPointPolar
A point in polar coordinates.
Definition: qwt_point_polar.h:29
QwtPointPolar::toPoint
QPointF toPoint() const
Definition: qwt_point_polar.cpp:68
QwtPolarCanvas
Canvas of a QwtPolarPlot.
Definition: qwt_polar_canvas.h:28
QwtPolarItemDict::autoDelete
bool autoDelete() const
Definition: qwt_polar_itemdict.cpp:106
QwtPolarItemDict::itemList
const QwtPolarItemList & itemList() const
A QwtPolarItemList of all attached plot items.
Definition: qwt_polar_itemdict.cpp:168
QwtPolarItemDict::insertItem
void insertItem(QwtPolarItem *)
Definition: qwt_polar_itemdict.cpp:117
QwtPolarItemDict::detachItems
void detachItems(int rtti=QwtPolarItem::Rtti_PolarItem, bool autoDelete=true)
Definition: qwt_polar_itemdict.cpp:140
QwtPolarItemDict::removeItem
void removeItem(QwtPolarItem *)
Definition: qwt_polar_itemdict.cpp:128
QwtPolarItem
Base class for items on a polar plot.
Definition: qwt_polar_item.h:38
QwtPolarItem::testItemAttribute
bool testItemAttribute(ItemAttribute) const
Definition: qwt_polar_item.cpp:221
QwtPolarItem::draw
virtual void draw(QPainter *painter, const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap, const QPointF &pole, double radius, const QRectF &canvasRect) const =0
Draw the item.
QwtPolarItem::boundingInterval
virtual QwtInterval boundingInterval(int scaleId) const
Definition: qwt_polar_item.cpp:381
QwtPolarItem::isVisible
bool isVisible() const
Definition: qwt_polar_item.cpp:344
QwtPolarItem::Legend
@ Legend
The item is represented on the legend.
Definition: qwt_polar_item.h:77
QwtPolarItem::AutoScale
@ AutoScale
Definition: qwt_polar_item.h:83
QwtPolarItem::updateScaleDiv
virtual void updateScaleDiv(const QwtScaleDiv &, const QwtScaleDiv &, const QwtInterval &)
Update the item to changes of the axes scale division.
Definition: qwt_polar_item.cpp:403
QwtPolarItem::legendData
virtual QList< QwtLegendData > legendData() const
Return all information, that is needed to represent the item on the legend.
Definition: qwt_polar_item.cpp:428
QwtPolarItem::testRenderHint
bool testRenderHint(RenderHint) const
Definition: qwt_polar_item.cpp:254
QwtPolarItem::Rtti_PolarGrid
@ Rtti_PolarGrid
For QwtPolarGrid.
Definition: qwt_polar_item.h:52
QwtPolarItem::Rtti_PolarItem
@ Rtti_PolarItem
Unspecific value, that can be used, when it doesn't matter.
Definition: qwt_polar_item.h:49
QwtPolarItem::marginHint
virtual int marginHint() const
Definition: qwt_polar_item.cpp:478
QwtPolarItem::RenderAntialiased
@ RenderAntialiased
Enable antialiasing.
Definition: qwt_polar_item.h:95
QwtPolarItem::rtti
virtual int rtti() const
Definition: qwt_polar_item.cpp:112
QwtPolarLayout
Layout class for QwtPolarPlot.
Definition: qwt_polar_layout.h:24
QwtPolarPlot::setScaleMaxMinor
void setScaleMaxMinor(int scaleId, int maxMinor)
Definition: qwt_polar_plot.cpp:401
QwtPolarPlot::plotLayout
QwtPolarLayout * plotLayout()
Definition: qwt_polar_plot.cpp:1274
QwtPolarPlot::itemToInfo
virtual QVariant itemToInfo(QwtPolarItem *) const
Build an information, that can be used to identify a plot item on the legend.
Definition: qwt_polar_plot.cpp:1337
QwtPolarPlot::scaleMaxMajor
int scaleMaxMajor(int scaleId) const
Definition: qwt_polar_plot.cpp:460
QwtPolarPlot::layoutChanged
void layoutChanged()
QwtPolarPlot::setScale
void setScale(int scaleId, double min, double max, double step=0)
Disable autoscaling and specify a fixed scale for a selected scale.
Definition: qwt_polar_plot.cpp:530
QwtPolarPlot::visibleInterval
QwtInterval visibleInterval() const
Definition: qwt_polar_plot.cpp:1170
QwtPolarPlot::scaleMap
QwtScaleMap scaleMap(int scaleId, double radius) const
Definition: qwt_polar_plot.cpp:730
QwtPolarPlot::drawCanvas
virtual void drawCanvas(QPainter *, const QRectF &) const
Definition: qwt_polar_plot.cpp:930
QwtPolarPlot::scaleMaxMinor
int scaleMaxMinor(int scaleId) const
Definition: qwt_polar_plot.cpp:423
QwtPolarPlot::plotMarginHint
int plotMarginHint() const
Definition: qwt_polar_plot.cpp:1095
QwtPolarPlot::zoomPos
QwtPointPolar zoomPos() const
Definition: qwt_polar_plot.cpp:682
QwtPolarPlot::unzoom
void unzoom()
Definition: qwt_polar_plot.cpp:668
QwtPolarPlot::autoRefresh
void autoRefresh()
Replots the plot if QwtPlot::autoReplot() is true.
Definition: qwt_polar_plot.cpp:847
QwtPolarPlot::scaleDiv
const QwtScaleDiv * scaleDiv(int scaleId) const
Return the scale division of a specified scale.
Definition: qwt_polar_plot.cpp:579
QwtPolarPlot::setAzimuthOrigin
void setAzimuthOrigin(double)
Change the origin of the azimuth scale.
Definition: qwt_polar_plot.cpp:615
QwtPolarPlot::plotBackground
const QBrush & plotBackground() const
Definition: qwt_polar_plot.cpp:322
QwtPolarPlot::scaleEngine
QwtScaleEngine * scaleEngine(int scaleId)
Definition: qwt_polar_plot.cpp:499
QwtPolarPlot::setScaleMaxMajor
void setScaleMaxMajor(int scaleId, int maxMajor)
Definition: qwt_polar_plot.cpp:438
QwtPolarPlot::updateLayout
virtual void updateLayout()
Rebuild the layout.
Definition: qwt_polar_plot.cpp:854
QwtPolarPlot::event
virtual bool event(QEvent *) override
Qt event handler.
Definition: qwt_polar_plot.cpp:762
QwtPolarPlot::hasAutoScale
bool hasAutoScale(int scaleId) const
Definition: qwt_polar_plot.cpp:386
QwtPolarPlot::replot
virtual void replot()
Redraw the plot.
Definition: qwt_polar_plot.cpp:899
QwtPolarPlot::zoom
void zoom(const QwtPointPolar &, double factor)
Translate and in/decrease the zoom factor.
Definition: qwt_polar_plot.cpp:651
QwtPolarPlot::zoomFactor
double zoomFactor() const
Definition: qwt_polar_plot.cpp:691
QwtPolarPlot::resizeEvent
virtual void resizeEvent(QResizeEvent *) override
Resize and update internal layout.
Definition: qwt_polar_plot.cpp:784
QwtPolarPlot::~QwtPolarPlot
virtual ~QwtPolarPlot()
Destructor.
Definition: qwt_polar_plot.cpp:106
QwtPolarPlot::autoReplot
bool autoReplot() const
Definition: qwt_polar_plot.cpp:348
QwtPolarPlot::itemAttached
void itemAttached(QwtPolarItem *plotItem, bool on)
QwtPolarPlot::azimuthOrigin
double azimuthOrigin() const
Definition: qwt_polar_plot.cpp:632
QwtPolarPlot::updateScale
void updateScale(int scaleId)
Definition: qwt_polar_plot.cpp:1040
QwtPolarPlot::title
QwtText title() const
Definition: qwt_polar_plot.cpp:147
QwtPolarPlot::insertLegend
void insertLegend(QwtAbstractLegend *, LegendPosition=RightLegend, double ratio=-1.0)
Insert a legend.
Definition: qwt_polar_plot.cpp:191
QwtPolarPlot::drawItems
virtual void drawItems(QPainter *painter, const QwtScaleMap &radialMap, const QwtScaleMap &azimuthMap, const QPointF &pole, double radius, const QRectF &canvasRect) const
Definition: qwt_polar_plot.cpp:975
QwtPolarPlot::setScaleEngine
void setScaleEngine(int scaleId, QwtScaleEngine *)
Definition: qwt_polar_plot.cpp:476
QwtPolarPlot::setAutoReplot
void setAutoReplot(bool tf=true)
Set or reset the autoReplot option.
Definition: qwt_polar_plot.cpp:342
QwtPolarPlot::QwtPolarPlot
QwtPolarPlot(QWidget *parent=NULL)
Definition: qwt_polar_plot.cpp:88
QwtPolarPlot::legendDataChanged
void legendDataChanged(const QVariant &itemInfo, const QList< QwtLegendData > &data)
QwtPolarPlot::plotRect
QRectF plotRect() const
Definition: qwt_polar_plot.cpp:1120
QwtPolarPlot::setScaleDiv
void setScaleDiv(int scaleId, const QwtScaleDiv &)
Disable autoscaling and specify a fixed scale for a selected scale.
Definition: qwt_polar_plot.cpp:554
QwtPolarPlot::legend
QwtAbstractLegend * legend()
Definition: qwt_polar_plot.cpp:286
QwtPolarPlot::setAutoScale
void setAutoScale(int scaleId)
Enable autoscaling.
Definition: qwt_polar_plot.cpp:368
QwtPolarPlot::setPlotBackground
void setPlotBackground(const QBrush &c)
Set the background of the plot area.
Definition: qwt_polar_plot.cpp:309
QwtPolarPlot::updateLegend
void updateLegend()
Definition: qwt_polar_plot.cpp:252
QwtPolarPlot::canvas
QwtPolarCanvas * canvas()
Definition: qwt_polar_plot.cpp:914
QwtPolarPlot::LegendPosition
LegendPosition
Definition: qwt_polar_plot.h:60
QwtPolarPlot::BottomLegend
@ BottomLegend
The legend will be below the canvas.
Definition: qwt_polar_plot.h:68
QwtPolarPlot::LeftLegend
@ LeftLegend
The legend will be left from the canvas.
Definition: qwt_polar_plot.h:62
QwtPolarPlot::TopLegend
@ TopLegend
The legend will be between canvas and title.
Definition: qwt_polar_plot.h:71
QwtPolarPlot::RightLegend
@ RightLegend
The legend will be right from the canvas.
Definition: qwt_polar_plot.h:65
QwtPolarPlot::titleLabel
QwtTextLabel * titleLabel()
Definition: qwt_polar_plot.cpp:153
QwtPolarPlot::setTitle
void setTitle(const QString &)
Definition: qwt_polar_plot.cpp:118
QwtPolarPlot::infoToItem
virtual QwtPolarItem * infoToItem(const QVariant &) const
Identify the plot item according to an item info object, that has bee generated from itemToInfo().
Definition: qwt_polar_plot.cpp:1357
QwtScaleDiv
A class representing a scale division.
Definition: qwt_scale_div.h:34
QwtScaleDiv::lowerBound
double lowerBound() const
Definition: qwt_scale_div.cpp:131
QwtScaleDiv::upperBound
double upperBound() const
Definition: qwt_scale_div.cpp:151
QwtScaleEngine
Base class for scale engines.
Definition: qwt_scale_engine.h:46
QwtScaleEngine::transformation
QwtTransform * transformation() const
Definition: qwt_scale_engine.cpp:265
QwtScaleMap
A scale map.
Definition: qwt_scale_map.h:27
QwtScaleMap::transform
double transform(double s) const
Definition: qwt_scale_map.h:137
QwtScaleMap::s1
double s1() const
Definition: qwt_scale_map.h:83
QwtScaleMap::s2
double s2() const
Definition: qwt_scale_map.h:91
QwtScaleMap::setPaintInterval
void setPaintInterval(double p1, double p2)
Specify the borders of the paint device interval.
Definition: qwt_scale_map.cpp:119
QwtScaleMap::setScaleInterval
void setScaleInterval(double s1, double s2)
Specify the borders of the scale interval.
Definition: qwt_scale_map.cpp:100
QwtScaleMap::invTransform
double invTransform(double p) const
Definition: qwt_scale_map.h:154
QwtScaleMap::p2
double p2() const
Definition: qwt_scale_map.h:107
QwtScaleMap::setTransformation
void setTransformation(QwtTransform *)
Definition: qwt_scale_map.cpp:76
QwtText
A class representing a text.
Definition: qwt_text.h:52
QwtText::isEmpty
bool isEmpty() const
Definition: qwt_text.cpp:739
QwtTextLabel
A Widget which displays a QwtText.
Definition: qwt_text_label.h:27
QwtAxis::isValid
bool isValid(int axisPos)
Definition: qwt_axis.h:45