00001 #include "histogramdlg.h" 00002 00003 HistogramDlg::HistogramDlg( QWidget *parent ) : 00004 QWidget( parent ) { 00005 setCaption( "Histogram" ); 00006 mHistUser = NULL; 00007 init(); 00008 } 00009 00010 00011 HistogramDlg::HistogramDlg( QWidget *parent, 00012 vector<HistogramDataSource*> hds, 00013 HistogramUser *huser ) : 00014 QWidget( parent ) { 00015 setCaption( "Histogram" ); 00016 00017 mHDS.HDS = hds; 00018 for ( unsigned int iHDS=0; iHDS < hds.size(); iHDS++ ) 00019 hds[iHDS]->setHistogramDlg( this ); 00020 00021 mHistUser = huser; 00022 } 00023 00024 void HistogramDlg::init( ) { 00025 mHDS.curHDS = -1; 00026 00027 mSLSet.isMerged = false; 00028 mSLSet.curArr = NULL; 00029 mSLSet.curLine = 0; 00030 mSLSet.isChanging = false; 00031 00032 mMouse.mLeftDown = false; 00033 mMouse.mMidDown = false; 00034 mMouse.mRightDown = false; 00035 mMouse.mPointMoving = -1; 00036 mMouse.mMouseX = 0; 00037 mMouse.mMouseY = 0; 00038 00039 initPntsFromUser(); 00040 00041 setMouseTracking( true ); 00042 buildMenuBar(); 00043 this->setBackgroundColor( QColor( 255,255,255 ) ); 00044 setMinimumSize( 200, 200 ); 00045 00046 resize( 400, 300 ); 00047 changeDataSource(); 00048 } 00049 00050 void HistogramDlg::buildMenuBar( ) { 00051 QAction *action = NULL; 00052 mMenuBar = new QMenuBar( this ); 00053 00054 // BUILD TOP LEVEL MENUS 00055 /* 00056 QPopupMenu *fileMenu = new QPopupMenu( this ); 00057 mMenuBar->insertItem( tr("&File"), fileMenu ); 00058 */ 00059 00060 QPopupMenu *editMenu = new QPopupMenu( this ); 00061 mMenuBar->insertItem( tr("&Edit"), editMenu ); 00062 00063 QPopupMenu *displayMenu = new QPopupMenu( this ); 00064 mMenuBar->insertItem( tr("&Display"), displayMenu ); 00065 00066 mDSMenu = new QPopupMenu( this ); 00067 mMenuBar->insertItem( tr("Data &Source"), mDSMenu ); 00068 00069 QPopupMenu *pointsMenu = new QPopupMenu( this ); 00070 mMenuBar->insertItem( tr("&Points"), pointsMenu ); 00071 00072 QPopupMenu *percentMenu = new QPopupMenu( pointsMenu ); 00073 pointsMenu->insertItem( tr("&Percent"), percentMenu ); 00074 00075 /* 00076 // BUILD THE FILE MENU 00077 action = new QAction( tr("Save"), tr("&Save"), 0, this ); 00078 action->addTo( fileMenu ); 00079 connect( action, SIGNAL( activated() ), this, SLOT( saveHist() ) ); 00080 00081 action = new QAction( tr("Print"), tr("&Print"), 0, this ); 00082 action->addTo( fileMenu ); 00083 connect( action, SIGNAL( activated() ), this, SLOT( printHist() ) ); 00084 00085 action = new QAction( tr("Close"), tr("&Close"), 0, this ); 00086 action->addTo( fileMenu ); 00087 connect( action, SIGNAL( activated() ), this, SLOT( close() ) ); 00088 */ 00089 00090 // BUILD THE EDIT MENU 00091 action = new QAction( tr("Undo"), tr("&Undo"), 0, this ); 00092 action->addTo( editMenu ); 00093 connect( action, SIGNAL( activated() ), this, SLOT( undoToLast() ) ); 00094 00095 action = new QAction( tr("Redo"), tr("&Redo"), 0, this ); 00096 action->addTo( editMenu ); 00097 connect( action, SIGNAL( activated() ), this, SLOT( redoToPrev() ) ); 00098 00099 // BUILD THE DISPLAY MENU 00100 action = new QAction( tr("Red"), tr("&Red"), 0, this ); 00101 action->addTo( displayMenu ); 00102 connect( action, SIGNAL( activated() ), this, SLOT( changeToRed() ) ); 00103 mColorAct.push_back( action ); 00104 00105 action = new QAction( tr("Green"), tr("&Green"), 0, this ); 00106 action->addTo( displayMenu ); 00107 connect( action, SIGNAL( activated() ), this, SLOT( changeToGreen() ) ); 00108 mColorAct.push_back( action ); 00109 00110 action = new QAction( tr("Blue"), tr("&Blue"), 0, this ); 00111 action->addTo( displayMenu ); 00112 connect( action, SIGNAL( activated() ), this, SLOT( changeToBlue() ) ); 00113 mColorAct.push_back( action ); 00114 00115 // BUILD THE DATASRC MENU 00116 mDSActGroup = new QActionGroup( mDSMenu ); 00117 00118 for ( unsigned int i=0; i < mHDS.HDS.size(); i++ ) { 00119 action = new QAction( tr( mHDS.HDS[i]->getHistName() ), 00120 tr( mHDS.HDS[i]->getHistName() ), 00121 0, this, 0, true ); 00122 action->addTo( mDSMenu ); 00123 connect( action, SIGNAL( activated() ), this, SLOT( changeDataSource() ) ); 00124 mDSActGroup->insert( action ); 00125 mHDS.actSet.push_back( action ); 00126 00127 if ( i == 0 ) 00128 action->setOn( true ); 00129 } 00130 00131 // BUILD THE POINTS MENU 00132 // QActionGroup *actgrp = new QActionGroup( percentMenu ); 00133 00134 action = new QAction( tr( "One %" ), tr( "One %" ), 0, this, 0, true ); 00135 action->addTo( percentMenu ); 00136 connect( action, SIGNAL( activated() ), this, SLOT( calcPercent() ) ); 00137 mPercentAct.push_back( action ); 00138 00139 action = new QAction( tr( "One %" ), tr( "Two %" ), 0, this, 0, true ); 00140 action->addTo( percentMenu ); 00141 connect( action, SIGNAL( activated() ), this, SLOT( calcPercent() ) ); 00142 mPercentAct.push_back( action ); 00143 00144 action = new QAction( tr( "One %" ), tr( "Five %" ), 0, this, 0, true ); 00145 action->addTo( percentMenu ); 00146 connect( action, SIGNAL( activated() ), this, SLOT( calcPercent() ) ); 00147 mPercentAct.push_back( action ); 00148 00149 action = new QAction( tr("Best Fit"), tr("&Best Fit"), 0, this ); 00150 action->addTo( pointsMenu ); 00151 connect( action, SIGNAL( activated() ), this, SLOT( bestFit() ) ); 00152 00153 action = new QAction( tr("Clear"), tr("&Clear"), 0, this ); 00154 action->addTo( pointsMenu ); 00155 connect( action, SIGNAL( activated() ), this, SLOT( clearPoints() ) ); 00156 00157 action = new QAction( tr("Merge"), tr("&Merge"), 0, this, 0, true ); 00158 action->addTo( pointsMenu ); 00159 connect( action, SIGNAL( activated() ), this, SLOT( mergeAll() ) ); 00160 mMergeAct = action; 00161 } 00162 00163 void HistogramDlg::paintEvent( QPaintEvent * ) { 00164 const int scaleW = mDspDims.scaleW; 00165 const int graphBorderW = mDspDims.graphBorderW; 00166 const int topY = mDspDims.topY; 00167 const int winW = mDspDims.winW; 00168 const int winH = mDspDims.winH; 00169 const int graphW = mDspDims.graphW; 00170 const int graphH = mDspDims.graphH; 00171 Histogram *hist = NULL; 00172 char bufDataMin[15]; 00173 char bufDataMax[15]; 00174 char bufDataMid[15]; 00175 double dataMin, dataMax, dataMid; 00176 bool haveDS = ( mHDS.HDS.size() == 0 || mHDS.curHDS == -1 ) ? false : true; 00177 00178 QBrush graphBrushSet[4]; 00179 QColor lineColorSet[4]; 00180 00181 graphBrushSet[0] = QBrush( QColor( 100,0,0 ), Dense4Pattern ); 00182 lineColorSet[0] = QColor( 255,0,0 ); 00183 graphBrushSet[1] = QBrush( QColor( 0,100,0 ), Dense4Pattern ); 00184 lineColorSet[1] = QColor( 0,255,0 ); 00185 graphBrushSet[2] = QBrush( QColor( 0,0,100 ), Dense4Pattern ); 00186 lineColorSet[2] = QColor( 0,0,255 ); 00187 // THE NON-COLOR BRUSH 00188 graphBrushSet[3] = QBrush( QColor( 100,100,100 ), Dense4Pattern ); 00189 // THE MERGED COLOR 00190 lineColorSet[3] = QColor( 75,75,75 ); 00191 00192 if ( haveDS ) { 00193 hist = mHDS.histSet[mHDS.curHist]; 00194 dataMin = hist->getMin(); 00195 dataMax = hist->getMax(); 00196 dataMid = ( dataMax - dataMin ) / 2; 00197 00198 sprintf( bufDataMin, "%6.3f", dataMin ); 00199 sprintf( bufDataMax, "%6.3f", dataMax ); 00200 sprintf( bufDataMid, "%6.3f", dataMid ); 00201 } 00202 00203 // OFFSCREEN PIXMAP/PAINTER 00204 QPixmap bufpm( winW, winH ); 00205 QPainter bufp( &bufpm ); 00206 bufp.setFont( QFont( "Times", 10 ) ); 00207 00208 // CLEAR DRAWING AREA 00209 QBrush brush( QColor( 255,255,255 ) ); 00210 bufp.fillRect( 0, 0, winW, winH, brush ); 00211 00212 if ( haveDS ) { 00213 // DRAW GRAPH BOARDER 00214 bufp.drawRect( scaleW, 00215 graphBorderW, 00216 graphW, 00217 graphH ); 00218 00219 // DRAW 0-255 SCALE 00220 bufp.rotate( -90 ); 00221 bufp.translate( -winH, 0 ); 00222 bufp.drawText( scaleW+1, 2, graphH, 12, AlignCenter, "Color" ); 00223 bufp.drawLine( scaleW+1, 33, scaleW + graphH-1, 33 ); 00224 bufp.drawLine( scaleW+1, 30, scaleW+1, 37 ); 00225 bufp.drawLine( scaleW+1 + (graphH / 2), 30, scaleW+1 + (graphH / 2), 37 ); 00226 bufp.drawLine( scaleW+graphH, 30, scaleW+graphH, 37 ); 00227 bufp.drawText( scaleW+1-30, 16, 60, 12, AlignCenter, "0" ); 00228 bufp.drawText( scaleW+1-30+(graphH/2), 16, 60, 12, AlignCenter, "128" ); 00229 bufp.drawText( scaleW+1-30+graphH, 16, 60, 12, AlignCenter, "256" ); 00230 bufp.translate( winH, 0 ); 00231 bufp.rotate( 90 ); 00232 00233 // DRAW DN SCALE 00234 bufp.drawText( scaleW, winH-14, graphW, 12, AlignCenter, "DN Value" ); 00235 bufp.drawLine( scaleW, winH-34, scaleW + graphW-1, winH-34 ); 00236 bufp.drawLine( scaleW, winH-31, scaleW, winH-38 ); 00237 bufp.drawLine( scaleW+(graphW/2), winH-31, scaleW+(graphW/2), winH-38 ); 00238 bufp.drawLine( scaleW+graphW-1, winH-31, scaleW+graphW-1, winH-38 ); 00239 bufp.drawText( scaleW+1-30, winH-29, 60, 12, AlignCenter, bufDataMin ); 00240 bufp.drawText( scaleW+1-30+(graphW/2), winH-29, 60, 12, AlignCenter, bufDataMid ); 00241 bufp.drawText( scaleW+1-30+graphW, winH-29, 60, 12, AlignCenter, bufDataMax ); 00242 00243 // DRAW DATA 00244 QBrush oldbrush = bufp.brush(); 00245 if ( !mHDS.histSet.isColor() ) { 00246 bufp.setBrush( graphBrushSet[3] ); 00247 bufp.drawPolygon( mHDS.dataPnts[0] ); 00248 } else if ( !mSLSet.isMerged ) { 00249 bufp.setBrush( graphBrushSet[mHDS.curHist] ); 00250 bufp.drawPolygon( mHDS.dataPnts[mHDS.curHist] ); 00251 } else { 00252 bufp.setBrush( graphBrushSet[0] ); 00253 bufp.drawPolygon( mHDS.dataPnts[0] ); 00254 bufp.setBrush( graphBrushSet[1] ); 00255 bufp.drawPolygon( mHDS.dataPnts[1] ); 00256 bufp.setBrush( graphBrushSet[2] ); 00257 bufp.drawPolygon( mHDS.dataPnts[2] ); 00258 } 00259 bufp.setBrush( oldbrush ); 00260 00261 // INIT STRETCH LINE 00262 if ( mSLSet.curArr == NULL ) { 00263 // INITIALIZE SL STACK 00264 for ( unsigned int iStk=0; iStk < 3; iStk++ ) { 00265 mSLSet.lineSet[iStk].push( QPointArray( 2 ) ); 00266 mSLSet.lineSet[iStk].top().setPoint( 0, mDspDims.graphZeroX, mDspDims.graphMaxY ); 00267 mSLSet.lineSet[iStk].top().setPoint( 1, mDspDims.graphMaxX, mDspDims.graphZeroY ); 00268 } 00269 mSLSet.curArr = &mSLSet.lineSet[0].top(); 00270 00271 alertUser(); 00272 } 00273 00274 // DRAW STRETCH LINE 00275 if ( !mHDS.histSet.isColor() ) 00276 bufp.setPen( lineColorSet[3] ); 00277 else if ( !mSLSet.isMerged ) 00278 bufp.setPen( lineColorSet[mHDS.curHist] ); 00279 else 00280 bufp.setPen( lineColorSet[3] ); 00281 00282 bufp.drawPolyline( *mSLSet.curArr ); 00283 00284 for ( unsigned int i=0; i < mSLSet.curArr->size(); i++ ) 00285 bufp.drawRect( (*mSLSet.curArr).at(i).x()-2, ((QPointArray)*mSLSet.curArr).at(i).y()-2, 5, 5 ); 00286 00287 // DRAW GUIDE LINE 00288 if ( mMouse.mPointMoving >= 0 ) { 00289 QPen oldpen = bufp.pen(); 00290 QPen newpen( QColor( 128,128,128 ), 0, DashLine ); 00291 bufp.setPen( newpen ); 00292 int px = (*mSLSet.curArr)[mMouse.mPointMoving].x(); 00293 int py = (*mSLSet.curArr)[mMouse.mPointMoving].y(); 00294 bufp.drawLine( px, py, px, mDspDims.graphMaxY ); 00295 bufp.setPen( oldpen ); 00296 } 00297 } else if ( mHDS.curHDS == -1 ) { 00298 bufp.drawText( 0, (winH / 2) - 10, winW, 20, AlignCenter, "No Data Sources Selected" ); 00299 } else { 00300 bufp.drawText( 0, (winH / 2) - 10, winW, 20, AlignCenter, "No Data Sources" ); 00301 } 00302 00303 QPainter p( this ); 00304 p.drawPixmap( 0, topY, bufpm ); 00305 } 00306 00307 void HistogramDlg::resizeEvent( QResizeEvent * ) { 00308 int newIntValX, newIntValY; 00309 double newDblValX, newDblValY; 00310 00311 mOldDspDims = mDspDims; 00312 mDspDims = calcDspDims(); 00313 00314 int newGraphW = mDspDims.graphMaxX - mDspDims.graphZeroX; 00315 int newGraphH = mDspDims.graphMaxY - mDspDims.graphZeroY; 00316 int oldGraphW = mOldDspDims.graphMaxX - mOldDspDims.graphZeroX; 00317 int oldGraphH = mOldDspDims.graphMaxY - mOldDspDims.graphZeroY; 00318 00319 double xscale = (double)newGraphW / (double)oldGraphW; 00320 double yscale = (double)newGraphH / (double)oldGraphH; 00321 00322 createDataPnts(); 00323 00324 if ( !mSLSet.curArr ) 00325 return; 00326 00327 // stack<QPointArray> newStk[3]; 00328 QPointArray curArr; 00329 for ( unsigned int iStk=0; iStk < 3; iStk++ ) { 00330 stack<QPointArray> tmpStk; 00331 int szStk = mSLSet.lineSet[iStk].size(); 00332 for ( int iArr=0; iArr < szStk; iArr++ ) { 00333 tmpStk.push( mSLSet.lineSet[iStk].top() ); 00334 mSLSet.lineSet[iStk].pop(); 00335 curArr = tmpStk.top(); 00336 00337 for ( unsigned int i=0; i < curArr.size(); i++ ) { 00338 curArr.setPoint( i, 00339 (int)( curArr.at(i).x() - mDspDims.graphZeroX ), 00340 (int)( curArr.at(i).y() - mDspDims.graphZeroY ) ); 00341 00342 newDblValX = (double)curArr.at(i).x() * xscale; 00343 newDblValY = (double)curArr.at(i).y() * yscale; 00344 newIntValX = (int)newDblValX; 00345 newIntValY = (int)newDblValY; 00346 newIntValX += ( ( (newDblValX-newIntValX)*10 ) > 5 ) ? 1 : 0; 00347 newIntValY += ( ( (newDblValY-newIntValY)*10 ) > 5 ) ? 1 : 0; 00348 00349 curArr.setPoint( i, 00350 newIntValX, 00351 newIntValY ); 00352 00353 curArr.setPoint( i, 00354 (int)( curArr.at(i).x() + mDspDims.graphZeroX ), 00355 (int)( curArr.at(i).y() + mDspDims.graphZeroY ) ); 00356 } 00357 00358 } 00359 00360 int tmpStkSz = tmpStk.size(); 00361 for ( int iTmp=0; iTmp < tmpStkSz; iTmp++ ) { 00362 mSLSet.lineSet[iStk].push( tmpStk.top() ); 00363 tmpStk.pop(); 00364 } 00365 } 00366 00367 stack<QPointArray> newRedoStk; 00368 stack<QPointArray> tmpStk; 00369 int redoStkSz = mSLSet.redoSet.size(); 00370 for ( int iRedoArr=0; iRedoArr < redoStkSz; iRedoArr++ ) { 00371 tmpStk.push( mSLSet.redoSet.top() ); 00372 mSLSet.redoSet.pop(); 00373 curArr = tmpStk.top(); 00374 00375 for ( unsigned int i=0; i < curArr.size(); i++ ) { 00376 curArr.setPoint( i, 00377 (int)( curArr.at(i).x() - mDspDims.graphZeroX ), 00378 (int)( curArr.at(i).y() - mDspDims.graphZeroY ) ); 00379 00380 newDblValX = (double)curArr.at(i).x() * xscale; 00381 newDblValY = (double)curArr.at(i).y() * yscale; 00382 newIntValX = (int)newDblValX; 00383 newIntValY = (int)newDblValY; 00384 newIntValX += ( ( (newDblValX-newIntValX)*10 ) > 5 ) ? 1 : 0; 00385 newIntValY += ( ( (newDblValY-newIntValY)*10 ) > 5 ) ? 1 : 0; 00386 00387 curArr.setPoint( i, 00388 newIntValX, 00389 newIntValY ); 00390 00391 curArr.setPoint( i, 00392 (int)( curArr.at(i).x() + mDspDims.graphZeroX ), 00393 (int)( curArr.at(i).y() + mDspDims.graphZeroY ) ); 00394 } 00395 } 00396 00397 int tmpStkSz = tmpStk.size(); 00398 for ( int iTmp=0; iTmp < tmpStkSz; iTmp++ ) { 00399 newRedoStk.push( tmpStk.top() ); 00400 tmpStk.pop(); 00401 } 00402 mSLSet.redoSet = newRedoStk; 00403 00404 mSLSet.curArr = &mSLSet.lineSet[mSLSet.curLine].top(); 00405 } 00406 00407 DspDims HistogramDlg::calcDspDims( ) { 00408 DspDims dspDims; 00409 dspDims.scaleW = 40; 00410 dspDims.graphBorderW = 30; 00411 dspDims.topY = mMenuBar->height(); 00412 dspDims.winW = this->width(); 00413 dspDims.winH = this->height() - dspDims.topY; 00414 dspDims.graphW = dspDims.winW - dspDims.scaleW - dspDims.graphBorderW; 00415 dspDims.graphH = dspDims.winH - dspDims.scaleW - dspDims.graphBorderW; 00416 dspDims.graphZeroX = dspDims.scaleW; 00417 dspDims.graphMaxX = dspDims.scaleW+dspDims.graphW-1; 00418 dspDims.graphZeroY = dspDims.graphBorderW; 00419 dspDims.graphMaxY = dspDims.graphBorderW+dspDims.graphH-1; 00420 00421 return dspDims; 00422 } 00423 00424 void HistogramDlg::mousePressEvent( QMouseEvent * ) { 00425 if ( mHDS.HDS.size() <= 0 || mHDS.curHDS == -1 ) 00426 return; 00427 mMouse.mPointMoving = mouseOnPoint(); 00428 } 00429 00430 void HistogramDlg::mouseReleaseEvent( QMouseEvent * ) { 00431 if ( mHDS.HDS.size() <= 0 || mHDS.curHDS == -1 ) 00432 return; 00433 00434 if ( mSLSet.isChanging ) { 00435 mSLSet.isChanging = false; 00436 alertUser(); 00437 } 00438 mMouse.mPointMoving = -1; 00439 repaint( false ); 00440 } 00441 00442 void HistogramDlg::mouseMoveEvent( QMouseEvent *me ) { 00443 int newX, newY; 00444 00445 if ( mHDS.HDS.size() <= 0 || mHDS.curHDS == -1 ) 00446 return; 00447 00448 mMouse.mMouseX = me->x(); 00449 mMouse.mMouseY = me->y() - mDspDims.topY; 00450 00451 if ( mMouse.mPointMoving >= 0 ) { 00452 // THIS ONLY HAPPENS ONCE DURING A POINT MOVE 00453 if ( !mSLSet.isChanging ) { 00454 if ( !mSLSet.isMerged ) { 00455 mSLSet.lineSet[mSLSet.curLine].push( mSLSet.curArr->copy() ); 00456 } else { 00457 mSLSet.lineSet[0].push( mSLSet.curArr->copy() ); 00458 mSLSet.lineSet[1].push( mSLSet.curArr->copy() ); 00459 mSLSet.lineSet[2].push( mSLSet.curArr->copy() ); 00460 } 00461 mSLSet.curArr = &mSLSet.lineSet[mSLSet.curLine].top(); 00462 mSLSet.redoSet.empty(); 00463 mSLSet.isChanging = true; 00464 } 00465 00466 if ( mMouse.mPointMoving == 0 || 00467 mMouse.mPointMoving == (int)mSLSet.curArr->size()-1 ) { 00468 newX = (*mSLSet.curArr)[mMouse.mPointMoving].x(); 00469 newY = mMouse.mMouseY; 00470 } else { 00471 if ( mMouse.mMouseX - (*mSLSet.curArr)[mMouse.mPointMoving-1].x() < 6 || 00472 (*mSLSet.curArr)[mMouse.mPointMoving+1].x() - mMouse.mMouseX < 6 ) 00473 newX = (*mSLSet.curArr)[mMouse.mPointMoving].x(); 00474 else 00475 newX = mMouse.mMouseX; 00476 00477 newY = mMouse.mMouseY; 00478 00479 if ( newX > mDspDims.graphMaxX ) newX = mDspDims.graphMaxX; 00480 if ( newX < mDspDims.graphZeroX ) newX = mDspDims.graphZeroX; 00481 } 00482 00483 if ( newY > mDspDims.graphMaxY ) newY = mDspDims.graphMaxY; 00484 if ( newY < mDspDims.graphZeroY ) newY = mDspDims.graphZeroY; 00485 00486 if ( !mSLSet.isMerged ) 00487 mSLSet.curArr->setPoint( mMouse.mPointMoving, newX, newY ); 00488 else { 00489 mSLSet.lineSet[0].top().setPoint( mMouse.mPointMoving, newX, newY ); 00490 mSLSet.lineSet[1].top().setPoint( mMouse.mPointMoving, newX, newY ); 00491 mSLSet.lineSet[2].top().setPoint( mMouse.mPointMoving, newX, newY ); 00492 } 00493 repaint( false ); 00494 } else { 00495 QCursor c1( PointingHandCursor ); 00496 if ( mouseOnPoint() >= 0 ) 00497 setCursor( c1 ); 00498 else 00499 setCursor( QCursor( ArrowCursor ) ); 00500 } 00501 } 00502 00503 00504 bool HistogramDlg::mouseInGraph( ) { 00505 if ( mMouse.mMouseX < mDspDims.graphMaxX && 00506 mMouse.mMouseX > mDspDims.graphZeroX && 00507 mMouse.mMouseY < mDspDims.graphMaxY && 00508 mMouse.mMouseY > mDspDims.graphZeroY ) 00509 return true; 00510 00511 return false; 00512 } 00513 00514 int HistogramDlg::mouseOnPoint( ) { 00515 for ( int i=0; i < (int)mSLSet.curArr->size(); i++ ) { 00516 if ( abs( mMouse.mMouseX - (*mSLSet.curArr)[i].x() ) <= 3 && 00517 abs( mMouse.mMouseY - (*mSLSet.curArr)[i].y() ) <= 3 ) 00518 return i; 00519 } 00520 00521 return -1; 00522 } 00523 00524 void HistogramDlg::mouseDoubleClickEvent( QMouseEvent * ) { 00525 unsigned int i, a; 00526 int pnt = mouseOnPoint(); 00527 00528 if ( !mouseInGraph() ) 00529 return; 00530 00531 if ( !mSLSet.isMerged ) { 00532 mSLSet.lineSet[mSLSet.curLine].push( mSLSet.curArr->copy() ); 00533 } else { 00534 mSLSet.lineSet[0].push( mSLSet.curArr->copy() ); 00535 mSLSet.lineSet[1].push( mSLSet.curArr->copy() ); 00536 mSLSet.lineSet[2].push( mSLSet.curArr->copy() ); 00537 } 00538 00539 mSLSet.curArr = &mSLSet.lineSet[mSLSet.curLine].top(); 00540 mSLSet.redoSet.empty(); 00541 00542 if ( pnt < 0 ) { 00543 for ( i=0; i < mSLSet.curArr->size(); i++ ) 00544 if ( abs( (*mSLSet.curArr).at(i).x() - mMouse.mMouseX ) <= 3 ) 00545 return; 00546 00547 QPointArray tmpPntArr( mSLSet.curArr->size() +1 ); 00548 bool mFoundIt = false; 00549 a=0; 00550 for ( i=0; i < mSLSet.curArr->size(); i++ ) { 00551 if ( !mFoundIt && (*mSLSet.curArr).at(i).x() > mMouse.mMouseX ) { 00552 tmpPntArr.setPoint( a, mMouse.mMouseX, mMouse.mMouseY ); 00553 i--; 00554 mFoundIt = true; 00555 mMouse.mPointMoving = a; 00556 } else 00557 tmpPntArr.setPoint( a, (*mSLSet.curArr).at(i).x(), (*mSLSet.curArr).at(i).y() ); 00558 a++; 00559 } 00560 setCursor( QCursor( PointingHandCursor ) ); 00561 if ( !mSLSet.isMerged ) 00562 (*mSLSet.curArr) = tmpPntArr; 00563 else { 00564 mSLSet.lineSet[0].top() = tmpPntArr; 00565 mSLSet.lineSet[1].top() = tmpPntArr; 00566 mSLSet.lineSet[2].top() = tmpPntArr; 00567 } 00568 00569 } else { 00570 if ( pnt == 0 || pnt == (int)mSLSet.curArr->size()-1 ) 00571 return; 00572 00573 QPointArray tmpPntArr( mSLSet.curArr->size() - 1 ); 00574 a = 0; 00575 for ( i=0; i < mSLSet.curArr->size(); i++ ) { 00576 if ( (int)i != pnt ) { 00577 tmpPntArr.at(a) = (*mSLSet.curArr).at(i); 00578 a++; 00579 } 00580 } 00581 setCursor( QCursor( ArrowCursor ) ); 00582 if ( !mSLSet.isMerged ) 00583 (*mSLSet.curArr) = tmpPntArr; 00584 else { 00585 mSLSet.lineSet[0].top() = tmpPntArr; 00586 mSLSet.lineSet[1].top() = tmpPntArr; 00587 mSLSet.lineSet[2].top() = tmpPntArr; 00588 } 00589 } 00590 00591 alertUser(); 00592 repaint( false ); 00593 } 00594 00595 void HistogramDlg::setHDS( vector<HistogramDataSource*> hds ) { 00596 mHDS.HDS = hds; 00597 00598 } 00599 00600 void HistogramDlg::setUser( HistogramUser *user ) { 00601 mHistUser = user; 00602 } 00603 00604 void HistogramDlg::addHDS( HistogramDataSource *hds ) { 00605 mHDS.HDS.push_back( hds ); 00606 hds->setHistogramDlg( this ); 00607 00608 QAction *action = new QAction( tr( hds->getHistName() ), 00609 tr( hds->getHistName() ), 00610 0, this, 0, true ); 00611 action->addTo( mDSMenu ); 00612 connect( action, SIGNAL( activated() ), this, SLOT( changeDataSource() ) ); 00613 mDSActGroup->insert( action ); 00614 mHDS.actSet.push_back( action ); 00615 action->setOn( true ); 00616 } 00617 00618 void HistogramDlg::changeToRed( ) { 00619 mHDS.curHist = 0; 00620 mSLSet.redoSet.empty(); 00621 mSLSet.curArr = &mSLSet.lineSet[0].top(); 00622 mSLSet.curLine = 0; 00623 repaint( false ); 00624 } 00625 00626 void HistogramDlg::changeToGreen( ) { 00627 mHDS.curHist = 1; 00628 mSLSet.redoSet.empty(); 00629 mSLSet.curArr = &mSLSet.lineSet[1].top(); 00630 mSLSet.curLine = 1; 00631 repaint( false ); 00632 } 00633 00634 void HistogramDlg::changeToBlue( ) { 00635 mHDS.curHist = 2; 00636 mSLSet.redoSet.empty(); 00637 mSLSet.curArr = &mSLSet.lineSet[2].top(); 00638 mSLSet.curLine = 2; 00639 repaint( false ); 00640 } 00641 00642 void HistogramDlg::changeToAll( ) { 00643 00644 } 00645 00646 void HistogramDlg::changeDataSource( ) { 00647 unsigned int cnt = 0; 00648 00649 while ( cnt < mHDS.actSet.size() && !mHDS.actSet[cnt]->isOn() ) 00650 cnt++; 00651 00652 if ( cnt >= mHDS.actSet.size() ) 00653 return; 00654 00655 mHDS.curHDS = cnt; 00656 00657 // HERE'S WHERE A THREAD GOES TO WAIT FOR HIST CALCULATION 00658 QApplication::setOverrideCursor( Qt::waitCursor ); 00659 mHDS.histSet = mHDS.HDS[mHDS.curHDS]->getHistSet(); 00660 QApplication::restoreOverrideCursor(); 00661 mHDS.curHist = mSLSet.curLine; 00662 00663 if ( !mHDS.histSet.isColor() ) { 00664 mSLSet.isMerged = false; 00665 mMergeAct->setOn( false ); 00666 mMergeAct->setEnabled( false ); 00667 00668 mColorAct[0]->setEnabled( false ); 00669 mColorAct[1]->setEnabled( false ); 00670 mColorAct[2]->setEnabled( false ); 00671 } else { 00672 mSLSet.isMerged = false; 00673 mMergeAct->setOn( false ); 00674 mMergeAct->setEnabled( true ); 00675 00676 mColorAct[0]->setEnabled( true ); 00677 mColorAct[1]->setEnabled( true ); 00678 mColorAct[2]->setEnabled( true ); 00679 } 00680 00681 createDataPnts(); 00682 repaint( false ); 00683 00684 } 00685 00686 void HistogramDlg::createDataPnts( ) { 00687 Histogram *hist; 00688 double min; 00689 double max; 00690 double scaleX; 00691 double scaleY; 00692 int cmax; 00693 00694 if ( mHDS.HDS.size() <= 0 ) 00695 return; 00696 00697 mDspDims = calcDspDims(); 00698 00699 int graphW = mDspDims.graphMaxX - mDspDims.graphZeroX; 00700 int graphH = mDspDims.graphMaxY - mDspDims.graphZeroY; 00701 00702 vector<QPoint> points; 00703 00704 QPoint begp( mDspDims.graphZeroX, mDspDims.graphMaxY ); 00705 QPoint endp( mDspDims.graphMaxX, mDspDims.graphMaxY ); 00706 00707 for ( int i=0; i < 3; i++ ) { 00708 if ( !mHDS.histSet.isColor() && i > 0 ) 00709 break; 00710 00711 hist = mHDS.histSet[i]; 00712 if ( hist == NULL ) 00713 continue; 00714 00715 min = hist->getMin(); 00716 max = hist->getMax(); 00717 cmax = hist->getMaxCnt(); 00718 00719 scaleX = (double)graphW / (double)(max-min); 00720 scaleY = (double)graphH / (double)cmax; 00721 00722 vector<Hash> hash = hist->getHist(); 00723 for ( unsigned int iHash=0; iHash < hash.size(); iHash++ ) { 00724 QPoint p( (int)((hash[iHash].mVal - min)*scaleX+mDspDims.graphZeroX), 00725 (int)(mDspDims.graphMaxY - (hash[iHash].mCnt*scaleY)) ); 00726 00727 points.push_back( p ); 00728 } 00729 00730 QPointArray parr( points.size() + 3 ); 00731 parr.setPoint( 0, begp ); 00732 unsigned int iPnt; 00733 for ( iPnt=0; iPnt < points.size(); iPnt++ ) 00734 parr.setPoint( iPnt+1, points[iPnt] ); 00735 00736 parr.setPoint( iPnt+1, endp ); 00737 parr.setPoint( iPnt+2, begp ); 00738 00739 mHDS.dataPnts[i] = parr.copy(); 00740 points.clear(); 00741 } 00742 } 00743 00744 void HistogramDlg::bestFit( ) { 00745 00746 } 00747 00748 void HistogramDlg::mergeAll( ) { 00749 if ( mSLSet.isMerged == false ) { 00750 mSLSet.isMerged = true; 00751 // PUSH CUR ARRAY TO ALL 00752 mSLSet.lineSet[0].push( *mSLSet.curArr ); 00753 mSLSet.lineSet[1].push( *mSLSet.curArr ); 00754 mSLSet.lineSet[2].push( *mSLSet.curArr ); 00755 mSLSet.curArr = &mSLSet.lineSet[0].top(); 00756 mSLSet.curLine = 0; 00757 } else { 00758 mSLSet.isMerged = false; 00759 } 00760 repaint( false ); 00761 } 00762 00763 void HistogramDlg::clearPoints( ) { 00764 QPointArray parr( 2 ); 00765 parr.setPoint( 0, mSLSet.curArr->at( 0 ) ); 00766 parr.setPoint( 1, mSLSet.curArr->at( mSLSet.curArr->size()-1 ) ); 00767 00768 mSLSet.lineSet[mSLSet.curLine].push( parr ); 00769 mSLSet.curArr = &mSLSet.lineSet[mSLSet.curLine].top(); 00770 mSLSet.redoSet.empty(); 00771 00772 alertUser(); 00773 repaint( false ); 00774 } 00775 00776 void HistogramDlg::undoToLast( ) { 00777 if ( mSLSet.lineSet[mSLSet.curLine].size() < 2 ) 00778 return; 00779 00780 mSLSet.redoSet.push( mSLSet.curArr->copy() ); 00781 mSLSet.lineSet[mSLSet.curLine].pop(); 00782 mSLSet.curArr = &mSLSet.lineSet[mSLSet.curLine].top(); 00783 00784 repaint( false ); 00785 } 00786 00787 void HistogramDlg::redoToPrev( ) { 00788 if ( mSLSet.redoSet.size() <= 0 ) 00789 return; 00790 00791 mSLSet.lineSet[mSLSet.curLine].push( mSLSet.redoSet.top().copy() ); 00792 mSLSet.curArr = &mSLSet.lineSet[mSLSet.curLine].top(); 00793 mSLSet.redoSet.pop(); 00794 00795 repaint( false ); 00796 00797 } 00798 00799 void HistogramDlg::calcPercent( ) { 00800 if ( mHDS.curHDS == -1 ) 00801 return; 00802 00803 unsigned int iPct = 0; 00804 double cntTot=0, cntTot2=0, cntTot3=0; 00805 double cntLeft=0, cntRight=0, 00806 cntLeft2=0, cntRight2=0, 00807 cntLeft3=0, cntRight3=0; 00808 double valR = 0.0, valL = 0.0, valR2 = 0.0, 00809 valL2 = 0.0, valR3 = 0.0, valL3 = 0.0; 00810 int h0sz, h1sz=0, h2sz=0; 00811 00812 vector<Hash> hist[3]; 00813 double percentVals[] = { .01, .02, .05}; 00814 00815 bool isColor = mHDS.histSet.isColor(); 00816 00817 while ( iPct < mPercentAct.size() && !mPercentAct[iPct]->isOn() ) 00818 iPct++; 00819 00820 mPercentAct[iPct]->setOn( false ); 00821 00822 if ( iPct >= mPercentAct.size() ) 00823 return; 00824 00825 mPercentAct[iPct]->setOn( false ); 00826 00827 // CALC COUNT TOTAL 00828 int iCnt=0; 00829 00830 hist[0] = mHDS.histSet[0]->getHist(); 00831 h0sz = hist[0].size(); 00832 for ( iCnt=0; iCnt < h0sz; iCnt++ ) 00833 cntTot += hist[0][iCnt].mCnt; 00834 00835 if ( isColor ) { 00836 hist[1] = mHDS.histSet[1]->getHist(); 00837 h1sz = hist[1].size(); 00838 for ( iCnt=0; iCnt < h1sz; iCnt++ ) 00839 cntTot2 += hist[1][iCnt].mCnt; 00840 00841 hist[2] = mHDS.histSet[2]->getHist(); 00842 h2sz = hist[2].size(); 00843 for ( iCnt=0; iCnt < h2sz; iCnt++ ) 00844 cntTot3 += hist[2][iCnt].mCnt; 00845 } 00846 00847 // CALC LEFT VAL 00848 iCnt = 1; 00849 while ( iCnt < h0sz && cntLeft < (cntTot*percentVals[iPct]) ) { 00850 valL = hist[0][iCnt].mVal; 00851 if ( iCnt < h0sz ) 00852 cntLeft += hist[0][iCnt].mCnt; 00853 iCnt++; 00854 } 00855 00856 if ( isColor ) { 00857 iCnt = 1; 00858 while ( iCnt < h1sz && cntLeft2 < (cntTot2*percentVals[iPct]) ) { 00859 valL2 = hist[1][iCnt].mVal; 00860 if ( iCnt < h0sz ) 00861 cntLeft2 += hist[1][iCnt].mCnt; 00862 iCnt++; 00863 } 00864 00865 iCnt = 1; 00866 while ( iCnt < h2sz && cntLeft3 < (cntTot3*percentVals[iPct]) ) { 00867 valL3 = hist[2][iCnt].mVal; 00868 if ( iCnt < h0sz ) 00869 cntLeft3 += hist[2][iCnt].mCnt; 00870 iCnt++; 00871 } 00872 } 00873 00874 00875 // CALC RIGHT VAL 00876 iCnt = 2; 00877 while ( iCnt < h0sz && cntRight < (cntTot*percentVals[iPct]) ) { 00878 valR = hist[0][h0sz-iCnt].mVal; 00879 cntRight += hist[0][h0sz-iCnt].mCnt; 00880 iCnt++; 00881 } 00882 00883 if ( isColor ) { 00884 iCnt = 2; 00885 while ( iCnt < h1sz && cntRight2 < (cntTot2*percentVals[iPct]) ) { 00886 valR2 = hist[1][h1sz-iCnt].mVal; 00887 cntRight2 += hist[1][h1sz-iCnt].mCnt; 00888 iCnt++; 00889 } 00890 00891 iCnt = 2; 00892 while ( iCnt < (int)h2sz && cntRight3 < (int)(cntTot3*percentVals[iPct]) ) { 00893 valR3 = hist[2][h2sz-iCnt].mVal; 00894 cntRight3 += hist[2][h2sz-iCnt].mCnt; 00895 iCnt++; 00896 } 00897 } 00898 00899 QPointArray parr( 4 ); 00900 QPointArray parr2( 4 ); 00901 QPointArray parr3( 4 ); 00902 00903 parr.setPoint( 0, mDspDims.graphZeroX, mDspDims.graphMaxY ); 00904 parr.setPoint( 3, mDspDims.graphMaxX, mDspDims.graphZeroY ); 00905 00906 if ( isColor ) { 00907 parr2.setPoint( 0, mDspDims.graphZeroX, mDspDims.graphMaxY ); 00908 parr2.setPoint( 3, mDspDims.graphMaxX, mDspDims.graphZeroY ); 00909 parr3.setPoint( 0, mDspDims.graphZeroX, mDspDims.graphMaxY ); 00910 parr3.setPoint( 3, mDspDims.graphMaxX, mDspDims.graphZeroY ); 00911 } 00912 00913 double min = hist[0][0].mVal; 00914 double max = hist[0][hist[0].size()-1].mVal; 00915 double graphW = mDspDims.graphMaxX - mDspDims.graphZeroX; 00916 double scaleX = graphW / (double)(max-min); 00917 00918 parr.setPoint( 1, (int)(valL*scaleX+mDspDims.graphZeroX), (int)mDspDims.graphMaxY ); 00919 parr.setPoint( 2, (int)(valR*scaleX+mDspDims.graphZeroX), (int)mDspDims.graphZeroY ); 00920 00921 if ( isColor ) { 00922 min = hist[1][0].mVal; 00923 max = hist[1][hist[1].size()-1].mVal; 00924 scaleX = graphW / (double)(max-min); 00925 parr2.setPoint( 1, (int)(valL2*scaleX+mDspDims.graphZeroX), (int)mDspDims.graphMaxY ); 00926 parr2.setPoint( 2, (int)(valR2*scaleX+mDspDims.graphZeroX), (int)mDspDims.graphZeroY ); 00927 00928 min = hist[2][0].mVal; 00929 max = hist[2][hist[2].size()-1].mVal; 00930 scaleX = graphW / (double)(max-min); 00931 parr3.setPoint( 1, (int)(valL3*scaleX+mDspDims.graphZeroX),(int)mDspDims.graphMaxY ); 00932 parr3.setPoint( 2, (int)(valR3*scaleX+mDspDims.graphZeroX), (int)mDspDims.graphZeroY ); 00933 } 00934 00935 mSLSet.lineSet[0].push( parr.copy() ); 00936 if ( isColor ) { 00937 mSLSet.lineSet[1].push( parr2.copy() ); 00938 mSLSet.lineSet[2].push( parr3.copy() ); 00939 } 00940 00941 mSLSet.redoSet.empty(); 00942 mSLSet.curArr = &mSLSet.lineSet[mSLSet.curLine].top(); 00943 00944 mSLSet.isMerged = false; 00945 mMergeAct->setOn( false ); 00946 00947 alertUser(); 00948 repaint( false ); 00949 00950 } 00951 00952 void HistogramDlg::initPntsFromUser( ) { 00953 if ( mHistUser ) { 00954 const QPointArray *parr = mHistUser->getHistPnts(); 00955 mSLSet.lineSet[0].empty(); 00956 mSLSet.lineSet[1].empty(); 00957 mSLSet.lineSet[2].empty(); 00958 mSLSet.redoSet.empty(); 00959 00960 mSLSet.lineSet[0].push( parr[0].copy() ); 00961 mSLSet.lineSet[1].push( parr[1].copy() ); 00962 mSLSet.lineSet[2].push( parr[2].copy() ); 00963 00964 resize( this->width(), this->height() ); 00965 } 00966 } 00967 00968 void HistogramDlg::alertUser( ) { 00969 if ( mHistUser ) { 00970 QPointArray parr[3]; 00971 parr[0] = mSLSet.lineSet[0].top().copy(); 00972 if ( mHDS.histSet.isColor() ) { 00973 parr[1] = mSLSet.lineSet[1].top().copy(); 00974 parr[2] = mSLSet.lineSet[2].top().copy(); 00975 } else { 00976 parr[1].resize( 0 ); 00977 parr[2].resize( 0 ); 00978 } 00979 00980 for ( unsigned int iArr=0; iArr < 3; iArr++ ) { 00981 if ( !mHDS.histSet.isColor() && iArr > 0 ) 00982 break; 00983 00984 double min = mHDS.histSet.getHist( iArr )->getMin(); 00985 double max = mHDS.histSet.getHist( iArr )->getMax(); 00986 double graphW = mDspDims.graphMaxX - mDspDims.graphZeroX; 00987 double graphH = mDspDims.graphMaxY - mDspDims.graphZeroY; 00988 00989 double scaleX = (max-min) / graphW; 00990 double scaleY = 255 / graphH; 00991 00992 for ( unsigned int iPnt=0; iPnt < parr[iArr].size(); iPnt++ ) { 00993 double x = parr[iArr].at(iPnt).x(); 00994 double y = parr[iArr].at(iPnt).y(); 00995 00996 x -= mDspDims.scaleW; 00997 y = mDspDims.graphMaxY - y; 00998 00999 x *= scaleX; 01000 y *= scaleY; 01001 01002 parr[iArr].setPoint( iPnt, (int)x, (int)y ); 01003 } 01004 } 01005 01006 mHistUser->setHistPnts( parr ); 01007 } 01008 } 01009 01010 void HistogramDlg::reloadHistSet( ) { 01011 /* 01012 if( mHistUser ) 01013 mHistUser->reset(); 01014 */ 01015 changeDataSource( ); 01016 } 01017 01018 01019 01020 01021
Home |
Search |
Disclaimers & Privacy |
Contact Us GLIMSView Maintainer: dsoltesz@usgs.gov |