9#include "qwt_polar_grid.h"
10#include "qwt_painter.h"
12#include "qwt_clipper.h"
13#include "qwt_scale_map.h"
14#include "qwt_scale_engine.h"
15#include "qwt_scale_div.h"
16#include "qwt_scale_draw.h"
17#include "qwt_round_scale_draw.h"
23static inline bool isClose(
double value1,
double value2 )
25 return qAbs( value1 - value2 ) < DBL_EPSILON;
55 , isMinorVisible( false )
68class QwtPolarGrid::PrivateData
71 GridData gridData[QwtPolar::ScaleCount];
72 AxisData axisData[QwtPolar::AxesCount];
87 m_data =
new PrivateData;
89 for (
int axisId = 0; axisId < QwtPolar::AxesCount; axisId++ )
91 AxisData& axis = m_data->axisData[axisId];
94 case QwtPolar::AxisAzimuth:
100 axis.isVisible =
true;
103 case QwtPolar::AxisLeft:
109 axis.isVisible =
false;
112 case QwtPolar::AxisRight:
118 axis.isVisible =
true;
121 case QwtPolar::AxisTop:
127 axis.isVisible =
false;
130 case QwtPolar::AxisBottom:
136 axis.isVisible =
true;
176 if ( ( ( m_data->displayFlags & flag ) != 0 ) != on )
179 m_data->displayFlags |= flag;
181 m_data->displayFlags &= ~flag;
193 return ( m_data->displayFlags & flag );
207 if (
bool( m_data->attributes & attribute ) == on )
211 m_data->attributes |= attribute;
213 m_data->attributes &= ~attribute;
224 return m_data->attributes & attribute;
237 if ( axisId < 0 || axisId >= QwtPolar::AxesCount )
240 AxisData& axisData = m_data->axisData[axisId];
241 if ( axisData.pen != pen )
256 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
259 GridData& grid = m_data->gridData[scaleId];
260 if ( grid.isVisible !=
show )
262 grid.isVisible =
show;
274 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
277 return m_data->gridData[scaleId].isVisible;
292 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
295 GridData& grid = m_data->gridData[scaleId];
296 if ( grid.isMinorVisible !=
show )
298 grid.isMinorVisible =
show;
310 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
313 return m_data->gridData[scaleId].isMinorVisible;
326 if ( axisId < 0 || axisId >= QwtPolar::AxesCount )
329 AxisData& axisData = m_data->axisData[axisId];
330 if ( axisData.isVisible !=
show )
332 axisData.isVisible =
show;
345 if ( axisId < 0 || axisId >= QwtPolar::AxesCount )
348 return m_data->axisData[axisId].isVisible;
359 bool isChanged =
false;
361 for (
int scaleId = 0; scaleId < QwtPolar::ScaleCount; scaleId++ )
363 GridData& grid = m_data->gridData[scaleId];
364 if ( grid.majorPen != pen || grid.minorPen != pen )
371 for (
int axisId = 0; axisId < QwtPolar::AxesCount; axisId++ )
373 AxisData& axis = m_data->axisData[axisId];
374 if ( axis.pen != pen )
392 bool isChanged =
false;
393 for (
int axisId = 0; axisId < QwtPolar::AxesCount; axisId++ )
395 AxisData& axis = m_data->axisData[axisId];
396 if ( axis.font != font )
414 bool isChanged =
false;
416 for (
int scaleId = 0; scaleId < QwtPolar::ScaleCount; scaleId++ )
418 GridData& grid = m_data->gridData[scaleId];
419 if ( grid.majorPen != pen )
438 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
441 GridData& grid = m_data->gridData[scaleId];
442 if ( grid.majorPen != pen )
456 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
459 const GridData& grid = m_data->gridData[scaleId];
460 return grid.majorPen;
471 bool isChanged =
false;
473 for (
int scaleId = 0; scaleId < QwtPolar::ScaleCount; scaleId++ )
475 GridData& grid = m_data->gridData[scaleId];
476 if ( grid.minorPen != pen )
495 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
498 GridData& grid = m_data->gridData[scaleId];
499 if ( grid.minorPen != pen )
512 if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount )
515 const GridData& grid = m_data->gridData[scaleId];
516 return grid.minorPen;
527 if ( axisId < 0 || axisId >= QwtPolar::AxesCount )
530 return m_data->axisData[axisId].pen;
541 if ( axisId < 0 || axisId >= QwtPolar::AxesCount )
544 AxisData& axisData = m_data->axisData[axisId];
545 if ( axisData.font != font )
547 axisData.font = font;
558 if ( axisId < 0 || axisId >= QwtPolar::AxesCount )
561 return m_data->axisData[axisId].font;
576 const QPointF& pole,
double radius,
577 const QRectF& canvasRect )
const
579 updateScaleDraws( azimuthMap, radialMap, pole, radius );
585 QRegion clipRegion( canvasRect.toRect() );
586 for (
int axisId = 0; axisId < QwtPolar::AxesCount; axisId++ )
588 const AxisData& axis = m_data->axisData[axisId];
589 if ( axisId != QwtPolar::AxisAzimuth && axis.isVisible )
596 for (
int i = 0; i < int( ticks.size() ); i++ )
604 const int margin = 2;
605 labelRect.adjust( -margin, -margin, margin, margin );
607 if ( labelRect.isValid() )
608 clipRegion -= QRegion( labelRect );
613 painter->setClipRegion( clipRegion );
618 const GridData& radialGrid = m_data->gridData[QwtPolar::Radius];
619 if ( radialGrid.isVisible && radialGrid.isMinorVisible )
621 painter->setPen( radialGrid.minorPen );
628 if ( radialGrid.isVisible )
630 painter->setPen( radialGrid.majorPen );
638 const GridData& azimuthGrid =
639 m_data->gridData[QwtPolar::Azimuth];
641 if ( azimuthGrid.isVisible && azimuthGrid.isMinorVisible )
643 painter->setPen( azimuthGrid.minorPen );
645 drawRays( painter, canvasRect, pole, radius, azimuthMap,
647 drawRays( painter, canvasRect, pole, radius, azimuthMap,
650 if ( azimuthGrid.isVisible )
652 painter->setPen( azimuthGrid.majorPen );
654 drawRays( painter, canvasRect, pole, radius, azimuthMap,
659 for (
int axisId = 0; axisId < QwtPolar::AxesCount; axisId++ )
661 const AxisData& axis = m_data->axisData[axisId];
662 if ( axis.isVisible )
682 QPainter* painter,
const QRectF& canvasRect,
683 const QPointF& pole,
double radius,
686 for (
int i = 0; i < int( values.size() ); i++ )
688 double azimuth = azimuthMap.
transform( values[i] );
689 azimuth = ::fmod( azimuth, 2 * M_PI );
691 bool skipLine =
false;
696 if ( isClose( azimuth, 0.0 ) )
698 const AxisData& axis = m_data->axisData[QwtPolar::AxisRight];
699 if ( axis.isVisible && axis.scaleDraw->hasComponent( bone ) )
702 else if ( isClose( azimuth, M_PI / 2 ) )
704 const AxisData& axis = m_data->axisData[QwtPolar::AxisTop];
705 if ( axis.isVisible && axis.scaleDraw->hasComponent( bone ) )
708 else if ( isClose( azimuth, M_PI ) )
710 const AxisData& axis = m_data->axisData[QwtPolar::AxisLeft];
711 if ( axis.isVisible && axis.scaleDraw->hasComponent( bone ) )
714 else if ( isClose( azimuth, 3 * M_PI / 2.0 ) )
716 const AxisData& axis = m_data->axisData[QwtPolar::AxisBottom];
717 if ( axis.isVisible && axis.scaleDraw->hasComponent( bone ) )
723 const QPointF pos = qwtPolar2Pos( pole, radius, azimuth );
730 QPolygonF polygon( 2 );
731 polygon[0] = pole.toPoint();
732 polygon[1] = pos.toPoint();
752 QPainter* painter,
const QRectF& canvasRect,
756 for (
int i = 0; i < int( values.size() ); i++ )
758 const double val = values[i];
760 const GridData& gridData =
761 m_data->gridData[QwtPolar::Radius];
763 bool skipLine =
false;
766 const AxisData& axis = m_data->axisData[QwtPolar::AxisAzimuth];
767 if ( axis.isVisible &&
770 if ( isClose( val, gridData.scaleDiv.
upperBound() ) )
775 if ( isClose( val, gridData.scaleDiv.
lowerBound() ) )
780 const double radius = radialMap.
transform( val );
782 QRectF outerRect( 0, 0, 2 * radius, 2 * radius );
783 outerRect.moveCenter( pole );
796 for (
int j = 0; j < angles.size(); j++ )
806 const double from = qwtDegrees( intv.
minValue() );
807 const double to = qwtDegrees( intv.
maxValue() );
809 double span = to - from;
813 painter->drawArc( outerRect,
814 qRound( from * 16 ), qRound( span * 16 ) );
834 if ( axisId < 0 || axisId >= QwtPolar::AxesCount )
837 AxisData& axis = m_data->axisData[axisId];
839 painter->setPen( axis.pen );
840 painter->setFont( axis.font );
843 pal.setColor( QPalette::WindowText, axis.pen.color() );
844 pal.setColor( QPalette::Text, axis.pen.color() );
846 axis.scaleDraw->draw( painter, pal );
859void QwtPolarGrid::updateScaleDraws(
861 const QPointF& pole,
double radius )
const
863 const QPoint p = pole.toPoint();
866 m_data->gridData[QwtPolar::ScaleRadius].scaleDiv.
interval();
870 const int l = max - min;
872 for (
int axisId = 0; axisId < QwtPolar::AxesCount; axisId++ )
874 AxisData& axis = m_data->axisData[axisId];
876 if ( axisId == QwtPolar::AxisAzimuth )
881 scaleDraw->setRadius( qRound( radius ) );
884 double from = ::fmod( 90.0 - qwtDegrees( azimuthMap.
p1() ), 360.0 );
888 scaleDraw->setAngleRange( from, from - 360.0 );
903 case QwtPolar::AxisLeft:
909 case QwtPolar::AxisRight:
915 case QwtPolar::AxisTop:
921 case QwtPolar::AxisBottom:
955 GridData& radialGrid = m_data->gridData[QwtPolar::Radius];
968 if ( radialGrid.scaleDiv != radialScaleDiv )
969 radialGrid.scaleDiv = radialScaleDiv;
972 GridData& azimuthGrid = m_data->gridData[QwtPolar::Azimuth];
973 if ( azimuthGrid.scaleDiv != azimuthScaleDiv )
975 azimuthGrid.scaleDiv = azimuthScaleDiv;
978 bool hasOrigin =
false;
979 for (
int axisId = 0; axisId < QwtPolar::AxesCount; axisId++ )
981 AxisData& axis = m_data->axisData[axisId];
982 if ( axis.isVisible && axis.scaleDraw )
984 if ( axisId == QwtPolar::AxisAzimuth )
986 axis.scaleDraw->setScaleDiv( azimuthGrid.scaleDiv );
989 axis.scaleDraw->enableComponent(
1001 bool skipOrigin = hasOrigin;
1004 if ( axisId == QwtPolar::AxisLeft
1005 || axisId == QwtPolar::AxisRight )
1007 if ( m_data->axisData[QwtPolar::AxisBottom].isVisible )
1012 if ( m_data->axisData[QwtPolar::AxisLeft].isVisible )
1016 if ( ticks.size() > 0 && ticks.first() == sd.
lowerBound() )
1019 ticks.removeFirst();
1027 if ( ticks.size() > 0 && ticks.last() == sd.
upperBound() )
1032 axis.scaleDraw->setScaleDiv( sd );
1036 axis.scaleDraw->enableComponent(
1051 const AxisData& axis = m_data->axisData[QwtPolar::AxisAzimuth];
1052 if ( axis.isVisible )
1054 const int extent = axis.scaleDraw->extent( axis.font );
1070 if ( axisId >= QwtPolar::AxisLeft && axisId <= QwtPolar::AxisBottom )
1071 return static_cast< QwtScaleDraw*
>( m_data->axisData[axisId].scaleDraw );
1085 if ( axisId >= QwtPolar::AxisLeft && axisId <= QwtPolar::AxisBottom )
1086 return static_cast< QwtScaleDraw*
>( m_data->axisData[axisId].scaleDraw );
1101 if ( axisId < QwtPolar::AxisLeft || axisId > QwtPolar::AxisBottom )
1104 AxisData& axisData = m_data->axisData[axisId];
1107 delete axisData.scaleDraw;
1120 m_data->axisData[QwtPolar::AxisAzimuth].scaleDraw );
1130 m_data->axisData[QwtPolar::AxisAzimuth].scaleDraw );
1141 AxisData& axisData = m_data->axisData[QwtPolar::AxisAzimuth];
1144 delete axisData.scaleDraw;
A abstract base class for drawing scales.
@ Backbone
Backbone = the line where the ticks are located.
void setTransformation(QwtTransform *)
bool hasComponent(ScaleComponent) const
const QwtScaleDiv & scaleDiv() const
A class representing an interval.
static void drawEllipse(QPainter *, const QRectF &)
Wrapper for QPainter::drawEllipse()
static void drawPolyline(QPainter *, const QPolygonF &)
Wrapper for QPainter::drawPolyline()
bool testDisplayFlag(DisplayFlag) const
GridAttribute
Grid attributes.
void setGridAttribute(GridAttribute, bool on=true)
Specify an attribute for the grid.
QFont axisFont(int axisId) const
QPen minorGridPen(int scaleId) const
QPen axisPen(int axisId) const
bool testGridAttribute(GridAttribute) const
void setScaleDraw(int axisId, QwtScaleDraw *)
Set a scale draw.
virtual ~QwtPolarGrid()
Destructor.
const QwtRoundScaleDraw * azimuthScaleDraw() const
virtual void updateScaleDiv(const QwtScaleDiv &azimuthMap, const QwtScaleDiv &radialMap, const QwtInterval &) override
Update the item to changes of the axes scale division.
void showMinorGrid(int scaleId, bool show=true)
void showGrid(int scaleId, bool show=true)
void setMinorGridPen(const QPen &p)
virtual int marginHint() const override
void setPen(const QPen &p)
void setAzimuthScaleDraw(QwtRoundScaleDraw *)
Set a scale draw for the azimuth scale.
void drawRays(QPainter *, const QRectF &, const QPointF &pole, double radius, const QwtScaleMap &azimuthMap, const QList< double > &) const
void drawCircles(QPainter *, const QRectF &, const QPointF &pole, const QwtScaleMap &radialMap, const QList< double > &) const
QFlags< GridAttribute > GridAttributes
bool isGridVisible(int scaleId) const
const QwtScaleDraw * scaleDraw(int axisId) const
bool isMinorGridVisible(int scaleId) const
virtual int rtti() const override
virtual void draw(QPainter *p, const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap, const QPointF &pole, double radius, const QRectF &rect) const override
bool isAxisVisible(int axisId) const
QPen majorGridPen(int scaleId) const
void setAxisFont(int axisId, const QFont &p)
void setAxisPen(int axisId, const QPen &p)
void drawAxis(QPainter *, int axisId) const
void showAxis(int axisId, bool show=true)
void setFont(const QFont &)
void setMajorGridPen(const QPen &p)
QFlags< DisplayFlag > DisplayFlags
void setDisplayFlag(DisplayFlag, bool on=true)
QwtPolarGrid()
Constructor.
Base class for items on a polar plot.
virtual void itemChanged()
@ Rtti_PolarGrid
For QwtPolarGrid.
QwtPolarPlot * plot() const
@ RenderAntialiased
Enable antialiasing.
void show()
Show the item.
void setRenderHint(RenderHint, bool on=true)
void setZ(double z)
Set the z value.
A plotting widget, displaying a polar coordinate system.
int scaleMaxMajor(int scaleId) const
int scaleMaxMinor(int scaleId) const
QwtScaleEngine * scaleEngine(int scaleId)
A class for drawing round scales.
A class representing a scale division.
double lowerBound() const
QwtInterval interval() const
double upperBound() const
QList< double > ticks(int tickType) const
bool contains(double value) const
@ MediumTick
Medium ticks.
void setTicks(int tickType, const QList< double > &)
A class for drawing scales.
void setLength(double length)
QRect boundingLabelRect(const QFont &, double value) const
Find the bounding rectangle for the label.
void move(double x, double y)
void setAlignment(Alignment)
@ BottomScale
The scale is below.
@ LeftScale
The scale is left.
Base class for scale engines.
virtual QwtScaleDiv divideScale(double x1, double x2, int maxMajorSteps, int maxMinorSteps, double stepSize=0.0) const =0
Calculate a scale division.
double transform(double s) const
const QwtTransform * transformation() const
Get the transformation.
A class representing a text.
QWT_EXPORT void clipPolygonF(const QRectF &, QPolygonF &, bool closePolygon=false)
QWT_EXPORT QVector< QwtInterval > clipCircle(const QRectF &, const QPointF &, double radius)