diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.cpp b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.cpp index 53a69be1ed..6f661f13ac 100644 --- a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.cpp +++ b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.cpp @@ -1,1663 +1,1675 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $ Version: $Revision: 21975 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ //=========FOR TESTING========== //random generation, number of points equal requested points // Blueberry application and interaction service #include #include // Qmitk #include "QmitkFiberBundleDeveloperView.h" #include // Qt #include // MITK #include #include #include //===needed when timeSlicedGeometry is null to invoke rendering mechansims ==== #include #include // VTK #include //for randomized FiberStructure #include //for fiberStructure #include //for fiberStructure #include //for geometry //ITK #include //============================================== //======== W O R K E R S ____ S T A R T ======== //============================================== /*=================================================================================== * THIS METHOD IMPLEMENTS THE ACTIONS WHICH SHALL BE EXECUTED by the according THREAD * --generate FiberIDs--*/ QmitkFiberIDWorker::QmitkFiberIDWorker(QThread* hostingThread, Package4WorkingThread itemPackage) : m_itemPackage(itemPackage), m_hostingThread(hostingThread) { } void QmitkFiberIDWorker::run() { if(m_itemPackage.st_Controls->checkBoxMonitorFiberThreads->isChecked()) m_itemPackage.st_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_RUNNING); /* MEASUREMENTS AND FANCY GUI EFFECTS * accurate time measurement using ITK timeProbe*/ itk::TimeProbe clock; clock.Start(); //set GUI representation of timer to 0, is essential for correct timer incrementation m_itemPackage.st_Controls->infoTimerGenerateFiberIds->setText(QString::number(0)); m_itemPackage.st_FancyGUITimer1->start(); //do processing m_itemPackage.st_FBX->DoGenerateFiberIds(); /* MEASUREMENTS AND FANCY GUI EFFECTS CLEANUP */ clock.Stop(); m_itemPackage.st_FancyGUITimer1->stop(); m_itemPackage.st_Controls->infoTimerGenerateFiberIds->setText( QString::number(clock.GetTotal()) ); delete m_itemPackage.st_FancyGUITimer1; // fancy timer is not needed anymore m_hostingThread->quit(); } /*=================================================================================== * THIS METHOD IMPLEMENTS THE ACTIONS WHICH SHALL BE EXECUTED by the according THREAD * -- extract fibers by given PlanarFigure --*/ QmitkFiberExtractorWorker::QmitkFiberExtractorWorker(QThread* hostingThread, Package4WorkingThread itemPackage) : m_itemPackage(itemPackage), m_hostingThread(hostingThread) { } void QmitkFiberExtractorWorker::run() { if(m_itemPackage.st_Controls->checkBoxMonitorFiberThreads->isChecked()) m_itemPackage.st_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_RUNNING); /* MEASUREMENTS AND FANCY GUI EFFECTS * accurate time measurement using ITK timeProbe*/ itk::TimeProbe clock; clock.Start(); //set GUI representation of timer to 0, is essential for correct timer incrementation m_itemPackage.st_Controls->infoTimerExtractFibers->setText(QString::number(0)); m_itemPackage.st_FancyGUITimer1->start(); //do processing std::vector fibIds = m_itemPackage.st_FBX->DoExtractFiberIds(m_itemPackage.st_PlanarFigure); //generate new fiberbundle by fiber iDs vtkSmartPointer newFBPolyData = m_itemPackage.st_FBX->GenerateNewFiberBundleByIds(fibIds); // call function to convert fiberstructure into fiberbundleX and pass it to datastorage (m_itemPackage.st_host->*m_itemPackage.st_pntr_to_Method_PutFibersToDataStorage)(newFBPolyData); /* MEASUREMENTS AND FANCY GUI EFFECTS CLEANUP */ clock.Stop(); m_itemPackage.st_FancyGUITimer1->stop(); m_itemPackage.st_Controls->infoTimerExtractFibers->setText( QString::number(clock.GetTotal()) ); delete m_itemPackage.st_FancyGUITimer1; // fancy timer is not needed anymore m_hostingThread->quit(); } /*=================================================================================== * THIS METHOD IMPLEMENTS THE ACTIONS WHICH SHALL BE EXECUTED by the according THREAD * --do color coding--*/ QmitkFiberColoringWorker::QmitkFiberColoringWorker(QThread* hostingThread, Package4WorkingThread itemPackage) : m_itemPackage(itemPackage) , m_hostingThread(hostingThread) { } void QmitkFiberColoringWorker::run() { if(m_itemPackage.st_Controls->checkBoxMonitorFiberThreads->isChecked()) m_itemPackage.st_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_RUNNING); /* MEASUREMENTS AND FANCY GUI EFFECTS * accurate time measurement using ITK timeProbe*/ itk::TimeProbe clock; clock.Start(); //set GUI representation of timer to 0, is essential for correct timer incrementation m_itemPackage.st_Controls->infoTimerColorCoding->setText(QString::number(0)); m_itemPackage.st_FancyGUITimer1->start(); //do processing //TODO check which colorcoding option is checked! m_itemPackage.st_FBX->DoColorCodingOrientationbased(); /* MEASUREMENTS AND FANCY GUI EFFECTS CLEANUP */ clock.Stop(); m_itemPackage.st_FancyGUITimer1->stop(); m_itemPackage.st_Controls->infoTimerColorCoding->setText( QString::number(clock.GetTotal()) ); delete m_itemPackage.st_FancyGUITimer1; // fancy timer is not needed anymore m_hostingThread->quit(); } /*=================================================================================== * THIS METHOD IMPLEMENTS THE ACTIONS WHICH SHALL BE EXECUTED by the according THREAD * --generate random fibers--*/ QmitkFiberGenerateRandomWorker::QmitkFiberGenerateRandomWorker(QThread* hostingThread, Package4WorkingThread itemPackage) : m_itemPackage(itemPackage), m_hostingThread(hostingThread) { } void QmitkFiberGenerateRandomWorker::run() { if(m_itemPackage.st_Controls->checkBoxMonitorFiberThreads->isChecked()) m_itemPackage.st_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_RUNNING); /* MEASUREMENTS AND FANCY GUI EFFECTS */ //MAKE SURE by yourself THAT NOTHING ELSE THAN A NUMBER IS SET IN THAT LABEL m_itemPackage.st_Controls->infoTimerGenerateFiberBundle->setText(QString::number(0)); m_itemPackage.st_FancyGUITimer1->start(); //do processing, generateRandomFibers int numOfFibers = m_itemPackage.st_Controls->boxFiberNumbers->value(); int distrRadius = m_itemPackage.st_Controls->boxDistributionRadius->value(); int numOfPoints = numOfFibers * distrRadius; std::vector< std::vector > fiberStorage; for (int i=0; i a; fiberStorage.push_back( a ); } /* Generate Point Cloud */ vtkSmartPointer randomPoints = vtkSmartPointer::New(); randomPoints->SetCenter(0.0, 0.0, 0.0); randomPoints->SetNumberOfPoints(numOfPoints); randomPoints->SetRadius(distrRadius); randomPoints->Update(); vtkPoints* pnts = randomPoints->GetOutput()->GetPoints(); /* ASSIGN EACH POINT TO A RANDOM FIBER */ srand((unsigned)time(0)); // init randomizer for (int i=0; iGetNumberOfPoints(); ++i) { //generate random number between 0 and numOfFibers-1 int random_integer; random_integer = (rand()%numOfFibers); //add current point to random fiber fiberStorage.at(random_integer).push_back(i); // MITK_INFO << "point" << i << " |" << pnts->GetPoint(random_integer)[0] << "|" << pnts->GetPoint(random_integer)[1]<< "|" << pnts->GetPoint(random_integer)[2] << "| into fiber" << random_integer; } // initialize accurate time measurement itk::TimeProbe clock; clock.Start(); /* GENERATE VTK POLYLINES OUT OF FIBERSTORAGE */ vtkSmartPointer linesCell = vtkSmartPointer::New(); // Host vtkPolyLines linesCell->Allocate(pnts->GetNumberOfPoints()*2); //allocate for each cellindex also space for the pointId, e.g. [idx | pntID] for (unsigned long i=0; i singleFiber = fiberStorage.at(i); vtkSmartPointer fiber = vtkSmartPointer::New(); fiber->GetPointIds()->SetNumberOfIds((int)singleFiber.size()); for (unsigned long si=0; siGetPointIds()->SetId( si, singleFiber.at(si) ); } linesCell->InsertNextCell(fiber); } /* checkpoint for cellarray allocation */ if ( (linesCell->GetSize()/pnts->GetNumberOfPoints()) != 2 ) //e.g. size: 12, number of points:6 .... each cell hosts point ids (6 ids) + cell index for each idPoint. 6 * 2 = 12 { MITK_INFO << "RANDOM FIBER ALLOCATION CAN NOT BE TRUSTED ANYMORE! Correct leak or remove command: linesCell->Allocate(pnts->GetNumberOfPoints()*2) but be aware of possible loss in performance."; } /* HOSTING POLYDATA FOR RANDOM FIBERSTRUCTURE */ vtkSmartPointer PDRandom = vtkPolyData::New(); //could also be a standard pointer instead of smartpointer cuz ther is no need to delete because data is managed in datastorage. PDRandom->SetPoints(pnts); PDRandom->SetLines(linesCell); // accurate timer measurement stop clock.Stop(); //MITK_INFO << "=====Assambling random Fibers to Polydata======\nMean: " << clock.GetMean() << " Total: " << clock.GetTotal() << std::endl; // call function to convert fiberstructure into fiberbundleX and pass it to datastorage (m_itemPackage.st_host->*m_itemPackage.st_pntr_to_Method_PutFibersToDataStorage)(PDRandom); /* MEASUREMENTS AND FANCY GUI EFFECTS CLEANUP */ m_itemPackage.st_FancyGUITimer1->stop(); m_itemPackage.st_Controls->infoTimerGenerateFiberBundle->setText( QString::number(clock.GetTotal()) ); delete m_itemPackage.st_FancyGUITimer1; // fancy timer is not needed anymore m_hostingThread->quit(); } /*=================================================================================== * THIS METHOD IMPLEMENTS THE ACTIONS WHICH SHALL BE EXECUTED by the according THREAD * --update GUI elements of thread monitor-- * implementation not thread safe, not needed so far because * there exists only 1 thread for fiberprocessing * for threadsafety, you need to implement checking mechanisms in methods "::threadFor...." */ QmitkFiberThreadMonitorWorker::QmitkFiberThreadMonitorWorker( QThread* hostingThread, Package4WorkingThread itemPackage ) : m_itemPackage(itemPackage) , m_hostingThread(hostingThread) , m_pixelstepper(10) //for next rendering call, move object 10px , m_steppingDistance(220) //use only a multiple value of pixelstepper, x-axis border for fancy stuff { //set timers m_thtimer_initMonitor = new QTimer; m_thtimer_initMonitor->setInterval(10); m_thtimer_initMonitorSetFinalPosition = new QTimer; m_thtimer_initMonitorSetFinalPosition->setInterval(10); m_thtimer_initMonitorSetMasks = new QTimer; m_thtimer_initMonitorSetFinalPosition->setInterval(10); m_thtimer_threadStarted = new QTimer; m_thtimer_threadStarted->setInterval(50); m_thtimer_threadFinished = new QTimer; m_thtimer_threadFinished->setInterval(50); m_thtimer_threadTerminated = new QTimer; m_thtimer_threadTerminated->setInterval(50); connect (m_thtimer_initMonitor, SIGNAL( timeout()), this, SLOT( fancyMonitorInitialization() ) ); connect ( m_thtimer_initMonitorSetFinalPosition, SIGNAL( timeout() ), this, SLOT( fancyMonitorInitializationFinalPos() ) ); connect ( m_thtimer_initMonitorSetMasks, SIGNAL( timeout() ), this, SLOT( fancyMonitorInitializationMask() ) ); connect (m_thtimer_threadStarted, SIGNAL( timeout()), this, SLOT( fancyTextFading_threadStarted() ) ); connect (m_thtimer_threadFinished, SIGNAL( timeout()), this, SLOT( fancyTextFading_threadFinished() ) ); connect (m_thtimer_threadTerminated, SIGNAL( timeout()), this, SLOT( fancyTextFading_threadTerminated() ) ); //first, the current text shall turn transparent m_decreaseOpacity_threadStarted = true; m_decreaseOpacity_threadFinished = true; m_decreaseOpacity_threadTerminated = true; } void QmitkFiberThreadMonitorWorker::run() { } void QmitkFiberThreadMonitorWorker::initializeMonitor() { //fancy configuration of animation start mitk::Point2D pntOpen; pntOpen[0] = 118; pntOpen[1] = 10; mitk::Point2D headPos; headPos[0] = 19; headPos[1] = 10; mitk::Point2D statusPos; statusPos[0] = 105; statusPos[1] = 23; mitk::Point2D startedPos; startedPos[0] = 68; startedPos[1] = 10; mitk::Point2D finishedPos; finishedPos[0] = 143; finishedPos[1] = 10; mitk::Point2D terminatedPos; terminatedPos[0] = 240; terminatedPos[1] = 10; m_itemPackage.st_FBX_Monitor->setBracketClosePosition(pntOpen); m_itemPackage.st_FBX_Monitor->setBracketOpenPosition(pntOpen); m_itemPackage.st_FBX_Monitor->setHeadingPosition(headPos); m_itemPackage.st_FBX_Monitor->setMaskPosition(headPos); m_itemPackage.st_FBX_Monitor->setStatusPosition(statusPos); m_itemPackage.st_FBX_Monitor->setStartedPosition(startedPos); m_itemPackage.st_FBX_Monitor->setFinishedPosition(finishedPos); m_itemPackage.st_FBX_Monitor->setTerminatedPosition(terminatedPos); m_thtimer_initMonitor->start(); } void QmitkFiberThreadMonitorWorker::setThreadStatus(QString status) { m_itemPackage.st_FBX_Monitor->setStatus(status); m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } /* Methods to set status of running threads * Following three methods are usually called - before a thread starts and - a thread is finished or terminated */ void QmitkFiberThreadMonitorWorker::threadForFiberProcessingStarted() { if(!m_thtimer_threadStarted->isActive()) { m_thtimer_threadStarted->start(); } else { //fast change without fancy stuff, needed to keep threaddebugger info up to date int counter = m_itemPackage.st_FBX_Monitor->getStarted(); m_itemPackage.st_FBX_Monitor->setStarted(++counter); } } void QmitkFiberThreadMonitorWorker::threadForFiberProcessingFinished() { if(!m_thtimer_threadFinished->isActive()) { m_thtimer_threadFinished->start(); } else { //fast change without fancy stuff int counter = m_itemPackage.st_FBX_Monitor->getFinished(); m_itemPackage.st_FBX_Monitor->setFinished(++counter); } } void QmitkFiberThreadMonitorWorker::threadForFiberProcessingTerminated() { if(!m_thtimer_threadTerminated->isActive()) { m_thtimer_threadTerminated->start(); } else { //fast change without fancy stuff int counter = m_itemPackage.st_FBX_Monitor->getTerminated(); m_itemPackage.st_FBX_Monitor->setTerminated(++counter); } } /* Helper methods for fancy fading efx for thread monitor */ void QmitkFiberThreadMonitorWorker::fancyTextFading_threadStarted() { if (m_decreaseOpacity_threadStarted) { int startedOpacity = m_itemPackage.st_FBX_Monitor->getStartedOpacity(); m_itemPackage.st_FBX_Monitor->setStartedOpacity( --startedOpacity ); if (startedOpacity == 0) { int counter = m_itemPackage.st_FBX_Monitor->getStarted(); m_itemPackage.st_FBX_Monitor->setStarted(++counter); m_decreaseOpacity_threadStarted = false; } m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } else { int startedOpacity = m_itemPackage.st_FBX_Monitor->getStartedOpacity(); m_itemPackage.st_FBX_Monitor->setStartedOpacity( ++startedOpacity ); if (startedOpacity >= 10) { m_thtimer_threadStarted->stop(); m_decreaseOpacity_threadStarted = true; //set back to true, cuz next iteration shall decrease opacity as well } m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } } void QmitkFiberThreadMonitorWorker::fancyTextFading_threadFinished() { if (m_decreaseOpacity_threadFinished) { int finishedOpacity = m_itemPackage.st_FBX_Monitor->getFinishedOpacity(); m_itemPackage.st_FBX_Monitor->setFinishedOpacity( --finishedOpacity ); if (finishedOpacity == 0) { int counter = m_itemPackage.st_FBX_Monitor->getFinished(); m_itemPackage.st_FBX_Monitor->setFinished(++counter); m_decreaseOpacity_threadFinished = false; } m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } else { int finishedOpacity = m_itemPackage.st_FBX_Monitor->getFinishedOpacity(); m_itemPackage.st_FBX_Monitor->setFinishedOpacity( ++finishedOpacity ); if (finishedOpacity >= 10) { m_thtimer_threadFinished->stop(); m_decreaseOpacity_threadFinished = true; //set back to true, cuz next iteration shall decrease opacity as well } m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } } void QmitkFiberThreadMonitorWorker::fancyTextFading_threadTerminated() { if (m_decreaseOpacity_threadTerminated) { int terminatedOpacity = m_itemPackage.st_FBX_Monitor->getTerminatedOpacity(); m_itemPackage.st_FBX_Monitor->setTerminatedOpacity( --terminatedOpacity ); if (terminatedOpacity == 0) { int counter = m_itemPackage.st_FBX_Monitor->getTerminated(); m_itemPackage.st_FBX_Monitor->setTerminated(++counter); m_decreaseOpacity_threadTerminated = false; } m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } else { int terminatedOpacity = m_itemPackage.st_FBX_Monitor->getTerminatedOpacity(); m_itemPackage.st_FBX_Monitor->setTerminatedOpacity( ++terminatedOpacity ); if (terminatedOpacity >= 10) { m_thtimer_threadTerminated->stop(); m_decreaseOpacity_threadTerminated = true; //set back to true, cuz next iteration shall decrease opacity as well } m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } } void QmitkFiberThreadMonitorWorker::fancyMonitorInitialization() { mitk::Point2D pntClose = m_itemPackage.st_FBX_Monitor->getBracketClosePosition(); //possible bottleneck, set pntClose to member mitk::Point2D pntOpen = m_itemPackage.st_FBX_Monitor->getBracketOpenPosition(); //possible bottleneck, set pntClose to member pntClose[0] += m_pixelstepper; pntOpen[0] -= m_pixelstepper; //MITK_INFO << pntClose[0] << " " << pntOpen[0]; m_itemPackage.st_FBX_Monitor->setBracketClosePosition(pntClose); m_itemPackage.st_FBX_Monitor->setBracketOpenPosition(pntOpen); int opacity = m_itemPackage.st_FBX_Monitor->getHeadingOpacity() + 1; if (opacity > 10) opacity = 10; m_itemPackage.st_FBX_Monitor->setHeadingOpacity(opacity); if (pntClose[0] >= m_steppingDistance) { if (m_itemPackage.st_FBX_Monitor->getHeadingOpacity() != 10 ) { m_itemPackage.st_FBX_Monitor->setHeadingOpacity(10); m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } m_thtimer_initMonitor->stop(); //position them to obt y=25 m_thtimer_initMonitorSetFinalPosition->start(); } m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } void QmitkFiberThreadMonitorWorker::fancyMonitorInitializationFinalPos() { //get y pos of mitk::Point2D pntClose = m_itemPackage.st_FBX_Monitor->getBracketClosePosition(); mitk::Point2D pntOpen = m_itemPackage.st_FBX_Monitor->getBracketOpenPosition(); mitk::Point2D pntHead = m_itemPackage.st_FBX_Monitor->getHeadingPosition(); pntClose[1] += 5; pntOpen[1] += 5; pntHead[1] += 5; m_itemPackage.st_FBX_Monitor->setBracketClosePosition(pntClose); m_itemPackage.st_FBX_Monitor->setBracketOpenPosition(pntOpen); m_itemPackage.st_FBX_Monitor->setHeadingPosition(pntHead); if (pntClose[1] >= 35) { //35 = y position m_thtimer_initMonitorSetFinalPosition->stop(); //now init mask of labels m_thtimer_initMonitorSetMasks->start(); } m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } void QmitkFiberThreadMonitorWorker::fancyMonitorInitializationMask() { //increase opacity int opacity = m_itemPackage.st_FBX_Monitor->getMaskOpacity(); opacity++; m_itemPackage.st_FBX_Monitor->setMaskOpacity(opacity); m_itemPackage.st_FBX_Monitor->setStartedOpacity(opacity); m_itemPackage.st_FBX_Monitor->setFinishedOpacity(opacity); m_itemPackage.st_FBX_Monitor->setTerminatedOpacity(opacity); m_itemPackage.st_FBX_Monitor->setStatusOpacity(opacity); if (opacity >=10) { m_thtimer_initMonitorSetMasks->stop(); } m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } //============================================== //======== W O R K E R S ________ E N D ======== //============================================== //========#########################===============###########################=====================######################### //========#########################===============###########################=====================######################### //========#########################===============###########################=====================######################### //========#########################===============###########################=====================######################### //========#########################===============###########################=====================######################### // HERE STARTS THE ACTUAL FIBERBUNDLE DEVELOPER VIEW IMPLEMENTATION //========#########################===============###########################=====================######################### //========#########################===============###########################=====================######################### //========#########################===============###########################=====================######################### //========#########################===============###########################=====================######################### const std::string QmitkFiberBundleDeveloperView::VIEW_ID = "org.mitk.views.fiberbundledeveloper"; const std::string id_DataManager = "org.mitk.views.datamanager"; using namespace berry; QmitkFiberBundleDeveloperView::QmitkFiberBundleDeveloperView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) , m_FiberIDGenerator( NULL) , m_GeneratorFibersRandom( NULL ) + , m_FiberColoringSlave(NULL) + , m_FiberExtractor(NULL) , m_fiberMonitorIsOn( false ) , m_CircleCounter( 0 ) { m_hostThread = new QThread; m_threadInProgress = false; } // Destructor QmitkFiberBundleDeveloperView::~QmitkFiberBundleDeveloperView() { //m_FiberBundleX->Delete(); using weakPointer, therefore no delete necessary delete m_hostThread; if (m_FiberIDGenerator != NULL) delete m_FiberIDGenerator; -// if (m_GeneratorFibersRandom != NULL) -// delete m_GeneratorFibersRandom; + // if (m_GeneratorFibersRandom != NULL) + // delete m_GeneratorFibersRandom; } void QmitkFiberBundleDeveloperView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done in QtDesigner, etc. if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkFiberBundleDeveloperViewControls; m_Controls->setupUi( parent ); /*=========INITIALIZE BUTTON CONFIGURATION ================*/ m_Controls->radioButton_directionX->setEnabled(false); m_Controls->radioButton_directionY->setEnabled(false); m_Controls->radioButton_directionZ->setEnabled(false); m_Controls->buttonGenerateFiberIds->setEnabled(false); m_Controls->buttonGenerateFibers->setEnabled(true); m_Controls->buttonColorFibers->setEnabled(false); m_Controls->ddAvailableColorcodings->setEnabled(false); m_Controls->buttonExtractFibers->setEnabled(false); m_Controls->buttonSMFibers->setEnabled(false);//not yet implemented m_Controls->buttonVtkDecimatePro->setEnabled(false);//not yet implemented m_Controls->buttonVtkSmoothPD->setEnabled(false);//not yet implemented m_Controls->buttonGenerateTubes->setEnabled(false);//not yet implemented connect( m_Controls->buttonGenerateFibers, SIGNAL(clicked()), this, SLOT(DoGenerateFibers()) ); connect( m_Controls->buttonGenerateFiberIds, SIGNAL(pressed()), this, SLOT(DoGenerateFiberIDs()) ); connect( m_Controls->buttonExtractFibers, SIGNAL(clicked()), this, SLOT(DoExtractFibers()) ); connect( m_Controls->radioButton_directionRandom, SIGNAL(clicked()), this, SLOT(DoUpdateGenerateFibersWidget()) ); connect( m_Controls->radioButton_directionX, SIGNAL(clicked()), this, SLOT(DoUpdateGenerateFibersWidget()) ); connect( m_Controls->radioButton_directionY, SIGNAL(clicked()), this, SLOT(DoUpdateGenerateFibersWidget()) ); connect( m_Controls->radioButton_directionZ, SIGNAL(clicked()), this, SLOT(DoUpdateGenerateFibersWidget()) ); connect( m_Controls->toolBox, SIGNAL(currentChanged ( int ) ), this, SLOT(SelectionChangedToolBox(int)) ); connect( m_Controls->tabWidget, SIGNAL(currentChanged ( int ) ), this, SLOT(SelectionChangedToolBox(int)) ); //needed to update GUI elements when tab selection of fiberProcessing page changes connect( m_Controls->m_CircleButton, SIGNAL( clicked() ), this, SLOT( ActionDrawEllipseTriggered() ) ); connect( m_Controls->buttonColorFibers, SIGNAL(clicked()), this, SLOT(DoColorFibers()) ); connect( m_Controls->ddAvailableColorcodings, SIGNAL(currentIndexChanged(int)), this, SLOT(SetCurrentColorCoding(int) )); connect( m_Controls->checkBoxMonitorFiberThreads, SIGNAL(stateChanged(int)), this, SLOT(DoMonitorFiberThreads(int)) ); } // Checkpoint for fiber ORIENTATION if ( m_DirectionRadios.empty() ) { m_DirectionRadios.insert(0, m_Controls->radioButton_directionRandom); m_DirectionRadios.insert(1, m_Controls->radioButton_directionX); m_DirectionRadios.insert(2, m_Controls->radioButton_directionY); m_DirectionRadios.insert(3, m_Controls->radioButton_directionZ); } // set GUI elements of FiberGenerator to according configuration DoUpdateGenerateFibersWidget(); } /* THIS METHOD UPDATES ALL GUI ELEMENTS OF QGroupBox DEPENDING ON CURRENTLY SELECTED * RADIO BUTTONS */ void QmitkFiberBundleDeveloperView::DoUpdateGenerateFibersWidget() { //get selected radioButton QString fibDirection; //stores the object_name of selected radiobutton QVector::const_iterator i; for (i = m_DirectionRadios.begin(); i != m_DirectionRadios.end(); ++i) { QRadioButton* rdbtn = *i; if (rdbtn->isChecked()) fibDirection = rdbtn->objectName(); } if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_RANDOM ) { // disable radiobuttons if (m_Controls->boxFiberMinLength->isEnabled()) m_Controls->boxFiberMinLength->setEnabled(false); if (m_Controls->labelFiberMinLength->isEnabled()) m_Controls->labelFiberMinLength->setEnabled(false); if (m_Controls->boxFiberMaxLength->isEnabled()) m_Controls->boxFiberMaxLength->setEnabled(false); if (m_Controls->labelFiberMaxLength->isEnabled()) m_Controls->labelFiberMaxLength->setEnabled(false); //enable radiobuttons if (!m_Controls->labelFibersTotal->isEnabled()) m_Controls->labelFibersTotal->setEnabled(true); if (!m_Controls->boxFiberNumbers->isEnabled()) m_Controls->boxFiberNumbers->setEnabled(true); if (!m_Controls->labelDistrRadius->isEnabled()) m_Controls->labelDistrRadius->setEnabled(true); if (!m_Controls->boxDistributionRadius->isEnabled()) m_Controls->boxDistributionRadius->setEnabled(true); } else { // disable radiobuttons if (m_Controls->labelDistrRadius->isEnabled()) m_Controls->labelDistrRadius->setEnabled(false); if (m_Controls->boxDistributionRadius->isEnabled()) m_Controls->boxDistributionRadius->setEnabled(false); //enable radiobuttons if (!m_Controls->labelFibersTotal->isEnabled()) m_Controls->labelFibersTotal->setEnabled(true); if (!m_Controls->boxFiberNumbers->isEnabled()) m_Controls->boxFiberNumbers->setEnabled(true); if (!m_Controls->boxFiberMinLength->isEnabled()) m_Controls->boxFiberMinLength->setEnabled(true); if (!m_Controls->labelFiberMinLength->isEnabled()) m_Controls->labelFiberMinLength->setEnabled(true); if (!m_Controls->boxFiberMaxLength->isEnabled()) m_Controls->boxFiberMaxLength->setEnabled(true); if (!m_Controls->labelFiberMaxLength->isEnabled()) m_Controls->labelFiberMaxLength->setEnabled(true); } } void QmitkFiberBundleDeveloperView::DoGenerateFibers() { // GET SELECTED FIBER DIRECTION QString fibDirection; //stores the object_name of selected radiobutton QVector::const_iterator i; for (i = m_DirectionRadios.begin(); i != m_DirectionRadios.end(); ++i) { QRadioButton* rdbtn = *i; if (rdbtn->isChecked()) fibDirection = rdbtn->objectName(); } // vtkPolyData* output; // FiberPD stores the generated PolyData... going to be generated in thread if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_RANDOM ) { // build polydata with random lines and fibers // output = GenerateVtkFibersRandom(); } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_X ) { // build polydata with XDirection fibers //output = GenerateVtkFibersDirectionX(); } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_Y ) { // build polydata with YDirection fibers // output = GenerateVtkFibersDirectionY(); } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_Z ) { // build polydata with ZDirection fibers // output = GenerateVtkFibersDirectionZ(); } } void QmitkFiberBundleDeveloperView::DoExtractFibers() { /* ===== TIMER CONFIGURATIONS for visual effect ====== * start and stop is called in Thread */ QTimer *localTimer = new QTimer; // timer must be initialized here, otherwise timer is not fancy enough localTimer->setInterval( 10 ); connect( localTimer, SIGNAL(timeout()), this, SLOT( UpdateExtractFibersTimer()) ); struct Package4WorkingThread ItemPackageForExtractor; ItemPackageForExtractor.st_FBX = m_FiberBundleX; ItemPackageForExtractor.st_Controls = m_Controls; ItemPackageForExtractor.st_FancyGUITimer1 = localTimer; ItemPackageForExtractor.st_host = this; //needed to access method "PutFibersToDataStorage()" ItemPackageForExtractor.st_pntr_to_Method_PutFibersToDataStorage = &QmitkFiberBundleDeveloperView::PutFibersToDataStorage; //actual functor calling method putFibersToDataStorage ItemPackageForExtractor.st_PlanarFigure = m_PlanarFigure; //set element for thread monitoring if (m_fiberMonitorIsOn) ItemPackageForExtractor.st_fiberThreadMonitorWorker = m_fiberThreadMonitorWorker; if (m_threadInProgress) return; //maybe popup window saying, working thread still in progress...pls wait m_FiberExtractor = new QmitkFiberExtractorWorker(m_hostThread, ItemPackageForExtractor); m_FiberExtractor->moveToThread(m_hostThread); //connections connect(m_hostThread, SIGNAL(started()), this, SLOT( BeforeThread_FiberExtraction() )); connect(m_hostThread, SIGNAL(started()), m_FiberExtractor, SLOT( run() )); connect(m_hostThread, SIGNAL(finished()), this, SLOT( AfterThread_FiberExtraction() )); connect(m_hostThread, SIGNAL(terminated()), this, SLOT( AfterThread_FiberExtraction() )); m_hostThread->start(QThread::HighestPriority) ; } void QmitkFiberBundleDeveloperView::UpdateExtractFibersTimer() { // Make sure that thread has set according info-label to number! here we do not check if value is numeric! shall be done in beforeThreadstarted() QString crntValue = m_Controls->infoTimerExtractFibers->text(); int tmpVal = crntValue.toInt(); m_Controls->infoTimerExtractFibers->setText(QString::number(++tmpVal)); m_Controls->infoTimerExtractFibers->update(); } void QmitkFiberBundleDeveloperView::BeforeThread_FiberExtraction() { m_threadInProgress = true; if (m_fiberMonitorIsOn){ m_fiberThreadMonitorWorker->threadForFiberProcessingStarted(); //m_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_STARTED); } } void QmitkFiberBundleDeveloperView::AfterThread_FiberExtraction() { m_threadInProgress = false; if (m_fiberMonitorIsOn){ m_fiberThreadMonitorWorker->threadForFiberProcessingFinished(); m_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_IDLE); } -// disconnect(m_hostThread, 0, 0, 0); + // disconnect(m_hostThread, 0, 0, 0); m_hostThread->disconnect(); -// m_FiberExtractor->disconnect(); + // m_FiberExtractor->disconnect(); delete m_FiberExtractor; + m_FiberBundleNode->Modified(); + m_MultiWidget->RequestUpdate(); + } void QmitkFiberBundleDeveloperView::PutFibersToDataStorage( vtkSmartPointer threadOutput) { MITK_INFO << "lines: " << threadOutput->GetNumberOfLines() << "pnts: " << threadOutput->GetNumberOfPoints(); //qthread mutex lock mitk::FiberBundleX::Pointer FB = mitk::FiberBundleX::New(threadOutput); mitk::DataNode::Pointer FBNode; FBNode = mitk::DataNode::New(); FBNode->SetName("FiberBundleX"); FBNode->SetData(FB); FBNode->SetVisibility(true); GetDataStorage()->Add(FBNode); - //output->Delete(); + FBNode->Modified(); const mitk::PlaneGeometry * tsgeo = m_MultiWidget->GetTimeNavigationController()->GetCurrentPlaneGeometry(); if (tsgeo == NULL) { /* GetDataStorage()->Modified etc. have no effect, therefore proceed as followed below */ // get all nodes that have not set "includeInBoundingBox" to false mitk::NodePredicateNot::Pointer pred = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("includeInBoundingBox" , mitk::BoolProperty::New(false))); mitk::DataStorage::SetOfObjects::ConstPointer rs = GetDataStorage()->GetSubset(pred); // calculate bounding geometry of these nodes mitk::TimeSlicedGeometry::Pointer bounds = GetDataStorage()->ComputeBoundingGeometry3D(rs); // initialize the views to the bounding geometry mitk::RenderingManager::GetInstance()->InitializeViews(bounds); } else { GetDataStorage()->Modified(); m_MultiWidget->RequestUpdate(); //necessary?? } //qthread mutex unlock } void QmitkFiberBundleDeveloperView::PutFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name) { mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetName(name.toStdString()); newNode->SetData(figure); std::vector selectedNodes = GetDataManagerSelection(); for(unsigned int i = 0; i < selectedNodes.size(); i++) { selectedNodes[i]->SetSelected(false); } newNode->SetSelected(true); newNode->AddProperty( "planarfigure.default.line.color", mitk::ColorProperty::New(1.0,0.0,0.0)); newNode->AddProperty( "planarfigure.line.width", mitk::FloatProperty::New(2.0)); newNode->AddProperty( "planarfigure.drawshadow", mitk::BoolProperty::New(true)); newNode->AddProperty( "selected", mitk::BoolProperty::New(true) ); newNode->AddProperty( "planarfigure.ishovering", mitk::BoolProperty::New(true) ); newNode->AddProperty( "planarfigure.drawoutline", mitk::BoolProperty::New(true) ); newNode->AddProperty( "planarfigure.drawquantities", mitk::BoolProperty::New(false) ); newNode->AddProperty( "planarfigure.drawshadow", mitk::BoolProperty::New(true) ); newNode->AddProperty( "planarfigure.line.width", mitk::FloatProperty::New(3.0) ); newNode->AddProperty( "planarfigure.shadow.widthmodifier", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.outline.width", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.helperline.width", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.default.line.color", mitk::ColorProperty::New(1.0,1.0,1.0) ); newNode->AddProperty( "planarfigure.default.line.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.default.outline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.default.outline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.default.helperline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.default.helperline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.default.markerline.color", mitk::ColorProperty::New(0.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.default.markerline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.default.marker.color", mitk::ColorProperty::New(1.0,1.0,1.0) ); newNode->AddProperty( "planarfigure.default.marker.opacity",mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.hover.line.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.hover.line.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.hover.outline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.hover.outline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.hover.helperline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.hover.helperline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.hover.markerline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.hover.markerline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.hover.marker.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.hover.marker.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.selected.line.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.selected.line.opacity",mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.selected.outline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.selected.outline.opacity", mitk::FloatProperty::New(2.0)); newNode->AddProperty( "planarfigure.selected.helperline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.selected.helperline.opacity",mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.selected.markerline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.selected.markerline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.selected.marker.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.selected.marker.opacity",mitk::FloatProperty::New(2.0)); // figure drawn on the topmost layer / image this->GetDataStorage()->Add(newNode); } /* * Generate polydata of random fibers */ void QmitkFiberBundleDeveloperView::GenerateVtkFibersRandom() { /* ===== TIMER CONFIGURATIONS for visual effect ====== * start and stop is called in Thread */ QTimer *localTimer = new QTimer; // timer must be initialized here, otherwise timer is not fancy enough localTimer->setInterval( 10 ); connect( localTimer, SIGNAL(timeout()), this, SLOT(UpdateGenerateRandomFibersTimer()) ); struct Package4WorkingThread ItemPackageForRandomGenerator; ItemPackageForRandomGenerator.st_FBX = m_FiberBundleX; ItemPackageForRandomGenerator.st_Controls = m_Controls; ItemPackageForRandomGenerator.st_FancyGUITimer1 = localTimer; ItemPackageForRandomGenerator.st_host = this; //needed to access method "PutFibersToDataStorage()" ItemPackageForRandomGenerator.st_pntr_to_Method_PutFibersToDataStorage = &QmitkFiberBundleDeveloperView::PutFibersToDataStorage; //actual functor calling method putFibersToDataStorage //set element for thread monitoring if (m_fiberMonitorIsOn) ItemPackageForRandomGenerator.st_fiberThreadMonitorWorker = m_fiberThreadMonitorWorker; if (m_threadInProgress) return; //maybe popup window saying, working thread still in progress...pls wait m_GeneratorFibersRandom = new QmitkFiberGenerateRandomWorker(m_hostThread, ItemPackageForRandomGenerator); m_GeneratorFibersRandom->moveToThread(m_hostThread); connect(m_hostThread, SIGNAL(started()), this, SLOT( BeforeThread_GenerateFibersRandom()) ); connect(m_hostThread, SIGNAL(started()), m_GeneratorFibersRandom, SLOT(run()) ); connect(m_hostThread, SIGNAL(finished()), this, SLOT(AfterThread_GenerateFibersRandom()) ); connect(m_hostThread, SIGNAL(terminated()), this, SLOT(AfterThread_GenerateFibersRandom()) ); m_hostThread->start(QThread::LowestPriority); } void QmitkFiberBundleDeveloperView::UpdateColorFibersTimer() { // Make sure that thread has set according info-label to number! here we do not check if value is numeric! QString crntValue = m_Controls->infoTimerColorCoding->text(); int tmpVal = crntValue.toInt(); m_Controls->infoTimerColorCoding->setText(QString::number(++tmpVal)); m_Controls->infoTimerColorCoding->update(); } void QmitkFiberBundleDeveloperView::UpdateGenerateRandomFibersTimer() { // Make sure that thread has set according info-label to number! here we do not check if value is numeric! QString crntValue = m_Controls->infoTimerGenerateFiberBundle->text(); int tmpVal = crntValue.toInt(); m_Controls->infoTimerGenerateFiberBundle->setText(QString::number(++tmpVal)); m_Controls->infoTimerGenerateFiberBundle->update(); } void QmitkFiberBundleDeveloperView::BeforeThread_GenerateFibersRandom() { m_threadInProgress = true; if (m_fiberMonitorIsOn){ m_fiberThreadMonitorWorker->threadForFiberProcessingStarted(); //m_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_STARTED); } } void QmitkFiberBundleDeveloperView::AfterThread_GenerateFibersRandom() { m_threadInProgress = false; if (m_fiberMonitorIsOn){ m_fiberThreadMonitorWorker->threadForFiberProcessingFinished(); m_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_IDLE); } -// disconnect(m_hostThread, 0, 0, 0); + // disconnect(m_hostThread, 0, 0, 0); m_hostThread->disconnect(); delete m_GeneratorFibersRandom; } vtkSmartPointer QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionX() { int numOfFibers = m_Controls->boxFiberNumbers->value(); vtkSmartPointer linesCell = vtkSmartPointer::New(); vtkSmartPointer points = vtkSmartPointer::New(); //insert Origin point, this point has index 0 in point array double originX = 0.0; double originY = 0.0; double originZ = 0.0; //after each iteration the origin of the new fiber increases //here you set which direction is affected. double increaseX = 0.0; double increaseY = 1.0; double increaseZ = 0.0; //walk along X axis //length of fibers increases in each iteration for (int i=0; i newFiber = vtkSmartPointer::New(); newFiber->GetPointIds()->SetNumberOfIds(i+2); //create starting point and add it to pointset points->InsertNextPoint(originX + (double)i * increaseX , originY + (double)i * increaseY, originZ + (double)i * increaseZ); //add starting point to fiber newFiber->GetPointIds()->SetId(0,points->GetNumberOfPoints()-1); //insert remaining points for fiber for (int pj=0; pj<=i ; ++pj) { //generate next point on X axis points->InsertNextPoint( originX + (double)pj+1 , originY + (double)i * increaseY, originZ + (double)i * increaseZ ); newFiber->GetPointIds()->SetId(pj+1,points->GetNumberOfPoints()-1); } linesCell->InsertNextCell(newFiber); } vtkSmartPointer PDX = vtkSmartPointer::New(); PDX->SetPoints(points); PDX->SetLines(linesCell); return PDX; } vtkSmartPointer QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionY() { vtkSmartPointer PDY = vtkSmartPointer::New(); //todo return PDY; } vtkSmartPointer QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionZ() { vtkSmartPointer PDZ = vtkSmartPointer::New(); //todo return PDZ; } void QmitkFiberBundleDeveloperView::DoColorFibers() { // MITK_INFO << "call fibercoloring in fiberBundleX"; QTimer *localTimer = new QTimer; // timer must be initialized here, otherwise timer is not fancy enough localTimer->setInterval( 10 ); connect( localTimer, SIGNAL(timeout()), this, SLOT( UpdateColorFibersTimer() ) ); // pack items which are needed by thread processing struct Package4WorkingThread ItemPackageForFiberColoring; ItemPackageForFiberColoring.st_FBX = m_FiberBundleX; ItemPackageForFiberColoring.st_FancyGUITimer1 = localTimer; ItemPackageForFiberColoring.st_Controls = m_Controls; //needed to catch up some selections and set options in GUI if (m_fiberMonitorIsOn) ItemPackageForFiberColoring.st_fiberThreadMonitorWorker = m_fiberThreadMonitorWorker; if (m_threadInProgress) return; //maybe popup window saying, working thread still in progress...pls wait m_FiberColoringSlave = new QmitkFiberColoringWorker(m_hostThread, ItemPackageForFiberColoring); m_FiberColoringSlave->moveToThread(m_hostThread); connect(m_hostThread, SIGNAL(started()), this, SLOT( BeforeThread_FiberColorCoding()) ); connect(m_hostThread, SIGNAL(started()), m_FiberColoringSlave, SLOT(run()) ); connect(m_hostThread, SIGNAL(finished()), this, SLOT(AfterThread_FiberColorCoding())); connect(m_hostThread, SIGNAL(terminated()), this, SLOT(AfterThread_FiberColorCoding())); m_hostThread->start(QThread::LowestPriority); } void QmitkFiberBundleDeveloperView::BeforeThread_FiberColorCoding() { m_threadInProgress = true; if (m_fiberMonitorIsOn){ m_fiberThreadMonitorWorker->threadForFiberProcessingStarted(); } } void QmitkFiberBundleDeveloperView::AfterThread_FiberColorCoding() { m_threadInProgress = false; if (m_fiberMonitorIsOn){ m_fiberThreadMonitorWorker->threadForFiberProcessingFinished(); m_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_IDLE); } disconnect(m_hostThread, 0, 0, 0); m_hostThread->disconnect(); //update renderer + m_FiberBundleNode->Modified(); m_MultiWidget->RequestUpdate(); //update QComboBox(dropDown menu) in view of available ColorCodings DoGatherColorCodings(); + + delete m_FiberColoringSlave; } void QmitkFiberBundleDeveloperView::DoGatherColorCodings() { QStringList fbxColorCodings = m_FiberBundleX->GetAvailableColorCodings(); //update dropDown Menu //remove all items from menu int ddItems = m_Controls->ddAvailableColorcodings->count(); for(int i=ddItems-1; i>=0; i--) { //note, after each item remove, index in QComboBox is updated, therefore we start from the back which causes less update calculation m_Controls->ddAvailableColorcodings->removeItem(i); } //fill new data into menu m_Controls->ddAvailableColorcodings->addItem("---"); m_Controls->ddAvailableColorcodings->addItems(fbxColorCodings); //highlight current colorcoding QString cc = m_FiberBundleX->GetCurrentColorCoding(); MITK_INFO << "current idx: " << m_Controls->ddAvailableColorcodings->findText(cc); m_Controls->ddAvailableColorcodings->setCurrentIndex( m_Controls->ddAvailableColorcodings->findText(cc) ); } void QmitkFiberBundleDeveloperView::SetCurrentColorCoding(int idx) { QString selectedColorCoding = m_Controls->ddAvailableColorcodings->itemText(idx); m_FiberBundleX->SetColorCoding(selectedColorCoding.toStdString().c_str() ); //QString to char // update rendering m_MultiWidget->RequestUpdate(); } /* === OutSourcedMethod: THIS METHOD GENERATES ESSENTIAL GEOMETRY PARAMETERS FOR THE MITK FRAMEWORK === * WITHOUT, the rendering mechanism will ignore objects without valid Geometry * for each object, MITK requires: ORIGIN, SPACING, TRANSFORM MATRIX, BOUNDING-BOX */ mitk::Geometry3D::Pointer QmitkFiberBundleDeveloperView::GenerateStandardGeometryForMITK() { mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); // generate origin mitk::Point3D origin; origin[0] = 0; origin[1] = 0; origin[2] = 0; geometry->SetOrigin(origin); // generate spacing float spacing[3] = {1,1,1}; geometry->SetSpacing(spacing); // generate identity transform-matrix vtkSmartPointer m = vtkMatrix4x4::New(); geometry->SetIndexToWorldTransformByVtkMatrix(m); // generate boundingbox // for an usable bounding-box use gui parameters to estimate the boundingbox float bounds[] = {500, 500, 500, -500, -500, -500}; // GET SELECTED FIBER DIRECTION QString fibDirection; //stores the object_name of selected radiobutton QVector::const_iterator i; for (i = m_DirectionRadios.begin(); i != m_DirectionRadios.end(); ++i) { QRadioButton* rdbtn = *i; if (rdbtn->isChecked()) fibDirection = rdbtn->objectName(); } if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_RANDOM ) { // use information about distribution parameter to calculate bounding box int distrRadius = m_Controls->boxDistributionRadius->value(); bounds[0] = distrRadius; bounds[1] = distrRadius; bounds[2] = distrRadius; bounds[3] = -distrRadius; bounds[4] = -distrRadius; bounds[5] = -distrRadius; } else { // so far only X,Y,Z directions are available MITK_INFO << "_______GEOMETRY ISSUE_____\n***BoundingBox for X, Y, Z fiber directions are not optimized yet!***"; int maxFibLength = m_Controls->boxFiberMaxLength->value(); bounds[0] = maxFibLength; bounds[1] = maxFibLength; bounds[2] = maxFibLength; bounds[3] = -maxFibLength; bounds[4] = -maxFibLength; bounds[5] = -maxFibLength; } geometry->SetFloatBounds(bounds); geometry->SetImageGeometry(true); //?? return geometry; } void QmitkFiberBundleDeveloperView::UpdateFiberIDTimer() { //MAKE SURE by yourself THAT NOTHING ELSE THAN A NUMBER IS SET IN THAT LABEL QString crntValue = m_Controls->infoTimerGenerateFiberIds->text(); int tmpVal = crntValue.toInt(); m_Controls->infoTimerGenerateFiberIds->setText(QString::number(++tmpVal)); m_Controls->infoTimerGenerateFiberIds->update(); } /* Initialie ID dataset in FiberBundleX */ void QmitkFiberBundleDeveloperView::DoGenerateFiberIDs() { /* ===== TIMER CONFIGURATIONS for visual effect ====== * start and stop is called in Thread */ QTimer *localTimer = new QTimer; // timer must be initialized here, otherwise timer is not fancy enough localTimer->setInterval( 10 ); connect( localTimer, SIGNAL(timeout()), this, SLOT(UpdateFiberIDTimer()) ); // pack items which are needed by thread processing struct Package4WorkingThread FiberIdPackage; FiberIdPackage.st_FBX = m_FiberBundleX; FiberIdPackage.st_FancyGUITimer1 = localTimer; FiberIdPackage.st_Controls = m_Controls; //set element for thread monitoring if (m_fiberMonitorIsOn) FiberIdPackage.st_fiberThreadMonitorWorker = m_fiberThreadMonitorWorker; if (m_threadInProgress) return; //maybe popup window saying, working thread still in progress...pls wait // THREAD CONFIGURATION m_FiberIDGenerator = new QmitkFiberIDWorker(m_hostThread, FiberIdPackage); m_FiberIDGenerator->moveToThread(m_hostThread); connect(m_hostThread, SIGNAL(started()), this, SLOT( BeforeThread_IdGenerate()) ); connect(m_hostThread, SIGNAL(started()), m_FiberIDGenerator, SLOT(run())); connect(m_hostThread, SIGNAL(finished()), this, SLOT(AfterThread_IdGenerate())); connect(m_hostThread, SIGNAL(terminated()), this, SLOT(AfterThread_IdGenerate())); m_hostThread->start(QThread::LowestPriority); // m_Controls->infoTimerGenerateFiberIds->setText(QString::number(clock.GetTotal())); } void QmitkFiberBundleDeveloperView::BeforeThread_IdGenerate() { m_threadInProgress = true; if (m_fiberMonitorIsOn){ m_fiberThreadMonitorWorker->threadForFiberProcessingStarted(); m_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_STARTED); } } void QmitkFiberBundleDeveloperView::AfterThread_IdGenerate() { m_threadInProgress = false; if (m_fiberMonitorIsOn){ m_fiberThreadMonitorWorker->threadForFiberProcessingFinished(); m_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_IDLE); } disconnect(m_hostThread, 0, 0, 0); m_hostThread->disconnect(); + delete m_FiberIDGenerator; } void QmitkFiberBundleDeveloperView::ResetFiberInfoWidget() { if (m_Controls->infoAnalyseNumOfFibers->isEnabled()) { m_Controls->infoAnalyseNumOfFibers->setText("-"); m_Controls->infoAnalyseNumOfPoints->setText("-"); m_Controls->infoAnalyseNumOfFibers->setEnabled(false); } } void QmitkFiberBundleDeveloperView::FeedFiberInfoWidget() { if (!m_Controls->infoAnalyseNumOfFibers->isEnabled()) m_Controls->infoAnalyseNumOfFibers->setEnabled(true); QString numOfFibers; numOfFibers.setNum( m_FiberBundleX->GetFiberPolyData()->GetNumberOfLines() ); QString numOfPoints; numOfPoints.setNum( m_FiberBundleX->GetFiberPolyData()->GetNumberOfPoints() ); m_Controls->infoAnalyseNumOfFibers->setText( numOfFibers ); m_Controls->infoAnalyseNumOfPoints->setText( numOfPoints ); } void QmitkFiberBundleDeveloperView::SelectionChangedToolBox(int idx) { // show/reset items of selected toolbox page FiberInfo if (m_Controls->page_FiberInfo->isVisible()) { if (m_FiberBundleX != NULL) { FeedFiberInfoWidget(); } else { //if infolables are disabled: return //else set info back to - and set label and info to disabled ResetFiberInfoWidget(); } } // show/reset items of selected toolbox page FiberProcessing if (m_Controls->page_FiberProcessing->isVisible()) { if (m_FiberBundleX.IsNotNull() && m_PlanarFigure.IsNotNull() ) { //show fiber extraction button m_Controls->buttonExtractFibers->setEnabled(true); } else { m_Controls->buttonExtractFibers->setEnabled(false); } if (m_FiberBundleX.IsNotNull()) { if (m_Controls->tabColoring->isVisible()){ //show button colorCoding m_Controls->buttonColorFibers->setEnabled(true); m_Controls->ddAvailableColorcodings->setEnabled(true); MITK_INFO << "Color"; }else if(m_Controls->tabCutting->isVisible()){ m_Controls->buttonGenerateFiberIds->setEnabled(true); }else if(m_Controls->tabShape->isVisible()){ // m_Controls->buttonSMFibers->setEnabled(true); // m_Controls->buttonVtkDecimatePro->setEnabled(true); // m_Controls->buttonVtkSmoothPD->setEnabled(true); // m_Controls->buttonGenerateTubes->setEnabled(true); } } else { m_Controls->buttonColorFibers->setEnabled(false); m_Controls->ddAvailableColorcodings->setEnabled(false); m_Controls->buttonGenerateFiberIds->setEnabled(false); m_Controls->buttonSMFibers->setEnabled(false); m_Controls->buttonVtkDecimatePro->setEnabled(false); m_Controls->buttonVtkSmoothPD->setEnabled(false); m_Controls->buttonGenerateTubes->setEnabled(true); } } } void QmitkFiberBundleDeveloperView::FBXDependendGUIElementsConfigurator() { // ==== FIBER PROCESSING ELEMENTS and ALL ELEMENTS WHICH NEED A FBX DATANODE====== // m_Controls->buttonGenerateFiberIds->setEnabled(isVisible); moved to selectionChangedToolBox SelectionChangedToolBox(-1); //set gui elements with respect to active tab, widget, etc. -1 has no effect } void QmitkFiberBundleDeveloperView::DoMonitorFiberThreads(int checkStatus) { //check if in datanode exists already a node of type mitkFiberBundleXThreadMonitor //if not then put node to datastorage //if checkStatus is 1 then start qtimer using fading in starting text in datanode //if checkStatus is 0 then fade out dataNode using qtimer if (checkStatus) { m_fiberMonitorIsOn = true; // Generate Node hosting thread information mitk::FiberBundleXThreadMonitor::Pointer FBXThreadMonitor = mitk::FiberBundleXThreadMonitor::New(); FBXThreadMonitor->SetGeometry(this->GenerateStandardGeometryForMITK()); m_MonitorNode = mitk::DataNode::New(); m_MonitorNode->SetName("FBX_threadMonitor"); m_MonitorNode->SetData(FBXThreadMonitor); m_MonitorNode->SetVisibility(true); m_MonitorNode->SetOpacity(1.0); GetDataStorage()->Add(m_MonitorNode); //following code is needed for rendering text in mitk! without geometry nothing is rendered const mitk::PlaneGeometry * tsgeo = m_MultiWidget->GetTimeNavigationController()->GetCurrentPlaneGeometry(); if (tsgeo == NULL) { /* GetDataStorage()->Modified etc. have no effect, therefore proceed as followed below */ // get all nodes that have not set "includeInBoundingBox" to false mitk::NodePredicateNot::Pointer pred = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New( "includeInBoundingBox" , mitk::BoolProperty::New(false))); mitk::DataStorage::SetOfObjects::ConstPointer rs = GetDataStorage()->GetSubset(pred); // calculate bounding geometry of these nodes mitk::TimeSlicedGeometry::Pointer bounds = GetDataStorage()->ComputeBoundingGeometry3D(rs); // initialize the views to the bounding geometry mitk::RenderingManager::GetInstance()->InitializeViews(bounds); } else { GetDataStorage()->Modified(); m_MultiWidget->RequestUpdate(); //necessary?? } //__GEOMETRY FOR THREADMONITOR GENERATED /* ====== initialize thread for managing fiberThread information ========= */ m_monitorThread = new QThread; // the package needs datastorage, MonitorDatanode, standardmultiwidget, struct Package4WorkingThread ItemPackageForThreadMonitor; ItemPackageForThreadMonitor.st_DataStorage = GetDataStorage(); ItemPackageForThreadMonitor.st_ThreadMonitorDataNode = m_MonitorNode; ItemPackageForThreadMonitor.st_MultiWidget = m_MultiWidget; ItemPackageForThreadMonitor.st_FBX_Monitor = FBXThreadMonitor; m_fiberThreadMonitorWorker = new QmitkFiberThreadMonitorWorker(m_monitorThread, ItemPackageForThreadMonitor); m_fiberThreadMonitorWorker->moveToThread(m_monitorThread); connect ( m_monitorThread, SIGNAL( started() ), m_fiberThreadMonitorWorker, SLOT( run() ) ); m_monitorThread->start(QThread::LowestPriority); m_fiberThreadMonitorWorker->initializeMonitor();//do some init animation ;-) } else { m_fiberMonitorIsOn = false; m_monitorThread->quit(); //think about outsourcing following lines to quit / terminate slot of thread GetDataStorage()->Remove(m_MonitorNode); GetDataStorage()->Modified(); m_MultiWidget->RequestUpdate(); //necessary?? } } void QmitkFiberBundleDeveloperView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkFiberBundleDeveloperView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } /* OnSelectionChanged is registered to SelectionService, therefore no need to implement SelectionService Listener explicitly */ void QmitkFiberBundleDeveloperView::OnSelectionChanged( std::vector nodes ) { if (nodes.empty()) return; /* ==== reset everyhing related to FiberBundleX ====== * - variable m_FiberBundleX * - visualization of analysed fiberbundle */ + m_FiberBundleNode = NULL; m_FiberBundleX = NULL; //reset pointer, so that member does not point to depricated locations m_PlanarFigure = NULL; ResetFiberInfoWidget(); //timer reset only when no thread is in progress if (!m_threadInProgress) { m_Controls->infoTimerGenerateFiberIds->setText("-"); //set GUI representation of timer to - m_Controls->infoTimerGenerateFiberBundle->setText( "-" ); m_Controls->infoTimerColorCoding->setText( "-" ); } //==================================================== for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; /* CHECKPOINT: FIBERBUNDLE*/ if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { + m_FiberBundleNode = node; m_FiberBundleX = dynamic_cast(node->GetData()); - if (m_FiberBundleX.IsNull()) + if (m_FiberBundleX.IsNull()){ MITK_INFO << "========ATTENTION=========\n unable to load selected FiberBundleX to FiberBundleDeveloper-plugin \n"; - + m_FiberBundleNode = NULL; + } // ==== FIBERBUNDLE_INFO ELEMENTS ==== if ( m_Controls->page_FiberInfo->isVisible() ) FeedFiberInfoWidget(); // enable FiberBundleX related Gui Elements, such as buttons etc. FBXDependendGUIElementsConfigurator(); } /* CHECKPOINT: PLANARFIGURE */ else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_PlanarFigure = dynamic_cast(node->GetData()); MITK_INFO << "PF selected"; if (m_PlanarFigure.IsNull()) MITK_INFO << "========ATTENTION=========\n unable to load selected Planarfigure to FiberBundleDeveloper-plugin \n"; } } //update gui elements depending on given nodes FBXDependendGUIElementsConfigurator(); //every gui element which needs a FBX for processing is disabled } void QmitkFiberBundleDeveloperView::ActionDrawEllipseTriggered() { // bool checked = m_Controls->m_CircleButton->isChecked(); mitk::PlanarCircle::Pointer figure = mitk::PlanarCircle::New(); this->PutFigureToDataStorage(figure, QString("Circle%1").arg(++m_CircleCounter)); MITK_INFO << "PlanarCircle created ..."; mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = this->GetDefaultDataStorage()->GetAll(); mitk::DataNode* node = 0; mitk::PlanarFigureInteractor::Pointer figureInteractor = 0; mitk::PlanarFigure* figureP = 0; for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End() ; it++) { node = const_cast(it->Value().GetPointer()); figureP = dynamic_cast(node->GetData()); if(figureP) { figureInteractor = dynamic_cast(node->GetInteractor()); if(figureInteractor.IsNull()) figureInteractor = mitk::PlanarFigureInteractor::New("PlanarFigureInteractor", node); mitk::GlobalInteraction::GetInstance()->AddInteractor(figureInteractor); } } } void QmitkFiberBundleDeveloperView::Activated() { MITK_INFO << "FB DevelopersV ACTIVATED()"; } diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.h b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.h index 9eea682eb5..490a0cd5ef 100644 --- a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.h +++ b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.h @@ -1,350 +1,351 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $ Version: $Revision: 21975 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef QmitkFiberBundleDeveloperView_h #define QmitkFiberBundleDeveloperView_h #include #include #include #include "ui_QmitkFiberBundleDeveloperViewControls.h" #include #include #include #include // Qt #include #include #include // VTK #include #include #include #include #include #include class QmitkFiberThreadMonitorWorker; //include needed for struct element class QmitkFiberBundleDeveloperView; //this include is needed for the struct element, especially for functors to QmitkFiberBundleDeveloperView /* ==== THIS STRUCT CONTAINS ALL NECESSARY VARIABLES * TO EXECUTE AND UPDATE GUI ELEMENTS DURING PROCESSING OF A THREAD * why? either you add tons of friendclasses (e.g. FiberWorker objects), or you create a package containing all items needed. Otherwise you have to set all members etc. to public! */ struct Package4WorkingThread { mitk::FiberBundleX* st_FBX; QTimer* st_FancyGUITimer1; Ui::QmitkFiberBundleDeveloperViewControls* st_Controls; //functors to outdoor methods QmitkFiberBundleDeveloperView* st_host; void (QmitkFiberBundleDeveloperView::*st_pntr_to_Method_PutFibersToDataStorage) (vtkSmartPointer); //==DO NOT TOUCH THIS SECTION=== you might extend this section, but do NOT shorten it! hai capito! //host MITK I/O elements, especially needed for thread monitoring QmitkFiberThreadMonitorWorker *st_fiberThreadMonitorWorker; mitk::FiberBundleXThreadMonitor::Pointer st_FBX_Monitor; //needed for direct access do animation/fancy methods mitk::DataNode::Pointer st_ThreadMonitorDataNode; //needed for renderer to recognize node modifications mitk::DataStorage::Pointer st_DataStorage; //well that is discussable if needed ;-) probably not QmitkStdMultiWidget* st_MultiWidget; //needed for rendering update mitk::PlanarFigure::Pointer st_PlanarFigure; //needed for fiberextraction }; // ==================================================================== // ============= WORKER WHICH IS PASSED TO THREAD ===================== // ==================================================================== //## Documentation //## This class does the actual work for generating fiber ids. class QmitkFiberIDWorker : public QObject { Q_OBJECT public: QmitkFiberIDWorker( QThread*, Package4WorkingThread ); public slots: void run(); private: Package4WorkingThread m_itemPackage; QThread* m_hostingThread; }; // ==================================================================== // ============= WORKER WHICH IS PASSED TO THREAD ===================== // ==================================================================== //## Documentation //## This class does the actual work for colorcoding fibers. class QmitkFiberColoringWorker : public QObject { Q_OBJECT public: QmitkFiberColoringWorker( QThread*, Package4WorkingThread ); public slots: void run(); private: Package4WorkingThread m_itemPackage; QThread* m_hostingThread; }; // ==================================================================== // ============= WORKER WHICH IS PASSED TO THREAD ===================== // ==================================================================== class QmitkFiberGenerateRandomWorker : public QObject { Q_OBJECT public: QmitkFiberGenerateRandomWorker( QThread*, Package4WorkingThread ); public slots: void run(); private: Package4WorkingThread m_itemPackage; QThread* m_hostingThread; }; // ==================================================================== // ============= WORKER WHICH IS PASSED TO THREAD ===================== // ==================================================================== class QmitkFiberExtractorWorker : public QObject { Q_OBJECT public: QmitkFiberExtractorWorker( QThread*, Package4WorkingThread ); public slots: void run(); private: Package4WorkingThread m_itemPackage; QThread* m_hostingThread; }; // ==================================================================== // ============= WORKER WHICH IS PASSED TO THREAD ===================== // ==================================================================== class QmitkFiberThreadMonitorWorker : public QObject { Q_OBJECT public: QmitkFiberThreadMonitorWorker( QThread*, Package4WorkingThread ); void initializeMonitor(); void threadForFiberProcessingStarted(); void threadForFiberProcessingFinished(); void threadForFiberProcessingTerminated(); void setThreadStatus(QString); public slots: void run(); void fancyMonitorInitialization(); void fancyMonitorInitializationFinalPos(); void fancyMonitorInitializationMask(); void fancyTextFading_threadStarted(); void fancyTextFading_threadFinished(); void fancyTextFading_threadTerminated(); private: Package4WorkingThread m_itemPackage; QThread* m_hostingThread; QTimer* m_thtimer_initMonitor; QTimer* m_thtimer_initMonitorSetFinalPosition; QTimer* m_thtimer_initMonitorSetMasks; QTimer* m_thtimer_threadStarted; QTimer* m_thtimer_threadFinished; QTimer* m_thtimer_threadTerminated; // flags for fancy fading bool m_decreaseOpacity_threadStarted; bool m_decreaseOpacity_threadFinished; bool m_decreaseOpacity_threadTerminated; // members for fancy animation int m_pixelstepper; int m_steppingDistance; }; // strings to display fiber_thread monitor const QString FBX_STATUS_IDLE = "idle"; const QString FBX_STATUS_STARTED = "starting"; const QString FBX_STATUS_RUNNING = "running"; // ========= HERE STARTS THE ACTUAL FIBERBUNDLE DEVELOPER VIEW ======= const QString FIB_RADIOBUTTON_DIRECTION_RANDOM = "radioButton_directionRandom"; const QString FIB_RADIOBUTTON_DIRECTION_X = "radioButton_directionX"; const QString FIB_RADIOBUTTON_DIRECTION_Y = "radioButton_directionY"; const QString FIB_RADIOBUTTON_DIRECTION_Z = "radioButton_directionZ"; /*! \brief QmitkFiberBundleView \warning This application module is not yet documented. Use "svn blame/praise/annotate" and ask the author to provide basic documentation. \sa QmitkFunctionality \ingroup Functionalities */ class QmitkFiberBundleDeveloperView : public QmitkFunctionality { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; QmitkFiberBundleDeveloperView(); virtual ~QmitkFiberBundleDeveloperView(); virtual void CreateQtPartControl(QWidget *parent); virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); virtual void StdMultiWidgetNotAvailable(); virtual void Activated(); protected slots: void DoGenerateFibers(); void DoGenerateFiberIDs(); void DoExtractFibers(); void DoUpdateGenerateFibersWidget(); void SelectionChangedToolBox(int); void DoMonitorFiberThreads(int); void DoColorFibers(); void DoGatherColorCodings(); void SetCurrentColorCoding(int); void ActionDrawEllipseTriggered(); //SLOTS FOR THREADS void BeforeThread_IdGenerate(); void AfterThread_IdGenerate(); void BeforeThread_GenerateFibersRandom(); void AfterThread_GenerateFibersRandom(); void BeforeThread_FiberColorCoding(); void AfterThread_FiberColorCoding(); void BeforeThread_FiberExtraction(); void AfterThread_FiberExtraction(); //SLOTS FOR TIMERS void UpdateFiberIDTimer(); void UpdateGenerateRandomFibersTimer(); void UpdateColorFibersTimer(); void UpdateExtractFibersTimer(); protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( std::vector nodes ); Ui::QmitkFiberBundleDeveloperViewControls* m_Controls; QmitkStdMultiWidget* m_MultiWidget; private: /* METHODS GENERATING FIBERSTRUCTURES */ void GenerateVtkFibersRandom(); vtkSmartPointer GenerateVtkFibersDirectionX(); vtkSmartPointer GenerateVtkFibersDirectionY(); vtkSmartPointer GenerateVtkFibersDirectionZ(); void PutFibersToDataStorage( vtkSmartPointer ); void PutFigureToDataStorage(mitk::PlanarFigure* , const QString& ); /* METHODS FOR FIBER PROCESSING OR PREPROCESSING */ /* HELPERMETHODS */ mitk::Geometry3D::Pointer GenerateStandardGeometryForMITK(); void ResetFiberInfoWidget(); void FeedFiberInfoWidget(); void FBXDependendGUIElementsConfigurator(); void SetGeneratedFBX(); //contains the selected FiberBundle, PlanarFigure + mitk::DataNode::Pointer m_FiberBundleNode; mitk::WeakPointer m_FiberBundleX; mitk::PlanarFigure::Pointer m_PlanarFigure; // radiobutton groups QVector< QRadioButton* > m_DirectionRadios; QVector< QRadioButton* > m_FARadios; QVector< QRadioButton* > m_GARadios; // Thread based Workers which do some processing of fibers QmitkFiberIDWorker* m_FiberIDGenerator; QmitkFiberGenerateRandomWorker* m_GeneratorFibersRandom; QmitkFiberColoringWorker* m_FiberColoringSlave; QmitkFiberExtractorWorker* m_FiberExtractor; QThread* m_hostThread; QThread* m_monitorThread; bool m_threadInProgress; mitk::DataNode::Pointer m_MonitorNode; QmitkFiberThreadMonitorWorker *m_fiberThreadMonitorWorker; bool m_fiberMonitorIsOn; // counters for ROI nodes int m_CircleCounter; }; #endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED diff --git a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp index 1f2272d85f..972de8ca00 100644 --- a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp +++ b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp @@ -1,964 +1,1003 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $ Version: $Revision: 21975 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkFiberBundleX.h" #include #include #include #include #include #include #include #include #include #include #include #include #include const char* mitk::FiberBundleX::COLORCODING_ORIENTATION_BASED = "Color_Orient"; const char* mitk::FiberBundleX::COLORCODING_FA_BASED = "Color_FA"; const char* mitk::FiberBundleX::FIBER_ID_ARRAY = "Fiber_IDs"; const char* mitk::FiberBundleX::FA_VALUE_ARRAY = "FA_Values"; mitk::FiberBundleX::FiberBundleX( vtkPolyData* fiberPolyData ) : m_currentColorCoding(NULL) , m_isModified(false) , m_NumFibers(0) { if (fiberPolyData == NULL) m_FiberPolyData = vtkSmartPointer::New(); else m_FiberPolyData = fiberPolyData; m_NumFibers = m_FiberPolyData->GetNumberOfLines(); UpdateFiberGeometry(); } mitk::FiberBundleX::~FiberBundleX() { } mitk::FiberBundleX::Pointer mitk::FiberBundleX::GetDeepCopy() { mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(); // newFib->m_FiberIdDataSet = vtkSmartPointer::New(); // newFib->m_FiberIdDataSet->DeepCopy(m_FiberIdDataSet); newFib->m_FiberPolyData = vtkSmartPointer::New(); newFib->m_FiberPolyData->DeepCopy(m_FiberPolyData); newFib->SetColorCoding(m_currentColorCoding); newFib->m_isModified = m_isModified; newFib->m_NumFibers = m_NumFibers; newFib->UpdateFiberGeometry(); return newFib; } vtkSmartPointer mitk::FiberBundleX::GenerateNewFiberBundleByIds(std::vector fiberIds) { MITK_INFO << "\n=====FINAL RESULT: fib_id ======\n"; MITK_INFO << "Number of new Fibers: " << fiberIds.size(); // iterate through the vectorcontainer hosting all desired fiber Ids vtkSmartPointer newFiberPolyData = vtkSmartPointer::New(); vtkSmartPointer newLineSet = vtkSmartPointer::New(); vtkSmartPointer newPointSet = vtkSmartPointer::New(); // if FA array available, initialize fa double array // if color orient array is available init color array vtkSmartPointer faValueArray; vtkSmartPointer colorsT; //colors and alpha value for each single point, RGBA = 4 components unsigned char rgba[4] = {0,0,0,0}; int componentSize = sizeof(rgba); if (m_FiberIdDataSet->GetPointData()->HasArray(FA_VALUE_ARRAY)){ MITK_INFO << "FA VALUES AVAILABLE, init array for new fiberbundle"; faValueArray = vtkSmartPointer::New(); } if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)){ MITK_INFO << "colorValues available, init array for new fiberbundle"; colorsT = vtkUnsignedCharArray::New(); colorsT->SetNumberOfComponents(componentSize); colorsT->SetName(COLORCODING_ORIENTATION_BASED); } std::vector::iterator finIt = fiberIds.begin(); while ( finIt != fiberIds.end() ) { -// MITK_INFO << *finIt; + // MITK_INFO << *finIt; vtkSmartPointer fiber = m_FiberIdDataSet->GetCell(*finIt);//->DeepCopy(fiber); vtkSmartPointer fibPoints = fiber->GetPoints(); vtkSmartPointer newFiber = vtkSmartPointer::New(); newFiber->GetPointIds()->SetNumberOfIds( fibPoints->GetNumberOfPoints() ); for(int i=0; iGetNumberOfPoints(); i++) { -// MITK_INFO << "id: " << fiber->GetPointId(i); -// MITK_INFO << fibPoints->GetPoint(i)[0] << " | " << fibPoints->GetPoint(i)[1] << " | " << fibPoints->GetPoint(i)[2]; + // MITK_INFO << "id: " << fiber->GetPointId(i); + // MITK_INFO << fibPoints->GetPoint(i)[0] << " | " << fibPoints->GetPoint(i)[1] << " | " << fibPoints->GetPoint(i)[2]; newFiber->GetPointIds()->SetId(i, newPointSet->GetNumberOfPoints()); newPointSet->InsertNextPoint(fibPoints->GetPoint(i)[0], fibPoints->GetPoint(i)[1], fibPoints->GetPoint(i)[2]); if (m_FiberIdDataSet->GetPointData()->HasArray(FA_VALUE_ARRAY)){ -// MITK_INFO << m_FiberIdDataSet->GetPointData()->GetArray(FA_VALUE_ARRAY)->GetTuple(fiber->GetPointId(i)); + // MITK_INFO << m_FiberIdDataSet->GetPointData()->GetArray(FA_VALUE_ARRAY)->GetTuple(fiber->GetPointId(i)); } if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)){ -// MITK_INFO << "ColorValue: " << m_FiberIdDataSet->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)->GetTuple(fiber->GetPointId(i))[0]; + // MITK_INFO << "ColorValue: " << m_FiberIdDataSet->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)->GetTuple(fiber->GetPointId(i))[0]; } } newLineSet->InsertNextCell(newFiber); ++finIt; } newFiberPolyData->SetPoints(newPointSet); newFiberPolyData->SetLines(newLineSet); MITK_INFO << "new fiberbundle polydata points: " << newFiberPolyData->GetNumberOfPoints(); MITK_INFO << "new fiberbundle polydata lines: " << newFiberPolyData->GetNumberOfLines(); MITK_INFO << "=====================\n"; -// mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(newFiberPolyData); + // mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(newFiberPolyData); return newFiberPolyData; } // merge two fiber bundles mitk::FiberBundleX::Pointer mitk::FiberBundleX::operator+(mitk::FiberBundleX* fib) { vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); vtkSmartPointer vLines = m_FiberPolyData->GetLines(); vLines->InitTraversal(); // add current fiber bundle int numFibers = GetNumFibers(); for( int i=0; iGetNextCell ( numPoints, points ); vtkSmartPointer container = vtkSmartPointer::New(); for( int j=0; jInsertNextPoint(m_FiberPolyData->GetPoint(points[j])); container->GetPointIds()->InsertNextId(id); } vNewLines->InsertNextCell(container); } vLines = fib->m_FiberPolyData->GetLines(); vLines->InitTraversal(); // add new fiber bundle numFibers = fib->GetNumFibers(); for( int i=0; iGetNextCell ( numPoints, points ); vtkSmartPointer container = vtkSmartPointer::New(); for( int j=0; jInsertNextPoint(fib->m_FiberPolyData->GetPoint(points[j])); container->GetPointIds()->InsertNextId(id); } vNewLines->InsertNextCell(container); } // initialize polydata vNewPolyData->SetPoints(vNewPoints); vNewPolyData->SetLines(vNewLines); // initialize fiber bundle mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(vNewPolyData); return newFib; } // subtract two fiber bundles mitk::FiberBundleX::Pointer mitk::FiberBundleX::operator-(mitk::FiberBundleX* fib) { vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); vtkSmartPointer vLines = m_FiberPolyData->GetLines(); vLines->InitTraversal(); // iterate over current fibers int numFibers = GetNumFibers(); for( int i=0; iGetNextCell ( numPoints, points ); vtkSmartPointer vLines2 = fib->m_FiberPolyData->GetLines(); vLines2->InitTraversal(); int numFibers2 = fib->GetNumFibers(); bool contained = false; for( int i2=0; i2GetNextCell ( numPoints2, points2 ); // check endpoints itk::Point point_start = GetItkPoint(m_FiberPolyData->GetPoint(points[0])); itk::Point point_end = GetItkPoint(m_FiberPolyData->GetPoint(points[numPoints-1])); itk::Point point2_start = GetItkPoint(fib->m_FiberPolyData->GetPoint(points2[0])); itk::Point point2_end = GetItkPoint(fib->m_FiberPolyData->GetPoint(points2[numPoints2-1])); if (point_start.SquaredEuclideanDistanceTo(point2_start)<=mitk::eps && point_end.SquaredEuclideanDistanceTo(point2_end)<=mitk::eps || point_start.SquaredEuclideanDistanceTo(point2_end)<=mitk::eps && point_end.SquaredEuclideanDistanceTo(point2_start)<=mitk::eps) { // further checking ??? contained = true; } } // add to result because fiber is not subtracted if (!contained) { vtkSmartPointer container = vtkSmartPointer::New(); for( int j=0; jInsertNextPoint(m_FiberPolyData->GetPoint(points[j])); container->GetPointIds()->InsertNextId(id); } vNewLines->InsertNextCell(container); } } // initialize polydata vNewPolyData->SetPoints(vNewPoints); vNewPolyData->SetLines(vNewLines); // initialize fiber bundle mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(vNewPolyData); return newFib; } itk::Point mitk::FiberBundleX::GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } /* * set polydata (additional flag to recompute fiber geometry, default = true) */ void mitk::FiberBundleX::SetFiberPolyData(vtkSmartPointer fiberPD, bool updateGeometry) { if (fiberPD == NULL) this->m_FiberPolyData = vtkSmartPointer::New(); else this->m_FiberPolyData = fiberPD; if (updateGeometry) UpdateFiberGeometry(); m_NumFibers = m_FiberPolyData->GetNumberOfLines(); m_isModified = true; } /* * return vtkPolyData */ vtkSmartPointer mitk::FiberBundleX::GetFiberPolyData() { return m_FiberPolyData; } void mitk::FiberBundleX::DoColorCodingOrientationbased() { //===== FOR WRITING A TEST ======================== // colorT size == tupelComponents * tupelElements // compare color results // to cover this code 100% also polydata needed, where colorarray already exists // + one fiber with exactly 1 point // + one fiber with 0 points //================================================= /* make sure that processing colorcoding is only called when necessary */ if ( m_FiberPolyData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED) && m_FiberPolyData->GetNumberOfPoints() == m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)->GetNumberOfTuples() ) { // fiberstructure is already colorcoded MITK_INFO << " NO NEED TO REGENERATE COLORCODING! " ; return; } /* Finally, execute color calculation */ vtkPoints* extrPoints = m_FiberPolyData->GetPoints(); int numOfPoints = extrPoints->GetNumberOfPoints(); //colors and alpha value for each single point, RGBA = 4 components unsigned char rgba[4] = {0,0,0,0}; int componentSize = sizeof(rgba); vtkSmartPointer colorsT = vtkUnsignedCharArray::New(); colorsT->Allocate(numOfPoints * componentSize); colorsT->SetNumberOfComponents(componentSize); colorsT->SetName(COLORCODING_ORIENTATION_BASED); /* checkpoint: does polydata contain any fibers */ int numOfFibers = m_FiberPolyData->GetNumberOfLines(); if (numOfFibers < 1) { MITK_INFO << "\n ========= Number of Fibers is 0 and below ========= \n"; return; } /* extract single fibers of fiberBundle */ vtkCellArray* fiberList = m_FiberPolyData->GetLines(); fiberList->InitTraversal(); for (int fi=0; fiGetNextCell(pointsPerFiber, idList); // MITK_INFO << "Fib#: " << fi << " of " << numOfFibers << " pnts in fiber: " << pointsPerFiber ; /* single fiber checkpoints: is number of points valid */ if (pointsPerFiber > 1) { /* operate on points of single fiber */ for (int i=0; i 0) { /* The color value of the current point is influenced by the previous point and next point. */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]); vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]); vnl_vector_fixed< double, 3 > diff1; diff1 = currentPntvtk - nextPntvtk; vnl_vector_fixed< double, 3 > diff2; diff2 = currentPntvtk - prevPntvtk; vnl_vector_fixed< double, 3 > diff; diff = (diff1 - diff2) / 2.0; diff.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff[2])); rgba[3] = (unsigned char) (255.0); } else if (i==0) { /* First point has no previous point, therefore only diff1 is taken */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]); vnl_vector_fixed< double, 3 > diff1; diff1 = currentPntvtk - nextPntvtk; diff1.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff1[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff1[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff1[2])); rgba[3] = (unsigned char) (255.0); } else if (i==pointsPerFiber-1) { /* Last point has no next point, therefore only diff2 is taken */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]); vnl_vector_fixed< double, 3 > diff2; diff2 = currentPntvtk - prevPntvtk; diff2.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff2[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff2[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff2[2])); rgba[3] = (unsigned char) (255.0); } colorsT->InsertTupleValue(idList[i], rgba); } //end for loop } else if (pointsPerFiber == 1) { /* a single point does not define a fiber (use vertex mechanisms instead */ continue; // colorsT->InsertTupleValue(0, rgba); } else { MITK_INFO << "Fiber with 0 points detected... please check your tractography algorithm!" ; continue; } }//end for loop m_FiberPolyData->GetPointData()->AddArray(colorsT); /*========================= - this is more relevant for renderer than for fiberbundleX datastructure - think about sourcing this to a explicit method which coordinates colorcoding */ this->SetColorCoding(COLORCODING_ORIENTATION_BASED); - m_isModified = true; + //m_isModified = true; // =========================== //mini test, shall be ported to MITK TESTINGS! if (colorsT->GetSize() != numOfPoints*componentSize) { MITK_INFO << "ALLOCATION ERROR IN INITIATING COLOR ARRAY"; } } void mitk::FiberBundleX::DoGenerateFiberIds() { if (m_FiberPolyData == NULL) return; // for (int i=0; i<10000000; ++i) // { // if(i%500 == 0) // MITK_INFO << i; // } // MITK_INFO << "Generating Fiber Ids"; vtkSmartPointer idFiberFilter = vtkSmartPointer::New(); idFiberFilter->SetInput(m_FiberPolyData); idFiberFilter->CellIdsOn(); // idFiberFilter->PointIdsOn(); // point id's are not needed idFiberFilter->SetIdsArrayName(FIBER_ID_ARRAY); idFiberFilter->FieldDataOn(); idFiberFilter->Update(); m_FiberIdDataSet = idFiberFilter->GetOutput(); MITK_INFO << "Generating Fiber Ids...[done] | " << m_FiberIdDataSet->GetNumberOfCells(); } //temporarely include only //#include //========================== std::vector mitk::FiberBundleX::DoExtractFiberIds(mitk::PlanarFigure::Pointer pf) { MITK_INFO << "Extracting fibers!"; // vector which is returned, contains all extracted FiberIds std::vector FibersInROI; /* Handle type of planarfigure */ // if incoming pf is a pfc mitk::PlanarFigureComposite::Pointer pfcomp= dynamic_cast(pf.GetPointer()); if (!pfcomp.IsNull()) { // process requested boolean operation of PFC + switch (pfcomp->getOperationType()) { + case 0: + { + //AND + //temporarly store results of the child in this vector, we need that to accumulate the + std::vector childResults = this->DoExtractFiberIds(pfcomp->getChildAt(0)); + std::sort(childResults.begin(), childResults.end()); + + std::vector AND_Assamblage; + AND_Assamblage.reserve(childResults.size()); //max size AND can reach anyway + + std::vector::iterator it; + for (int i=1; igetNumberOfChildren(); ++i) + { + std::vector tmpChild = this->DoExtractFiberIds(pfcomp->getChildAt(i)); + sort(tmpChild.begin(), tmpChild.end()); + it = std::set_intersection(childResults.begin(), childResults.end(), + tmpChild.begin(), tmpChild.end(), + AND_Assamblage.begin() ); + } + + + return AND_Assamblage; + break; + + } + case 1: + { + //OR + } + case 2: + { + //NOT + } + default: + MITK_INFO << "we have an UNDEFINED composition... ERROR" ; + break; + + } } else { mitk::Geometry2D::ConstPointer pfgeometry = pf->GetGeometry2D(); const mitk::PlaneGeometry* planeGeometry = dynamic_cast (pfgeometry.GetPointer()); Vector3D planeNormal = planeGeometry->GetNormal(); planeNormal.Normalize(); Point3D planeOrigin = planeGeometry->GetOrigin(); MITK_INFO << "planeOrigin: " << planeOrigin[0] << " | " << planeOrigin[1] << " | " << planeOrigin[2] << endl; MITK_INFO << "planeNormal: " << planeNormal[0] << " | " << planeNormal[1] << " | " << planeNormal[2] << endl; /* init necessary vectors hosting pointIds and FiberIds */ // contains all pointIds which are crossing the cutting plane std::vector PointsOnPlane; // based on PointsOnPlane, all ROI relevant point IDs are stored here std::vector PointsInROI; /* Define cutting plane by ROI (PlanarFigure) */ vtkSmartPointer plane = vtkSmartPointer::New(); plane->SetOrigin(planeOrigin[0],planeOrigin[1],planeOrigin[2]); plane->SetNormal(planeNormal[0],planeNormal[1],planeNormal[2]); //same plane but opposite normal direction. so point cloud will be reduced -> better performance vtkSmartPointer planeR = vtkSmartPointer::New(); //define new origin along the normal but close to the original one // OriginNew = OriginOld + 1*Normal // Vector3D extendedNormal; // int multiplyFactor = 1; // extendedNormal[0] = planeNormal[0] * multiplyFactor; // extendedNormal[1] = planeNormal[1] * multiplyFactor; // extendedNormal[2] = planeNormal[2] * multiplyFactor; // Point3D RplaneOrigin = planeOrigin - extendedNormal; // planeR->SetOrigin(RplaneOrigin[0],RplaneOrigin[1],RplaneOrigin[2]); // planeR->SetNormal(-planeNormal[0],-planeNormal[1],-planeNormal[2]); // MITK_INFO << "RPlaneOrigin: " << RplaneOrigin[0] << " | " << RplaneOrigin[1] // << " | " << RplaneOrigin[2]; /* get all points/fibers cutting the plane */ MITK_INFO << "start clipping"; vtkSmartPointer clipper = vtkSmartPointer::New(); clipper->SetInput(m_FiberIdDataSet); clipper->SetClipFunction(plane); clipper->GenerateClipScalarsOn(); clipper->GenerateClippedOutputOn(); vtkSmartPointer clipperout = clipper->GetClippedOutput(); MITK_INFO << "end clipping"; /* for some reason clipperoutput is not initialized for futher processing * so far only writing out clipped polydata provides requested */ // MITK_INFO << "writing clipper output"; // vtkSmartPointer writerC = vtkSmartPointer::New(); // writerC->SetInput(clipperout1); // writerC->SetFileName("/vtkOutput/Clipping.vtk"); // writerC->SetFileTypeToASCII(); // writerC->Write(); // MITK_INFO << "writing done"; MITK_INFO << "init and update clipperoutput"; clipperout->GetPointData()->Initialize(); clipperout->Update(); MITK_INFO << "init and update clipperoutput completed"; // MITK_INFO << "start clippingRecursive"; // vtkSmartPointer Rclipper = vtkSmartPointer::New(); // Rclipper->SetInput(clipperout1); // Rclipper->SetClipFunction(planeR); // Rclipper->GenerateClipScalarsOn(); // Rclipper->GenerateClippedOutputOn(); // vtkSmartPointer clipperout = Rclipper->GetClippedOutput(); // MITK_INFO << "end clipping recursive"; // MITK_INFO << "writing clipper output 2"; // vtkSmartPointer writerC1 = vtkSmartPointer::New(); // writerC1->SetInput(clipperout); // writerC1->SetFileName("/vtkOutput/RClipping.vtk"); // writerC1->SetFileTypeToASCII(); // writerC1->Write(); // MITK_INFO << "init and update clipperoutput"; // clipperout->GetPointData()->Initialize(); // clipperout->Update(); // MITK_INFO << "init and update clipperoutput completed"; MITK_INFO << "STEP 1: find all points which have distance 0 to the given plane"; /*======STEP 1====== * extract all points, which are crossing the plane */ // Scalar values describe the distance between each remaining point to the given plane. Values sorted by point index vtkSmartPointer distanceList = clipperout->GetPointData()->GetScalars(); vtkIdType sizeOfList = distanceList->GetNumberOfTuples(); PointsOnPlane.reserve(sizeOfList); /* use reserve for high-performant push_back, no hidden copy procedures are processed then! * size of list can be optimized by reducing allocation, but be aware of iterator and vector size*/ for (int i=0; iGetTuple(i); //std::cout << "distance of point " << i << " : " << distance[0] << std::endl; // check if point is on plane. // 0.01 due to some approximation errors when calculating distance if (distance[0] >= -0.01 && distance[0] <= 0.01) { //std::cout << "adding " << i << endl; PointsOnPlane.push_back(i); //push back in combination with reserve is fastest way to fill vector with various values //optimize: here also check if point is inside radius } } // DEBUG print out all interesting points, stop where array starts with value -1. after -1 no more interesting idx are set! // std::vector::iterator rit = PointsOnPlane.begin(); // while (rit != PointsOnPlane.end() ) { // std::cout << "interesting point: " << *rit << " coord: " << clipperout->GetPoint(*rit)[0] << " | " << clipperout->GetPoint(*rit)[1] << " | " << clipperout->GetPoint(*rit)[2] << endl; // rit++; // } MITK_INFO << "Num Of points on plane: " << PointsOnPlane.size(); MITK_INFO << "Step 2: extract Interesting points with respect to given extraction planarFigure"; PointsInROI.reserve(PointsOnPlane.size()); /*=======STEP 2===== * extract ROI relevant pointIds */ mitk::PlanarCircle::Pointer circleName = mitk::PlanarCircle::New(); mitk::PlanarPolygon::Pointer polyName = mitk::PlanarPolygon::New(); if (pf->GetNameOfClass() == circleName->GetNameOfClass() ) { //calculate circle radius mitk::Point3D V1w = pf->GetWorldControlPoint(0); //centerPoint mitk::Point3D V2w = pf->GetWorldControlPoint(1); //radiusPoint //calculate distance between those 2 and double distPF; distPF = sqrt((double) (V2w[0] - V1w[0]) * (V2w[0] - V1w[0]) + (V2w[1] - V1w[1]) * (V2w[1] - V1w[1]) + (V2w[2] - V1w[2]) * (V2w[2] - V1w[2])); //MITK_INFO << "Circle Radius: " << distPF; for (int i=0; iGetPoint(PointsOnPlane[i])[0] << " - " << V1w[0]; // MITK_INFO << clipperout->GetPoint(PointsOnPlane[i])[1] << " - " << V1w[1]; // MITK_INFO << clipperout->GetPoint(PointsOnPlane[i])[2] << " - " << V1w[2]; //distance between circle radius and given point double XdistPnt = sqrt((double) (clipperout->GetPoint(PointsOnPlane[i])[0] - V1w[0]) * (clipperout->GetPoint(PointsOnPlane[i])[0] - V1w[0]) + (clipperout->GetPoint(PointsOnPlane[i])[1] - V1w[1]) * (clipperout->GetPoint(PointsOnPlane[i])[1] - V1w[1]) + (clipperout->GetPoint(PointsOnPlane[i])[2] - V1w[2]) * (clipperout->GetPoint(PointsOnPlane[i])[2] - V1w[2])) ; // MITK_INFO << "PntDistance to Radius: " << XdistPnt; if( XdistPnt <= distPF) { // MITK_INFO << "point in Circle"; PointsInROI.push_back(PointsOnPlane[i]); } }//end for(i) // MITK_INFO << "Points inside circle radius: " << PointsInROI.size(); } MITK_INFO << "Step3: Identify fibers"; /*======STEP 3======= * identify fiberIds for points in ROI */ // we need to access the fiberId Array, so make sure that this array is available if (!clipperout->GetCellData()->HasArray(FIBER_ID_ARRAY)) { MITK_INFO << "ERROR: FiberID array does not exist, no correlation between points and fiberIds possible! Make sure calling GenerateFiberIds()"; return FibersInROI; // FibersInRoi is empty then } // prepare a structure where each point id is represented as an indexId. // vector looks like: | pntId | fiberIdx | std::vector< unsigned long > pointindexFiberMap; // walk through the whole subline section and create an vector sorted by point index vtkCellArray *clipperlines = clipperout->GetLines(); clipperlines->InitTraversal(); long numOfLineCells = clipperlines->GetNumberOfCells(); unsigned long numofClippedPoints = clipperout->GetNumberOfPoints(); pointindexFiberMap.reserve(numofClippedPoints); //prepare resulting vector FibersInROI.reserve(PointsInROI.size()); MITK_INFO << "\n===== Pointindex based structure initialized ======\n"; // go through resulting "sub"lines which are stored as cells, "i" corresponds to current line id. for (int i=0, ic=0 ; iGetCell(ic, npts, pts); // go through point ids in hosting subline, "j" corresponds to current pointindex in current line i. eg. idx[0]=45; idx[1]=46 for (long j=0; jGetCellData()->GetArray(FIBER_ID_ARRAY)->GetTuple(i)[0] << " to pointId: " << pts[j]; pointindexFiberMap[ pts[j] ] = clipperout->GetCellData()->GetArray(FIBER_ID_ARRAY)->GetTuple(i)[0]; // MITK_INFO << "in array: " << pointindexFiberMap[ pts[j] ]; } } MITK_INFO << "\n===== Pointindex based structure finalized ======\n"; // get all Points in ROI with according fiberID for (long k = 0; k < PointsInROI.size(); k++) { // MITK_INFO << "point " << PointsInROI[k] << " belongs to fiber " << pointindexFiberMap[ PointsInROI[k] ]; FibersInROI.push_back(pointindexFiberMap[ PointsInROI[k] ]); } } return FibersInROI; } void mitk::FiberBundleX::UpdateFiberGeometry() { if (m_NumFibers<=0) { mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); geometry->SetImageGeometry(true); float b[] = {0, 1, 0, 1, 0, 1}; geometry->SetFloatBounds(b); SetGeometry(geometry); return; } float min = itk::NumericTraits::min(); float max = itk::NumericTraits::max(); float b[] = {max, min, max, min, max, min}; vtkCellArray* cells = m_FiberPolyData->GetLines(); cells->InitTraversal(); for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); int p = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); for (int j=0; jGetPoint(j, p); if (p[0]b[1]) b[1]=p[0]; if (p[1]b[3]) b[3]=p[1]; if (p[2]b[5]) b[5]=p[2]; } } // provide some border margin for(int i=0; i<=4; i+=2) b[i] -=10; for(int i=1; i<=5; i+=2) b[i] +=10; mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); geometry->SetImageGeometry(true); geometry->SetFloatBounds(b); this->SetGeometry(geometry); } QStringList mitk::FiberBundleX::GetAvailableColorCodings() { QStringList availableColorCodings; int numColors = m_FiberPolyData->GetPointData()->GetNumberOfArrays(); for(int i=0; iGetPointData()->GetArrayName(i)); } //this controlstructure shall be implemented by the calling method if (availableColorCodings.isEmpty()) MITK_INFO << "no colorcodings available in fiberbundleX"; // for(int i=0; im_currentColorCoding = (char*) COLORCODING_ORIENTATION_BASED; this->m_isModified = true; } else if(strcmp (COLORCODING_FA_BASED,requestedColorCoding) == 0 ) { this->m_currentColorCoding = (char*) COLORCODING_FA_BASED; this->m_isModified = true; } else { MITK_INFO << "FIBERBUNDLE X: UNKNOWN COLORCODING in FIBERBUNDLEX Datastructure"; this->m_currentColorCoding = "---"; //will cause blank colorcoding of fibers this->m_isModified = true; } } bool mitk::FiberBundleX::isFiberBundleXModified() { return m_isModified; } void mitk::FiberBundleX::setFBXModificationDone() { m_isModified = false; } void mitk::FiberBundleX::ResampleFibers() { mitk::Geometry3D::Pointer geometry = GetGeometry(); mitk::Vector3D spacing = geometry->GetSpacing(); float minSpacing = 1; if(spacing[0] newPoly = vtkSmartPointer::New(); vtkSmartPointer newCellArray = vtkSmartPointer::New(); vtkSmartPointer newPoints = vtkSmartPointer::New(); vtkSmartPointer vLines = m_FiberPolyData->GetLines(); vLines->InitTraversal(); int numberOfLines = m_NumFibers; for (int i=0; iGetNextCell ( numPoints, points ); vtkSmartPointer container = vtkSmartPointer::New(); double* point = m_FiberPolyData->GetPoint(points[0]); vtkIdType pointId = newPoints->InsertNextPoint(point); container->GetPointIds()->InsertNextId(pointId); float dtau = 0; int cur_p = 1; itk::Vector dR; float normdR = 0; for (;;) { while (dtau <= len && cur_p < numPoints) { itk::Vector v1; point = m_FiberPolyData->GetPoint(points[cur_p-1]); v1[0] = point[0]; v1[1] = point[1]; v1[2] = point[2]; itk::Vector v2; point = m_FiberPolyData->GetPoint(points[cur_p]); v2[0] = point[0]; v2[1] = point[1]; v2[2] = point[2]; dR = v2 - v1; normdR = std::sqrt(dR.GetSquaredNorm()); dtau += normdR; cur_p++; } if (dtau >= len) { itk::Vector v1; point = m_FiberPolyData->GetPoint(points[cur_p-1]); v1[0] = point[0]; v1[1] = point[1]; v1[2] = point[2]; itk::Vector v2 = v1 - dR*( (dtau-len)/normdR ); pointId = newPoints->InsertNextPoint(v2.GetDataPointer()); container->GetPointIds()->InsertNextId(pointId); } else { point = m_FiberPolyData->GetPoint(points[numPoints-1]); pointId = newPoints->InsertNextPoint(point); container->GetPointIds()->InsertNextId(pointId); break; } dtau = dtau-len; } newCellArray->InsertNextCell(container); } newPoly->SetPoints(newPoints); newPoly->SetLines(newCellArray); m_FiberPolyData = newPoly; UpdateFiberGeometry(); } /* ESSENTIAL IMPLEMENTATION OF SUPERCLASS METHODS */ void mitk::FiberBundleX::UpdateOutputInformation() { } void mitk::FiberBundleX::SetRequestedRegionToLargestPossibleRegion() { } bool mitk::FiberBundleX::RequestedRegionIsOutsideOfTheBufferedRegion() { return false; } bool mitk::FiberBundleX::VerifyRequestedRegion() { return true; } void mitk::FiberBundleX::SetRequestedRegion( itk::DataObject *data ) { }