Qwt User's Guide 6.3.0
Loading...
Searching...
No Matches
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
25static 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
33namespace
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
65class 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
89 : QFrame( parent )
90{
91 initPlot( QwtText() );
92}
93
99QwtPolarPlot::QwtPolarPlot( const QwtText& title, QWidget* parent )
100 : QFrame( parent )
101{
102 initPlot( title );
103}
104
107{
109
110 delete m_data->layout;
111 delete m_data;
112}
113
118void 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
134void 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
148{
149 return m_data->titleLabel->text();
150}
151
154{
155 return m_data->titleLabel;
156}
157
160{
161 return m_data->titleLabel;
162}
163
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
253{
254 const QwtPolarItemList& itmList = itemList();
255 for ( QwtPolarItemIterator it = itmList.begin();
256 it != itmList.end(); ++it )
257 {
258 updateLegend( *it );
259 }
260}
261
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
287{
288 return m_data->legend;
289}
290
296{
297 return m_data->legend;
298}
299
309void QwtPolarPlot::setPlotBackground( const QBrush& brush )
310{
311 if ( brush != m_data->canvasBrush )
312 {
313 m_data->canvasBrush = brush;
314 autoRefresh();
315 }
316}
317
322const QBrush& QwtPolarPlot::plotBackground() const
323{
324 return m_data->canvasBrush;
325}
326
343{
344 m_data->autoReplot = enable;
345}
346
349{
350 return m_data->autoReplot;
351}
352
368void 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
386bool 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
401void 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
423int 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
438void 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
460int 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
476void 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
500{
501 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
502 return NULL;
503
504 return m_data->scaleData[scaleId].scaleEngine;
505}
506
513const 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
530void 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
554void 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
579const 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
599{
600 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
601 return NULL;
602
603 return &m_data->scaleData[scaleId].scaleDiv;
604}
605
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
633{
634 return m_data->azimuthOrigin;
635}
636
651void 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
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
683{
684 return m_data->zoomPos;
685}
686
692{
693 return m_data->zoomFactor;
694}
695
711{
712 const QRectF pr = plotRect();
713 return scaleMap( scaleId, pr.width() / 2.0 );
714}
715
730QwtScaleMap 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
762bool 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
784void QwtPolarPlot::resizeEvent( QResizeEvent* e )
785{
786 QFrame::resizeEvent( e );
787 updateLayout();
788}
789
790void 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
848{
849 if ( m_data->autoReplot )
850 replot();
851}
852
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
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
915{
916 return m_data->canvas;
917}
918
921{
922 return m_data->canvas;
923}
924
930void 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
975void 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,
1026
1027 item->draw( painter, azimuthMap, radialMap,
1028 pole, radius, canvasRect );
1029
1030 painter->restore();
1031 }
1032 }
1033}
1034
1040void 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;
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
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
1121{
1122 return plotRect( canvas()->contentsRect() );
1123}
1124
1133QRectF 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
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
1275{
1276 return m_data->layout;
1277}
1278
1283{
1284 return m_data->layout;
1285}
1286
1293void 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
1337QVariant QwtPolarPlot::itemToInfo( QwtPolarItem* plotItem ) const
1338{
1339 return QVariant::fromValue( plotItem );
1340}
1341
1357QwtPolarItem* 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#include "moc_qwt_polar_plot.cpp"
Abstract base class for legend widgets.
A class representing an interval.
double minValue() const
void setMaxValue(double)
double maxValue() const
void setMinValue(double)
bool isValid() const
The legend widget.
Definition qwt_legend.h:32
uint maxColumns() const
void setMaxColumns(uint numColums)
Set the maximum number of entries in a row.
A scale engine for linear scales.
static void drawEllipse(QPainter *, const QRectF &)
Wrapper for QPainter::drawEllipse()
static void drawRect(QPainter *, qreal x, qreal y, qreal w, qreal h)
Wrapper for QPainter::drawRect()
A point in polar coordinates.
double radius() const
Returns the radius.
bool isValid() const
Returns true if radius() >= 0.0.
double azimuth() const
Returns the azimuth.
QPointF toPoint() const
Canvas of a QwtPolarPlot.
const QwtPolarItemList & itemList() const
A QwtPolarItemList of all attached plot items.
void insertItem(QwtPolarItem *)
void detachItems(int rtti=QwtPolarItem::Rtti_PolarItem, bool autoDelete=true)
void removeItem(QwtPolarItem *)
Base class for items on a polar plot.
bool testItemAttribute(ItemAttribute) const
virtual void draw(QPainter *painter, const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap, const QPointF &pole, double radius, const QRectF &canvasRect) const =0
Draw the item.
virtual QwtInterval boundingInterval(int scaleId) const
bool isVisible() const
@ Legend
The item is represented on the legend.
virtual void updateScaleDiv(const QwtScaleDiv &, const QwtScaleDiv &, const QwtInterval &)
Update the item to changes of the axes scale division.
virtual QList< QwtLegendData > legendData() const
Return all information, that is needed to represent the item on the legend.
bool testRenderHint(RenderHint) const
@ Rtti_PolarGrid
For QwtPolarGrid.
@ Rtti_PolarItem
Unspecific value, that can be used, when it doesn't matter.
virtual int marginHint() const
@ RenderAntialiased
Enable antialiasing.
virtual int rtti() const
Layout class for QwtPolarPlot.
const QRectF & legendRect() const
void setLegendPosition(QwtPolarPlot::LegendPosition pos, double ratio)
Specify the position of the legend.
QwtPolarPlot::LegendPosition legendPosition() const
virtual void activate(const QwtPolarPlot *, const QRectF &rect, Options options=Options())
Recalculate the geometry of all components.
const QRectF & titleRect() const
const QRectF & canvasRect() const
void setScaleMaxMinor(int scaleId, int maxMinor)
QwtPolarLayout * plotLayout()
virtual QVariant itemToInfo(QwtPolarItem *) const
Build an information, that can be used to identify a plot item on the legend.
int scaleMaxMajor(int scaleId) const
void layoutChanged()
void setScale(int scaleId, double min, double max, double step=0)
Disable autoscaling and specify a fixed scale for a selected scale.
QwtInterval visibleInterval() const
QwtScaleMap scaleMap(int scaleId, double radius) const
virtual void drawCanvas(QPainter *, const QRectF &) const
int scaleMaxMinor(int scaleId) const
int plotMarginHint() const
QwtPointPolar zoomPos() const
void autoRefresh()
Replots the plot if QwtPlot::autoReplot() is true.
const QwtScaleDiv * scaleDiv(int scaleId) const
Return the scale division of a specified scale.
void setAzimuthOrigin(double)
Change the origin of the azimuth scale.
const QBrush & plotBackground() const
QwtScaleEngine * scaleEngine(int scaleId)
void setScaleMaxMajor(int scaleId, int maxMajor)
virtual void updateLayout()
Rebuild the layout.
virtual bool event(QEvent *) override
Qt event handler.
bool hasAutoScale(int scaleId) const
virtual void replot()
Redraw the plot.
void zoom(const QwtPointPolar &, double factor)
Translate and in/decrease the zoom factor.
double zoomFactor() const
virtual void resizeEvent(QResizeEvent *) override
Resize and update internal layout.
virtual ~QwtPolarPlot()
Destructor.
bool autoReplot() const
void itemAttached(QwtPolarItem *plotItem, bool on)
double azimuthOrigin() const
void updateScale(int scaleId)
QwtText title() const
void insertLegend(QwtAbstractLegend *, LegendPosition=RightLegend, double ratio=-1.0)
Insert a legend.
virtual void drawItems(QPainter *painter, const QwtScaleMap &radialMap, const QwtScaleMap &azimuthMap, const QPointF &pole, double radius, const QRectF &canvasRect) const
void setScaleEngine(int scaleId, QwtScaleEngine *)
void setAutoReplot(bool tf=true)
Set or reset the autoReplot option.
QwtPolarPlot(QWidget *parent=NULL)
void legendDataChanged(const QVariant &itemInfo, const QList< QwtLegendData > &data)
QRectF plotRect() const
void setScaleDiv(int scaleId, const QwtScaleDiv &)
Disable autoscaling and specify a fixed scale for a selected scale.
QwtAbstractLegend * legend()
void setAutoScale(int scaleId)
Enable autoscaling.
void setPlotBackground(const QBrush &c)
Set the background of the plot area.
QwtPolarCanvas * canvas()
@ BottomLegend
The legend will be below the canvas.
@ LeftLegend
The legend will be left from the canvas.
@ TopLegend
The legend will be between canvas and title.
@ RightLegend
The legend will be right from the canvas.
QwtTextLabel * titleLabel()
void setTitle(const QString &)
virtual QwtPolarItem * infoToItem(const QVariant &) const
Identify the plot item according to an item info object, that has bee generated from itemToInfo().
A class representing a scale division.
double lowerBound() const
double upperBound() const
Base class for scale engines.
QwtTransform * transformation() const
virtual void autoScale(int maxNumSteps, double &x1, double &x2, double &stepSize) const =0
virtual QwtScaleDiv divideScale(double x1, double x2, int maxMajorSteps, int maxMinorSteps, double stepSize=0.0) const =0
Calculate a scale division.
A scale map.
double transform(double s) const
double s1() const
double s2() const
void setPaintInterval(double p1, double p2)
Specify the borders of the paint device interval.
void setScaleInterval(double s1, double s2)
Specify the borders of the scale interval.
double invTransform(double p) const
double p2() const
void setTransformation(QwtTransform *)
A class representing a text.
Definition qwt_text.h:52
bool isEmpty() const
Definition qwt_text.cpp:739
A Widget which displays a QwtText.
bool isValid(int axisPos)
Definition qwt_axis.h:45