|
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