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 b308902cda..aba60085ed 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,1677 +1,1683 @@ /*========================================================================= 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(); + if(m_itemPackage.st_Controls->radioButton_ColorOrient->isChecked()) { + m_itemPackage.st_FBX->DoColorCodingOrientationbased(); + + } else if(m_itemPackage.st_Controls->radioButton_ColorFA) { + m_itemPackage.st_FBX->DoColorCodingFAbased(); + + } else if(m_itemPackage.st_Controls->radioButton_OpacityFA) { + m_itemPackage.st_FBX->DoUseFAasColorOpacity(); + } /* 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 (long i=0; i singleFiber = fiberStorage.at(i); vtkSmartPointer fiber = vtkSmartPointer::New(); fiber->GetPointIds()->SetNumberOfIds((int)singleFiber.size()); for (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_FiberIDGenerator != NULL) + // delete m_FiberIDGenerator; // 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); m_hostThread->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); FBNode->SetOpacity(1.0); GetDataStorage()->Add(FBNode); 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); 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->ForceImmediateUpdate(); //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("custom"); m_Controls->ddAvailableColorcodings->addItems(fbxColorCodings); + m_Controls->ddAvailableColorcodings->addItem(m_FiberBundleX->COLORCODING_CUSTOM); //highlight current colorcoding QString cc = m_FiberBundleX->GetCurrentColorCoding(); - MITK_INFO << "current idx: " << m_Controls->ddAvailableColorcodings->findText(cc); + MITK_INFO << cc.toStdString().c_str() << " is at idx: " << m_Controls->ddAvailableColorcodings->findText(cc); m_Controls->ddAvailableColorcodings->setCurrentIndex( m_Controls->ddAvailableColorcodings->findText(cc) ); - + m_Controls->ddAvailableColorcodings->update(); } void QmitkFiberBundleDeveloperView::SetCurrentColorCoding(int idx) { QString selectedColorCoding = m_Controls->ddAvailableColorcodings->itemText(idx); + MITK_INFO << "SetCurrentCC: " << selectedColorCoding.toStdString().c_str(); m_FiberBundleX->SetColorCoding(selectedColorCoding.toStdString().c_str() ); //QString to char // update rendering m_FiberBundleNode->Modified(); m_MultiWidget->ForceImmediateUpdate(); } /* === 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()){ + 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()){ 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(); + this->FBXDependendGUIElementsConfigurator(); + this->DoGatherColorCodings(); } /* 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/QmitkFiberBundleDeveloperViewControls.ui b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperViewControls.ui index 8cef47a5ca..efde6afd2e 100644 --- a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperViewControls.ui +++ b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperViewControls.ui @@ -1,1142 +1,1149 @@ QmitkFiberBundleDeveloperViewControls 0 0 467 - 966 + 570 Form 12 50 false 1 0 0 - 500 - 449 + 428 + 540 Fiber Generator 0 Fiber Bundles Generate Fiberbundle Fiber Parameters 11 Total number of Fibers 10 999999999 100 11 Distribution Radius 10 9999 100 11 Fiber Length Max (points) 10 50 11 Fiber Length Min (points) 10 10 Qt::Horizontal 40 20 11 Fiber Orientation along Z Axis along X Axis random true along Y Axis Qt::Horizontal 40 20 Qt::Vertical 20 40 QFrame::StyledPanel QFrame::Raised 10 Time: 10 - DWI Values GA Values no values true nothing yet implemented 11 FA Values const value false 10 1.000000000000000 0.100000000000000 1.000000000000000 random range false 10 1.000000000000000 0.100000000000000 no values true false 10 1.000000000000000 0.100000000000000 Qt::Vertical 20 40 Page Select a FiberBundle in Datamanager Qt::Vertical 20 40 0 0 - 443 - 403 + 445 + 472 Fiber Processor - 2 + 0 Colors Generate Fiber Coloring QFrame::StyledPanel QFrame::Raised Orientation based true - FA based + FA as Color + + + + + + + FA as Opacity Colorcode Fibers QFrame::StyledPanel QFrame::Raised QFormLayout::FieldsStayAtSizeHint 10 Timer: 10 - Qt::Horizontal 40 20 Qt::Vertical 20 40 Fiber Color Information Qt::Horizontal 40 20 Shape Qt::Vertical 20 40 Fiber Smoothing Smooth Fibers QFrame::StyledPanel QFrame::Raised static value relative in% false 10 none true false 10 9999 Qt::Horizontal 40 20 vtkFilters Tubes vtkDecimatePro vtkSmoothPolyDataFilter Cutting Qt::Vertical 20 40 Step 3 Extract Fibers by ROI Extract Fibers QFrame::StyledPanel QFrame::Raised 10 Timer: 10 - Step 1 Generate Fibers IDs in FBX Generate Fiber Ids QFrame::StyledPanel QFrame::Raised QFormLayout::FieldsStayAtSizeHint 10 Timer: 10 - Step 2 Define ROI QFrame::StyledPanel QFrame::Raised 30 30 Draw circular ROI :/QmitkDiffusionImaging/circle.png:/QmitkDiffusionImaging/circle.png 32 32 false true 30 30 Draw polygonal ROI :/QmitkDiffusionImaging/polygon.png:/QmitkDiffusionImaging/polygon.png 32 32 true true Qt::Horizontal 40 20 Qt::Vertical 20 40 Qt::Horizontal 40 20 0 0 - 515 - 348 + 443 + 156 FiberInfo General Information Number of Fibers: - Number of Points: - Qt::Vertical 20 40 Qt::Horizontal Monitor Fiber Threading in mitkRenderWindow4 Qt::Vertical 20 40 diff --git a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp index ed94aae833..ff0232d1c7 100644 --- a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp +++ b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp @@ -1,1145 +1,1150 @@ /*========================================================================= 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::COLORCODING_FA_AS_OPACITY = "Color_Orient_FA_Opacity"; -const char* mitk::FiberBundleX::COLORCODING_CUSTOM = "custom"; const char* mitk::FiberBundleX::FA_VALUE_ARRAY = "FA_Values"; +const char* mitk::FiberBundleX::COLORCODING_CUSTOM = "custom"; const char* mitk::FiberBundleX::FIBER_ID_ARRAY = "Fiber_IDs"; mitk::FiberBundleX::FiberBundleX( vtkPolyData* fiberPolyData ) : m_currentColorCoding(NULL) , m_NumFibers(0) { if (fiberPolyData == NULL) m_FiberPolyData = vtkSmartPointer::New(); else m_FiberPolyData = fiberPolyData; m_NumFibers = m_FiberPolyData->GetNumberOfLines(); this->UpdateFiberGeometry(); //generate colorcoding this->DoColorCodingOrientationbased(); this->SetColorCoding(COLORCODING_ORIENTATION_BASED); this->DoGenerateFiberIds(); } 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() ) { if (*finIt < 0){ MITK_INFO << "!!!!!! ERROR !!!!!! ERROR !!!!!\n=======================\nERROR, fiberID can not be negative!!! check id Extraction!" << *finIt; break; } 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]; 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)); } if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)){ // 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); 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; // =========================== //mini test, shall be ported to MITK TESTINGS! - if (colorsT->GetSize() != numOfPoints*componentSize) { + if (colorsT->GetSize() != numOfPoints*componentSize) MITK_INFO << "ALLOCATION ERROR IN INITIATING COLOR ARRAY"; - } + } +void mitk::FiberBundleX::DoColorCodingFAbased() +{ + if(!m_FiberPolyData->GetPointData()->HasArray(FA_VALUE_ARRAY)) + return; + + this->SetColorCoding(FA_VALUE_ARRAY); +} + void mitk::FiberBundleX::DoUseFAasColorOpacity() { if(!m_FiberPolyData->GetPointData()->HasArray(FA_VALUE_ARRAY)) return; if(!m_FiberPolyData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)) return; vtkDoubleArray* FAValArray = (vtkDoubleArray*) m_FiberPolyData->GetPointData()->GetArray(FA_VALUE_ARRAY); vtkUnsignedCharArray* ColorArray = dynamic_cast (m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)); for(long i=0; iGetNumberOfTuples(); i++) { double faValue = FAValArray->GetTuple1(i); faValue = faValue * 255.0; ColorArray->SetComponent(i,3, faValue ); } + this->SetColorCoding(COLORCODING_FA_AS_OPACITY); } void mitk::FiberBundleX::ResetFiberColorOpacity() { vtkUnsignedCharArray* ColorArray = dynamic_cast (m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)); for(long i=0; iGetNumberOfTuples(); i++) { ColorArray->SetComponent(i,3, 255.0 ); } } void mitk::FiberBundleX::SetFAMap(mitk::Image::Pointer FAimage) { vtkSmartPointer faValues = vtkDoubleArray::New(); faValues->SetName(FA_VALUE_ARRAY); faValues->Allocate(m_FiberPolyData->GetNumberOfPoints()); MITK_INFO << faValues->GetNumberOfTuples(); MITK_INFO << faValues->GetSize(); faValues->SetNumberOfValues(m_FiberPolyData->GetNumberOfPoints()); MITK_INFO << faValues->GetNumberOfTuples(); MITK_INFO << faValues->GetSize(); vtkPoints* pointSet = m_FiberPolyData->GetPoints(); for(long i=0; iGetNumberOfPoints(); ++i) { Point3D px; px[0] = pointSet->GetPoint(i)[0]; px[1] = pointSet->GetPoint(i)[1]; px[2] = pointSet->GetPoint(i)[2]; double faPixelValue = FAimage->GetPixelValueByWorldCoordinate(px); faValues->InsertNextValue(faPixelValue); } m_FiberPolyData->GetPointData()->AddArray(faValues); + this->DoGenerateFiberIds(); } 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: { MITK_INFO << "AND PROCESSING"; //AND //temporarly store results of the child in this vector, we need that to accumulate the std::vector childResults = this->DoExtractFiberIds(pfcomp->getChildAt(0)); MITK_INFO << "first roi got fibers in ROI: " << childResults.size(); MITK_INFO << "sorting..."; std::sort(childResults.begin(), childResults.end()); MITK_INFO << "sorting done"; std::vector AND_Assamblage(childResults.size()); //std::vector AND_Assamblage; fill(AND_Assamblage.begin(), AND_Assamblage.end(), -1); //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)); MITK_INFO << "ROI " << i << " has fibers in ROI: " << tmpChild.size(); sort(tmpChild.begin(), tmpChild.end()); it = std::set_intersection(childResults.begin(), childResults.end(), tmpChild.begin(), tmpChild.end(), AND_Assamblage.begin() ); } MITK_INFO << "resize Vector"; long i=0; while (i < AND_Assamblage.size() && AND_Assamblage[i] != -1){ //-1 represents a placeholder in the array ++i; } AND_Assamblage.resize(i); MITK_INFO << "returning AND vector, size: " << AND_Assamblage.size(); return AND_Assamblage; // break; } case 1: { //OR std::vector OR_Assamblage = this->DoExtractFiberIds(pfcomp->getChildAt(0)); std::vector::iterator it; MITK_INFO << OR_Assamblage.size(); for (int i=1; igetNumberOfChildren(); ++i) { it = OR_Assamblage.end(); std::vector tmpChild = this->DoExtractFiberIds(pfcomp->getChildAt(i)); OR_Assamblage.insert(it, tmpChild.begin(), tmpChild.end()); MITK_INFO << "ROI " << i << " has fibers in ROI: " << tmpChild.size() << " OR Assamblage: " << OR_Assamblage.size(); } sort(OR_Assamblage.begin(), OR_Assamblage.end()); it = unique(OR_Assamblage.begin(), OR_Assamblage.end()); OR_Assamblage.resize( it - OR_Assamblage.begin() ); MITK_INFO << "returning OR vector, size: " << OR_Assamblage.size(); return OR_Assamblage; } case 2: { //NOT //get IDs of all fibers std::vector childResults; childResults.reserve(this->GetNumFibers()); vtkSmartPointer idSet = m_FiberIdDataSet->GetCellData()->GetArray(FIBER_ID_ARRAY); MITK_INFO << "m_NumOfFib: " << this->GetNumFibers() << " cellIdNum: " << idSet->GetNumberOfTuples(); for(long i=0; iGetNumFibers(); i++) { MITK_INFO << "i: " << i << " idset: " << idSet->GetTuple(i)[0]; childResults.push_back(idSet->GetTuple(i)[0]); } std::sort(childResults.begin(), childResults.end()); std::vector NOT_Assamblage(childResults.size()); //fill it with -1, otherwise 0 will be stored and 0 can also be an ID of fiber! fill(NOT_Assamblage.begin(), NOT_Assamblage.end(), -1); std::vector::iterator it; for (long i=0; igetNumberOfChildren(); ++i) { std::vector tmpChild = DoExtractFiberIds(pfcomp->getChildAt(i)); sort(tmpChild.begin(), tmpChild.end()); it = std::set_difference(childResults.begin(), childResults.end(), tmpChild.begin(), tmpChild.end(), NOT_Assamblage.begin() ); } MITK_INFO << "resize Vector"; long i=0; while (NOT_Assamblage[i] != -1){ //-1 represents a placeholder in the array ++i; } NOT_Assamblage.resize(i); return NOT_Assamblage; } 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 } } // 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< 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(); 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] ]); } } // detecting fiberId duplicates MITK_INFO << "check for duplicates"; sort(FibersInROI.begin(), FibersInROI.end()); bool hasDuplicats = false; for(long i=0; i::iterator it; it = unique (FibersInROI.begin(), FibersInROI.end()); FibersInROI.resize( it - FibersInROI.begin() ); } 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; - } else if(strcmp (COLORCODING_FA_BASED,requestedColorCoding) == 0 ) { - this->m_currentColorCoding = (char*) COLORCODING_FA_BASED; - } else if(strcmp (COLORCODING_CUSTOM,requestedColorCoding) ) { + + } else if( strcmp (FA_VALUE_ARRAY,requestedColorCoding) == 0 ) { + this->m_currentColorCoding = (char*) FA_VALUE_ARRAY; + + } else if( strcmp (COLORCODING_CUSTOM,requestedColorCoding) == 0 ) { this->m_currentColorCoding = (char*) COLORCODING_CUSTOM; + } else { MITK_INFO << "FIBERBUNDLE X: UNKNOWN COLORCODING in FIBERBUNDLEX Datastructure"; - this->m_currentColorCoding = "custom"; //will cause blank colorcoding of fibers + this->m_currentColorCoding = (char*) COLORCODING_CUSTOM; //will cause blank colorcoding of fibers } } -//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 ) { } diff --git a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.h b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.h index 129345975a..fabceb0142 100644 --- a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.h +++ b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.h @@ -1,114 +1,114 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date$ Version: $Revision: 11989 $ 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. =========================================================================*/ /* =============== IMPORTANT TODO =================== * ==== USE vtkSmartPointer<> when necessary ONLY!!!! */ #ifndef _MITK_FiberBundleX_H #define _MITK_FiberBundleX_H //includes for MITK datastructure #include #include "MitkDiffusionImagingExports.h" #include //includes storing fiberdata #include //may be replaced by class precompile argument #include // may be replaced by class #include // my be replaced by class #include #include #include namespace mitk { /** * \brief Base Class for Fiber Bundles; */ class MitkDiffusionImaging_EXPORT FiberBundleX : public BaseData { public: static const char* COLORCODING_ORIENTATION_BASED; - static const char* COLORCODING_FA_BASED; static const char* COLORCODING_FA_AS_OPACITY; - static const char* COLORCODING_CUSTOM; static const char* FA_VALUE_ARRAY; + static const char* COLORCODING_CUSTOM; static const char* FIBER_ID_ARRAY; virtual void UpdateOutputInformation(); virtual void SetRequestedRegionToLargestPossibleRegion(); virtual bool RequestedRegionIsOutsideOfTheBufferedRegion(); virtual bool VerifyRequestedRegion(); virtual void SetRequestedRegion( itk::DataObject *data ); mitkClassMacro( FiberBundleX, BaseData ) itkNewMacro( Self ) mitkNewMacro1Param(Self, vtkSmartPointer) // custom constructor // set/get vtkPolyData void SetFiberPolyData(vtkSmartPointer, bool updateGeometry = true); vtkSmartPointer GetFiberPolyData(); mitk::FiberBundleX::Pointer operator+(mitk::FiberBundleX* fib); mitk::FiberBundleX::Pointer operator-(mitk::FiberBundleX* fib); char* GetCurrentColorCoding(); void SetColorCoding(const char*); + void SetFAMap(mitk::Image::Pointer); QStringList GetAvailableColorCodings(); void DoColorCodingOrientationbased(); - void SetFAMap(mitk::Image::Pointer); + void DoColorCodingFAbased(); void DoUseFAasColorOpacity(); void ResetFiberColorOpacity(); void DoGenerateFiberIds(); void ResampleFibers(float len); void ResampleFibers(); std::vector DoExtractFiberIds(mitk::PlanarFigure::Pointer ); vtkSmartPointer GenerateNewFiberBundleByIds( std::vector ); itkGetMacro(NumFibers, int); mitk::FiberBundleX::Pointer GetDeepCopy(); protected: FiberBundleX( vtkPolyData* fiberPolyData = NULL ); virtual ~FiberBundleX(); void UpdateFiberGeometry(); itk::Point GetItkPoint(double point[3]); private: // actual fiber container vtkSmartPointer m_FiberPolyData; // contains all additional IDs of Fibers which are needed for efficient fiber manipulation such as extracting etc. vtkSmartPointer m_FiberIdDataSet; char* m_currentColorCoding; int m_NumFibers; }; } // namespace mitk #endif /* _MITK_FiberBundleX_H */ diff --git a/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper2D.cpp b/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper2D.cpp index 39b0b19763..6cbb4d7645 100644 --- a/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper2D.cpp +++ b/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper2D.cpp @@ -1,323 +1,315 @@ /* * mitkFiberBundleMapper2D.cpp * mitk-all * * Created by HAL9000 on 1/17/11. * Copyright 2011 __MyCompanyName__. All rights reserved. * */ #include "mitkFiberBundleXMapper2D.h" #include #include #include #include #include //#include //#include #include #include #include #include #include #include #include #include //#include #include #include #include #include #include #include #include mitk::FiberBundleXMapper2D::FiberBundleXMapper2D() { - + m_lut = vtkLookupTable::New(); + m_lut->Build(); } mitk::FiberBundleXMapper2D::~FiberBundleXMapper2D() { } mitk::FiberBundleX* mitk::FiberBundleXMapper2D::GetInput() { return dynamic_cast< mitk::FiberBundleX * > ( GetData() ); } void mitk::FiberBundleXMapper2D::Update(mitk::BaseRenderer * renderer) { if ( !this->IsVisible( renderer ) ) { return; } // Calculate time step of the input data for the specified renderer (integer value) // this method is implemented in mitkMapper this->CalculateTimeStep( renderer ); //check if updates occured in the node or on the display FBXLocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); const DataNode *node = this->GetDataNode(); if ( (localStorage->m_LastUpdateTime < node->GetMTime()) || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified? || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) ) { // MITK_INFO << "UPDATE NEEDED FOR _ " << renderer->GetName(); this->GenerateDataForRenderer( renderer ); } if ((localStorage->m_LastUpdateTime < renderer->GetDisplayGeometry()->GetMTime()) ) //was the display geometry modified? e.g. zooming, panning) { this->UpdateShaderParameter(renderer); } } void mitk::FiberBundleXMapper2D::UpdateShaderParameter(mitk::BaseRenderer * renderer) { FBXLocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); //get information about current position of views mitk::SliceNavigationController::Pointer sliceContr = renderer->GetSliceNavigationController(); mitk::PlaneGeometry::ConstPointer planeGeo = sliceContr->GetCurrentPlaneGeometry(); //generate according cutting planes based on the view position float sliceN[3], planeOrigin[3]; // since shader uses camera coordinates, transform origin and normal from worldcoordinates to cameracoordinates planeOrigin[0] = (float) planeGeo->GetOrigin()[0]; planeOrigin[1] = (float) planeGeo->GetOrigin()[1]; planeOrigin[2] = (float) planeGeo->GetOrigin()[2]; sliceN[0] = planeGeo->GetNormal()[0]; sliceN[1] = planeGeo->GetNormal()[1]; sliceN[2] = planeGeo->GetNormal()[2]; float tmp1 = planeOrigin[0] * sliceN[0]; float tmp2 = planeOrigin[1] * sliceN[1]; float tmp3 = planeOrigin[2] * sliceN[2]; float d1 = tmp1 + tmp2 + tmp3; //attention, correct normalvector float plane1[4]; plane1[0] = sliceN[0]; plane1[1] = sliceN[1]; plane1[2] = sliceN[2]; plane1[3] = d1; float thickness = 2.0; if(!this->GetDataNode()->GetPropertyValue("Fiber2DSliceThickness",thickness)) MITK_INFO << "FIBER2D SLICE THICKNESS PROPERTY ERROR"; bool fiberfading = false; if(!this->GetDataNode()->GetPropertyValue("Fiber2DfadeEFX",fiberfading)) MITK_INFO << "FIBER2D SLICE FADE EFX PROPERTY ERROR"; int fiberfading_i = 1; if (!fiberfading) fiberfading_i = 0; // set Opacity float fiberOpacity; this->GetDataNode()->GetOpacity(fiberOpacity, NULL); localStorage->m_PointActor->GetProperty()->AddShaderVariable("slicingPlane",4, plane1); localStorage->m_PointActor->GetProperty()->AddShaderVariable("fiberThickness",1, &thickness); localStorage->m_PointActor->GetProperty()->AddShaderVariable("fiberFadingON",1, &fiberfading_i); localStorage->m_PointActor->GetProperty()->AddShaderVariable("fiberOpacity", 1, &fiberOpacity); } // ALL RAW DATA FOR VISUALIZATION IS GENERATED HERE. // vtkActors and Mappers are feeded here void mitk::FiberBundleXMapper2D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) { //the handler of local storage gets feeded in this method with requested data for related renderwindow FBXLocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); //this procedure is depricated, //not needed after initializaton anymore mitk::DataNode* node = this->GetDataNode(); if ( node == NULL ) { MITK_INFO << "check DATANODE: ....[Fail] "; return; } /////////////////////////////////// ///THIS GET INPUT mitk::FiberBundleX* fbx = this->GetInput(); - - vtkSmartPointer lut = vtkLookupTable::New(); - lut->Build(); - localStorage->m_PointMapper->SetScalarModeToUsePointFieldData(); - // set color if (fbx->GetCurrentColorCoding() != NULL){ localStorage->m_PointMapper->SelectColorArray(fbx->GetCurrentColorCoding()); MITK_INFO << "MapperFBX 2D: " << fbx->GetCurrentColorCoding(); + if(fbx->GetCurrentColorCoding() == fbx->COLORCODING_CUSTOM){ float temprgb[3]; this->GetDataNode()->GetColor( temprgb, NULL ); double trgb[3] = { (double) temprgb[0], (double) temprgb[1], (double) temprgb[2] }; localStorage->m_PointActor->GetProperty()->SetColor(trgb); } } - localStorage->m_PointMapper->SetLookupTable(lut); //apply the properties after the slice was set - - // feed the vtk fiber mapper with point data ...TODO do in constructor + localStorage->m_PointMapper->SetScalarModeToUsePointFieldData(); + localStorage->m_PointMapper->SetLookupTable(m_lut); //apply the properties after the slice was set localStorage->m_PointMapper->SetInput(fbx->GetFiberPolyData()); localStorage->m_PointActor->SetMapper(localStorage->m_PointMapper); localStorage->m_PointActor->GetProperty()->ShadingOn(); // Applying shading properties { - //Superclass::ApplyProperties( ls->m_Actor, renderer ) ; - // VTK Properties - //ApplyMitkPropertiesToVtkProperty( this->GetDataNode(), ls->m_Actor->GetProperty(), renderer ); - // Shaders mitk::ShaderRepository::GetGlobalShaderRepository()->ApplyProperties(this->GetDataNode(),localStorage->m_PointActor,renderer, localStorage->m_LastUpdateTime); } this->UpdateShaderParameter(renderer); // We have been modified => save this for next Update() localStorage->m_LastUpdateTime.Modified(); } vtkProp* mitk::FiberBundleXMapper2D::GetVtkProp(mitk::BaseRenderer *renderer) { //MITK_INFO << "FiberBundleMapper2D GetVtkProp(renderer)"; this->Update(renderer); return m_LSH.GetLocalStorage(renderer)->m_PointActor; } void mitk::FiberBundleXMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { //add shader to datano //####### load shader from file ######### QString applicationDir = QCoreApplication::applicationDirPath(); if (applicationDir.endsWith("bin")) applicationDir.append("/"); else if (applicationDir.endsWith("MacOS")) { //on osx, check if path for installer or MITK development is needed applicationDir.append("/"); QFile f( applicationDir+"FiberTrackingLUTBaryCoords.bin" ); if( !f.exists() ) // if file does not exist, then look in MITK development build directory applicationDir.append("../../../"); }else applicationDir.append("\\..\\"); mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch( applicationDir.toStdString().c_str(), false ); mitk::ShaderRepository::Pointer shaderRepository = mitk::ShaderRepository::GetGlobalShaderRepository(); shaderRepository->LoadShader(mitk::StandardFileLocations::GetInstance()->FindFile("mitkShaderFiberClipping.xml")); //#################################################################### node->SetProperty("shader",mitk::ShaderProperty::New("mitkShaderFiberClipping")); mitk::ShaderRepository::GetGlobalShaderRepository()->AddDefaultProperties(node,renderer,overwrite); //add other parameters to propertylist node->AddProperty( "Fiber2DSliceThickness", mitk::FloatProperty::New(2.0f), renderer, overwrite ); node->AddProperty( "Fiber2DfadeEFX", mitk::BoolProperty::New(true), renderer, overwrite ); Superclass::SetDefaultProperties(node, renderer, overwrite); } // following methods are essential, they actually call the GetVtkProp() method // which returns the desired actors void mitk::FiberBundleXMapper2D::MitkRenderOverlay(BaseRenderer* renderer) { // MITK_INFO << "FiberBundleMapper2D MitkRenderOVerlay(renderer)"; if ( this->IsVisible(renderer)==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) { this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer()); } } void mitk::FiberBundleXMapper2D::MitkRenderOpaqueGeometry(BaseRenderer* renderer) { // MITK_INFO << "FiberBundleMapper2D MitkRenderOpaqueGeometry(renderer)"; if ( this->IsVisible( renderer )==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() ); } void mitk::FiberBundleXMapper2D::MitkRenderTranslucentGeometry(BaseRenderer* renderer) { // MITK_INFO << "FiberBundleMapper2D MitkRenderTranslucentGeometry(renderer)"; if ( this->IsVisible(renderer)==false ) return; //TODO is it possible to have a visible BaseRenderer AND an invisible VtkRenderer??? if ( this->GetVtkProp(renderer)->GetVisibility() ) this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer()); } void mitk::FiberBundleXMapper2D::MitkRenderVolumetricGeometry(BaseRenderer* renderer) { // MITK_INFO << "FiberBundleMapper2D MitkRenderVolumentricGeometry(renderer)"; if(IsVisible(renderer)==false) return; //TODO is it possible to have a visible BaseRenderer AND an invisible VtkRenderer??? if ( GetVtkProp(renderer)->GetVisibility() ) this->GetVtkProp(renderer)->RenderVolumetricGeometry(renderer->GetVtkRenderer()); } mitk::FiberBundleXMapper2D::FBXLocalStorage::FBXLocalStorage() { m_PointActor = vtkSmartPointer::New(); m_PointMapper = vtkSmartPointer::New(); } diff --git a/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper2D.h b/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper2D.h index e520ddc131..073938ca11 100644 --- a/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper2D.h +++ b/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper2D.h @@ -1,110 +1,112 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2010-09-26 20:40:22 +0200 (So, 26 Sep 2010) $ Version: $Revision$ 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 FIBERBUNDLEXMAPPER2D_H_HEADER_INCLUDED #define FIBERBUNDLEXMAPPER2D_H_HEADER_INCLUDED //MITK Rendering #include #include //#include "MitkDiffusionImagingExports.h" #include #include #include class vtkActor; //class vtkPropAssembly; //lets see if we need it class mitkBaseRenderer; class vtkPolyDataMapper; class vtkCutter; class vtkPlane; class vtkPolyData; namespace mitk { class FiberBundleXMapper2D : public VtkMapper2D { public: mitkClassMacro(FiberBundleXMapper2D, VtkMapper2D); itkNewMacro(Self); mitk::FiberBundleX* GetInput(); /** \brief Checks whether this mapper needs to update itself and generate * data. */ virtual void Update(mitk::BaseRenderer * renderer); static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false ); //### methods of MITK-VTK rendering pipeline virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); virtual void MitkRenderOverlay(BaseRenderer* renderer); virtual void MitkRenderOpaqueGeometry(BaseRenderer* renderer); virtual void MitkRenderTranslucentGeometry(BaseRenderer* renderer); virtual void MitkRenderVolumetricGeometry(BaseRenderer* renderer); //### end of methods of MITK-VTK rendering pipeline class FBXLocalStorage : public mitk::Mapper::BaseLocalStorage { public: /** \brief Point Actor of a 2D render window. */ vtkSmartPointer m_PointActor; /** \brief Point Mapper of a 2D render window. */ vtkSmartPointer m_PointMapper; vtkSmartPointer m_SlicingPlane; //needed later when optimized 2D mapper vtkSmartPointer m_SlicedResult; //might be depricated in optimized 2D mapper /** \brief Timestamp of last update of stored data. */ itk::TimeStamp m_LastUpdateTime; /** \brief Constructor of the local storage. Do as much actions as possible in here to avoid double executions. */ FBXLocalStorage(); //if u copy&paste from this 2Dmapper, be aware that the implementation of this constructor is in the cpp file ~FBXLocalStorage() { } }; /** \brief This member holds all three LocalStorages for the three 2D render windows. */ mitk::Mapper::LocalStorageHandler m_LSH; protected: FiberBundleXMapper2D(); virtual ~FiberBundleXMapper2D(); /** Does the actual resampling, without rendering. */ virtual void GenerateDataForRenderer(mitk::BaseRenderer*); void UpdateShaderParameter(mitk::BaseRenderer*); + private: + vtkSmartPointer m_lut; }; }//end namespace #endif diff --git a/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper3D.cpp b/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper3D.cpp index 0539b66d2e..7d5e7c91b7 100644 --- a/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper3D.cpp +++ b/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper3D.cpp @@ -1,198 +1,200 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-05-12 19:56:03 +0200 (Di, 12 Mai 2009) $ Version: $Revision: 17179 $ 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 "mitkFiberBundleXMapper3D.h" #include //#include //#include #include #include #include //not essential for mapper #include mitk::FiberBundleXMapper3D::FiberBundleXMapper3D() { m_lut = vtkLookupTable::New(); m_lut->Build(); } mitk::FiberBundleXMapper3D::~FiberBundleXMapper3D() { } const mitk::FiberBundleX* mitk::FiberBundleXMapper3D::GetInput() { MITK_INFO << "FiberBundleXxXXMapper3D() GetInput()"; return static_cast ( GetData() ); } /* This method is called once the mapper gets new input, for UI rotation or changes in colorcoding this method is NOT called */ void mitk::FiberBundleXMapper3D::GenerateData(mitk::BaseRenderer *renderer) { //MITK_INFO << "GENERATE DATA FOR FBX :)"; //=====timer measurement==== QTime myTimer; myTimer.start(); //========================== mitk::FiberBundleX* FBX = dynamic_cast (this->GetData()); if (FBX == NULL) return; vtkSmartPointer FiberData = FBX->GetFiberPolyData(); if (FiberData == NULL) return; FBXLocalStorage3D *localStorage = m_LSH.GetLocalStorage(renderer); localStorage->m_FiberMapper->SetInput(FiberData); if ( FiberData->GetPointData()->GetNumberOfArrays() > 0 ) localStorage->m_FiberMapper->SelectColorArray( FBX->GetCurrentColorCoding() ); localStorage->m_FiberMapper->ScalarVisibilityOn(); localStorage->m_FiberMapper->SetScalarModeToUsePointFieldData(); localStorage->m_FiberActor->SetMapper(localStorage->m_FiberMapper); // set Opacity float tmpopa; this->GetDataNode()->GetOpacity(tmpopa, NULL); localStorage->m_FiberActor->GetProperty()->SetOpacity((double) tmpopa); // set color if (FBX->GetCurrentColorCoding() != NULL){ localStorage->m_FiberMapper->SelectColorArray(FBX->GetCurrentColorCoding()); MITK_INFO << "MapperFBX: " << FBX->GetCurrentColorCoding(); - if(FBX->GetCurrentColorCoding() == FBX->COLORCODING_CUSTOM){ + if(FBX->GetCurrentColorCoding() == FBX->COLORCODING_CUSTOM) { float temprgb[3]; this->GetDataNode()->GetColor( temprgb, NULL ); double trgb[3] = { (double) temprgb[0], (double) temprgb[1], (double) temprgb[2] }; localStorage->m_FiberActor->GetProperty()->SetColor(trgb); } + + } localStorage->m_FiberMapper->SetLookupTable(m_lut); localStorage->m_FiberAssembly->AddPart(localStorage->m_FiberActor); localStorage->m_LastUpdateTime.Modified(); //since this method is called after generating all necessary data for fiber visualization, all modifications are represented so far. //====timer measurement======== MITK_INFO << "Execution Time GenerateData() (nmiliseconds): " << myTimer.elapsed(); //============================= } void mitk::FiberBundleXMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { if ( !this->IsVisible( renderer ) ) return; // Calculate time step of the input data for the specified renderer (integer value) // this method is implemented in mitkMapper this->CalculateTimeStep( renderer ); //check if updates occured in the node or on the display FBXLocalStorage3D *localStorage = m_LSH.GetLocalStorage(renderer); const DataNode *node = this->GetDataNode(); if ( (localStorage->m_LastUpdateTime < node->GetMTime()) || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified? || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) ) { MITK_INFO << "UPDATE NEEDED FOR _ " << renderer->GetName(); this->GenerateData(renderer); } } void mitk::FiberBundleXMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { // MITK_INFO << "FiberBundleXxXXMapper3D()SetDefaultProperties"; //MITK_INFO << "FiberBundleMapperX3D SetDefault Properties(...)"; // node->AddProperty( "DisplayChannel", mitk::IntProperty::New( true ), renderer, overwrite ); node->AddProperty( "LineWidth", mitk::IntProperty::New( true ), renderer, overwrite ); node->AddProperty( "opacity", mitk::FloatProperty::New( 1.0 ), renderer, overwrite); // node->AddProperty( "VertexOpacity_1", mitk::BoolProperty::New( false ), renderer, overwrite); // node->AddProperty( "Set_FA_VertexAlpha", mitk::BoolProperty::New( false ), renderer, overwrite); // node->AddProperty( "pointSize", mitk::FloatProperty::New(0.5), renderer, overwrite); // node->AddProperty( "setShading", mitk::IntProperty::New(1), renderer, overwrite); // node->AddProperty( "Xmove", mitk::IntProperty::New( 0 ), renderer, overwrite); // node->AddProperty( "Ymove", mitk::IntProperty::New( 0 ), renderer, overwrite); // node->AddProperty( "Zmove", mitk::IntProperty::New( 0 ), renderer, overwrite); // node->AddProperty( "RepPoints", mitk::BoolProperty::New( false ), renderer, overwrite); // node->AddProperty( "TubeSides", mitk::IntProperty::New( 8 ), renderer, overwrite); // node->AddProperty( "TubeRadius", mitk::FloatProperty::New( 0.15 ), renderer, overwrite); // node->AddProperty( "TubeOpacity", mitk::FloatProperty::New( 1.0 ), renderer, overwrite); node->AddProperty( "pickable", mitk::BoolProperty::New( true ), renderer, overwrite); Superclass::SetDefaultProperties(node, renderer, overwrite); } vtkProp* mitk::FiberBundleXMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) { //MITK_INFO << "FiberBundleXxXXMapper3D()GetVTKProp"; //this->GenerateData(); return m_LSH.GetLocalStorage(renderer)->m_FiberAssembly; } void mitk::FiberBundleXMapper3D::ApplyProperties(mitk::BaseRenderer* renderer) { } void mitk::FiberBundleXMapper3D::UpdateVtkObjects() { } void mitk::FiberBundleXMapper3D::SetVtkMapperImmediateModeRendering(vtkMapper *) { } mitk::FiberBundleXMapper3D::FBXLocalStorage3D::FBXLocalStorage3D() { m_FiberActor = vtkSmartPointer::New(); m_FiberMapper = vtkSmartPointer::New(); m_FiberAssembly = vtkSmartPointer::New(); }