| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
|
|
||
| /** Render checker for tests in python */ | ||
|
|
||
| class QgsRenderChecker | ||
| { | ||
| %TypeHeaderCode | ||
| #include <qgsrenderchecker.h> | ||
| %End | ||
| public: | ||
|
|
||
| QgsRenderChecker(); | ||
|
|
||
| ~QgsRenderChecker(); | ||
|
|
||
| QString controlImagePath() const; | ||
|
|
||
| QString report(); | ||
|
|
||
| float matchPercent(); | ||
|
|
||
| unsigned int mismatchCount(); | ||
|
|
||
| unsigned int matchTarget(); | ||
|
|
||
| int elapsedTime(); | ||
|
|
||
| void setControlName( const QString theName ); | ||
|
|
||
| void setControlPathPrefix( const QString theName ); | ||
|
|
||
| QString imageToHash( QString theImageFile ); | ||
|
|
||
| void setRenderedImage( QString theImageFileName ); | ||
|
|
||
| void setMapRenderer( QgsMapRenderer * thepMapRenderer ); | ||
|
|
||
| bool runTest( QString theTestName, unsigned int theMismatchCount = 0 ); | ||
|
|
||
| bool compareImages( QString theTestName, unsigned int theMismatchCount = 0, QString theRenderedImageFile = "" ); | ||
|
|
||
| bool isKnownAnomaly( QString theDiffImageFile ); | ||
| }; | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| /*************************************************************************** | ||
| qgsdiagramproperties.h | ||
| Properties for diagram layers | ||
| ------------------- | ||
| begin : August 2012 | ||
| copyright : (C) Matthias Kuhn | ||
| email : matthias dot kuhn at gmx dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef QGSDIAGRAMPROPERTIES_H | ||
| #define QGSDIAGRAMPROPERTIES_H | ||
|
|
||
| #include <QDialog> | ||
| #include <ui_qgsdiagrampropertiesbase.h> | ||
|
|
||
| class QgsVectorLayer; | ||
|
|
||
| class QgsDiagramProperties : public QWidget, private Ui::QgsDiagramPropertiesBase | ||
| { | ||
| Q_OBJECT | ||
|
|
||
| public: | ||
| QgsDiagramProperties( QgsVectorLayer* layer, QWidget* parent ); | ||
| /**Adds an attribute from the list of available attributes to the assigned attributes with a random color.*/ | ||
| void addAttribute( QTreeWidgetItem * item ); | ||
|
|
||
| public slots: | ||
| void apply(); | ||
| void on_mDiagramTypeComboBox_currentIndexChanged( int index ); | ||
| void on_mTransparencySlider_valueChanged( int value ); | ||
| void on_mAddCategoryPushButton_clicked(); | ||
| void on_mAttributesTreeWidget_itemDoubleClicked( QTreeWidgetItem * item, int column ); | ||
| void on_mBackgroundColorButton_clicked(); | ||
| void on_mFindMaximumValueButton_clicked(); | ||
| void on_mDiagramPenColorButton_clicked(); | ||
| void on_mDisplayDiagramsGroupBox_toggled( bool checked ); | ||
| void on_mRemoveCategoryPushButton_clicked(); | ||
| void on_mDiagramFontButton_clicked(); | ||
| void on_mDiagramAttributesTreeWidget_itemDoubleClicked( QTreeWidgetItem * item, int column ); | ||
| void on_mEngineSettingsButton_clicked(); | ||
|
|
||
| protected: | ||
| QFont mDiagramFont; | ||
|
|
||
| QgsVectorLayer* mLayer; | ||
|
|
||
| private: | ||
| }; | ||
|
|
||
| #endif // QGSDIAGRAMPROPERTIES_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| /*************************************************************************** | ||
| qgsdiagram.cpp | ||
| --------------------- | ||
| begin : March 2011 | ||
| copyright : (C) 2011 by Marco Hugentobler | ||
| email : marco dot hugentobler at sourcepole dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
| #include "qgsdiagram.h" | ||
| #include "qgsdiagramrendererv2.h" | ||
| #include "qgsrendercontext.h" | ||
|
|
||
| #include <QPainter> | ||
|
|
||
| void QgsDiagram::setPenWidth( QPen& pen, const QgsDiagramSettings& s, const QgsRenderContext& c ) | ||
| { | ||
| if ( s.sizeType == QgsDiagramSettings::MM ) | ||
| { | ||
| pen.setWidthF( s.penWidth * c.scaleFactor() ); | ||
| } | ||
| else | ||
| { | ||
| pen.setWidthF( s.penWidth / c.mapToPixel().mapUnitsPerPixel() ); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| QSizeF QgsDiagram::sizePainterUnits( const QSizeF& size, const QgsDiagramSettings& s, const QgsRenderContext& c ) | ||
| { | ||
| if ( s.sizeType == QgsDiagramSettings::MM ) | ||
| { | ||
| return QSizeF( size.width() * c.scaleFactor(), size.height() * c.scaleFactor() ); | ||
| } | ||
| else | ||
| { | ||
| return QSizeF( size.width() / c.mapToPixel().mapUnitsPerPixel(), size.height() / c.mapToPixel().mapUnitsPerPixel() ); | ||
| } | ||
| } | ||
|
|
||
| float QgsDiagram::sizePainterUnits( float l, const QgsDiagramSettings& s, const QgsRenderContext& c ) | ||
| { | ||
| if ( s.sizeType == QgsDiagramSettings::MM ) | ||
| { | ||
| return l * c.scaleFactor(); | ||
| } | ||
| else | ||
| { | ||
| return l / c.mapToPixel().mapUnitsPerPixel(); | ||
| } | ||
| } | ||
|
|
||
| QFont QgsDiagram::scaledFont( const QgsDiagramSettings& s, const QgsRenderContext& c ) | ||
| { | ||
| QFont f = s.font; | ||
| if ( s.sizeType == QgsDiagramSettings::MM ) | ||
| { | ||
| f.setPixelSize( s.font.pointSizeF() * 0.376 * c.scaleFactor() ); | ||
| } | ||
| else | ||
| { | ||
| f.setPixelSize( s.font.pointSizeF() / c.mapToPixel().mapUnitsPerPixel() ); | ||
| } | ||
|
|
||
| return f; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| /*************************************************************************** | ||
| qgsdiagram.h | ||
| --------------------- | ||
| begin : March 2011 | ||
| copyright : (C) 2011 by Marco Hugentobler | ||
| email : marco dot hugentobler at sourcepole dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
| #ifndef QGSDIAGRAM_H | ||
| #define QGSDIAGRAM_H | ||
|
|
||
| #include "qgsfeature.h" | ||
| #include <QPen> | ||
| #include <QBrush> | ||
|
|
||
| class QPainter; | ||
| class QPointF; | ||
| struct QgsDiagramSettings; | ||
| struct QgsDiagramInterpolationSettings; | ||
|
|
||
| class QgsRenderContext; | ||
|
|
||
|
|
||
|
|
||
| /**Base class for all diagram types*/ | ||
| class CORE_EXPORT QgsDiagram | ||
| { | ||
| public: | ||
| virtual ~QgsDiagram() {} | ||
| /**Draws the diagram at the given position (in pixel coordinates)*/ | ||
| virtual void renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position ) = 0; | ||
| virtual QString diagramName() const = 0; | ||
| /**Returns the size in map units the diagram will use to render.*/ | ||
| virtual QSizeF diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s ) = 0; | ||
| /**Returns the size in map units the diagram will use to render. Interpolate size*/ | ||
| virtual QSizeF diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is ) = 0; | ||
|
|
||
| protected: | ||
| /** Changes the pen width to match the current settings and rendering context | ||
| * @param pen The pen to modify | ||
| * @param s The settings that specify the pen width | ||
| * @param c The rendering specifying the proper scale units for pixel conversion | ||
| */ | ||
| void setPenWidth( QPen& pen, const QgsDiagramSettings& s, const QgsRenderContext& c ); | ||
|
|
||
| /** Calculates a size to match the current settings and rendering context | ||
| * @param size The size to convert | ||
| * @param s The settings that specify the size type | ||
| * @param c The rendering specifying the proper scale units for pixel conversion | ||
| * | ||
| * @return The converted size for rendering | ||
| */ | ||
| QSizeF sizePainterUnits( const QSizeF& size, const QgsDiagramSettings& s, const QgsRenderContext& c ); | ||
|
|
||
| /** Calculates a length to match the current settings and rendering context | ||
| * @param l The length to convert | ||
| * @param s Unused | ||
| * @param c The rendering specifying the proper scale units for pixel conversion | ||
| * | ||
| * @return The converted length for rendering | ||
| */ | ||
| float sizePainterUnits( float l, const QgsDiagramSettings& s, const QgsRenderContext& c ); | ||
|
|
||
| /** Calculates a size to match the current settings and rendering context | ||
| * @param s The settings that contain the font size and size type | ||
| * @param c The rendering specifying the proper scale units for pixel conversion | ||
| * | ||
| * @return The properly scaled font for rendering | ||
| */ | ||
| QFont scaledFont( const QgsDiagramSettings& s, const QgsRenderContext& c ); | ||
| }; | ||
|
|
||
| #endif // QGSDIAGRAM_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,167 @@ | ||
| /*************************************************************************** | ||
| qgshistogramdiagram.cpp | ||
| --------------------- | ||
| begin : August 2012 | ||
| copyright : (C) 2012 by Matthias Kuhn | ||
| email : matthias dot kuhn at gmx dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
| #include "qgshistogramdiagram.h" | ||
| #include "qgsdiagramrendererv2.h" | ||
| #include "qgsrendercontext.h" | ||
|
|
||
| #include <QPainter> | ||
|
|
||
| QgsHistogramDiagram::QgsHistogramDiagram() | ||
| { | ||
| mCategoryBrush.setStyle( Qt::SolidPattern ); | ||
| mPen.setStyle( Qt::SolidLine ); | ||
| mScaleFactor = 0; | ||
| } | ||
|
|
||
| QgsHistogramDiagram::~QgsHistogramDiagram() | ||
| { | ||
| } | ||
|
|
||
| QSizeF QgsHistogramDiagram::diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is ) | ||
| { | ||
| Q_UNUSED( c ); | ||
| QSize size; | ||
| QgsAttributeMap::const_iterator attIt = attributes.constBegin(); | ||
| if ( attIt == attributes.constEnd() ) | ||
| { | ||
| return QSizeF(); //zero size if no attributes | ||
| } | ||
|
|
||
| double maxValue = attIt.value().toDouble(); | ||
|
|
||
| for ( ++attIt; attIt != attributes.constEnd(); ++attIt ) | ||
| { | ||
| maxValue = qMax( attIt.value().toDouble(), maxValue ); | ||
| } | ||
|
|
||
| // Scale, if extension is smaller than the specified minimum | ||
| if ( maxValue < s.minimumSize ) | ||
| { | ||
| maxValue = s.minimumSize; | ||
| } | ||
|
|
||
| switch ( s.diagramOrientation ) | ||
| { | ||
| case QgsDiagramSettings::Up: | ||
| case QgsDiagramSettings::Down: | ||
| mScaleFactor = (( is.upperSize.width() - is.lowerSize.height() ) / ( is.upperValue - is.lowerValue ) ); | ||
| size.scale( s.barWidth * attributes.size(), maxValue * mScaleFactor, Qt::IgnoreAspectRatio ); | ||
| break; | ||
|
|
||
| case QgsDiagramSettings::Right: | ||
| case QgsDiagramSettings::Left: | ||
| mScaleFactor = (( is.upperSize.width() - is.lowerSize.width() ) / ( is.upperValue - is.lowerValue ) ); | ||
| size.scale( maxValue * mScaleFactor, s.barWidth * attributes.size(), Qt::IgnoreAspectRatio ); | ||
| break; | ||
| } | ||
|
|
||
| return size; | ||
| } | ||
|
|
||
| QSizeF QgsHistogramDiagram::diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s ) | ||
| { | ||
| Q_UNUSED( c ); | ||
| QSizeF size; | ||
|
|
||
| QgsAttributeMap::const_iterator attIt = attributes.constBegin(); | ||
| if ( attIt == attributes.constEnd() ) | ||
| { | ||
| return QSizeF(); //zero size if no attributes | ||
| } | ||
|
|
||
| double maxValue = attIt.value().toDouble(); | ||
|
|
||
| for ( ; attIt != attributes.constEnd(); ++attIt ) | ||
| { | ||
| maxValue = qMax( attIt.value().toDouble(), maxValue ); | ||
| } | ||
|
|
||
| switch ( s.diagramOrientation ) | ||
| { | ||
| case QgsDiagramSettings::Up: | ||
| case QgsDiagramSettings::Down: | ||
| mScaleFactor = maxValue / s.size.height(); | ||
| size.scale( s.barWidth * s.categoryColors.size(), s.size.height(), Qt::IgnoreAspectRatio ); | ||
| break; | ||
|
|
||
| case QgsDiagramSettings::Right: | ||
| case QgsDiagramSettings::Left: | ||
| default: // just in case... | ||
| mScaleFactor = maxValue / s.size.width(); | ||
| size.scale( s.size.width(), s.barWidth * s.categoryColors.size(), Qt::IgnoreAspectRatio ); | ||
| break; | ||
| } | ||
|
|
||
| return size; | ||
| } | ||
|
|
||
| void QgsHistogramDiagram::renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position ) | ||
| { | ||
| QPainter* p = c.painter(); | ||
| if ( !p ) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| QList<double> values; | ||
|
|
||
| QList<int>::const_iterator catIt = s.categoryIndices.constBegin(); | ||
| for ( ; catIt != s.categoryIndices.constEnd(); ++catIt ) | ||
| { | ||
| double currentVal = att[*catIt].toDouble(); | ||
| values.push_back( currentVal ); | ||
| } | ||
|
|
||
| double currentOffset = 0; | ||
| double scaledWidth = sizePainterUnits( s.barWidth, s, c ); | ||
|
|
||
| double baseX = position.x(); | ||
| double baseY = position.y(); | ||
|
|
||
| mPen.setColor( s.penColor ); | ||
| setPenWidth( mPen, s, c ); | ||
| p->setPen( mPen ); | ||
|
|
||
| QList<double>::const_iterator valIt = values.constBegin(); | ||
| QList< QColor >::const_iterator colIt = s.categoryColors.constBegin(); | ||
| for ( ; valIt != values.constEnd(); ++valIt, ++colIt ) | ||
| { | ||
| double length = sizePainterUnits( *valIt * mScaleFactor, s, c ); | ||
|
|
||
| mCategoryBrush.setColor( *colIt ); | ||
| p->setBrush( mCategoryBrush ); | ||
|
|
||
| switch ( s.diagramOrientation ) | ||
| { | ||
| case QgsDiagramSettings::Up: | ||
| p->drawRect( baseX + currentOffset, baseY, scaledWidth, 0 - length ); | ||
| break; | ||
|
|
||
| case QgsDiagramSettings::Down: | ||
| p->drawRect( baseX + currentOffset, baseY, scaledWidth, length ); | ||
| break; | ||
|
|
||
| case QgsDiagramSettings::Right: | ||
| p->drawRect( baseX, baseY + currentOffset, length, scaledWidth ); | ||
| break; | ||
|
|
||
| case QgsDiagramSettings::Left: | ||
| p->drawRect( baseX, baseY + currentOffset, 0 - length, scaledWidth ); | ||
| break; | ||
| } | ||
|
|
||
| currentOffset += scaledWidth; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| /*************************************************************************** | ||
| qgshistogramdiagram.h | ||
| --------------------- | ||
| begin : August 2012 | ||
| copyright : (C) 2012 by Matthias Kuhn | ||
| email : matthias dot kuhn at gmx dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef QGSHISTOGRAMDIAGRAM_H | ||
| #define QGSHISTOGRAMDIAGRAM_H | ||
|
|
||
| #define DIAGRAM_NAME_HISTOGRAM "Histogram" | ||
|
|
||
| #include "qgsdiagram.h" | ||
| #include "qgsfeature.h" | ||
| #include <QPen> | ||
| #include <QBrush> | ||
|
|
||
| class QPainter; | ||
| class QPointF; | ||
| struct QgsDiagramSettings; | ||
| struct QgsDiagramInterpolationSettings; | ||
|
|
||
| class QgsRenderContext; | ||
|
|
||
|
|
||
| class CORE_EXPORT QgsHistogramDiagram: public QgsDiagram | ||
| { | ||
| public: | ||
| QgsHistogramDiagram(); | ||
| ~QgsHistogramDiagram(); | ||
|
|
||
| void renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position ); | ||
| QSizeF diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s ); | ||
| QSizeF diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is ); | ||
| QString diagramName() const { return DIAGRAM_NAME_HISTOGRAM; } | ||
|
|
||
| private: | ||
| QBrush mCategoryBrush; | ||
| QPen mPen; | ||
| double mScaleFactor; | ||
| }; | ||
|
|
||
|
|
||
| #endif // QGSHISTOGRAMDIAGRAM_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,153 @@ | ||
| /*************************************************************************** | ||
| qgspiediagram.cpp | ||
| --------------------- | ||
| begin : March 2011 | ||
| copyright : (C) 2011 by Marco Hugentobler | ||
| email : marco dot hugentobler at sourcepole dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
| #include "qgspiediagram.h" | ||
| #include "qgsdiagramrendererv2.h" | ||
| #include "qgsrendercontext.h" | ||
|
|
||
| #include <QPainter> | ||
|
|
||
|
|
||
| QgsPieDiagram::QgsPieDiagram() | ||
| { | ||
| mCategoryBrush.setStyle( Qt::SolidPattern ); | ||
| mPen.setStyle( Qt::SolidLine ); | ||
| } | ||
|
|
||
| QgsPieDiagram::~QgsPieDiagram() | ||
| { | ||
| } | ||
|
|
||
| QSizeF QgsPieDiagram::diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is ) | ||
| { | ||
| Q_UNUSED( c ); | ||
| QgsAttributeMap::const_iterator attIt = attributes.find( is.classificationAttribute ); | ||
| if ( attIt == attributes.constEnd() ) | ||
| { | ||
| return QSizeF(); //zero size if attribute is missing | ||
| } | ||
|
|
||
| double scaledValue = attIt.value().toDouble(); | ||
| double scaledLowerValue = is.lowerValue; | ||
| double scaledUpperValue = is.upperValue; | ||
| double scaledLowerSizeWidth = is.lowerSize.width(); | ||
| double scaledLowerSizeHeight = is.lowerSize.height(); | ||
| double scaledUpperSizeWidth = is.upperSize.width(); | ||
| double scaledUpperSizeHeight = is.upperSize.height(); | ||
|
|
||
| // interpolate the squared value if scale by area | ||
| if ( s.scaleByArea ) | ||
| { | ||
| scaledValue = sqrt( scaledValue ); | ||
| scaledLowerValue = sqrt( scaledLowerValue ); | ||
| scaledUpperValue = sqrt( scaledUpperValue ); | ||
| scaledLowerSizeWidth = sqrt( scaledLowerSizeWidth ); | ||
| scaledLowerSizeHeight = sqrt( scaledLowerSizeHeight ); | ||
| scaledUpperSizeWidth = sqrt( scaledUpperSizeWidth ); | ||
| scaledUpperSizeHeight = sqrt( scaledUpperSizeHeight ); | ||
| } | ||
|
|
||
| //interpolate size | ||
| double scaledRatio = ( scaledValue - scaledLowerValue ) / ( scaledUpperValue - scaledLowerValue ); | ||
|
|
||
| QSizeF size = QSizeF( is.upperSize.width() * scaledRatio + is.lowerSize.width() * ( 1 - scaledRatio ), | ||
| is.upperSize.height() * scaledRatio + is.lowerSize.height() * ( 1 - scaledRatio ) ); | ||
|
|
||
| // Scale, if extension is smaller than the specified minimum | ||
| if ( size.width() <= s.minimumSize && size.height() <= s.minimumSize ) | ||
| { | ||
| size.scale( s.minimumSize, s.minimumSize, Qt::KeepAspectRatio ); | ||
| } | ||
|
|
||
| return size; | ||
| } | ||
|
|
||
| QSizeF QgsPieDiagram::diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s ) | ||
| { | ||
| Q_UNUSED( c ); | ||
| Q_UNUSED( attributes ); | ||
| return s.size; | ||
| } | ||
|
|
||
| int QgsPieDiagram::sCount = 0; | ||
|
|
||
| void QgsPieDiagram::renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position ) | ||
| { | ||
| QPainter* p = c.painter(); | ||
| if ( !p ) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| //get sum of values | ||
| QList<double> values; | ||
| double currentVal = 0; | ||
| double valSum = 0; | ||
| int valCount = 0; | ||
|
|
||
| QList<int>::const_iterator catIt = s.categoryIndices.constBegin(); | ||
| for ( ; catIt != s.categoryIndices.constEnd(); ++catIt ) | ||
| { | ||
| currentVal = att[*catIt].toDouble(); | ||
| values.push_back( currentVal ); | ||
| valSum += currentVal; | ||
| if ( currentVal ) valCount++; | ||
| } | ||
|
|
||
| //draw the slices | ||
| double totalAngle = 0; | ||
| double currentAngle; | ||
|
|
||
| //convert from mm / map units to painter units | ||
| QSizeF spu = sizePainterUnits( s.size, s, c ); | ||
| double w = spu.width(); | ||
| double h = spu.height(); | ||
|
|
||
| double baseX = position.x(); | ||
| double baseY = position.y() - h; | ||
|
|
||
| mPen.setColor( s.penColor ); | ||
| setPenWidth( mPen, s, c ); | ||
| p->setPen( mPen ); | ||
|
|
||
| // there are some values > 0 available | ||
| if ( valSum > 0 ) | ||
| { | ||
| QList<double>::const_iterator valIt = values.constBegin(); | ||
| QList< QColor >::const_iterator colIt = s.categoryColors.constBegin(); | ||
| for ( ; valIt != values.constEnd(); ++valIt, ++colIt ) | ||
| { | ||
| currentAngle = *valIt / valSum * 360 * 16; | ||
| mCategoryBrush.setColor( *colIt ); | ||
| p->setBrush( mCategoryBrush ); | ||
| // if only 1 value is > 0, draw a circle | ||
| if ( valCount == 1 ) | ||
| { | ||
| p->drawEllipse( baseX, baseY, w, h ); | ||
| } | ||
| else | ||
| { | ||
| p->drawPie( baseX, baseY, w, h, totalAngle, currentAngle ); | ||
| } | ||
| totalAngle += currentAngle; | ||
| } | ||
| } | ||
| else // valSum > 0 | ||
| { | ||
| // draw empty circle if no values are defined at all | ||
| mCategoryBrush.setColor( Qt::transparent ); | ||
| p->setBrush( mCategoryBrush ); | ||
| p->drawEllipse( baseX, baseY, w, h ); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| /*************************************************************************** | ||
| qgspiediagram.h | ||
| --------------------- | ||
| begin : March 2011 | ||
| copyright : (C) 2011 by Marco Hugentobler | ||
| email : marco dot hugentobler at sourcepole dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
| #ifndef QGSPIEDIAGRAM_H | ||
| #define QGSPIEDIAGRAM_H | ||
|
|
||
| #define DIAGRAM_NAME_PIE "Pie" | ||
|
|
||
| #include "qgsdiagram.h" | ||
| #include "qgsfeature.h" | ||
| #include <QPen> | ||
| #include <QBrush> | ||
|
|
||
| class QPainter; | ||
| class QPointF; | ||
| struct QgsDiagramSettings; | ||
| struct QgsDiagramInterpolationSettings; | ||
|
|
||
| class QgsRenderContext; | ||
|
|
||
| class CORE_EXPORT QgsPieDiagram: public QgsDiagram | ||
| { | ||
| public: | ||
| QgsPieDiagram(); | ||
| ~QgsPieDiagram(); | ||
|
|
||
| void renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position ); | ||
| QSizeF diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s ); | ||
| QSizeF diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is ); | ||
| QString diagramName() const { return DIAGRAM_NAME_PIE; } | ||
|
|
||
| private: | ||
| QBrush mCategoryBrush; | ||
| QPen mPen; | ||
|
|
||
| static int sCount; | ||
| }; | ||
|
|
||
| #endif // QGSPIEDIAGRAM_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,236 @@ | ||
| /*************************************************************************** | ||
| qgsrasterchecker.cpp | ||
| -------------------------------------- | ||
| Date : 5 Sep 2012 | ||
| Copyright : (C) 2012 by Radim Blazek | ||
| Email : radim dot blazek at gmail dot com | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #include "qgsrasterchecker.h" | ||
| #include "qgsrasterdataprovider.h" | ||
| #include "qgsrasterlayer.h" | ||
|
|
||
| #include <qmath.h> | ||
| #include <QColor> | ||
| #include <QPainter> | ||
| #include <QImage> | ||
| #include <QTime> | ||
| #include <QCryptographicHash> | ||
| #include <QByteArray> | ||
| #include <QDebug> | ||
| #include <QBuffer> | ||
|
|
||
| QgsRasterChecker::QgsRasterChecker( ) : | ||
| mReport( "" ) | ||
| { | ||
| mTabStyle = "border-spacing: 0px; border-width: 1px 1px 0 0; border-style: solid;"; | ||
| mCellStyle = "border-width: 0 0 1px 1px; border-style: solid; font-size: smaller; text-align: center;"; | ||
| mOkStyle = "background: #00ff00;"; | ||
| mErrStyle = "background: #ff0000;"; | ||
| mErrMsgStyle = "color: #ff0000;"; | ||
| } | ||
|
|
||
| bool QgsRasterChecker::runTest( QString theVerifiedKey, QString theVerifiedUri, | ||
| QString theExpectedKey, QString theExpectedUri ) | ||
| { | ||
| bool ok = true; | ||
| mReport += "\n\n"; | ||
|
|
||
| QgsRasterDataProvider* verifiedProvider = QgsRasterLayer::loadProvider( theVerifiedKey, theVerifiedUri ); | ||
| if ( !verifiedProvider || !verifiedProvider->isValid() ) | ||
| { | ||
| error( QString( "Cannot load provider %1 with URI: %2" ).arg( theVerifiedKey).arg( theVerifiedUri), mReport ); | ||
| ok = false; | ||
| } | ||
|
|
||
| QgsRasterDataProvider* expectedProvider = QgsRasterLayer::loadProvider( theExpectedKey, theExpectedUri ); | ||
| if ( !expectedProvider || !expectedProvider->isValid() ) | ||
| { | ||
| error( QString( "Cannot load provider %1 with URI: %2" ).arg( theExpectedKey).arg( theExpectedUri ), mReport ); | ||
| ok = false; | ||
| } | ||
|
|
||
| if ( !ok ) return false; | ||
|
|
||
| mReport += QString( "Verified URI: %1<br>" ).arg( theVerifiedUri.replace( "&", "&" ) ); | ||
| mReport += QString( "Expected URI: %1<br>" ).arg( theExpectedUri.replace( "&", "&" ) ); | ||
|
|
||
| mReport += "<br>"; | ||
| mReport += QString("<table style='%1'>\n").arg( mTabStyle ); | ||
| mReport += compareHead(); | ||
|
|
||
| compare( "Band count", verifiedProvider->bandCount(), expectedProvider->bandCount(), mReport, ok ); | ||
|
|
||
| compare( "Width", verifiedProvider->xSize(), expectedProvider->xSize(), mReport, ok ); | ||
| compare( "Height", verifiedProvider->ySize(), expectedProvider->ySize(), mReport, ok ); | ||
|
|
||
| compareRow( "Extent", verifiedProvider->extent().toString(), expectedProvider->extent().toString(), mReport, verifiedProvider->extent() == expectedProvider->extent() ); | ||
|
|
||
| if ( verifiedProvider->extent() != expectedProvider->extent() ) ok = false; | ||
|
|
||
| compare( "No data (NULL) value", verifiedProvider->noDataValue(), expectedProvider->noDataValue(), mReport, ok ); | ||
|
|
||
| mReport += "</table>\n"; | ||
|
|
||
| if ( !ok ) return false; | ||
|
|
||
| bool allOk = true; | ||
| for ( int band = 1; band <= expectedProvider->bandCount(); band++ ) | ||
| { | ||
| bool bandOk = true; | ||
| mReport += QString( "<h3>Band %1</h3>\n" ).arg( band ); | ||
| mReport += QString("<table style='%1'>\n").arg( mTabStyle ); | ||
| mReport += compareHead(); | ||
|
|
||
| // Data types may differ (?) | ||
| bool typesOk = true; | ||
| compare( "Source data type", verifiedProvider->srcDataType( band ), expectedProvider->srcDataType( band ), mReport, typesOk ); | ||
| compare( "Data type", verifiedProvider->dataType( band ), expectedProvider->dataType( band ), mReport, typesOk ) ; | ||
|
|
||
| bool statsOk = true; | ||
| QgsRasterBandStats verifiedStats = verifiedProvider->bandStatistics( band ); | ||
| QgsRasterBandStats expectedStats = expectedProvider->bandStatistics( band ); | ||
|
|
||
| // Min/max may 'slightly' differ, for big numbers however, the difference may | ||
| // be quite big, for example for Float32 with max -3.332e+38, the difference is 1.47338e+24 | ||
| double tol = tolerance( expectedStats.minimumValue ); | ||
| compare( "Minimum value", verifiedStats.minimumValue, expectedStats.minimumValue, mReport, statsOk, tol ); | ||
| tol = tolerance( expectedStats.maximumValue ); | ||
| compare( "Maximum value", verifiedStats.maximumValue, expectedStats.maximumValue, mReport, statsOk, tol ); | ||
|
|
||
| // TODO: enable once fixed (WCS excludes nulls but GDAL does not) | ||
| //compare( "Cells count", verifiedStats.elementCount, expectedStats.elementCount, mReport, statsOk ); | ||
|
|
||
| tol = tolerance( expectedStats.mean ); | ||
| compare( "Mean", verifiedStats.mean, expectedStats.mean, mReport, statsOk, tol ); | ||
|
|
||
| // stdDev usually differ significantly | ||
| tol = tolerance( expectedStats.stdDev, 1 ); | ||
| compare( "Standard deviation", verifiedStats.stdDev, expectedStats.stdDev, mReport, statsOk, tol ); | ||
|
|
||
| mReport += "</table>"; | ||
| mReport += "<br>"; | ||
|
|
||
| if ( !bandOk ) | ||
| { | ||
| allOk = false; | ||
| continue; | ||
| } | ||
|
|
||
| if ( !statsOk || !typesOk ) | ||
| { | ||
| allOk = false; | ||
| // create values table anyway so that values are available | ||
| } | ||
|
|
||
| mReport += "<table><tr>"; | ||
| mReport += "<td>Data comparison</td>"; | ||
| mReport += QString( "<td style='%1 %2 border: 1px solid'>correct value</td>" ).arg( mCellStyle).arg( mOkStyle ); | ||
| mReport += "<td></td>"; | ||
| mReport += QString( "<td style='%1 %2 border: 1px solid'>wrong value<br>expected value</td></tr>").arg( mCellStyle).arg( mErrStyle ); | ||
| mReport += "</tr></table>"; | ||
| mReport += "<br>"; | ||
|
|
||
| int width = expectedProvider->xSize(); | ||
| int height = expectedProvider->ySize(); | ||
| int blockSize = width * height * expectedProvider->typeSize( expectedProvider->dataType( band ) ) ; | ||
| void * expectedData = malloc( blockSize ); | ||
| void * verifiedData = malloc( blockSize ); | ||
|
|
||
| expectedProvider->readBlock( band, expectedProvider->extent(), width, height, expectedData ); | ||
| verifiedProvider->readBlock( band, expectedProvider->extent(), width, height, verifiedData ); | ||
|
|
||
| // compare data values | ||
| QString htmlTable = QString("<table style='%1'>").arg( mTabStyle ); | ||
| for ( int row = 0; row < height; row ++ ) | ||
| { | ||
| htmlTable += "<tr>"; | ||
| for ( int col = 0; col < width; col ++ ) | ||
| { | ||
| bool cellOk = true; | ||
| double verifiedVal = verifiedProvider->readValue( verifiedData, verifiedProvider->dataType( band ), row * width + col ); | ||
| double expectedVal = expectedProvider->readValue( expectedData, expectedProvider->dataType( band ), row * width + col ); | ||
|
|
||
| QString valStr; | ||
| if ( compare( verifiedVal, expectedVal, 0 ) ) | ||
| { | ||
| valStr = QString( "%1" ).arg( verifiedVal ); | ||
| } | ||
| else | ||
| { | ||
| cellOk = false; | ||
| allOk = false; | ||
| valStr = QString( "%1<br>%2" ).arg( verifiedVal ).arg( expectedVal ); | ||
| } | ||
| htmlTable += QString( "<td style='%1 %2'>%3</td>" ).arg( mCellStyle).arg( cellOk ? mOkStyle : mErrStyle ).arg( valStr ); | ||
| } | ||
| htmlTable += "</tr>"; | ||
| } | ||
| htmlTable += "</table>"; | ||
|
|
||
| mReport += htmlTable; | ||
|
|
||
| free( expectedData ); | ||
| free( verifiedData ); | ||
| } | ||
| delete verifiedProvider; | ||
| delete expectedProvider; | ||
| return allOk; | ||
| } | ||
|
|
||
| void QgsRasterChecker::error( QString theMessage, QString &theReport ) | ||
| { | ||
| theReport += QString( "<font style='%1'>Error: ").arg(mErrMsgStyle); | ||
| theReport += theMessage; | ||
| theReport += "</font>"; | ||
| } | ||
|
|
||
| double QgsRasterChecker::tolerance( double val, int places ) | ||
| { | ||
| // float precision is about 7 decimal digits, double about 16 | ||
| // default places = 6 | ||
| return 1. * qPow( 10, qRound( log10( qAbs( val ) ) - places ) ); | ||
| } | ||
|
|
||
| QString QgsRasterChecker::compareHead() | ||
| { | ||
| QString html; | ||
| html += QString( "<tr><th style='%1'>Param name</th><th style='%1'>Verified value</th><th style='%1'>Eexpected value</th><th style='%1'>Difference</th><th style='%1'>Tolerance</th></tr>").arg( mCellStyle ); | ||
| return html; | ||
| } | ||
|
|
||
| void QgsRasterChecker::compare( QString theParamName, int verifiedVal, int expectedVal, QString &theReport, bool &theOk ) | ||
| { | ||
| bool ok = verifiedVal == expectedVal; | ||
| compareRow( theParamName, QString::number( verifiedVal ), QString::number( expectedVal ), theReport, ok, QString::number( verifiedVal - expectedVal ) ); | ||
| if ( !ok ) theOk = false; | ||
| } | ||
|
|
||
| bool QgsRasterChecker::compare( double verifiedVal, double expectedVal, double theTolerance ) | ||
| { | ||
| // values may be nan | ||
| return ( qIsNaN( verifiedVal ) && qIsNaN( expectedVal ) ) || ( qAbs( verifiedVal - expectedVal ) <= theTolerance ); | ||
| } | ||
|
|
||
| void QgsRasterChecker::compare( QString theParamName, double verifiedVal, double expectedVal, QString &theReport, bool &theOk, double theTolerance ) | ||
| { | ||
| bool ok = compare( verifiedVal, expectedVal, theTolerance ); | ||
| compareRow( theParamName, QString::number( verifiedVal ), QString::number( expectedVal ), theReport, ok, QString::number( verifiedVal - expectedVal ), QString::number( theTolerance ) ); | ||
| if ( !ok ) theOk = false; | ||
| } | ||
|
|
||
| void QgsRasterChecker::compareRow( QString theParamName, QString verifiedVal, QString expectedVal, QString &theReport, bool theOk, QString theDifference, QString theTolerance ) | ||
| { | ||
| theReport += "<tr>\n"; | ||
| theReport += QString( "<td style='%1'>%2</td><td style='%1 %3'>%4</td><td style='%1'>%5</td>\n" ).arg(mCellStyle).arg( theParamName ).arg( theOk ? mOkStyle : mErrStyle ).arg( verifiedVal ).arg( expectedVal ); | ||
| theReport += QString( "<td style='%1'>%2</td>\n" ).arg(mCellStyle).arg( theDifference ); | ||
| theReport += QString( "<td style='%1'>%2</td>\n" ).arg(mCellStyle).arg( theTolerance ); | ||
| theReport += "</tr>"; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| /*************************************************************************** | ||
| qgsrasterchecker.h - compare two rasters | ||
| -------------------------------------- | ||
| Date : 5 Sep 2012 | ||
| Copyright : (C) 2012 by Radim Blazek | ||
| email : radim dot blazek at gmail dot com | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef QGSRASTERCHECKER_H | ||
| #define QGSRASTERCHECKER_H | ||
|
|
||
| #include <QDir> | ||
| #include <QString> | ||
| #include <qgsmaprenderer.h> | ||
| class QImage; | ||
|
|
||
| /** \ingroup UnitTests | ||
| * This is a helper class for unit tests that need to | ||
| * write an image and compare it to an expected result | ||
| * or render time. | ||
| */ | ||
| class CORE_EXPORT QgsRasterChecker | ||
| { | ||
| public: | ||
|
|
||
| QgsRasterChecker(); | ||
|
|
||
| //! Destructor | ||
| ~QgsRasterChecker() {}; | ||
|
|
||
| QString controlImagePath() const; | ||
|
|
||
| QString report() { return mReport; }; | ||
| /** | ||
| * Test using renderer to generate the image to be compared. | ||
| * @param theVerifiedKey verified provider key | ||
| * @param theVerifiedUri URI of the raster to be verified | ||
| * @param theExpectedKey expected provider key | ||
| * @param theExpectedUri URI of the expected (control) raster | ||
| */ | ||
| bool runTest( QString theVerifiedKey, QString theVerifiedUri, | ||
| QString theExpectedKey, QString theExpectedUri ); | ||
| private: | ||
| QString mReport; | ||
| QString mExpectedUri; | ||
| QString mCheckedUri; | ||
| QString mTabStyle; | ||
| QString mCellStyle; | ||
| QString mOkStyle; | ||
| QString mErrStyle; | ||
| QString mErrMsgStyle; | ||
|
|
||
| // Log error in html | ||
| void error( QString theMessage, QString &theReport ); | ||
| // compare values and add table row in html report, set ok to false if not equal | ||
| QString compareHead(); | ||
| bool compare( double verifiedVal, double expectedVal, double theTolerance ); | ||
| void compare( QString theParamName, int verifiedVal, int expectedVal, QString &theReport, bool &theOk ); | ||
| void compare( QString theParamName, double verifiedVal, double expectedVal, QString &theReport, bool &theOk, double theTolerance = 0 ); | ||
| void compareRow( QString theParamName, QString verifiedVal, QString expectedVal, QString &theReport, bool theOk, QString theDifference = "", QString theTolerance = "" ); | ||
| double tolerance( double val, int places = 6 ); | ||
| }; // class QgsRasterChecker | ||
|
|
||
| #endif |