|
51 | 51 | #include <QMouseEvent> |
52 | 52 | #include "qgslogger.h" |
53 | 53 |
|
| 54 | +// QWT Charting widget |
| 55 | +#include <qwt_array.h> |
| 56 | +#include <qwt_legend.h> |
| 57 | +#include <qwt_plot.h> |
| 58 | +#include <qwt_plot_curve.h> |
| 59 | +#include <qwt_plot_grid.h> |
54 | 60 |
|
55 | 61 | const char * const ident = |
56 | 62 | "$Id$"; |
@@ -218,8 +224,6 @@ QgsRasterLayerProperties::QgsRasterLayerProperties( QgsMapLayer* lyr, QgsMapCanv |
218 | 224 | myPixmap.fill( Qt::gray ); |
219 | 225 | } |
220 | 226 | lstHistogramLabels->addItem( new QListWidgetItem( myPixmap, myRasterBandNameQString ) ); |
221 | | - mGradientHeight = pixHistogram->height() / 2; |
222 | | - mGradientWidth = pixHistogram->width() / 2; |
223 | 227 | //keep a list of band names for later use |
224 | 228 | //! @note band names should not be translated! |
225 | 229 | myBandNameList.append( myRasterBandNameQString ); |
@@ -1948,8 +1952,8 @@ void QgsRasterLayerProperties::on_pbnHistRefresh_clicked() |
1948 | 1952 | int myXAxisMax = 0; |
1949 | 1953 | bool myFirstItemFlag = true; |
1950 | 1954 | for ( int myIteratorInt = 1; |
1951 | | - myIteratorInt <= myBandCountInt; |
1952 | | - ++myIteratorInt ) |
| 1955 | + myIteratorInt <= myBandCountInt; |
| 1956 | + ++myIteratorInt ) |
1953 | 1957 | { |
1954 | 1958 | QgsRasterBandStats myRasterBandStats = mRasterLayer->bandStatistics( myIteratorInt ); |
1955 | 1959 | //calculate the x axis min max |
@@ -1998,318 +2002,51 @@ void QgsRasterLayerProperties::on_pbnHistRefresh_clicked() |
1998 | 2002 | QgsDebugMsg( QString( "max %1" ).arg( myYAxisMax ) ); |
1999 | 2003 | QgsDebugMsg( QString( "min %1" ).arg( myYAxisMin ) ); |
2000 | 2004 |
|
2001 | | - //create the image onto which graph and axes will be drawn |
2002 | | - int myImageWidth = pixHistogram->width() - 2; |
2003 | | - int myImageHeight = pixHistogram->height() - 2; //Take two pixels off to account for the boarder around the QLabel |
2004 | | - QPixmap myPixmap( myImageWidth, myImageHeight ); |
2005 | | - myPixmap.fill( Qt::white ); |
2006 | | - |
2007 | | - // TODO: Confirm that removing the "const QWidget * copyAttributes" 2nd parameter, |
2008 | | - // in order to make things work in Qt4, doesn't break things in Qt3. |
2009 | | - //QPainter myPainter(&myPixmap, this); |
2010 | | - QPainter myPainter( &myPixmap ); |
2011 | | - //anti alias lines in the graph |
2012 | | - myPainter.setRenderHint( QPainter::Antialiasing ); |
2013 | | - //determine labels sizes and draw them |
2014 | | - QFont myQFont( "arial", 8, QFont::Normal ); |
2015 | | - QFontMetrics myFontMetrics( myQFont ); |
2016 | | - myPainter.setFont( myQFont ); |
2017 | | - myPainter.setPen( Qt::black ); |
2018 | | - QString myYMaxLabel = QString::number( static_cast < unsigned int >( myYAxisMax ) ); |
2019 | | - QString myXMinLabel = QString::number( myXAxisMin ); |
2020 | | - QString myXMaxLabel = QString::number( myXAxisMax ); |
2021 | | - //calculate the gutters |
2022 | | - int myYGutterWidth = 0; |
2023 | | - if ( myFontMetrics.width( myXMinLabel ) < myFontMetrics.width( myYMaxLabel ) ) |
2024 | | - { |
2025 | | - myYGutterWidth = myFontMetrics.width( myYMaxLabel ) + 2; //add 2 so we can have 1 pix whitespace either side of label |
2026 | | - } |
2027 | | - else |
2028 | | - { |
2029 | | - myYGutterWidth = myFontMetrics.width( myXMinLabel ) + 2; //add 2 so we can have 1 pix whitespace either side of label |
2030 | | - } |
2031 | | - int myXGutterHeight = myFontMetrics.height() + 2; |
2032 | | - int myXGutterWidth = myFontMetrics.width( myXMaxLabel ) + 1;//1 pix whtispace from right edge of image |
2033 | | - |
| 2005 | + QwtPlot * mypPlot = new QwtPlot( mChartWidget ); |
| 2006 | + //ensure all children get removed |
| 2007 | + mypPlot->setAutoDelete( true ); |
| 2008 | + QVBoxLayout *mpHistogramLayout = new QVBoxLayout( mChartWidget ); |
| 2009 | + mpHistogramLayout->setContentsMargins( 0, 0, 0, 0 ); |
| 2010 | + mpHistogramLayout->addWidget( mypPlot ); |
| 2011 | + mChartWidget->setLayout( mpHistogramLayout ); |
| 2012 | + mypPlot->setTitle(QObject::tr("Raster Histogram")); |
| 2013 | + mypPlot->insertLegend(new QwtLegend(), QwtPlot::BottomLegend); |
| 2014 | + // Set axis titles |
| 2015 | + mypPlot->setAxisTitle(QwtPlot::xBottom, QObject::tr("Pixel Value")); |
| 2016 | + mypPlot->setAxisTitle(QwtPlot::yLeft, QObject::tr("Frequency")); |
2034 | 2017 | // |
2035 | | - // Now calculate the graph drawable area after the axis labels have been taken |
2036 | | - // into account |
| 2018 | + // add a grid |
2037 | 2019 | // |
2038 | | - int myGraphImageWidth = myImageWidth - myYGutterWidth; |
2039 | | - int myGraphImageHeight = myImageHeight - myXGutterHeight; |
2040 | | - |
2041 | | - //find out how wide to draw bars when in bar chart mode |
2042 | | - int myBarWidth = static_cast<int>(((( double )myGraphImageWidth ) / (( double )BINCOUNT ) ) ); |
2043 | | - |
2044 | | - |
| 2020 | + QwtPlotGrid * myGrid = new QwtPlotGrid(); |
| 2021 | + myGrid->attach(mypPlot); |
2045 | 2022 | // |
2046 | 2023 | //now draw actual graphs |
2047 | 2024 | // |
2048 | | - if ( mRasterLayer->rasterType() |
2049 | | - == QgsRasterLayer::Palette ) //paletted layers have hard coded color entries |
| 2025 | + QList<QColor> myColors; |
| 2026 | + myColors << Qt::black << Qt::red << Qt::green << Qt::blue << Qt::magenta << Qt::darkRed << Qt::darkGreen << Qt::darkBlue; |
| 2027 | + for ( int myIteratorInt = 1; |
| 2028 | + myIteratorInt <= myBandCountInt; |
| 2029 | + ++myIteratorInt ) |
2050 | 2030 | { |
2051 | | - QPolygonF myPolygon; |
2052 | | - QgsColorRampShader* myRasterShaderFunction = ( QgsColorRampShader* )mRasterLayer->rasterShader()->rasterShaderFunction(); |
2053 | | - QgsDebugMsg( "Making paletted image histogram....computing band stats" ); |
2054 | | - QgsDebugMsg( QString( "myLastBinWithData = %1" ).arg( myLastBinWithData ) ); |
2055 | | - |
2056 | | - QgsRasterBandStats myRasterBandStats = mRasterLayer->bandStatistics( 1 ); |
2057 | | - for ( int myBin = 0; myBin < myLastBinWithData; myBin++ ) |
| 2031 | + QgsRasterBandStats myRasterBandStats = mRasterLayer->bandStatistics( myIteratorInt ); |
| 2032 | + QListWidgetItem *myItem = lstHistogramLabels->item( myIteratorInt - 1 ); |
| 2033 | + if ( myItem->isSelected() ) |
2058 | 2034 | { |
2059 | | - double myBinValue = myRasterBandStats.histogramVector->at( myBin ); |
2060 | | - QgsDebugMsg( QString( "myBin = %1 myBinValue = %2" ).arg( myBin ).arg( myBinValue ) ); |
2061 | | - //NOTE: Int division is 0 if the numerator is smaller than the denominator. |
2062 | | - //hence the casts |
2063 | | - int myX = static_cast<int>(((( double )myGraphImageWidth ) / (( double )myLastBinWithData ) ) * myBin ); |
2064 | | - //height varies according to freq. and scaled to greatet value in all layers |
2065 | | - int myY = 0; |
2066 | | - if ( myYAxisMax != 0 ) |
| 2035 | + QwtPlotCurve * mypCurve = new QwtPlotCurve( tr( "Band %i" ).arg( myIteratorInt ) ); |
| 2036 | + mypCurve->setRenderHint( QwtPlotItem::RenderAntialiased ); |
| 2037 | + mypCurve->setPen(QPen( myColors.at( myIteratorInt ) ) ); |
| 2038 | + QwtArray<double> myX2Data;//qwtarray is just a wrapped qvector |
| 2039 | + QwtArray<double> myY2Data;//qwtarray is just a wrapped qvector |
| 2040 | + for ( int myBin = 0; myBin < myLastBinWithData; myBin++ ) |
2067 | 2041 | { |
2068 | | - myY = static_cast<int>((( double )myBinValue / ( double )myYAxisMax ) * myGraphImageHeight ); |
| 2042 | + double myBinValue = myRasterBandStats.histogramVector->at( myBin ); |
| 2043 | + myX2Data.append(myBin); |
| 2044 | + myY2Data.append(myBinValue); |
2069 | 2045 | } |
2070 | | - |
2071 | | - //see wehter to draw something each loop or to save up drawing for after iteration |
2072 | | - if ( myGraphType == BAR_CHART ) |
2073 | | - { |
2074 | | - //determine which color to draw the bar |
2075 | | - int c1, c2, c3; |
2076 | | - // Take middle of the interval for color |
2077 | | - // TODO: this is not precise |
2078 | | - double myInterval = ( myXAxisMax - myXAxisMin ) / myLastBinWithData; |
2079 | | - double myMiddle = myXAxisMin + myBin * myInterval + myInterval / 2; |
2080 | | - |
2081 | | - QgsDebugMsg( QString( "myMiddle = %1" ).arg( myMiddle ) ); |
2082 | | - |
2083 | | - if ( myRasterShaderFunction->shade( myMiddle, &c1, &c2, &c3 ) ) |
2084 | | - { |
2085 | | - QgsDebugMsg( "Color not found" ); |
2086 | | - c1 = c2 = c3 = 180; // grey |
2087 | | - } |
2088 | | - |
2089 | | - QgsDebugMsg( QString( "c1 = %1 c2 = %2 c3 = %3" ).arg( c1 ).arg( c2 ).arg( c3 ) ); |
2090 | | - |
2091 | | - //draw the bar |
2092 | | - //QBrush myBrush(QColor(c1,c2,c3)); |
2093 | | - myPainter.setBrush( QColor( c1, c2, c3 ) ); |
2094 | | - myPainter.setPen( QColor( c1, c2, c3 ) ); |
2095 | | - QgsDebugMsg( QString( "myX = %1 myY = %2" ).arg( myX ).arg( myY ) ); |
2096 | | - QgsDebugMsg( QString( "rect: %1, %2, %3, %4" ).arg( myX + myYGutterWidth ).arg( myImageHeight - ( myY + myXGutterHeight ) ).arg( myBarWidth ).arg( myY ) ); |
2097 | | - myPainter.drawRect( myX + myYGutterWidth, myImageHeight - ( myY + myXGutterHeight ), myBarWidth, myY ); |
2098 | | - } |
2099 | | - //store this point in our line too |
2100 | | - myY = myGraphImageHeight - myY; |
2101 | | - myPolygon << QPointF( myX + myYGutterWidth, myY - myXGutterHeight ); |
2102 | | - } |
2103 | | - //draw a line on the graph along the bar peaks; |
2104 | | - if ( myGraphType == LINE_CHART ) |
2105 | | - { |
2106 | | - //close of the point array so it makes a nice polygon |
2107 | | - //bottom right point |
2108 | | - myPolygon << QPointF( |
2109 | | - myImageWidth, |
2110 | | - myImageHeight - myXGutterHeight ); |
2111 | | - //bottom left point |
2112 | | - myPolygon << QPointF( |
2113 | | - myYGutterWidth, |
2114 | | - myImageHeight - myXGutterHeight ); |
2115 | | - myPainter.setPen( Qt::black ); |
2116 | | - //set a gradient fill for the path |
2117 | | - QLinearGradient myGradient = greenGradient(); |
2118 | | - myPainter.setBrush( myGradient ); |
2119 | | - QPainterPath myPath; |
2120 | | - myPath.addPolygon( myPolygon ); |
2121 | | - myPainter.drawPath( myPath ); |
| 2046 | + mypCurve->setData(myX2Data,myY2Data); |
| 2047 | + mypCurve->attach(mypPlot); |
2122 | 2048 | } |
2123 | 2049 | } |
2124 | | - else |
2125 | | - { |
2126 | | - |
2127 | | - for ( int myIteratorInt = 1; |
2128 | | - myIteratorInt <= myBandCountInt; |
2129 | | - ++myIteratorInt ) |
2130 | | - { |
2131 | | - QgsRasterBandStats myRasterBandStats = mRasterLayer->bandStatistics( myIteratorInt ); |
2132 | | - QListWidgetItem *myItem = lstHistogramLabels->item( myIteratorInt - 1 ); |
2133 | | - if ( myItem->isSelected() ) |
2134 | | - { |
2135 | | - |
2136 | | - QPolygonF myPolygon; |
2137 | | - for ( int myBin = 0; myBin < myLastBinWithData; myBin++ ) |
2138 | | - { |
2139 | | - double myBinValue = myRasterBandStats.histogramVector->at( myBin ); |
2140 | | - //NOTE: Int division is 0 if the numerator is smaller than the denominator. |
2141 | | - //hence the casts |
2142 | | - int myX = static_cast<int>(((( double )myGraphImageWidth ) / (( double )myLastBinWithData ) ) * myBin ); |
2143 | | - //height varies according to freq. and scaled to greatet value in all layers |
2144 | | - int myY = static_cast<int>((( double )myBinValue / ( double )myYAxisMax ) * myGraphImageHeight ); |
2145 | | - //adjust for image origin being top left |
2146 | | - QgsDebugMsg( "-------------" ); |
2147 | | - QgsDebugMsg( "int myY = (myBinValue/myCellCount)*myGraphImageHeight" ); |
2148 | | - QgsDebugMsg( QString( "int myY = (%1/%2)*%3" ).arg( myBinValue ).arg( myCellCount ).arg( myGraphImageHeight ) ); |
2149 | | - QgsDebugMsg( QString( "Band %1, bin %2, Hist Value : %3, Scaled Value : %4" ).arg( myIteratorInt ).arg( myBin ).arg( myBinValue ).arg( myY ) ); |
2150 | | - QgsDebugMsg( "myY = myGraphImageHeight - myY" ); |
2151 | | - QgsDebugMsg( QString( "myY = %1-%2" ).arg( myGraphImageHeight ).arg( myY ) ); |
2152 | | - |
2153 | | - if ( myGraphType == BAR_CHART ) |
2154 | | - { |
2155 | | - //draw the bar |
2156 | | - if ( myBandCountInt == 1 ) //draw single band images with black |
2157 | | - { |
2158 | | - myPainter.setPen( Qt::black ); |
2159 | | - } |
2160 | | - else if ( myIteratorInt == 1 ) |
2161 | | - { |
2162 | | - myPainter.setPen( Qt::red ); |
2163 | | - } |
2164 | | - else if ( myIteratorInt == 2 ) |
2165 | | - { |
2166 | | - myPainter.setPen( Qt::green ); |
2167 | | - } |
2168 | | - else if ( myIteratorInt == 3 ) |
2169 | | - { |
2170 | | - myPainter.setPen( Qt::blue ); |
2171 | | - } |
2172 | | - else if ( myIteratorInt == 4 ) |
2173 | | - { |
2174 | | - myPainter.setPen( Qt::magenta ); |
2175 | | - } |
2176 | | - else if ( myIteratorInt == 5 ) |
2177 | | - { |
2178 | | - myPainter.setPen( Qt::darkRed ); |
2179 | | - } |
2180 | | - else if ( myIteratorInt == 6 ) |
2181 | | - { |
2182 | | - myPainter.setPen( Qt::darkGreen ); |
2183 | | - } |
2184 | | - else if ( myIteratorInt == 7 ) |
2185 | | - { |
2186 | | - myPainter.setPen( Qt::darkBlue ); |
2187 | | - } |
2188 | | - else |
2189 | | - { |
2190 | | - myPainter.setPen( Qt::gray ); |
2191 | | - } |
2192 | | - |
2193 | | - // QgsDebugMsg(QString("myPainter.fillRect(QRect(%1,%2,%3,%2), myBrush );").arg(myX).arg(myY).arg(myBarWidth)); |
2194 | | - |
2195 | | - myPainter.drawRect( myX + myYGutterWidth, myImageHeight - ( myY + myXGutterHeight ), myBarWidth, myY ); |
2196 | | - } |
2197 | | - else //line graph |
2198 | | - { |
2199 | | - myY = myGraphImageHeight - myY; |
2200 | | - myPolygon << QPointF( myX + myYGutterWidth, myY ); |
2201 | | - } |
2202 | | - } |
2203 | | - |
2204 | | - if ( myGraphType == LINE_CHART ) |
2205 | | - { |
2206 | | - QLinearGradient myGradient; |
2207 | | - if ( myBandCountInt == 1 ) //draw single band images with black |
2208 | | - { |
2209 | | - myPainter.setPen( Qt::black ); |
2210 | | - myGradient = grayGradient(); |
2211 | | - } |
2212 | | - else if ( myIteratorInt == 1 ) |
2213 | | - { |
2214 | | - myPainter.setPen( Qt::red ); |
2215 | | - myGradient = redGradient(); |
2216 | | - } |
2217 | | - else if ( myIteratorInt == 2 ) |
2218 | | - { |
2219 | | - myPainter.setPen( Qt::green ); |
2220 | | - myGradient = greenGradient(); |
2221 | | - } |
2222 | | - else if ( myIteratorInt == 3 ) |
2223 | | - { |
2224 | | - myPainter.setPen( Qt::blue ); |
2225 | | - myGradient = blueGradient(); |
2226 | | - } |
2227 | | - else if ( myIteratorInt == 4 ) |
2228 | | - { |
2229 | | - myPainter.setPen( Qt::magenta ); |
2230 | | - myGradient = grayGradient(); |
2231 | | - } |
2232 | | - else if ( myIteratorInt == 5 ) |
2233 | | - { |
2234 | | - myPainter.setPen( Qt::darkRed ); |
2235 | | - myGradient = grayGradient(); |
2236 | | - } |
2237 | | - else if ( myIteratorInt == 6 ) |
2238 | | - { |
2239 | | - myPainter.setPen( Qt::darkGreen ); |
2240 | | - myGradient = grayGradient(); |
2241 | | - } |
2242 | | - else if ( myIteratorInt == 7 ) |
2243 | | - { |
2244 | | - myPainter.setPen( Qt::darkBlue ); |
2245 | | - myGradient = grayGradient(); |
2246 | | - } |
2247 | | - else |
2248 | | - { |
2249 | | - myPainter.setPen( Qt::gray ); |
2250 | | - myGradient = grayGradient(); |
2251 | | - } |
2252 | | - //close of the point array so it makes a nice polygon |
2253 | | - //bottom right point |
2254 | | - myPolygon << QPointF( |
2255 | | - myImageWidth, |
2256 | | - myImageHeight - myXGutterHeight ); |
2257 | | - //bottom left point |
2258 | | - myPolygon << QPointF( |
2259 | | - myYGutterWidth, |
2260 | | - myImageHeight - myXGutterHeight ); |
2261 | | - myPainter.setPen( Qt::black ); |
2262 | | - myPainter.setBrush( myGradient ); |
2263 | | - QPainterPath myPath; |
2264 | | - myPath.addPolygon( myPolygon ); |
2265 | | - myPainter.drawPath( myPath ); |
2266 | | - } |
2267 | | - } |
2268 | | - } |
2269 | | - } |
2270 | | - |
2271 | | - // |
2272 | | - // Now draw interval markers on the x axis |
2273 | | - // |
2274 | | - int myXDivisions = myGraphImageWidth / 10; |
2275 | | - myPainter.setPen( Qt::gray ); |
2276 | | - for ( int i = 0; i < myXDivisions; ++i ) |
2277 | | - { |
2278 | | - QPolygon myPolygon; |
2279 | | - myPolygon << QPoint(( i*myXDivisions ) + myYGutterWidth, myImageHeight - myXGutterHeight ); |
2280 | | - myPolygon << QPoint(( i*myXDivisions ) + myYGutterWidth, myImageHeight - ( myXGutterHeight - 5 ) ); |
2281 | | - myPolygon << QPoint(( i*myXDivisions ) + myYGutterWidth, myImageHeight - myXGutterHeight ); |
2282 | | - myPolygon << QPoint((( i + 1 )*myXDivisions ) + myYGutterWidth, myImageHeight - myXGutterHeight ); |
2283 | | - myPainter.drawPolyline( myPolygon ); |
2284 | | - } |
2285 | | - // |
2286 | | - // Now draw interval markers on the y axis |
2287 | | - // |
2288 | | - int myYDivisions = myGraphImageHeight / 10; |
2289 | | - myPainter.setPen( Qt::gray ); |
2290 | | - for ( int i = myYDivisions; i > 0; --i ) |
2291 | | - { |
2292 | | - |
2293 | | - QPolygon myPolygon; |
2294 | | - int myYOrigin = myImageHeight - myXGutterHeight; |
2295 | | - myPolygon << QPoint( myYGutterWidth, myYOrigin - ( i*myYDivisions ) ); |
2296 | | - myPolygon << QPoint( myYGutterWidth - 5, myYOrigin - ( i*myYDivisions ) ); |
2297 | | - myPolygon << QPoint( myYGutterWidth, myYOrigin - ( i*myYDivisions ) ); |
2298 | | - myPolygon << QPoint( myYGutterWidth, myYOrigin - (( i - 1 )*myYDivisions ) ); |
2299 | | - myPainter.drawPolyline( myPolygon ); |
2300 | | - } |
2301 | | - |
2302 | | - //now draw the axis labels onto the graph |
2303 | | - myPainter.drawText( 1, 12, myYMaxLabel ); |
2304 | | - myPainter.drawText( 1, myImageHeight - myXGutterHeight, QString::number( static_cast < unsigned int >( myYAxisMin ) ) ); |
2305 | | - myPainter.drawText( myYGutterWidth, myImageHeight - 1, myXMinLabel ); |
2306 | | - myPainter.drawText( myImageWidth - myXGutterWidth, myImageHeight - 1, myXMaxLabel ); |
2307 | | - |
2308 | | - // |
2309 | | - // Finish up |
2310 | | - // |
2311 | | - myPainter.end(); |
2312 | | - pixHistogram->setPixmap( myPixmap ); |
2313 | 2050 | QApplication::restoreOverrideCursor(); |
2314 | 2051 | } |
2315 | 2052 |
|
|
0 commit comments