Skip to content
Permalink
Browse files

let diagrams decide how much space they need themselves

  • Loading branch information
m-kuhn committed Aug 9, 2012
1 parent 55ff09e commit 07839fab88f44cf0f5967bdec158734133ecfa2b
Showing with 187 additions and 57 deletions.
  1. +128 −3 src/core/qgsdiagram.cpp
  2. +14 −0 src/core/qgsdiagram.h
  3. +22 −36 src/core/qgsdiagramrendererv2.cpp
  4. +23 −18 src/core/qgsdiagramrendererv2.h
@@ -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;
}
}
}
@@ -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;
};


@@ -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<QgsDiagramSettings> QgsSingleCategoryDiagramRenderer::diagramSettings() const
{
QList<QgsDiagramSettings> settingsList;
@@ -377,46 +382,27 @@ bool QgsLinearlyInterpolatedDiagramRenderer::diagramSettings( const QgsAttribute
QList<int> QgsLinearlyInterpolatedDiagramRenderer::diagramAttributes() const
{
QList<int> 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 );
@@ -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

0 comments on commit 07839fa

Please sign in to comment.