/external/qwtpolar-1.1.1/qwt_polar_grid.cpp

https://github.com/ricardogsilva/Quantum-GIS · C++ · 1138 lines · 749 code · 129 blank · 260 comment · 170 complexity · f19c1a7f794c3fc20584e30583d11403 MD5 · raw file

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