diff --git a/src/core/qgsdiagram.cpp b/src/core/qgsdiagram.cpp index 60dcb5636638..16db5fc38295 100644 --- a/src/core/qgsdiagram.cpp +++ b/src/core/qgsdiagram.cpp @@ -82,6 +82,34 @@ QgsTextDiagram::~QgsTextDiagram() { } +QSizeF QgsTextDiagram::diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is ) +{ + QgsAttributeMap::const_iterator attIt = attributes.find( is.classificationAttribute ); + if ( attIt == attributes.constEnd() ) + { + return QSizeF(); //zero size if attribute is missing + } + double value = attIt.value().toDouble(); + + //interpolate size + double ratio = ( value - is.lowerValue ) / ( is.upperValue - is.lowerValue ); + QSizeF size = QSizeF( is.upperSize.width() * ratio + is.lowerSize.width() * ( 1 - ratio ), + is.upperSize.height() * ratio + is.lowerSize.height() * ( 1 - ratio ) ); + + // 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 QgsTextDiagram::diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s ) +{ + return s.size; +} + void QgsTextDiagram::renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position ) { QPainter* p = c.painter(); @@ -275,6 +303,34 @@ QgsPieDiagram::~QgsPieDiagram() { } +QSizeF QgsPieDiagram::diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is ) +{ + QgsAttributeMap::const_iterator attIt = attributes.find( is.classificationAttribute ); + if ( attIt == attributes.constEnd() ) + { + return QSizeF(); //zero size if attribute is missing + } + double value = attIt.value().toDouble(); + + //interpolate size + double ratio = ( value - is.lowerValue ) / ( is.upperValue - is.lowerValue ); + QSizeF size = QSizeF( is.upperSize.width() * ratio + is.lowerSize.width() * ( 1 - ratio ), + is.upperSize.height() * ratio + is.lowerSize.height() * ( 1 - ratio ) ); + + // 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 ) +{ + return s.size; +} + void QgsPieDiagram::renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position ) { QPainter* p = c.painter(); @@ -328,12 +384,81 @@ 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 ) +{ + 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 ); + } + + // Scale, if extension is smaller than the specified minimum + if ( maxValue < s.minimumSize ) + { + maxValue = s.minimumSize; + } + + mScaleFactor = ( maxValue - is.lowerValue ) / ( is.upperValue - is.lowerValue ); + + switch ( s.diagramOrientation ) + { + case QgsDiagramSettings::Up: + case QgsDiagramSettings::Down: + return QSizeF( s.barWidth * attributes.size(), maxValue ); + + case QgsDiagramSettings::Right: + case QgsDiagramSettings::Left: + return QSizeF( maxValue, s.barWidth * attributes.size() ); + } + + return QSizeF(); +} + +QSizeF QgsHistogramDiagram::diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s ) +{ + 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(); + return QSizeF( s.barWidth * attributes.size(), s.size.height() ); + + case QgsDiagramSettings::Right: + case QgsDiagramSettings::Left: + mScaleFactor = maxValue / s.size.width(); + return QSizeF( s.size.width(), s.barWidth * attributes.size() ); + } + + return QSizeF(); +} + void QgsHistogramDiagram::renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position ) { QPainter* p = c.painter(); @@ -365,14 +490,14 @@ void QgsHistogramDiagram::renderDiagram( const QgsAttributeMap& att, QgsRenderCo QList< QColor >::const_iterator colIt = s.categoryColors.constBegin(); for ( ; valIt != values.constEnd(); ++valIt, ++colIt ) { - double length = sizePainterUnits( *valIt, s, c ); + double length = sizePainterUnits( *valIt * mScaleFactor, s, c ); mCategoryBrush.setColor( *colIt ); p->setBrush( mCategoryBrush ); switch ( s.diagramOrientation ) { - case QgsDiagramSettings::Up: + case QgsDiagramSettings::Up: p->drawRect( baseX + currentOffset, baseY, scaledWidth, 0 - length ); break; @@ -391,4 +516,4 @@ void QgsHistogramDiagram::renderDiagram( const QgsAttributeMap& att, QgsRenderCo currentOffset += scaledWidth; } -} +} \ No newline at end of file diff --git a/src/core/qgsdiagram.h b/src/core/qgsdiagram.h index 480d76353a25..20f03945b12d 100644 --- a/src/core/qgsdiagram.h +++ b/src/core/qgsdiagram.h @@ -22,9 +22,12 @@ class QPainter; class QPointF; struct QgsDiagramSettings; +struct QgsDiagramInterpolationSettings; class QgsRenderContext; + + /**Base class for all diagram types*/ class CORE_EXPORT QgsDiagram { @@ -33,6 +36,10 @@ class CORE_EXPORT 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. Interpolat size*/ + virtual QSizeF diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is ) = 0; protected: void setPenWidth( QPen& pen, const QgsDiagramSettings& s, const QgsRenderContext& c ); @@ -60,6 +67,8 @@ class CORE_EXPORT QgsTextDiagram: public QgsDiagram QgsTextDiagram(); ~QgsTextDiagram(); 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 "Text"; } @@ -81,6 +90,8 @@ class CORE_EXPORT QgsPieDiagram: public QgsDiagram ~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 "Pie"; } private: @@ -95,11 +106,14 @@ class CORE_EXPORT QgsHistogramDiagram: public QgsDiagram ~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 "Histogram"; } private: QBrush mCategoryBrush; QPen mPen; + double mScaleFactor; }; diff --git a/src/core/qgsdiagramrendererv2.cpp b/src/core/qgsdiagramrendererv2.cpp index 40e56a419572..ce12ec99116c 100644 --- a/src/core/qgsdiagramrendererv2.cpp +++ b/src/core/qgsdiagramrendererv2.cpp @@ -324,6 +324,11 @@ bool QgsSingleCategoryDiagramRenderer::diagramSettings( const QgsAttributeMap&, return true; } +QSizeF QgsSingleCategoryDiagramRenderer::diagramSize(const QgsAttributeMap &attributes, const QgsRenderContext &c) +{ + return mDiagram->diagramSize( attributes, c, mSettings ); +} + QList QgsSingleCategoryDiagramRenderer::diagramSettings() const { QList settingsList; @@ -377,46 +382,27 @@ bool QgsLinearlyInterpolatedDiagramRenderer::diagramSettings( const QgsAttribute QList QgsLinearlyInterpolatedDiagramRenderer::diagramAttributes() const { QList attributes = mSettings.categoryIndices; - if ( !attributes.contains( mClassificationAttribute ) ) + if ( !attributes.contains( mInterpolationSettings.classificationAttribute ) ) { - attributes.push_back( mClassificationAttribute ); + attributes.push_back( mInterpolationSettings.classificationAttribute ); } return attributes; } QSizeF QgsLinearlyInterpolatedDiagramRenderer::diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c ) { - Q_UNUSED( c ); - QgsAttributeMap::const_iterator attIt = attributes.find( mClassificationAttribute ); - if ( attIt == attributes.constEnd() ) - { - return QSizeF(); //zero size if attribute is missing - } - double value = attIt.value().toDouble(); - - //interpolate size - double ratio = ( value - mLowerValue ) / ( mUpperValue - mLowerValue ); - QSizeF size = QSizeF( mUpperSize.width() * ratio + mLowerSize.width() * ( 1 - ratio ), - mUpperSize.height() * ratio + mLowerSize.height() * ( 1 - ratio ) ); - - // Scale, if extension is smaller than the specified minimum - if ( size.width() <= mSettings.minimumSize && size.height() <= mSettings.minimumSize ) - { - size.scale( mSettings.minimumSize, mSettings.minimumSize, Qt::KeepAspectRatio ); - } - - return size; + return mDiagram->diagramSize( attributes, c, mSettings, mInterpolationSettings ); } void QgsLinearlyInterpolatedDiagramRenderer::readXML( const QDomElement& elem ) { - mLowerValue = elem.attribute( "lowerValue" ).toDouble(); - mUpperValue = elem.attribute( "upperValue" ).toDouble(); - mLowerSize.setWidth( elem.attribute( "lowerWidth" ).toDouble() ); - mLowerSize.setHeight( elem.attribute( "lowerHeight" ).toDouble() ); - mUpperSize.setWidth( elem.attribute( "upperWidth" ).toDouble() ); - mUpperSize.setHeight( elem.attribute( "upperHeight" ).toDouble() ); - mClassificationAttribute = elem.attribute( "classificationAttribute" ).toInt(); + mInterpolationSettings.lowerValue = elem.attribute( "lowerValue" ).toDouble(); + mInterpolationSettings.upperValue = elem.attribute( "upperValue" ).toDouble(); + mInterpolationSettings.lowerSize.setWidth( elem.attribute( "lowerWidth" ).toDouble() ); + mInterpolationSettings.lowerSize.setHeight( elem.attribute( "lowerHeight" ).toDouble() ); + mInterpolationSettings.upperSize.setWidth( elem.attribute( "upperWidth" ).toDouble() ); + mInterpolationSettings.upperSize.setHeight( elem.attribute( "upperHeight" ).toDouble() ); + mInterpolationSettings.classificationAttribute = elem.attribute( "classificationAttribute" ).toInt(); QDomElement settingsElem = elem.firstChildElement( "DiagramCategory" ); if ( !settingsElem.isNull() ) { @@ -428,13 +414,13 @@ void QgsLinearlyInterpolatedDiagramRenderer::readXML( const QDomElement& elem ) void QgsLinearlyInterpolatedDiagramRenderer::writeXML( QDomElement& layerElem, QDomDocument& doc ) const { QDomElement rendererElem = doc.createElement( "LinearlyInterpolatedDiagramRenderer" ); - rendererElem.setAttribute( "lowerValue", QString::number( mLowerValue ) ); - rendererElem.setAttribute( "upperValue", QString::number( mUpperValue ) ); - rendererElem.setAttribute( "lowerWidth", QString::number( mLowerSize.width() ) ); - rendererElem.setAttribute( "lowerHeight", QString::number( mLowerSize.height() ) ); - rendererElem.setAttribute( "upperWidth", QString::number( mUpperSize.width() ) ); - rendererElem.setAttribute( "upperHeight", QString::number( mUpperSize.height() ) ); - rendererElem.setAttribute( "classificationAttribute", mClassificationAttribute ); + rendererElem.setAttribute( "lowerValue", QString::number( mInterpolationSettings.lowerValue ) ); + rendererElem.setAttribute( "upperValue", QString::number( mInterpolationSettings.upperValue ) ); + rendererElem.setAttribute( "lowerWidth", QString::number( mInterpolationSettings.lowerSize.width() ) ); + rendererElem.setAttribute( "lowerHeight", QString::number( mInterpolationSettings.lowerSize.height() ) ); + rendererElem.setAttribute( "upperWidth", QString::number( mInterpolationSettings.upperSize.width() ) ); + rendererElem.setAttribute( "upperHeight", QString::number( mInterpolationSettings.upperSize.height() ) ); + rendererElem.setAttribute( "classificationAttribute", mInterpolationSettings.classificationAttribute ); mSettings.writeXML( rendererElem, doc ); _writeXML( rendererElem, doc ); layerElem.appendChild( rendererElem ); diff --git a/src/core/qgsdiagramrendererv2.h b/src/core/qgsdiagramrendererv2.h index 2dd132e405d9..6863734de9d8 100644 --- a/src/core/qgsdiagramrendererv2.h +++ b/src/core/qgsdiagramrendererv2.h @@ -136,6 +136,17 @@ struct CORE_EXPORT QgsDiagramSettings void writeXML( QDomElement& rendererElem, QDomDocument& doc ) const; }; +//additional diagram settings for interpolated size rendering +struct CORE_EXPORT QgsDiagramInterpolationSettings +{ + QSizeF lowerSize; + QSizeF upperSize; + double lowerValue; + double upperValue; + /**Index of the classification attribute*/ + int classificationAttribute; +}; + /**Returns diagram settings for a feature*/ class CORE_EXPORT QgsDiagramRendererV2 { @@ -210,8 +221,7 @@ class CORE_EXPORT QgsSingleCategoryDiagramRenderer: public QgsDiagramRendererV2 protected: bool diagramSettings( const QgsAttributeMap&, const QgsRenderContext& c, QgsDiagramSettings& s ); - QSizeF diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c ) - { Q_UNUSED( attributes ); Q_UNUSED( c ); return mSettings.size; } + QSizeF diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c ); private: QgsDiagramSettings mSettings; @@ -232,20 +242,20 @@ class CORE_EXPORT QgsLinearlyInterpolatedDiagramRenderer: public QgsDiagramRende QString rendererName() const { return "LinearlyInterpolated"; } - void setLowerValue( double val ) { mLowerValue = val; } - double lowerValue() const { return mLowerValue; } + void setLowerValue( double val ) { mInterpolationSettings.lowerValue = val; } + double lowerValue() const { return mInterpolationSettings.lowerValue; } - void setUpperValue( double val ) { mUpperValue = val; } - double upperValue() const { return mUpperValue; } + void setUpperValue( double val ) { mInterpolationSettings.upperValue = val; } + double upperValue() const { return mInterpolationSettings.upperValue; } - void setLowerSize( QSizeF s ) { mLowerSize = s; } - QSizeF lowerSize() const { return mLowerSize; } + void setLowerSize( QSizeF s ) { mInterpolationSettings.lowerSize = s; } + QSizeF lowerSize() const { return mInterpolationSettings.lowerSize; } - void setUpperSize( QSizeF s ) { mUpperSize = s; } - QSizeF upperSize() const { return mUpperSize; } + void setUpperSize( QSizeF s ) { mInterpolationSettings.upperSize = s; } + QSizeF upperSize() const { return mInterpolationSettings.upperSize; } - int classificationAttribute() const { return mClassificationAttribute; } - void setClassificationAttribute( int index ) { mClassificationAttribute = index; } + int classificationAttribute() const { return mInterpolationSettings.classificationAttribute; } + void setClassificationAttribute( int index ) { mInterpolationSettings.classificationAttribute = index; } void readXML( const QDomElement& elem ); void writeXML( QDomElement& layerElem, QDomDocument& doc ) const; @@ -257,12 +267,7 @@ class CORE_EXPORT QgsLinearlyInterpolatedDiagramRenderer: public QgsDiagramRende private: QgsDiagramSettings mSettings; - QSizeF mLowerSize; - QSizeF mUpperSize; - double mLowerValue; - double mUpperValue; - /**Index of the classification attribute*/ - int mClassificationAttribute; + QgsDiagramInterpolationSettings mInterpolationSettings; }; #endif // QGSDIAGRAMRENDERERV2_H