|
QGIS API Documentation
master-59fd5e0
|
00001 /*************************************************************************** 00002 qgspiediagram.cpp 00003 --------------------- 00004 begin : March 2011 00005 copyright : (C) 2011 by Marco Hugentobler 00006 email : marco dot hugentobler at sourcepole dot ch 00007 *************************************************************************** 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 ***************************************************************************/ 00015 #include "qgspiediagram.h" 00016 #include "qgsdiagramrendererv2.h" 00017 #include "qgsrendercontext.h" 00018 00019 #include <QPainter> 00020 00021 00022 QgsPieDiagram::QgsPieDiagram() 00023 { 00024 mCategoryBrush.setStyle( Qt::SolidPattern ); 00025 mPen.setStyle( Qt::SolidLine ); 00026 } 00027 00028 QgsPieDiagram::~QgsPieDiagram() 00029 { 00030 } 00031 00032 QSizeF QgsPieDiagram::diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is ) 00033 { 00034 Q_UNUSED( c ); 00035 QVariant attrVal = attributes[is.classificationAttribute]; 00036 if ( !attrVal.isValid() ) 00037 { 00038 return QSizeF(); //zero size if attribute is missing 00039 } 00040 00041 double scaledValue = attrVal.toDouble(); 00042 double scaledLowerValue = is.lowerValue; 00043 double scaledUpperValue = is.upperValue; 00044 double scaledLowerSizeWidth = is.lowerSize.width(); 00045 double scaledLowerSizeHeight = is.lowerSize.height(); 00046 double scaledUpperSizeWidth = is.upperSize.width(); 00047 double scaledUpperSizeHeight = is.upperSize.height(); 00048 00049 // interpolate the squared value if scale by area 00050 if ( s.scaleByArea ) 00051 { 00052 scaledValue = sqrt( scaledValue ); 00053 scaledLowerValue = sqrt( scaledLowerValue ); 00054 scaledUpperValue = sqrt( scaledUpperValue ); 00055 scaledLowerSizeWidth = sqrt( scaledLowerSizeWidth ); 00056 scaledLowerSizeHeight = sqrt( scaledLowerSizeHeight ); 00057 scaledUpperSizeWidth = sqrt( scaledUpperSizeWidth ); 00058 scaledUpperSizeHeight = sqrt( scaledUpperSizeHeight ); 00059 } 00060 00061 //interpolate size 00062 double scaledRatio = ( scaledValue - scaledLowerValue ) / ( scaledUpperValue - scaledLowerValue ); 00063 00064 QSizeF size = QSizeF( is.upperSize.width() * scaledRatio + is.lowerSize.width() * ( 1 - scaledRatio ), 00065 is.upperSize.height() * scaledRatio + is.lowerSize.height() * ( 1 - scaledRatio ) ); 00066 00067 // Scale, if extension is smaller than the specified minimum 00068 if ( size.width() <= s.minimumSize && size.height() <= s.minimumSize ) 00069 { 00070 size.scale( s.minimumSize, s.minimumSize, Qt::KeepAspectRatio ); 00071 } 00072 00073 return size; 00074 } 00075 00076 QSizeF QgsPieDiagram::diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s ) 00077 { 00078 Q_UNUSED( c ); 00079 Q_UNUSED( attributes ); 00080 return s.size; 00081 } 00082 00083 int QgsPieDiagram::sCount = 0; 00084 00085 void QgsPieDiagram::renderDiagram( const QgsAttributes& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position ) 00086 { 00087 QPainter* p = c.painter(); 00088 if ( !p ) 00089 { 00090 return; 00091 } 00092 00093 //get sum of values 00094 QList<double> values; 00095 double currentVal = 0; 00096 double valSum = 0; 00097 int valCount = 0; 00098 00099 QList<int>::const_iterator catIt = s.categoryIndices.constBegin(); 00100 for ( ; catIt != s.categoryIndices.constEnd(); ++catIt ) 00101 { 00102 currentVal = att[*catIt].toDouble(); 00103 values.push_back( currentVal ); 00104 valSum += currentVal; 00105 if ( currentVal ) valCount++; 00106 } 00107 00108 //draw the slices 00109 double totalAngle = 0; 00110 double currentAngle; 00111 00112 //convert from mm / map units to painter units 00113 QSizeF spu = sizePainterUnits( s.size, s, c ); 00114 double w = spu.width(); 00115 double h = spu.height(); 00116 00117 double baseX = position.x(); 00118 double baseY = position.y() - h; 00119 00120 mPen.setColor( s.penColor ); 00121 setPenWidth( mPen, s, c ); 00122 p->setPen( mPen ); 00123 00124 // there are some values > 0 available 00125 if ( valSum > 0 ) 00126 { 00127 QList<double>::const_iterator valIt = values.constBegin(); 00128 QList< QColor >::const_iterator colIt = s.categoryColors.constBegin(); 00129 for ( ; valIt != values.constEnd(); ++valIt, ++colIt ) 00130 { 00131 if ( *valIt ) 00132 { 00133 currentAngle = *valIt / valSum * 360 * 16; 00134 mCategoryBrush.setColor( *colIt ); 00135 p->setBrush( mCategoryBrush ); 00136 // if only 1 value is > 0, draw a circle 00137 if ( valCount == 1 ) 00138 { 00139 p->drawEllipse( baseX, baseY, w, h ); 00140 } 00141 else 00142 { 00143 p->drawPie( baseX, baseY, w, h, totalAngle + s.angleOffset, currentAngle ); 00144 } 00145 totalAngle += currentAngle; 00146 } 00147 } 00148 } 00149 else // valSum > 0 00150 { 00151 // draw empty circle if no values are defined at all 00152 mCategoryBrush.setColor( Qt::transparent ); 00153 p->setBrush( mCategoryBrush ); 00154 p->drawEllipse( baseX, baseY, w, h ); 00155 } 00156 }