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 
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 
107 {
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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,
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;
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 
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 
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 
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
Abstract base class for legend widgets.
A class representing an interval.
Definition: qwt_interval.h:23
double minValue() const
Definition: qwt_interval.h:192
void setMaxValue(double)
Definition: qwt_interval.h:186
double maxValue() const
Definition: qwt_interval.h:198
void setMinValue(double)
Definition: qwt_interval.h:176
bool isValid() const
Definition: qwt_interval.h:210
The legend widget.
Definition: qwt_legend.h:32
uint maxColumns() const
Definition: qwt_legend.cpp:310
void setMaxColumns(uint numColums)
Set the maximum number of entries in a row.
Definition: qwt_legend.cpp:296
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.
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.
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.
Definition: qwt_scale_div.h:34
double lowerBound() const
double upperBound() const
Base class for scale engines.
QwtTransform * transformation() const
A scale map.
Definition: qwt_scale_map.h:27
double transform(double s) const
double s1() const
Definition: qwt_scale_map.h:83
double s2() const
Definition: qwt_scale_map.h:91
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