commit f18e57ff0e37c84853c3c17fe10c8dfd3cdb27ad Author: Giovanni Fattori Date: Mon Oct 13 15:41:02 2014 +0200 Working version of gLocalize software installed at the CNAO. This extends the embedded function in gOTS code with: - manual volume masking - visualization tools - no memory issues. diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..4b3477a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,154 @@ +cmake_minimum_required (VERSION 2.8) + +IF (NOT CMAKE_BUILD_TYPE) + SET (CMAKE_BUILD_TYPE "Release" CACHE STRING + "Choose the type of build, options are: Debug Release + RelWithDebInfo MinSizeRel." FORCE) +ENDIF () + +project(gLocalize) +set(TRG gLocalize) + + +include_directories (BEFORE ${CMAKE_CURRENT_SOURCE_DIR}) + + +find_package(VTK REQUIRED) +include(${VTK_USE_FILE}) +ADD_DEFINITIONS(${VTK_DEFINITIONS}) + +find_package(Qt4 REQUIRED) +include(${QT_USE_FILE}) +ADD_DEFINITIONS(${QT_DEFINITIONS}) + + +FIND_PACKAGE(GDCM REQUIRED) +IF(NOT GDCM_DIR) + MESSAGE(FATAL_ERROR "Please set GDCM_DIR.") +ELSE(NOT GDCM_DIR) + include(${GDCM_USE_FILE}) + INCLUDE_DIRECTORIES(${GDCM_INCLUDE_DIRS}) +ENDIF(NOT GDCM_DIR) + + +SET(ITK_MIN_VERSION "3.20") + + +FIND_PACKAGE(ITK REQUIRED) +IF(NOT ITK_FOUND) + MESSAGE(SEND_ERROR "ITK ${ITK_MIN_VERSION} not found. Please set the ITK_DIR variable.") +ELSE(NOT ITK_FOUND) + # The version check fails with cmake + # 2.8.4+linux, manually perform check +IF("${ITK_VERSION_MAJOR}.${ITK_VERSION_MINOR}" + VERSION_LESS + ${ITK_MIN_VERSION}) + MESSAGE(SEND_ERROR "ITK ${ITK_MIN_VERSION} not found (version ${ITK_VERSION_MAJOR}.${ITK_VERSION_MINOR} provided). Please set the ITK_DIR variable.") +ELSE("${ITK_VERSION_MAJOR}.${ITK_VERSION_MINOR}" VERSION_LESS ${ITK_MIN_VERSION}) + INCLUDE(${ITK_USE_FILE}) +ENDIF("${ITK_VERSION_MAJOR}.${ITK_VERSION_MINOR}" VERSION_LESS ${ITK_MIN_VERSION}) + +ENDIF(NOT ITK_FOUND) + +# set(QT_ROOT "C:/Qt/4.8.2") +# SET(ZLIB_INCLUDE_DIRS "${QT_ROOT}/src/3rdparty/zlib") +# message("QT_ROOT variable: ${QT_ROOT}") +# message("${ZLIB_INCLUDE_DIRS}") +# include_directories(${ZLIB_INCLUDE_DIRS}) + +IF(UNIX) + find_package(ZLIB REQUIRED) +ELSE(UNIX) + # SET(ZLIB_INCLUDE_DIRS + # "${QT_ROOT}/src/3rdparty/zlib" + # CACHE + # STRING + # "Path + # to + # ZLIB + # headers + # of + # Qt") + SET(ZLIB_LIBRARIES "") + IF(NOT EXISTS "${ZLIB_INCLUDE_DIRS}/zlib.h") + MESSAGE("Please specify a valid zlib include dir") + ENDIF(NOT EXISTS "${ZLIB_INCLUDE_DIRS}/zlib.h") +ENDIF(UNIX) + +include_directories(${PROJECT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${PROJECT_SOURCE_DIR}/src) + +set(SRCS + ${PROJECT_SOURCE_DIR}/main.cpp + ${PROJECT_SOURCE_DIR}/mainw.cpp + ${PROJECT_SOURCE_DIR}/mainw.h + ${PROJECT_SOURCE_DIR}/connectITKVTK.h + ${PROJECT_SOURCE_DIR}/dicomUtils.cpp + ${PROJECT_SOURCE_DIR}/dicomUtils.h + ${PROJECT_SOURCE_DIR}/gPatientRTGeneralInfos.h + ${PROJECT_SOURCE_DIR}/gRen.h + ${PROJECT_SOURCE_DIR}/gRen.cpp + #${PROJECT_SOURCE_DIR}/loadDCM2VTK.h + #${PROJECT_SOURCE_DIR}/loadDCM2VTK.cpp + #${PROJECT_SOURCE_DIR}/wrkDirParser.cpp + #${PROJECT_SOURCE_DIR}/wrkDirParser.h + ${PROJECT_SOURCE_DIR}/gLoadPatient.h + ${PROJECT_SOURCE_DIR}/gLoadPatient.cpp + ${PROJECT_SOURCE_DIR}/gLocalize.h + ${PROJECT_SOURCE_DIR}/gLocalize.cpp + ${PROJECT_SOURCE_DIR}/gSkullRemoval.h + ${PROJECT_SOURCE_DIR}/gSkullRemoval.cpp + ${PROJECT_SOURCE_DIR}/itkQtAdaptor.h + ) + +set(HDR + ${PROJECT_SOURCE_DIR}/mainw.h + ${PROJECT_SOURCE_DIR}/connectITKVTK.h + ${PROJECT_SOURCE_DIR}/dicomUtils.h + ${PROJECT_SOURCE_DIR}/gPatientRTGeneralInfos.h + ${PROJECT_SOURCE_DIR}/gRen.h + #${PROJECT_SOURCE_DIR}/loadDCM2VTK.h + #${PROJECT_SOURCE_DIR}/wrkDirParser.h + ${PROJECT_SOURCE_DIR}/gLoadPatient.h + ${PROJECT_SOURCE_DIR}/gLocalize.h + ${PROJECT_SOURCE_DIR}/gSkullRemoval.h + ${PROJECT_SOURCE_DIR}/itkQtAdaptor.h + + ) +QT4_WRAP_CPP(HDR_MOC ${HDR}) + + + # SET(RES ${PROJECT_SOURCE_DIR}/resources/images.qrc) + # QT4_ADD_RESOURCES(RES_RCC ${RES}) + + +SET(RES ${PROJECT_SOURCE_DIR}/images.qrc) +QT4_ADD_RESOURCES(RES_RCC ${RES}) + + + + ADD_DEFINITIONS(-Wall -O3 -DQT_DLL -DQT_THREAD_SUPPORT) + + add_executable(${TRG} ${SRCS} ${HDR_MOC} ${RES_RCC} ) + #${RES_RCC} ) + + target_link_libraries(${TRG} + ${QT_LIBRARIES} + ${QT_QTMAIN_LIBRARY} + QVTK + ${VTK_LIBRARIES} + ${QT_QTCORE_LIBRARY} + ${QT_QTGUI_LIBRARY} + gdcmCommon + gdcmDICT + ITKIO + ITKCommon + ITKBasicFilters + ITKAlgorithms + ITKNumerics + ITKStatistics + ITKSpatialObject + ) + + diff --git a/connectITKVTK.h b/connectITKVTK.h new file mode 100755 index 0000000..27b625f --- /dev/null +++ b/connectITKVTK.h @@ -0,0 +1,51 @@ +#ifndef __ConnectVTKITK_h +#define __ConnectVTKITK_h + + +#include "itkVTKImageImport.h" +#include "itkVTKImageExport.h" +#include "itkVTKImageExportBase.h" +#include +#include + +//template +//void ConnectITKToVTK(ITK_Exporter in, VTK_Importer* out) + +/*template +void ConnectITKToVTK(itk::VTKImageExport* in, vtkImageImport* out) */ +template +void ConnectITKToVTK(ITK_Exporter in, VTK_Importer* out) +{ + out->SetUpdateInformationCallback(in->GetUpdateInformationCallback()); + out->SetPipelineModifiedCallback(in->GetPipelineModifiedCallback()); + out->SetWholeExtentCallback(in->GetWholeExtentCallback()); + out->SetSpacingCallback(in->GetSpacingCallback()); + out->SetOriginCallback(in->GetOriginCallback()); + out->SetScalarTypeCallback(in->GetScalarTypeCallback()); + out->SetNumberOfComponentsCallback(in->GetNumberOfComponentsCallback()); + out->SetPropagateUpdateExtentCallback(in->GetPropagateUpdateExtentCallback()); + out->SetUpdateDataCallback(in->GetUpdateDataCallback()); + out->SetDataExtentCallback(in->GetDataExtentCallback()); + out->SetBufferPointerCallback(in->GetBufferPointerCallback()); + out->SetCallbackUserData(in->GetCallbackUserData()); + }; + + //template + //void ConnectVTKToITK(vtkImageExport* in, itk::VTKImageImport* out) +template +void ConnectVTKToITK(VTK_Exporter *in, ITK_Importer out) + { + out->SetUpdateInformationCallback(in->GetUpdateInformationCallback()); + out->SetPipelineModifiedCallback(in->GetPipelineModifiedCallback()); + out->SetWholeExtentCallback(in->GetWholeExtentCallback()); + out->SetSpacingCallback(in->GetSpacingCallback()); + out->SetOriginCallback(in->GetOriginCallback()); + out->SetScalarTypeCallback(in->GetScalarTypeCallback()); + out->SetNumberOfComponentsCallback(in->GetNumberOfComponentsCallback()); + out->SetPropagateUpdateExtentCallback(in->GetPropagateUpdateExtentCallback()); + out->SetUpdateDataCallback(in->GetUpdateDataCallback()); + out->SetDataExtentCallback(in->GetDataExtentCallback()); + out->SetBufferPointerCallback(in->GetBufferPointerCallback()); + out->SetCallbackUserData(in->GetCallbackUserData()); + }; + #endif \ No newline at end of file diff --git a/dicomUtils.cpp b/dicomUtils.cpp new file mode 100755 index 0000000..c089dd2 --- /dev/null +++ b/dicomUtils.cpp @@ -0,0 +1,485 @@ +#include "dicomUtils.h" + + +//FUNCTION DECLARATION NECESSARY FOR COPY/PASTE FROM vtkGDCMImageReader +// const char *gGetStringValueFromTag(const gdcm::Tag& t, const gdcm::DataSet& ds); + + const char *gGetStringValueFromTag(const gdcm::Tag& t, const gdcm::DataSet& ds) +{ + static std::string buffer; + buffer = ""; // cleanup previous call + if( ds.FindDataElement( t ) ) + { + const gdcm::DataElement& de = ds.GetDataElement( t ); + const gdcm::ByteValue *bv = de.GetByteValue(); + if( bv ) // Can be Type 2 + { + buffer = std::string( bv->GetPointer(), bv->GetLength() ); + // Will be padded with at least one \0 + } + } + // Since return is a const char* the very first \0 will be considered + return buffer.c_str(); +}; + + //GENERAL INDEPENDENT FUNCTION TO CHECK FOR FILE DICOM MODALITY (PLAN, STRUCT, IMAGE) REQUIRES CORRECT PATH +const char * gCheckDICOMModality(const char *filename) +{ + gdcm::Reader gR; + gR.SetFileName(filename);//str.toAscii().data()); + if(!gR.Read()) + return("NODCMFILE"); + + const gdcm::File &file = gR.GetFile(); + const gdcm::DataSet &ds = file.GetDataSet(); + return(gGetStringValueFromTag( gdcm::Tag(0x0008,0x0060), ds) ); //RETURN MODALITY +}; + +int gCheckDICOMModalityToInt(const char *filename){ + + const char * tmp = gCheckDICOMModality(filename); + //cout<< tmp< sqiPS = gSetupSequence.GetValueAsSQ(); + const gdcm::DataSet& gPatSetupNest = sqiPS->GetItem(1).GetNestedDataSet(); + //SET PATIENT ORIENTATION STRING + strcpy(PatientOrientation, gGetStringValueFromTag(gdcm::Tag(0x0018, 0x5100),gPatSetupNest)); + + const gdcm::DataElement &gBeamSequence=ds.GetDataElement(gdcm::Tag(0x300a,(IsCarbon==false ? 0x03a2 : 0x00b0))); +// (THESE ARE THE BEAMS) + gdcm::SmartPointer sqi = gBeamSequence.GetValueAsSQ(); + if(!sqi || !sqi->GetNumberOfItems()) + { + cout<<"usteria" <GetNumberOfItems(); + //ALLOCATE BEAM STRUCTURES + Beams=new IonBeamProperties* [NumberOfBeams]; + memset(Beams,NULL,NumberOfBeams*sizeof(IonBeamProperties *)); + + + //ITERATES ON BEAM NUMBER + for(int i=0;iGetItem(i+1); //ITEM START FROM 1 + const gdcm::DataSet& gBeamNestedds = item.GetNestedDataSet(); //THIS IS BEAM DATASET + + //ALLOCATE BEAM CLASS + Beams[i]=new IonBeamProperties; + //READ BEAM DATA + Beams[i]->BeamNumber = (atoi(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x00c0),gBeamNestedds))); //BEAM NUMBER + strcpy (Beams[i]->BeamName,(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x00c2),gBeamNestedds))); //BEAM NAME + + if(IsCarbon==false) + strcpy (Beams[i]->SupportType,gGetStringValueFromTag(gdcm::Tag(0x300a, 0x0350),gBeamNestedds));//PATIENT SUPPORT TYPE IMPLEMENT TRICK FOR THE CHAIR + else strcpy(Beams[i]->SupportType,"TABLE"); + + strcpy(Beams[i]->SupportId,gGetStringValueFromTag(gdcm::Tag(0x300a, 0x0352),gBeamNestedds));//PATIENT SUPPORT TYPE IMPLEMENT TRICK FOR THE CHAIR + +//gBeams[i]->gSetSupportType("CHAIR"); + + //READ GEOMETRY + //READ SEQUENCE OF CONTROL POINTS + //v04Build27 DO DIFFERENTLY IF PROTONS OR CARBONS + const gdcm::DataElement &gCPSequence=gBeamNestedds.GetDataElement(gdcm::Tag(0x300a,IsCarbon==false ? 0x03a8 : 0x0111)); + //FIND ITEM SEQUENCE (THESE ARE THE CONTROL POINTS) + gdcm::SmartPointer sqicp = gCPSequence.GetValueAsSQ(); + + //READ DATA FROM ITEM 1 + const gdcm::DataSet& gCPNestedds = sqicp->GetItem(1).GetNestedDataSet(); + + //GANTRY ANGLE (NEEDED FOR CHAIR ?) + Beams[i]->GantryAngle=atoi(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x011e),gCPNestedds)); + + //ISOCENTER POSITION (THIS IS BEAM POSITION NOT PATIENT ALIGNMENT (VOLUME CENTER) POSITION) + double iso[3]; + char str[MAXSTRINGLENGHT]; + strcpy(str,gGetStringValueFromTag(gdcm::Tag(0x300a, 0x012c),gCPNestedds)); + + Beams[i]->IsocenterPosition[0]=atof(strtok(str,"\\")); + Beams[i]->IsocenterPosition[1]=atof(strtok(NULL,"\\")); + Beams[i]->IsocenterPosition[2]=atof(strtok(NULL,"\\")); +// Beams[i]->IsocenterPosition[](iso[0],iso[1],iso[2]); + + //SUPPORT ANGLE (YAW ANGLE OF SUPPORT WITH RESPECT TO FIXED REFERENCE SYSTEM) AROUND Z AXIS (VERTICAL) + //POSITIVE COUNTER-CLOCKWISE WHEN VIEWED FROM TOP OF Z-Axis + Beams[i]->TableYawAngle=atof(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x0122),gCPNestedds)); +/*if(i==1) + gBeams[i]->gSetTableYawAngle(0); +*/ + //TABLE TOP PITCH (ROTATION AROUND X AXIS, i.e. LATERAL AXIS OF TABLE AND BEAM DIRECTION IN FIXED REF SYS) + ////v04Build27 IF PROTONS READ IT FROM PLAN; IF CARBONS SET DEFAULT VALUE (0.0) AND FORGET CHAIR + if(IsCarbon==false) + { gdcm::Attribute <0x300a, 0x0140> pa; + pa.SetFromDataElement(gCPNestedds.GetDataElement( pa.GetTag())); + Beams[i]->TablePitchAngle =pa.GetValue(); + } + else + (Beams[i]->TablePitchAngle)=(0.0); + +//v04 Build23 SET SUPPORT TYPE CORRECTLY IF PITCH IS 90 (IT IS CHAIR); DO IT FOR ALL BEAMS +// if(i==0) +// { if(Beams[i]->TablePitchAngle()>45) +// strcpy (Beams[i]->SupportType,("CHAIR")); +// } +// else if (i>0) +// { if(Beams[0]->SupportChair()==true) +// Beams[i]->gSetSupportType("CHAIR"); +// } + + //TABLE TOP ROLL (ROTATION AROUND Y AXIS, i.e. LONGITUDINAL AXIS OF TABLE) + //v04Build27 IF PROTONS READ IT FROM PLAN; IF CARBONS SET DEFAULT VALUE (0.0) + if(IsCarbon==false) + { gdcm::Attribute <0x300a, 0x0144> ra; + ra.SetFromDataElement(gCPNestedds.GetDataElement(ra.GetTag())); + Beams[i]->TableRollAngle =(ra.GetValue()); + } + else + (Beams[i]->TableRollAngle)=(0.0); + + + + + + //WHAT ABOUT TABLE TOP VERTICAL POSITION, LOGITUDINAL AND LATERAL POSITION ? USEFUL SOMEHOW ? + // THEY ARE READ AND USED TO REALIZE VOLUME CENTER ALIGNMENT IN ROOM ISOCENTER + //FIND PATIENT SETUP SEQUENCE (IT IS UNIQUE FOR ALL BEAMS BUT I DO IT BEAM BY BEAM) + //v04Build27 DO NOT LOOK FOR PATIENT SETUPSEQUENCE + /* if(!ds.FindDataElement(gdcm::Tag(0x300a,0x0180))) + throw(gException("CRITICAL: PATIENT SETUP SEQUENCE NOT FOUND IN RT ION PLAN")); + const gdcm::DataElement &gPatientSetupSequence=ds.GetDataElement(gdcm::Tag(0x300a,0x0180)); + gdcm::SmartPointer sqpt = gPatientSetupSequence.GetValueAsSQ(); + int psuseq=sqpt->GetNumberOfItems(); //CHECK NUMBER OF SETUPSEQUENCE VS BEAM NUMBER + + //READ DATA FROM ITEM 1 OR BEAM IS MORE PATIENT SETUP SEQUENCE ARE FOUND (ATTENTION !!!!) + //v03 Build30: READ TABLE POSITIONS FROM SETUPSEQUENCE + const gdcm::DataSet& gPSNestedds = sqpt->GetItem((i+1)<=psuseq ? (i+1) : 1).GetNestedDataSet(); //IF PSTIENT SETUP SEQUENCE < THAN BEAMS USE FIRST +*/ + //v04Build27 READ BEAMS ABSOLUTE GEOMETRY NOT FROM SETUP SEQUENCE BUT FROM CONTROL POINT SEQUENCE (NEW VERSION OIS FOR CARBONS) + + /*float tablelat=atof(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x01d6),gPSNestedds)); + float tablelong=atof(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x01d4),gPSNestedds)); + float tablevert=atof(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x01d2),gPSNestedds));*/ + + float deltatablelat=atof(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x012a),gCPNestedds)); + float deltatablelong=atof(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x0129),gCPNestedds)); + float deltatablevert=atof(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x0128),gCPNestedds)); + + //v03 (Build 30) NOW ADD TO TREATMENT BEMA EVENTUAL RELATIVE SHIFTS BETWEEN SETUP SEQUENCE AND STORE IN BEAM STRUCTURE ONLY TO TREATMETN BEAMS + // if(i==0) //THIS IS SETUP BEAM DO NOTHING +//v04Build26 TREAT ALL BEAMS THE SAME WAY (SET-UP+BEAMS)(NEW VERSION OF OIS) +//v04Build27 USE PPS GEOMETRY READ FROM POINT SEQUENCE + { Beams[i]->TableLatDispl=(deltatablelat); + Beams[i]->TableLongDispl=(deltatablelong); + Beams[i]->TableVertDispl=(deltatablevert); + } + /* else + { gBeams[i]->gSetTableLatDispl(tablelat); + gBeams[i]->gSetTableLongDispl(tablelong); + gBeams[i]->gSetTableVertDispl(tablevert); + }*/ +//v04Build26 DO NOT ADD DELTASHIFTS (NEW VERSION OF OIS) + //v04Build1: CHECK FOR VIRTUAL ISO + + + //ADD DELTASHIFTS TO TABLE DISPLACEMENTS + //v04Build26 DO NOT ADD DELTASHIFTS (NEW VERSION OF OIS) + /*gBeams[i]->gSetTableLatDispl(tablelat+atof(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x012a),gCPNestedds))); + gBeams[i]->gSetTableLongDispl(tablelong+atof(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x0129),gCPNestedds))); + gBeams[i]->gSetTableVertDispl(tablevert+atof(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x0128),gCPNestedds))); + + //UPDATE ISOCENTER POSITION ON TREATMENT BEAM USING CT REFERENCE (LONG IS Z COORDINATE; Y IS VERTICAL; Z I) + //v04Build26 DO NOT ADD DELTASHIFTS (NEW VERSION OF OIS) + + gBeams[i]->gSetIsocenterPosition(iso[0]-deltatablelat,iso[1]-deltatablevert,iso[2]-deltatablelong); //SIGNS AND COORDINATE TO BE CHECKED (OK for LONG) + + } +*/ + + //v04Build28 CORRECT ISO POSITION IN CASE OF VIRTUAL ISO + /* if(i<0) //DO THIS ONLY FOR TREATMENT BEAMS + gBeams[i]->gSetIsocenterPosition(iso[0]-(gBeams[i]->gGetTableLatDispl()-gBeams[0]->gGetTableLatDispl()),iso[1]-(gBeams[i]->gGetTableVertDispl()-gBeams[0]->gGetTableVertDispl()),iso[2]-(gBeams[i]->gGetTableLongDispl()-gBeams[0]->gGetTableLongDispl())); //SIGNS AND COORDINATE TO BE CHECKED (OK for LONG) +*/ + //UPDATE AT FIRST CNAO PATIENT SET TABLE POSITION FROM PLAN AT THE ISOCENTER POSITION FOR EVERY BEAM + /* gBeams[i]->gSetTableLatDispl(gBeams[i]->gGetIsocenterPosition()[0]); + gBeams[i]->gSetTableLongDispl(gBeams[i]->gGetIsocenterPosition()[1]);gui + gBeams[i]->gSetTableVertDispl(gBeams[i]->gGetIsocenterPosition()[2]); +*/ + // FILL gPPS CLASS WITH CURRENT PPS CONFIGURATION UPDATING CONVENTIONS FROM PLAN TO PPS (-90 FOR CONVENTION CT-PPS) +// Beams[i]->gGetCurrentPPS()->gSetPPSXPlan(gBeams[i]->gGetTableLatDispl()); +// Beams[i]->gGetCurrentPPS()->gSetPPSYPlan(gBeams[i]->gGetTableLongDispl()); +// Beams[i]->gGetCurrentPPS()->gSetPPSYOrig(gBeams[i]->gGetTableLongDispl()); //SAVE ALSO AN ORIGINAL COPY FROM PLAN OF LONGITUFINAL POSITION (FOR INDEXING DIALOG) +// Beams[i]->gGetCurrentPPS()->gSetPPSZPlan(gBeams[i]->gGetTableVertDispl()); +// + + + //v03 Build35: ADD TO TREATMENT BEAMS YAW THE YAW VALUE OF SETUP BEAM TO RECOVER ABSOLUTE VALUES FROM RELATIVE ONES AS SENT BY OIS + if(i>0) // THIS IS TREATMENT BEAM + { //v04Build03 SET PROPER DELTA ANGLES FOR BEAM ROTATION (IF DELTA IS NEGATIVE SET IT NEGATIVE) + double yaw=Beams[i]->TableYawAngle; + if(yaw>180) + yaw=yaw-360; + //V04Build26 NEW VERSION OF MOSAIQ OIS DO NOT USE RELATIVE ANGLES + //yaw=yaw+gBeams[0]->gGetTableYawAngle(); + Beams[i]->TableYawAngle=(yaw); + + double pitch=Beams[i]->TablePitchAngle; + if(pitch>180) + pitch=pitch-360; + //V04Build26 NEW VERSION OF MOSAIQ OIS DO NOT USE RELATIVE ANGLES + //pitch=pitch+gBeams[0]->gGetTablePitchAngle(); + //v04Build23 SET ALL PITCH AT 90 (NOT STABLE) IT IS FOR THE CHAIR + if(pitch>150) pitch=90; + Beams[i]->TablePitchAngle=(pitch); + + + double roll=Beams[i]->TableRollAngle; + if(roll>180) + roll=roll-360; + //V04Build26 NEW VERSION OF MOSAIQ OIS DO NOT USE RELATIVE ANGLES + //roll=roll+gBeams[0]->gGetTableRollAngle(); + Beams[i]->TableRollAngle=(roll); + } + + //HERE 90 DEGREES IS SUMMED IN ORDER TO SOLVE TEH AMBIGUITY BETWEEN TPS REFERENCE AND ROOM/ODEVIS REFERENCE + //0 DEGREE YAW IN TPS BECOMES +90 YAW IN ROOM/PPS MEANING BEAM IS FROM LATERAL + //THIS WE DO IT JUST FOR THE USER INTERFACE DISPLAYING DEGREES OF YAW ROTATION EXPECTED OR TO BE INSERTED IN THE PPS + //v04Build24 ADJUST PPS YAW ANGLE FOR PPS AND CHAIR +// double yaw=gBeams[0]->gIsSupportChair()==false ? gBeams[i]->gGetTableYawAngle()+90.0 : gBeams[i]->gGetTableYawAngle()-90.0; +// //NOW SET +- 180 YAW ROTATION CONVENTION +// if(yaw>180) +// yaw=yaw-360; +// gBeams[i]->gGetCurrentPPS()->gSetPPSRotateDegreePlan(yaw); //CONVERSION FROM CT BASE PLAN TO PPS (ANGLE RANGES -180 +180) +// +// //v04Build23 ATTENZIONE ! +// if(gBeams[0]->gIsSupportChair()==false) gBeams[i]->gGetCurrentPPS()->gSetPPSPitchDegreePlan(gBeams[i]->gGetTablePitchAngle()); +// else gBeams[i]->gGetCurrentPPS()->gSetPPSPitchDegreePlan(gBeams[i]->gGetTablePitchAngle()-90); //NEED TO SUBTRACT 90 DEGRESS FOR PPS CONFIGURATION : THERE IS THE CHAIR +// +// gBeams[i]->gGetCurrentPPS()->gSetPPSRollDegreePlan(gBeams[i]->gGetTableRollAngle()); +// +// +// +// //SET CURRENT PPS CONFIGURATION WITH PLAN CONFIGURATION (THERE I TAKE CARE OF THE CHAIR) +// gBeams[i]->gGetCurrentPPS()->gSetPlanConfig(); + + /* //UPDATE TABLE DISPLACEMENT ACCORDING TO SIEMENS TPS USING THE ISOCENTER CO-ORDINATESIF DEFINE W.R.T. INDEXING POINT + //MIGHT NEED TO SUBTRACT COORDINATES OF STRUCTURE VOLUMECENTER IF RELATIVE REFERENCE SYSTEM IS NOT DEFINED IN TPS + gBeams[i]->gSetTableLatDispl(gBeams[i]->gGetIsocenterPosition()[0]); + gBeams[i]->gSetTableLongDispl(gBeams[i]->gGetIsocenterPosition()[1]); + gBeams[i]->gSetTableVertDispl(gBeams[i]->gGetIsocenterPosition()[2]);*/ +// gBeams[i]->gSetIsocenterPosition(iso[0]- gBeams[i]->gGetCurrentPPS()->getPPSXPlan(),iso[1]- gBeams[i]->gGetCurrentPPS()->getPPSYPlan(),iso[2]- gBeams[i]->gGetCurrentPPS()->getPPSZPlan()); + + + } + return true; + }; diff --git a/dicomUtils.h b/dicomUtils.h new file mode 100755 index 0000000..cbfdd3c --- /dev/null +++ b/dicomUtils.h @@ -0,0 +1,95 @@ + +//FUNCTION DECLARATION NECESSARY FOR COPY/PASTE FROM vtkGDCMImageReader +// const char *gGetStringValueFromTag(const gdcm::Tag& t, const gdcm::DataSet& ds); + +#ifndef DICOMUTILITIES +#define DICOMUTILITIES +//gdcm +#include +#include +#include +#include +#include + +using namespace std; + +#define MAXSTRINGLENGHT 255 +#define BADVALUE -9999 + +enum{ + RTPLAN, + RTSTRUCT, + IMAGE, + NODCMFILE +}; + +const char *gGetStringValueFromTag(const gdcm::Tag& t, const gdcm::DataSet& ds); +const char * gCheckDICOMModality(const char *filename); +int gCheckDICOMModalityToInt(const char *filename); + + +class IonBeamProperties{ +public: +IonBeamProperties(); + +~IonBeamProperties(); + +int BeamNumber; +char* BeamName; +char* SupportType; +char* SupportId; +int GantryAngle; +double* IsocenterPosition; +float TableYawAngle; +float TablePitchAngle; +float TableRollAngle; +float TableLatDispl; +float TableLongDispl; +float TableVertDispl; + +void PrintSelf(); +}; + +/*-----*/ +//CLASS gIonBEAMProperties +class RTPlan +{ + public: + char* PatientName; + char* PatientID; + char* PatientSex; + char* PatientAge; + char* PatientBirthDate; + char* SeriesNumber; + char* SeriesDescription; + char* StudyID; + char* StudyDescription; + char* Modality; + + double* IsocenterPosition; + double* VolumeCenter; + int BeamNumber; + char* BeamName; + double TableRollAngle; + double TableYawAngle; + double TablePitchAngle; + double TableLatDispl; + double TableVertDispl; + double TableLongDispl; + char* SupportType; + char* SupportId; + char* PatientOrientation; + int NumberOfBeams; + + IonBeamProperties** Beams; + + + ~RTPlan(); + + RTPlan(); + void PrintSelf(); + + bool fillRTPlan( char *filertionplan); + }; + +#endif \ No newline at end of file diff --git a/gLoadPatient.cpp b/gLoadPatient.cpp new file mode 100755 index 0000000..dccab8b --- /dev/null +++ b/gLoadPatient.cpp @@ -0,0 +1,434 @@ +#include "gLoadPatient.h" + + +/*_________________________________________________________- + +Patient loader for gLocalize. +no wrkDir behaviour. just load data +____________________________________________________________*/ + + +gLoadPatient::gLoadPatient(){ + patientInfos = new gPatientRTGeneralInfos; + readRT=0; + m_rtIsocenter=0; + initialized=false; + virtualIso=false; + //cout<< "gLoadPatient::gLoadPatient" <parse(p_loadDir); + + if(patientInfos->CTfiles .size()!=0){ + cout<< "this->load2VTK(patientInfos)" <rtIonPlanPath.isEmpty()){ + readRT = new RTPlan; + readRT->fillRTPlan(patientInfos->rtIonPlanPath.toLatin1().data() ); + m_rtIsocenter = new double[3]; + if (readRT->NumberOfBeams > 0){ + memcpy(m_rtIsocenter, readRT->Beams[0]->IsocenterPosition, 3* sizeof(double) ); + if (strncmp (readRT->PatientOrientation,"HFS",3) == 0 ) + m_patientOrientation = SUPINE; + else if (strncmp (readRT->PatientOrientation,"HFP",3) == 0 ) + m_patientOrientation = PRONE; + else m_patientOrientation = NOTDEFINED; + + emit loadedRTIso(m_rtIsocenter); + //for (int ii=0;iiNumberOfBeams; ii++){ + // cout<< readRT->Beams[ii]->IsocenterPosition[0]<<" "; + // cout<< readRT->Beams[ii]->IsocenterPosition[1]<<" "; + // cout<< readRT->Beams[ii]->IsocenterPosition[2]<<" "<NumberOfBeams <Beams[0]->IsocenterPosition[0] <Beams[2]->IsocenterPosition[0]<Beams[0]->IsocenterPosition[1] <Beams[2]->IsocenterPosition[1]<Beams[0]->IsocenterPosition[2] <Beams[2]->IsocenterPosition[2]<NumberOfBeams > 2 && + (readRT->Beams[0]->IsocenterPosition[0] != readRT->Beams[2]->IsocenterPosition[0] || + readRT->Beams[0]->IsocenterPosition[1] != readRT->Beams[2]->IsocenterPosition[1] || + readRT->Beams[0]->IsocenterPosition[2] != readRT->Beams[2]->IsocenterPosition[2]) + ) + virtualIso=true; + else + virtualIso=false; + //cout << "virtual Iso: "<loadDICOM(patientInfos->CTfiles); + this->connectToVTK(); + this->changeRef(GOTSREF); + //trueOffset_rot_prev=trueOffset_rot; + + + //this->load2VTK(patientInfos); + } else { + //DO NOTHING. THE folderisempty signal was already emitted. + } + cout<< " gLoadPatient::load _ END" <SetDirection( /*imageDir*/directionToWCS ); + myImage->SetOrigin( trueOffset_rot ); + myImage->Update(); + + in->SetInput(myImage); + this->connectToVTK(); + this->actualizeOut(); + + /*calculate deltas for marker representation update*/ + if(initialized){ + emit referenceChange( + trueOffset_rot_prev[0]-trueOffset_rot[0], + trueOffset_rot_prev[1]-trueOffset_rot[1], + trueOffset_rot_prev[2]-trueOffset_rot[2]); + trueOffset_rot_prev=trueOffset_rot; + } else { + trueOffset_rot_prev=trueOffset_rot; + initialized=true; + } + +} + +void gLoadPatient::loadDICOM(std::vector CTfilenames){ + + myImage = myImageType::New(); + rDICOM = itk::ImageSeriesReader::New(); + iGDCMimage = itk::GDCMImageIO::New(); + myDICOMseries = itk::GDCMSeriesFileNames::New(); + + rDICOM->SetImageIO(iGDCMimage); + rDICOM->SetFileNames(CTfilenames); + // rDICOM->SetReverseOrder(true); + try{ + rDICOM->Update(); + } + catch (itk::ExceptionObject &ex){ + std::cout << ex << std::endl; + return; // error! + } + + myImage=rDICOM->GetOutput(); + imageDir = myImage->GetDirection( ); + origin = myImage->GetOrigin( ); + sizeOfImage = myImage->GetLargestPossibleRegion().GetSize(); + +} + +void gLoadPatient::connectToVTK(){ + + + out = vtkSmartPointer::New(); + + in = itk::VTKImageExport ::New(); + in->SetInput(myImage); + + out->SetUpdateInformationCallback(in->GetUpdateInformationCallback()); + out->SetPipelineModifiedCallback(in->GetPipelineModifiedCallback()); + out->SetWholeExtentCallback(in->GetWholeExtentCallback()); + out->SetSpacingCallback(in->GetSpacingCallback()); + out->SetOriginCallback(in->GetOriginCallback()); + out->SetScalarTypeCallback(in->GetScalarTypeCallback()); + out->SetNumberOfComponentsCallback(in->GetNumberOfComponentsCallback()); + out->SetPropagateUpdateExtentCallback(in->GetPropagateUpdateExtentCallback()); + out->SetUpdateDataCallback(in->GetUpdateDataCallback()); + out->SetDataExtentCallback(in->GetDataExtentCallback()); + out->SetBufferPointerCallback(in->GetBufferPointerCallback()); + out->SetCallbackUserData(in->GetCallbackUserData()); + +} + +void gLoadPatient::actualizeOut(){ + + //in->Update(); + out->Update(); + //vol3D = vtkSmartPointer ::New(); + //vol3D->DeepCopy(out->GetOutput()); + //vol3D->Update(); + vol3D = out->GetOutput(); + cout<GetSpacing()[0] <<" "<GetSpacing()[1] <<" "<GetSpacing()[2] <clearInfo() " <clearInfo(); + + std::cout<<"parsing dir: "<c_str()).fileName().split(".").last() != QString("raw") ) + patientInfos->filenames.push_back( it->c_str() ); + } + patientInfos->filenames.size() == 0 ? result = PARSER_FOLDER_EMPTY : result = NOERRORS; + } else { + result=PARSER_FOLDER_NOTEXISTING; + }; + + cout << " patientInfos->filenames.size() "<filenames.size() <filenames.size()-1);i>-1;i--) + { + //cout << gCheckDICOMModalityToInt(patientInfos->filenames.at(i).c_str()) <SetFileName (patientInfos->filenames.at(i).c_str()); + + if( !fileReader->Read() ) { + cout<< "Error reading file: "<< patientInfos->filenames.at(i).data() <filenames.erase(patientInfos->filenames.begin()+i); + continue; + } + + //msStructRTIonPlan.SetFromFile( fileReader->GetFile() ); + //if( msStructRTIonPlan == gdcm::MediaStorage::RTIonPlanStorage ) + if( gCheckDICOMModalityToInt(patientInfos->filenames.at(i).c_str()) == RTPLAN ) + { + if(!patientInfos->rtIonPlanPath.isEmpty()) { +// result=PARSER_RTPLAN_NOTUNIQUE; + continue; + } else { + const gdcm::File &file = fileReader->GetFile(); + const gdcm::DataSet &ds = file.GetDataSet(); + //PATIENT NAME + strcpy( patientInfos->PatientName,gGetStringValueFromTag( gdcm::Tag(0x0010,0x0010), ds)); + // // // PATIENT ID For ex: DICOM (0010,0020) = 1933197 + strcpy( patientInfos->PatientID , gGetStringValueFromTag( gdcm::Tag(0x0010,0x0020), ds)); + // // // PATIENT AGE For ex: DICOM (0010,1010) = 031Y + strcpy( patientInfos->PatientAge , gGetStringValueFromTag( gdcm::Tag(0x0010,0x1010), ds)) ; + // // // PATIENT SEX For ex: DICOM (0010,0040) = M + strcpy( patientInfos->PatientSex, gGetStringValueFromTag( gdcm::Tag(0x0010,0x0040), ds) ); + // // // PATIENT BIRTHDATE For ex: DICOM (0010,0030) = 19680427 + strcpy( patientInfos->PatientBirthDate, gGetStringValueFromTag( gdcm::Tag(0x0010,0x0030), ds) ); + // // // SERIES NUMBER For ex: DICOM (0020,0011) = 902 + strcpy( patientInfos->SeriesNumber, gGetStringValueFromTag( gdcm::Tag(0x0020,0x0011), ds) ); + // // // SERIES DESCRIPTION For ex: DICOM (0008,103e) = SCOUT + strcpy( patientInfos->SeriesDescription , gGetStringValueFromTag( gdcm::Tag(0x0008,0x103e), ds) ); + // // // STUDY ID For ex: DICOM (0020,0010) = 37481 + strcpy( patientInfos->StudyID, gGetStringValueFromTag( gdcm::Tag(0x0020,0x0010), ds) ); + // // // STUDY DESCRIPTION For ex: DICOM (0008,1030) = BRAIN/C-SP/FACIAL + strcpy( patientInfos->StudyDescription, gGetStringValueFromTag( gdcm::Tag(0x0008,0x1030), ds) ); + + const gdcm::DataElement &gSetupSequence=ds.GetDataElement(gdcm::Tag(0x300a,0x0180)); + //LOOK FOR PATIENT ORIENTATION + gdcm::SmartPointer sqiPS = gSetupSequence.GetValueAsSQ(); + const gdcm::DataSet& gPatSetupNest = sqiPS->GetItem(1).GetNestedDataSet(); + //SET PATIENT ORIENTATION STRING + strcpy(patientInfos->PatientOrientation, gGetStringValueFromTag(gdcm::Tag(0x0018, 0x5100),gPatSetupNest)); + + + + patientInfos->rtIonPlanPath=QString(patientInfos->filenames.at(i).c_str()); + cout<< "RTPlan import success" <filenames.erase(patientInfos->filenames.begin()+i); + delete fileReader; + continue; + } + } + + // msStructRTStruct.SetFromFile( fileReader->GetFile() ); + // if( msStructRTStruct == gdcm::MediaStorage::RTStructureSetStorage ) { + if( gCheckDICOMModalityToInt(patientInfos->filenames.at(i).c_str()) == RTSTRUCT ){ + if(!patientInfos->rtStructurePath.isEmpty()) { + patientInfos->rtStructurePath.clear(); +// result=PARSER_RTSTRUCT_NOTUNIQUE; + continue; + } else { + patientInfos->rtStructurePath=QString(patientInfos->filenames.at(i).c_str()); + cout<< "RTStruct import success" <filenames.erase(patientInfos->filenames.begin()+i); + delete fileReader; + continue; + } + } + delete fileReader; + } + + + //OK + //if(result == NOERRORS && patientInfos->rtIonPlanPath.isEmpty() ) + // result= PARSER_RTPLAN_MISSING; + //if(result == NOERRORS && patientInfos->rtStructurePath.isEmpty()) + // result=PARSER_RTSTRUCT_MISSING; + + s.SetComputeZSpacing( true ); + s.SetZSpacingTolerance( 1e-2 ); + + if(result==NOERRORS) + if(!s.Sort( patientInfos->filenames ) ) { + result=PARSER_CT_FAILED_SORTING; + } else { + s.GetFilenames().size() == 0 ? result = PARSER_CT_FILES_MISSING : result=NOERRORS; + } + + if(result == NOERRORS){ + patientInfos->CTfiles=s.GetFilenames (); + //cout<< "CT files sorting succeeded" < +#include +#include "gPatientRTGeneralInfos.h" +//#include "wrkDirParser.h" +#include +#include +#include +#include +#include +#include "dicomUtils.h" + + +/*_________________________________________________________- + +Patient loader for gLocalize. +no wrkDir behaviour. just load data +____________________________________________________________*/ + + +#include "connectITKVTK.h" +#include "itkAnalyzeImageIO.h" +#include "itkChangeInformationImageFilter.h" +#include "itkImage.h" +#include "itkImage.h" +#include "itkImageFileWriter.h" +#include "itkOrientImageFilter.h" +#include "itkPermuteAxesImageFilter.h" +#include "itkRescaleIntensityImageFilter.h" +#include "itkImageSeriesReader.h" +#include "itkGDCMImageIO.h" +#include "itkGDCMSeriesFileNames.h" +#include "gdcmIPPSorter.h" + + +#ifndef TPATIENTORIENTATION +#define TPATIENTORIENTATION + typedef enum { + NOTDEFINED=0, + SUPINE = 1, + PRONE =2 + } t_patientOrientation; +#endif + +#ifndef PARSERVARIABLES +#define PARSERVARIABLES + enum patientErrors { + NOERRORS, + PARSER_FOLDER_NOTEXISTING, + PARSER_FOLDER_EMPTY, + PARSER_RTPLAN_NOTUNIQUE, + PARSER_RTPLAN_MISSING, + PARSER_RTSTRUCT_NOTUNIQUE, + PARSER_RTSTRUCT_MISSING, + PARSER_CT_FILES_MISSING, + PARSER_CT_FAILED_SORTING, + POPULATE_INCONSISTENT_DATASET, + POPULATE_NOTEXISTING, + CLEAR_FOLDER_NOTEXISTING + }; + + + enum patientParseOption{ + NOCLEAN, + CLEAN + }; + enum patientCleanMode{ + JUSTCLEAR, + ISLOADINGCHECK + }; +#endif + +#ifndef _T_REFERENCE_ +#define _T_REFERENCE_ +typedef enum{ + DCMREF=0, + RTREF=1, + GOTSREF=2 +}t_reference; + +#endif + + typedef itk::Image myImageType; + + +class gLoadPatient : public QObject{ + Q_OBJECT +public: + gLoadPatient(); + +public slots: + void load(QString p_loadDir); + void changeRef(int selectedRef); + +private: + QString loadDir; + gPatientRTGeneralInfos* patientInfos; + void loadDICOM(std::vector CTfilenames); + void connectToVTK(); + void actualizeOut(); + void parse(QString p_loadDir); + t_patientOrientation m_patientOrientation; + vtkSmartPointer vol3D; + + myImageType::Pointer myImage; + itk::ImageSeriesReader::Pointer rDICOM; + itk::GDCMImageIO::Pointer iGDCMimage ; + itk::GDCMSeriesFileNames::Pointer myDICOMseries; + myImageType::DirectionType imageDir; + myImageType::PointType origin; + myImageType::SizeType sizeOfImage; + myImageType::PointType trueOffset; + myImageType::PointType trueOffset_rot; + myImageType::PointType trueOffset_rot_prev; + myImageType::DirectionType directionToWCS; + + bool initialized; + + vtkSmartPointer out; + itk::VTKImageExport ::Pointer in; + + RTPlan * readRT; + double* m_rtIsocenter; + bool virtualIso; + t_reference m_reference; + +signals: + void folderIsEmpty(); + void statusInfo(QString msg); + void parse_result(int result, gPatientRTGeneralInfos* patientInfos); + void loadFail(QString msg); + void loadEnd(vtkImageData* vol); + void loadedRTIso(double *iso); + void loadedVolBBox(double* bbox, double* spacing, int* dimension); + void referenceChange(double dx, double dy, double dz); + void virtualIsoTested(bool virtualIso); + +}; + +#endif \ No newline at end of file diff --git a/gLocalize.cpp b/gLocalize.cpp new file mode 100755 index 0000000..ba52403 --- /dev/null +++ b/gLocalize.cpp @@ -0,0 +1,380 @@ +#include "gLocalize.h" + +#include +#include + +gLocalize::gLocalize(){ + + abortSignal=false; +} + + +void gLocalize::localize(vtkImageData* vol, + int march_tresh, + double thrDown_D, + double thrUp_D, + double thr_HAUSD, + double thr_S, + QList selectedFilters){ + + abortSignal=false; + int i=0; + int progress=0; + //variabili + vtkSmartPointer fixOutput = vtkSmartPointer::New(); + + vtkSmartPointer filter = vtkSmartPointer::New(); + vtkSmartPointer marchingcubes = vtkSmartPointer::New() ; + vtkSmartPointer smoother = vtkSmartPointer::New(); + vtkSmartPointer fixed = vtkSmartPointer :: New(); + + + + + + marchingcubes->SetInput(vol); + + + //The algorithm starts with a marching cube at a given intensity level threshold + marchingcubes->SetValue(0,march_tresh); // Surface #0, iso-value=1 + marchingcubes->SetComputeNormals(0); + if (marchingcubes.GetPointer()->GetNumberOfInputConnections(0)==0) + {return; + //EMIT FAIL QUALCOSA + //return -1; + } + marchingcubes->Update(); + std::cout<< "inizio run" <GetNumberOfContours()); + if(item.toInt()<=0){ + throw("CRITICAL: No surfaces found with given treshold"); + QList dummylist; + // emit sendrenderMarkerList (dummylist); + } + +// Smoothing filter and normals calculation on marching cubes output data + smoother->SetInput(marchingcubes->GetOutput()); + smoother->SetNumberOfIterations(20); + smoother->NormalizeCoordinatesOn(); + smoother->SetPassBand(0.01); + smoother->BoundarySmoothingOn(); + smoother->Update(); + + + vtkSmartPointer normals=vtkSmartPointer::New(); + normals->SetInput(smoother->GetOutput()); + vtkSmartPointer normalact=vtkSmartPointer::New(); + vtkSmartPointer normalmap=vtkSmartPointer::New(); + normalmap->SetInput( normals->GetOutput()); + normalact->SetMapper(normalmap); + +// Start of marker recognitioning procedure + + filter->AddInput(normals->GetOutput()); + filter->SetExtractionModeToAllRegions(); + filter->SetColorRegions(0); + filter->Update(); + QString regionnumber = regionnumber.number(filter->GetNumberOfExtractedRegions()); + filter->SetExtractionModeToSpecifiedRegions(); + filter->Update(); + + //Some data allocation: + //surflist: list of surfaces where the recognized marker are added + //tempsurf: one surface used as temporary variable during geometrical filtering + QList surflist; + surflist.clear(); + surf tempsurf; + + + //Double check on number of surface in ConnectivityFilter output + if(regionnumber.toInt()==0){ + std::cout<<"ok"< dummylist; + + // emit sendrenderMarkerList (dummylist); + }; + if(regionnumber.toInt()>3000){ + cout<<"ho trovato troppe superfici: "<AddSpecifiedRegion(idouble); + filter->Update(); + + // Filter on bounding box diagonal lenght + if(selectedFilters.at(0)) + if(ok==1) { + tempsurf.lenght=filter->GetOutput()->GetLength(); + if(tempsurf.lenghtthrUp_D ) + ok=0; + } + + //Hausdorf reads from tempsurf the bounding box center and use it as reference center + if(selectedFilters.at(1)) + if(ok==1) { + OKd++; + filter->GetOutput()->GetCenter(tempsurf.center); + tempsurf.hausdorff=hausdorff(filter,tempsurf); + if(tempsurf.hausdorff> (thr_HAUSD) ) + ok=0; + + } + +// Filter based on sides difference + if(selectedFilters.at(2)) + if(ok==1) { + OKh++; + filter->GetOutput()->GetBounds(tempsurf.bounds); + tempsurf.confronto_lati=lati(tempsurf.bounds); + if(tempsurf.confronto_lati>thr_S) + ok=0; + } + + //if all filters are verified, add a surface index and append it to the surflist + if(ok==1) { + OKs++; + tempsurf.sorting=idouble; //indexing + surflist.append(tempsurf); + } + + // MANDATORY filter cleaning + filter->DeleteSpecifiedRegion(idouble); + +} + +cout<<"Nsurfaces"< final_list; + surf tmp_p; + + if(surflist.count()!=0){ + for(i=0;iAddSpecifiedRegion(surflist.at(i).sorting); + filter->Update(); + + //Centroid calculation needs mesh vertex + vtkSmartPointer edge_extractor =vtkSmartPointer::New(); + edge_extractor->RemoveAllInputs(); + edge_extractor->SetInput(filter->GetOutput()); + edge_extractor->Update(); + + vtkSmartPointer tmp = vtkSmartPointer::New(); + tmp=edge_extractor->GetOutput(); + tmp->Update(); + tmp->BuildCells(); + tmp->BuildLinks(); + + QList punti; + point ptemp; + + for (int id=0;id< (int) tmp->GetNumberOfPoints();id++){ + ptemp.x=tmp->GetPoint(id)[0]; + ptemp.y=tmp->GetPoint(id)[1]; + ptemp.z=tmp->GetPoint(id)[2]; + /*cout<GetOutput()->GetPoint(id)[0]<<" "<GetOutput()->GetPoint(id)[1]<<" "<GetOutput()->GetPoint(id)[2]<DeleteSpecifiedRegion(surflist.at(i).sorting); + + final_list.append(tmp_p); + }; + + }; + + + for(int ii=0;ii punti) +{ + int i; + point centroide; + centroide.x=0,centroide.y=0,centroide.z=0; + for ( i=0;id2 && d1>d3) return d1; + if(d2>d1 && d2>d3) return d2; + if(d3>d2 && d3>d1) return d3; + return 9999; +} + + +int gLocalize::get_byteorder() +{ + union { + long l; + char c[4]; + } test; + test.l = 1; + if( test.c[3] && !test.c[2] && !test.c[1] && !test.c[0] ) + return ORDER_BIGENDIAN; + + if( !test.c[3] && !test.c[2] && !test.c[1] && test.c[0] ) + return ORDER_LITTLEENDIAN; + + return ORDER_UNKNOWN; +} + +/** + * Implementation of the Hausdorff distance from a reference 1 cm diameter sphere + */ +double gLocalize::hausdorff(vtkPolyDataConnectivityFilter* filter, surf tempsurf) +{ + vtkSmartPointer source_sphere = vtkSmartPointer::New(); + source_sphere->SetCenter(tempsurf.center[0],tempsurf.center[1],tempsurf.center[2]); + source_sphere->SetRadius(5.0); + source_sphere->Update(); + + vtkSmartPointer sphere = source_sphere->GetOutput(); + sphere->Update(); + sphere->BuildCells(); + + vtkSmartPointer edge_extractor =vtkSmartPointer::New(); + edge_extractor->RemoveAllInputs(); + edge_extractor->SetInput(filter->GetOutput()); + edge_extractor->Update(); + + vtkSmartPointer tmp = vtkSmartPointer::New(); + tmp=edge_extractor->GetOutput(); + tmp->Update(); + tmp->BuildCells(); + tmp->BuildLinks(); + + QList punti_sup; + point ptemp; + + for (int id=0;id< (int) tmp->GetNumberOfPoints();id++){ + ptemp.x=tmp->GetPoint(id)[0]; + ptemp.y=tmp->GetPoint(id)[1]; + ptemp.z=tmp->GetPoint(id)[2]; + /*cout<GetOutput()->GetPoint(id)[0]<<" "<GetOutput()->GetPoint(id)[1]<<" "<GetOutput()->GetPoint(id)[2]< punti_sphere; + for (int id=0;id< (int) sphere->GetNumberOfPoints();id++){ + ptemp.x=sphere->GetPoint(id)[0]; + ptemp.y=sphere->GetPoint(id)[1]; + ptemp.z=sphere->GetPoint(id)[2]; + /*cout<GetOutput()->GetPoint(id)[0]<<" "<GetOutput()->GetPoint(id)[1]<<" "<GetOutput()->GetPoint(id)[2]< largest) largest = dist; + } + + summin += smallest; + summax += largest; + + if (smallest > maxmin) maxmin = smallest; // so this is max min + if (largest > maxmax) maxmax = largest; // and this is max max + } + +punti_sphere.clear(); +punti_sup.clear(); +return maxmin; // Hausdorff distance +} \ No newline at end of file diff --git a/gLocalize.h b/gLocalize.h new file mode 100755 index 0000000..a590f53 --- /dev/null +++ b/gLocalize.h @@ -0,0 +1,215 @@ +#ifndef _GLOCALIZE_H_ +#define _GLOCALIZE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#include "gSkullRemoval.h" + +#include +#include +#include +#include +#include +#include +//#include "gTRiPtools_b.h" +#include +//#include "resampler.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// #include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + + +#define ORDER_BIGENDIAN 0 +#define ORDER_LITTLEENDIAN 1 +#define ORDER_UNKNOWN 2 + +// Some Macros to make the code more readable +// + +//#ifndef SWAP_TMP_INT +// #define SWAP_TMP_INT +// #define EVAL_INDEX(X,Y,L) (reference[ (Y)*(L) +(X)]) +// int swap_tmp_int; +// #define INT_SWAP(X,Y) swap_tmp_int=X; X=Y; Y=swap_tmp_int; +//#endif +// +// + +#define N_ITERAZ_ICP 100 + + +typedef struct { + +public: +double x; +double y; +double z; +}point; + + +typedef struct { + +public: +int sorting; +int surfn; +double lenght; +int ntriangle; +int npoint; +double bounds[6]; +double center[3]; +double volume; +int ismarker; +point centroid; +double centroid_median [3]; +point fitting ; +double confronto_lati; +double hausdorff; +}surf; + + + + + +class gLocalize : public QObject{ + +Q_OBJECT + +public: + gLocalize(); + +public slots: + void localize(vtkImageData* vol, + int march_tresh, + double thrDown_D, + double thrUp_D, + double thr_HAUSD, + double thr_S, + QList selectedFilters); + void callAbort(){ + cout<< "Aborted" <); + void localizationProgress(int); + void localizationAborted(); + +private: + double hausdorff(vtkPolyDataConnectivityFilter* filter, surf tempsurf); + int get_byteorder(); + double lati(double p[6]); + point centroid(QList< point > punti); + volatile bool abortSignal; + + + /** + * Functions for Qlist sorting + */ + bool lenghtLessThan(const surf &d1, const surf &d2){ return d1.lenght > d2.lenght; }; + bool tringleLessThan(const surf &d1, const surf &d2){ return d1.ntriangle > d2.ntriangle; }; + bool zLessThan(const surf &d1, const surf &d2){ return d1.center[2] < d2.center[2]; }; + bool confronto_latiLessThan(const surf &d1, const surf &d2){return d1.confronto_lati +#include +#define MAXSTRINGLENGHT 256 + + +class gPatientRTGeneralInfos { + +public: + gPatientRTGeneralInfos(){ + PatientName = new char [MAXSTRINGLENGHT]; + PatientID = new char [MAXSTRINGLENGHT]; + PatientSex = new char [MAXSTRINGLENGHT]; + PatientAge = new char [MAXSTRINGLENGHT]; + PatientBirthDate = new char [MAXSTRINGLENGHT]; + + SeriesNumber = new char [MAXSTRINGLENGHT]; + SeriesDescription = new char [MAXSTRINGLENGHT]; + StudyID = new char [MAXSTRINGLENGHT]; + StudyDescription = new char [MAXSTRINGLENGHT]; + + PatientOrientation= new char [MAXSTRINGLENGHT]; + + clearInfo(); + }; + + void clearInfo(){ + filenames.clear(); + CTfiles.clear(); + rtIonPlanPath.clear(); + rtStructurePath.clear(); + PatientName[0]=0; + PatientID[0]=0; + PatientSex[0]=0; + PatientBirthDate[0]=0; + SeriesNumber[0]=0; + SeriesDescription[0]=0; + StudyID[0]=0; + StudyDescription[0]=0; + PatientOrientation[0]=0; + }; + + ~gPatientRTGeneralInfos(){ + delete [] PatientName; + delete [] PatientID; + delete [] PatientSex; + delete [] PatientAge; + delete [] PatientBirthDate; + delete [] SeriesNumber; + delete [] SeriesDescription; + delete [] StudyID; + delete [] StudyDescription; + delete [] PatientOrientation; + }; + +public: + char* PatientName; + char* PatientID; + char* PatientSex; + char* PatientAge; + char* PatientBirthDate; + char* SeriesNumber; + char* SeriesDescription; + char* StudyID; + char* StudyDescription; + char* PatientOrientation; + + std::vector filenames; + QString rtIonPlanPath; + QString rtStructurePath; + std::vector CTfiles; + +}; + + +#endif \ No newline at end of file diff --git a/gRen.cpp b/gRen.cpp new file mode 100755 index 0000000..e130afa --- /dev/null +++ b/gRen.cpp @@ -0,0 +1,434 @@ + +#include "gRen.h" + +gRen::gRen( QVTKWidget* m_qvtk){ + CTinfos.clear(); + qvtk= m_qvtk; + nmarker=0; + + markerSources = 0; + markerMappers = 0; + markerActors = 0; + + this-> buildRenderPipe(); + this-> createRenderers(); + +} + + +void gRen::onAutoSkullMaskEnd(vtkImageData* fixedVol){ + cout << "Auto masking complete"<::New(); + //CTvolume->Initialize(); + CTvolume->DeepCopy(fixedVol); + CTvolume->Update(); + + extractVOI->Update(); + ren1->Render(); + qvtk->GetRenderWindow()->Render(); +} + + +void gRen::loadVolume(vtkImageData* volCT){ + + CTvolume=vtkSmartPointer::New(); + CTvolume->Initialize(); + CTvolume->DeepCopy(volCT); + CTvolume->Update(); + CTvolume->GetExtent(CTinfos.extent); + CTvolume->GetSpacing(CTinfos.spacing); + CTvolume->GetOrigin(CTinfos.origin); + cout<< "ORIGIN REN: "<SetInput(CTvolume/*extractVOI->GetOutput()*/); +#else + volumeMapper->SetInputData(CTvolume); +#endif + ren1->AddViewProp(volume); + + if(volume->GetVisibility() == 0) + volume->SetVisibility(false); + else + volume->SetVisibility(true); + + extractVOI->SetInput(CTvolume); + extractVOI->SetVOI(CTvolume->GetExtent()); + extractVOI->Update(); + + boxCallback_NEW->setNominalGeometry(volCT->GetExtent(),volCT->GetBounds(),volCT->GetSpacing()); + boxWidget_NEW->SetRotationEnabled(false); + boxWidget_NEW->SetScalingEnabled(true); + boxWidget_NEW->SetTranslationEnabled(true); + boxWidget_NEW->SetPriority(1); + boxWidget_NEW->SetInput((vtkDataSet *) CTvolume); + boxWidget_NEW->PlaceWidget(); + boxWidget_NEW->InsideOutOn(); + boxWidget_NEW->GetOutlineProperty()->SetRepresentationToWireframe(); + boxWidget_NEW->GetOutlineProperty()->SetAmbient(1.0); + boxWidget_NEW->GetOutlineProperty()->SetAmbientColor(1,1,1); + boxWidget_NEW->GetOutlineProperty()->SetLineWidth(3); + boxWidget_NEW->GetSelectedOutlineProperty()->SetRepresentationToWireframe(); + boxWidget_NEW->GetSelectedOutlineProperty()->SetAmbient(1.0); + boxWidget_NEW->GetSelectedOutlineProperty()->SetAmbientColor(1,0,0); + boxWidget_NEW->GetSelectedOutlineProperty()->SetLineWidth(3); + + outline-> SetInputConnection(extractVOI->GetOutputPort()); + + planeWidgetX->SetInput(extractVOI->GetOutput()); + planeWidgetY->SetInput(extractVOI->GetOutput()); + planeWidgetZ->SetInput(extractVOI->GetOutput()); + + if(outlineActor->GetVisibility() == 0){ + } + else{ + planeWidgetX->On(); + planeWidgetY->On(); + planeWidgetZ->On(); + } + + orthoPlanes->SetPlane(0, planeWidgetX); + orthoPlanes->SetPlane(1, planeWidgetY); + orthoPlanes->SetPlane(2, planeWidgetZ); + orthoPlanes->ResetPlanes(); + + vtkCamera * cam = ren1->GetActiveCamera(); + cam->SetPosition(0, 0, -1); + cam->SetFocalPoint(0, 0, 0); + cam->SetViewUp(0, -1, 0); + + ren1->ResetCamera(); + ren1->Render(); + qvtk->GetRenderWindow()->Render(); + + emit PatientLoaded(); +} + +void gRen::createRenderers(){ + ren1 = vtkRenderer::New(); + ren1->SetBackground(0.13, 0.25, 0.32); + qvtk->GetRenderWindow()->AddRenderer(ren1); + ren1->Render(); + + ren1->AddActor(assi); + ren1->AddActor( outlineActor); + + + boxWidget_NEW = vtkBoxWidget::New(); + boxWidget_NEW->SetInteractor(qvtk->GetInteractor()); + boxWidget_NEW->SetPlaceFactor(1.0); + + // - - - - - - - - - - - - - - - - - - - - - + + boxCallback_NEW->rcm=volumeMapper; + + boxWidget_NEW->AddObserver(vtkCommand::InteractionEvent, boxCallback_NEW); +} + +void gRen::buildRenderPipe(){ + + outline = vtkSmartPointer::New(); + + vtkPolyDataMapper* outlineMapper = vtkPolyDataMapper::New(); + outlineMapper->SetInputConnection(outline->GetOutputPort()); + + outlineActor = vtkSmartPointer ::New(); + outlineActor->SetMapper( outlineMapper); + + vtkCellPicker* picker = vtkCellPicker::New(); + picker->SetTolerance(0.005); + + vtkProperty* ipwProp = vtkProperty::New(); + //// //assign default props to the ipw's texture plane actor + + planeWidgetX = vtkImagePlaneWidget::New(); + planeWidgetX->SetInteractor( qvtk->GetRenderWindow()->GetInteractor()); + planeWidgetX->SetKeyPressActivationValue('x'); + planeWidgetX->SetPicker(picker); + planeWidgetX->RestrictPlaneToVolumeOn(); + planeWidgetX->GetPlaneProperty()->SetColor(1,0,0); + planeWidgetX->SetTexturePlaneProperty(ipwProp); + planeWidgetX->TextureInterpolateOff(); + planeWidgetX->SetResliceInterpolateToNearestNeighbour(); + planeWidgetX->SetPlaneOrientationToXAxes(); + planeWidgetX->DisplayTextOn(); + planeWidgetX->InteractionOff(); + planeWidgetX->InteractionOn(); + + planeWidgetY = vtkImagePlaneWidget::New(); + planeWidgetY->SetInteractor( qvtk->GetRenderWindow()->GetInteractor()); + planeWidgetY->SetKeyPressActivationValue('y'); + planeWidgetY->SetPicker(picker); + planeWidgetY->GetPlaneProperty()->SetColor(1,1,0); + planeWidgetY->SetTexturePlaneProperty(ipwProp); + planeWidgetY->TextureInterpolateOn(); + planeWidgetY->SetResliceInterpolateToLinear(); + planeWidgetY->SetPlaneOrientationToYAxes(); + planeWidgetY->SetLookupTable( planeWidgetX->GetLookupTable()); + planeWidgetY->DisplayTextOn(); + planeWidgetY->UpdatePlacement(); + + planeWidgetZ = vtkImagePlaneWidget::New(); + planeWidgetZ->SetInteractor( qvtk->GetRenderWindow()->GetInteractor()); + planeWidgetZ->SetKeyPressActivationValue('z'); + planeWidgetZ->SetPicker(picker); + planeWidgetZ->GetPlaneProperty()->SetColor(0,0,1); + planeWidgetZ->SetTexturePlaneProperty(ipwProp); + planeWidgetZ->TextureInterpolateOn(); + planeWidgetZ->SetResliceInterpolateToCubic(); + planeWidgetZ->SetPlaneOrientationToZAxes(); + planeWidgetZ->SetLookupTable( planeWidgetX->GetLookupTable()); + planeWidgetZ->DisplayTextOn(); + + + assi= vtkAxesActor::New(); + assi->SetOrigin(0,0,0); + assi->AxisLabelsOff(); + assi->SetTotalLength(15,15,15); + + volumeMapper = vtkSmartPointer::New(); + volumeMapper->SetBlendModeToComposite(); // composite first + + volumeProperty = vtkSmartPointer::New(); + volumeProperty->ShadeOff(); + volumeProperty->SetInterpolationType(VTK_LINEAR_INTERPOLATION); + + compositeOpacity = vtkSmartPointer::New(); + compositeOpacity->AddPoint(-3024, 0, 0.5, 0.0 ); + compositeOpacity->AddPoint(-16, 0, .49, .61 ); + compositeOpacity->AddPoint(-10, .1, .49, .4 ); + compositeOpacity->AddPoint(500, .4, .49, .4 ); + compositeOpacity->AddPoint(641, .72, .5, 0.0 ); + compositeOpacity->AddPoint(1700, .8, .5, 0.0 ); + compositeOpacity->AddPoint(2500, .8, .5, 0.0 ); + compositeOpacity->AddPoint(3071, .71, 0.5, 0.0); + volumeProperty->SetScalarOpacity(compositeOpacity); // composite first. + + + color = vtkSmartPointer::New(); + color->AddRGBPoint( -3024, 0, 0, 0, 0.5, 0.0 ); + color->AddRGBPoint( -16, 0.73, 0.25, 0.30, 0.49, .61 ); + color->AddRGBPoint( -10, .3, .3, .3, .5, 0.0 ); + color->AddRGBPoint( 500, .7, .7, .7, .5, 0.0 ); + color->AddRGBPoint( 641, .90, .82, .56, .5, 0.0 ); + color->AddRGBPoint( 1700, 1, 0,0, .5, 1 ); + color->AddRGBPoint( 2500, 1, 0,0, .5,.1 ); + color->AddRGBPoint( 3071, 1, 1, 1, .5, 0.0 ); + volumeProperty->SetColor(color); + + volumeProperty->ShadeOn(); + volumeProperty->SetAmbient(0.1); + volumeProperty->SetDiffuse(0.9); + volumeProperty->SetSpecular(0.2); + volumeProperty->SetSpecularPower(10.0); + volumeProperty->SetScalarOpacityUnitDistance(0.8919); + + //compositeOpacity = vtkSmartPointer::New(); + //compositeOpacity->AddPoint(0.0,0.0); + //compositeOpacity->AddPoint(80.0,1.0); + //compositeOpacity->AddPoint(80.1,0.0); + //compositeOpacity->AddPoint(255.0,0.0); + //volumeProperty->SetScalarOpacity(compositeOpacity); // composite first. + // + //color = vtkSmartPointer::New(); + //color->AddRGBPoint(0.0 ,0.0,0.0,1.0); + //color->AddRGBPoint(40.0 ,1.0,0.0,0.0); + //color->AddRGBPoint(255.0,1.0,1.0,1.0); + //volumeProperty->SetColor(color); + + volume = vtkSmartPointer::New(); + volume->SetMapper(volumeMapper); + volume->SetProperty(volumeProperty); + volume->SetVisibility(false); + + outlineActor->SetVisibility(true); + planeWidgetX->EnabledOn(); + planeWidgetY->EnabledOn(); + planeWidgetZ->EnabledOn(); + planeWidgetX->On(); + planeWidgetY->On(); + planeWidgetZ->On(); + + + extractVOI = vtkSmartPointer::New(); + boxCallback_NEW = vtkSmartPointer::New(); + boxCallback_NEW->setExtractVoiFilter(extractVOI); + + orthoPlanes = vtkImageOrthoPlanes::New(); + + +} + +void gRen::onSingleMarkerChange(int idx, bool state){ + + cout<< "onSingleMarkerChange : "<GetProperty()->SetColor(0,1,0); + } else { + markerActors[idx]->GetProperty()->SetColor(1,1,1); + } + qvtk->GetRenderWindow()->Render(); +} + + +void gRen::renderMarkers(QList marker_list){ + + cout << "renderMarkers" << endl; + + if(markerSources != 0) { + for(int ii=0;iiRemoveActor(markerActors[ii]); + markerActors[ii]->RemoveAllObservers(); + markerMappers[ii]->RemoveAllObservers(); + markerSources[ii]->RemoveAllObservers(); + markerSources[ii]->Delete(); + markerActors[ii]->Delete(); + markerMappers[ii]->Delete(); + } + delete [] markerActors; + delete [] markerMappers; + delete [] markerSources; + ren1->RemoveActor(pointLabels); + //modelPoints->Delete(); + //stringData->Delete(); + //pointLabels->Delete(); + //cells->Delete(); + //polyData->Delete(); + //ids->Delete(); + //ldm->Delete(); + } + + nmarker = marker_list.size(); + markerSources = new vtkSphereSource* [nmarker]; + markerMappers = new vtkPolyDataMapper* [nmarker]; + markerActors = new vtkActor* [nmarker]; + + modelPoints = vtkSmartPointer::New(); + modelPoints->Reset(); + modelPoints->SetNumberOfPoints(nmarker); + + + stringData = vtkSmartPointer::New(); + stringData->Reset(); + stringData->SetName("Labels"); + + for(int i=0;iInsertNextValue(QString::number(i).toLatin1().constData()); + modelPoints->InsertPoint(i,marker_list.at(i).centroid.x*1000,marker_list.at(i).centroid.y*1000,marker_list.at(i).centroid.z*1000); + + markerSources[i] = vtkSphereSource::New(); + markerSources[i]->SetCenter(marker_list.at(i).centroid.x*1000,marker_list.at(i).centroid.y*1000,marker_list.at(i).centroid.z*1000); + markerSources[i]->SetRadius(10); + + markerMappers[i]= vtkPolyDataMapper::New(); + markerMappers[i]->SetInputConnection (markerSources[i]->GetOutputPort()); + + markerActors[i]= vtkActor::New(); + markerActors[i]->SetMapper(markerMappers[i]); + markerActors[i]->GetProperty()->SetRepresentationToWireframe(); + markerActors[i]->GetProperty()->SetColor(0,1,0); + ren1->AddActor(markerActors[i]); + } + + cout << "modelPoints" << endl; + modelPoints->Modified(); + + cells = vtkSmartPointer::New(); + cells->Reset(); + cells->InsertNextCell(nmarker); + for(int i = 0; i < nmarker; i++) + cells->InsertCellPoint(i); + + polyData = vtkSmartPointer::New(); + polyData->Reset(); + polyData->SetPoints(modelPoints); + polyData->SetVerts(cells); + polyData->GetPointData()->AddArray(stringData); + + ids = vtkSmartPointer::New(); + ids->SetInput( polyData ); + ids->PointIdsOn(); + ids->CellIdsOn(); + ids->FieldDataOn(); + cout << "ids" << endl; + ldm = vtkSmartPointer::New(); + ldm->SetInputConnection( ids->GetOutputPort() ); + ldm->SetLabelModeToLabelFieldData(); + ldm->GetLabelTextProperty()->SetShadow(false); + ldm->GetLabelTextProperty()->SetFontSize(22); + cout << "plab" << endl; + pointLabels = vtkSmartPointer::New(); + pointLabels->SetMapper( ldm ); + ren1->AddActor(pointLabels); + qvtk->GetRenderWindow()->Render(); +} + +void gRen::onReferenceChange(double dx, double dy, double dz){ + + if(markerSources == 0) + return; + + for(int i=0;iSetCenter( + markerSources[i]->GetCenter()[0]-dx, + markerSources[i]->GetCenter()[1]-dy, + markerSources[i]->GetCenter()[2]-dz); + markerSources[i]->Update(); + + modelPoints->SetPoint(i, + modelPoints->GetPoint(i)[0]-dx, + modelPoints->GetPoint(i)[1]-dy, + modelPoints->GetPoint(i)[2]-dz); + } + + modelPoints->Modified(); + qvtk->GetRenderWindow()->Render(); +} + +void gRen::onRequestRenderChange(int idx){ + switch (idx){ + case 0: + volume->SetVisibility(true); + outlineActor->SetVisibility(false); + planeWidgetX->EnabledOff(); + planeWidgetY->EnabledOff(); + planeWidgetZ->EnabledOff(); + ren1->Render(); + break; + + case 1: + volume->SetVisibility(false); + outlineActor->SetVisibility(true); + planeWidgetX->EnabledOn(); + planeWidgetY->EnabledOn(); + planeWidgetZ->EnabledOn(); + ren1->Render(); + break; + + default: + break; + } +} + + +void gRen::onRequestManualMask(int idx){ + + switch (idx){ + case 0: + boxWidget_NEW->On(); + qvtk->GetRenderWindow()->Render(); + break; + + case 1: + boxWidget_NEW->Off(); + qvtk->GetRenderWindow()->Render(); + break; + + default: + break; + } + +} + + diff --git a/gRen.h b/gRen.h new file mode 100755 index 0000000..ed42f26 --- /dev/null +++ b/gRen.h @@ -0,0 +1,298 @@ +#ifndef _GREN_H_ +#define _GREN_H_ + + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "gLocalize.h" + + +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + + +#include +#include +#include + + + + +class vtkMyCallback : public vtkCommand +{ +public: + vtkSmartVolumeMapper *rcm; + static vtkMyCallback *New() { return new vtkMyCallback; } + + virtual void Execute(vtkObject *caller, unsigned long, void*) + { + vtkBoxWidget *boxWidget = reinterpret_cast(caller); + + // Get the actual box coordinates/planes + vtkSmartPointer polydata = vtkSmartPointer::New(); + //static_cast(boxWidget->GetRepresentation())->GetPolyData (polydata); + + boxWidget->GetPolyData(polydata); + double *ac_bounds=polydata->GetBounds(); + /*check if box is larger than volume size*/ + // double *ac_bounds= boxWidget->GetRepresentation()->GetBounds(); + + for(int ii =0 ;ii<6 ;ii+=2 ){ + if(ac_bounds[ii]nominalBounds[ii]) + ac_bounds[ii]=nominalBounds[ii]; + } + + boxWidget->PlaceWidget(ac_bounds); +// boxWidget->Render(); + + /*clip the orthoplanes*/ + extractVOI->SetVOI( nominalExtent[0] + (int) (abs(ac_bounds[0]-nominalBounds[0])/VolSpacing[0]), + nominalExtent[1] - (int) (abs(ac_bounds[1]-nominalBounds[1])/VolSpacing[0]), + nominalExtent[2] +(int) (abs(ac_bounds[2]-nominalBounds[2])/VolSpacing[1]), + nominalExtent[3] -(int) (abs(ac_bounds[3]-nominalBounds[3])/VolSpacing[1]), + nominalExtent[4] + (int) (abs(ac_bounds[4]-nominalBounds[4])/VolSpacing[2]), + nominalExtent[5] -(int) (abs(ac_bounds[5]-nominalBounds[5])/VolSpacing[2]) + ); + + + /*clip the vol ren*/ + vtkPlanes *planes = vtkPlanes::New(); + // The implicit function vtkPlanes is used in conjunction with the + // volume ray cast mapper to limit which portion of the volume is + // volume rendered. + boxWidget->GetPlanes(planes); + this->rcm->SetClippingPlanes(planes); + } + + void setNominalGeometry(int* extents, double* bounds, double* spacing){ + memcpy(&nominalBounds,bounds,6*sizeof(double)); + memcpy(&nominalExtent,extents,6*sizeof(int)); + memcpy(&VolSpacing,spacing,3*sizeof(double)); + } + + void setExtractVoiFilter(vtkExtractVOI* p_extractVOI){ + extractVOI=p_extractVOI; + }; + +private: + vtkExtractVOI* extractVOI; + double nominalBounds[6]; + int nominalExtent[6]; + double VolSpacing[3]; +}; + + +// This does the actual work. +// Callback for the interaction +class vtkBoxCallback : public vtkCommand +{ + public: + static vtkBoxCallback *New() + { + return new vtkBoxCallback; + } + + void setExtractVoiFilter(vtkExtractVOI* p_extractVOI){ + extractVOI=p_extractVOI; + }; + + void setVolumeMapper(vtkSmartVolumeMapper* p_mapper){ + volMapper=p_mapper; + } + + void setRenderer(vtkRenderer* p_ren){ + ren=p_ren; + } + + void setNominalGeometry(int* extents, double* bounds, double* spacing){ + memcpy(&nominalBounds,bounds,6*sizeof(double)); + memcpy(&nominalExtent,extents,6*sizeof(int)); + memcpy(&VolSpacing,spacing,3*sizeof(double)); + } + + virtual void Execute(vtkObject *caller, unsigned long, void*) + { + + vtkBoxWidget2 *boxWidget = reinterpret_cast(caller); + + // Get the actual box coordinates/planes + vtkSmartPointer polydata = vtkSmartPointer::New(); + static_cast(boxWidget->GetRepresentation())->GetPolyData (polydata); + + /*check if box is larger than volume size*/ + double *ac_bounds= boxWidget->GetRepresentation()->GetBounds(); + + for(int ii =0 ;ii<6 ;ii+=2 ){ + if(ac_bounds[ii]nominalBounds[ii]) + ac_bounds[ii]=nominalBounds[ii]; + } + + boxWidget->GetRepresentation()->PlaceWidget(ac_bounds); + boxWidget->Render(); + + // Display the center of the box + // double p[3]; + // polydata->GetPoint(14,p); // As per the vtkBoxRepresentation documentation, the 15th point (index 14) is the center of the box + //std::cout << "Box center: " << p[0] << " " << p[1] << " " << p[2] << std::endl; + + //cout<<"nominal VOI"<GetVOI()[0]<<" "<GetVOI()[1]<<" "<GetVOI()[2]<<" "<< + // extractVOI->GetVOI()[3]<<" "<GetVOI()[4]<<" "<GetVOI()[5]<SetVOI( nominalExtent[0] + (int) (abs(ac_bounds[0]-nominalBounds[0])/VolSpacing[0]), + nominalExtent[1] - (int) (abs(ac_bounds[1]-nominalBounds[1])/VolSpacing[0]), + nominalExtent[2] +(int) (abs(ac_bounds[2]-nominalBounds[2])/VolSpacing[1]), + nominalExtent[3] -(int) (abs(ac_bounds[3]-nominalBounds[3])/VolSpacing[1]), + nominalExtent[4] + (int) (abs(ac_bounds[4]-nominalBounds[4])/VolSpacing[2]), + nominalExtent[5] -(int) (abs(ac_bounds[5]-nominalBounds[5])/VolSpacing[2]) + ); + + //extractVOI->Update(); + //volMapper->Update(); + ren->Render(); + + } + vtkBoxCallback(){} + +private: + vtkExtractVOI* extractVOI; + double nominalBounds[6]; + int nominalExtent[6]; + double VolSpacing[3]; + vtkRenderer* ren; + vtkSmartVolumeMapper* volMapper; + +}; + +class gRen : public QObject{ + Q_OBJECT + +public: + gRen( QVTKWidget* m_qvtk); + vtkImageData* getVolume(){return extractVOI->GetOutput();} + double* getSpacing(){return CTvolume->GetSpacing();}; + +private: + vtkSmartPointer CTvolume; + vtkSmartPointer outline; + vtkSmartPointer outlineActor; + vtkImageMapToColors* colorMap_X; + vtkImagePlaneWidget* planeWidgetX; + vtkImagePlaneWidget* planeWidgetY; + vtkImagePlaneWidget* planeWidgetZ; + QVTKWidget* qvtk; + vtkImageOrthoPlanes* orthoPlanes; + vtkAxesActor * assi; + vtkRenderer* ren1; + + vtkSmartPointer volumeMapper; + vtkSmartPointer color; + vtkSmartPointer compositeOpacity; + vtkSmartPointer volume; + vtkSmartPointer volumeProperty; + vtkSmartPointer boxWidget; + vtkSmartPointer boxRepresentation; + vtkSmartPointer boxCallback ; + vtkSmartPointer boxCallback_NEW; + vtkSmartPointer extractVOI; + vtkBoxWidget *boxWidget_NEW; + + vtkSphereSource** markerSources; + vtkPolyDataMapper** markerMappers; + vtkActor** markerActors; + vtkSmartPointer modelPoints; + vtkSmartPointer pointLabels; + int nmarker; + vtkSmartPointer stringData; + vtkSmartPointer cells ; + vtkSmartPointer polyData; + vtkSmartPointer ids; + vtkSmartPointer ldm; + + struct{ + int extent [6]; + double center [3]; + double origin [3]; + double spacing [3]; + QString fName; + void clear(){ + std::fill(extent,extent+6,9999); + std::fill(center,center+3,9999); + std::fill(origin,origin+3,9999); + std::fill(spacing,spacing+3,9999); + fName.clear(); + }; + }CTinfos; + + void buildRenderPipe(); + void createRenderers(); + + +public slots: + void loadVolume (vtkImageData* volCT); + void renderMarkers(QList marker_list); + void onRequestRenderChange(int idx); + void onRequestManualMask(int idx); + void onAutoSkullMaskEnd(vtkImageData* fixedVol); + void onSingleMarkerChange(int idx,bool state); + void onReferenceChange(double dx, double dy, double dz); + + + +signals: + void PatientLoaded(); + +}; + +#endif \ No newline at end of file diff --git a/gSkullRemoval.cpp b/gSkullRemoval.cpp new file mode 100755 index 0000000..80991ae --- /dev/null +++ b/gSkullRemoval.cpp @@ -0,0 +1,264 @@ +#include "gSkullRemoval.h" +// +///** +// * This will be setup as a callback for a progress event on an ITK +// * filter. +// */ +//struct ProgressDisplay +//{ +// +//public: +// QString observedProcess; +// +// ProgressDisplay(itk::ProcessObject* process,QString observed): m_Process(process) { +// observedProcess=observed; +// } +// +// void Display() +// { +// float progress = m_Process->GetProgress()*100.0; +// cout <::New(); + vtkExporter = vtkSmartPointer::New(); + smoothing = CurvatureFlowImageFilterType::New(); + connectedThreshold = ConnectedFilterType::New(); + binaryErodeFilter = ErodeFilterType::New(); + binaryDilateFilter = DilateFilterType::New(); + itkExporter1 = ExportFilter1Type::New(); + itkImporter = ImportFilterType::New(); + caster_writer_inv =CastingwriterINVFilterType::New(); + maskNegatedFilter = MaskNegatedFilterType::New(); + caster_writer = CastingwriterFilterType::New(); + caster = CastingFilterType::New(); + + /*TEST*/ + m_RedrawCommand = RedrawCommandType::New(); + m_RedrawCommand->SetCallbackFunction( this, &gSkullRemoval::ProcessEvent ); + m_RedrawCommand->SetCallbackFunction( this, &gSkullRemoval::ConstProcessEvent ); + + this->Observe(smoothing.GetPointer()); + this->Observe(connectedThreshold.GetPointer()); + this->Observe(binaryErodeFilter.GetPointer()); + this->Observe(binaryDilateFilter.GetPointer()); + this->Observe(maskNegatedFilter.GetPointer()); +} +gSkullRemoval::~gSkullRemoval() +{ + + +} + + + +void gSkullRemoval::runFilter(vtkImageData* inputVolume,double thr_low, double thr_up) +{ +// imageProcessing(); + // ProgressDisplay progDisplaySmooth (smoothing,"Smoothing"); + //itk::SimpleMemberCommand::Pointer progEventSmooth = itk::SimpleMemberCommand::New(); + //progEventSmooth->SetCallbackFunction(&progDisplaySmooth,&ProgressDisplay::Display); + //smoothing->AddObserver(itk::ProgressEvent(), progEventSmooth); + // ProgressDisplay progDisplayRegion (connectedThreshold,"Region growing"); + //itk::SimpleMemberCommand::Pointer progEventRegion = itk::SimpleMemberCommand::New(); + //progEventRegion->SetCallbackFunction(&progDisplayRegion,&ProgressDisplay::Display); + //connectedThreshold->AddObserver(itk::ProgressEvent(), progEventRegion); + + // ProgressDisplay progDisplayErode (binaryErodeFilter,"Morphological erode"); + // itk::SimpleMemberCommand::Pointer progEventErode = itk::SimpleMemberCommand::New(); + // progEventErode->SetCallbackFunction(&progDisplayErode,&ProgressDisplay::Display); + // binaryErodeFilter->AddObserver(itk::ProgressEvent(), progEventErode); + + // ProgressDisplay progDisplayDilate(binaryDilateFilter,"Morphological dilate"); + // itk::SimpleMemberCommand::Pointer progEventDilate = itk::SimpleMemberCommand::New(); + // progEventDilate->SetCallbackFunction(&progDisplayDilate,&ProgressDisplay::Display); + // binaryDilateFilter->AddObserver(itk::ProgressEvent(), progEventDilate); + + + vtkExporter->SetInput(inputVolume); + ConnectPipelines(vtkExporter.GetPointer(), itkImporter); + caster_writer_inv->SetInput(itkImporter->GetOutput()); + smoothing->SetInput( caster_writer_inv->GetOutput() ); + connectedThreshold->SetInput( smoothing->GetOutput() ); + connectedThreshold->Update(); + caster->SetInput( connectedThreshold->GetOutput() ); + smoothing->SetNumberOfIterations( 10 ); + smoothing->SetTimeStep( 0.125 ); + const InternalPixelType lowerThreshold = thr_low ; + const InternalPixelType upperThreshold = thr_up; + connectedThreshold->SetLower( lowerThreshold ); + connectedThreshold->SetUpper( upperThreshold ); + connectedThreshold->SetReplaceValue( 255 ); + InternalImageType::Pointer inputImage = caster_writer_inv->GetOutput(); + InternalImageType::SizeType size = inputImage->GetBufferedRegion().GetSize(); + InternalImageType::IndexType start = inputImage->GetBufferedRegion().GetIndex(); + + // set a seed by default in the center of the image. + InternalImageType::IndexType seed; + seed[0] = start[0] + size[0] / 2; + seed[1] = start[1] + size[1] / 2; + seed[2] = start[2] + size[2] / 2; + connectedThreshold->SetSeed( seed ); + + StructuringElementType structuringElement; + structuringElement.SetRadius( 10 ); + structuringElement.CreateStructuringElement(); + binaryDilateFilter->SetKernel( structuringElement ); + binaryErodeFilter->SetKernel( structuringElement ); + binaryDilateFilter->SetInput( caster->GetOutput() ); + binaryErodeFilter->SetInput( binaryDilateFilter->GetOutput() ); + binaryDilateFilter->SetDilateValue( 255 ); + binaryErodeFilter->SetErodeValue( 255 ); + +// if (dcmoutput == 1) writer->SetInput(binaryErodeFilter->GetOutput()); + maskNegatedFilter->SetInput1(caster_writer_inv->GetOutput()); + maskNegatedFilter->SetInput2(binaryErodeFilter->GetOutput()); + +// maskNegatedFilter->Update(); + + //caster_writer->SetInput(maskNegatedFilter->GetOutput()); + // if (dcmoutput == 1){ writer_internal->SetFileName( "/home/gio/dati/output/out_mask.dcm" ); + // writer_internal->SetInput(caster_writer->GetOutput());}; + +bool execeptCaught = false; + + itkImporter->ReleaseDataFlagOn(); + //caster_writer_inv->ReleaseDataFlagOn(); + connectedThreshold->ReleaseDataFlagOn(); + binaryDilateFilter->ReleaseDataFlagOn(); + binaryErodeFilter->ReleaseDataFlagOn(); + + //maskNegatedFilter->ReleaseDataFlagOn(); + + try { + maskNegatedFilter.GetPointer()->Update(); + } + catch( itk::ExceptionObject & excep ) + { + if (aborted) std::cerr << "Abort caught!" << std::endl; + else { + execeptCaught=true; + emit errMsg(QString(excep.GetDescription())); + std::cerr << "Exception caught !" << std::endl; + std::cerr << excep << std::endl; + } + }; + + if (!aborted && execeptCaught==false){ + + +// fixedVolume->DeepCopy(inputVolume); + +// try +// { +// // if (dcmoutput == 1) {writer->Update(); +// // writer_internal->Update();}; +// fixedVolume->DeepCopy(vtkImporter1->GetOutput()); +// cout<<"finito itk"< WriterType; + //WriterType::Pointer writer = WriterType::New(); + //writer->SetFileName("out.mha"); + //writer->SetInput( maskNegatedFilter->GetOutput() ); + //writer->Update(); + // + + + itkExporter1->SetInput( maskNegatedFilter->GetOutput() ); + ConnectPipelines(itkExporter1.GetPointer(), vtkImporter1); + vtkImporter1->Update(); + + emit skull_mask_end(vtkImporter1->GetOutput()); + //fixedVolume->DeepCopy(); + } +} + + +void gSkullRemoval::abortSignal() +{ + aborted=true; +// cout<<"arrivato segnale di abort in itk: setto gli abort generate data"<AbortExecuteOn(); + maskNegatedFilter.GetPointer()->AbortGenerateDataOn(); + binaryErodeFilter.GetPointer()->AbortGenerateDataOn(); + binaryDilateFilter.GetPointer()->AbortGenerateDataOn(); + connectedThreshold.GetPointer()->AbortGenerateDataOn(); + smoothing.GetPointer()->AbortGenerateDataOn(); + + // cout<<"fatto"<( caller ); + if(caller == smoothing) + emit skull_mask_upd("2/5 : Surface smoothing...", process->GetProgress()); + + if(caller == connectedThreshold) + emit skull_mask_upd("1/5 : Region growing...", process->GetProgress()); + + if(caller == binaryErodeFilter) + emit skull_mask_upd("4/5 : Morphological erode...", process->GetProgress()); + + if(caller ==binaryDilateFilter) + emit skull_mask_upd("3/5 : Morphological dilate...", process->GetProgress()); + + if(caller == maskNegatedFilter) + emit skull_mask_upd("5/5 : Volume masking...", process->GetProgress()); + + + + } +} + + + + +void +gSkullRemoval::ConstProcessEvent( const itk::Object * caller, + const itk::EventObject & event ) +{ + if( typeid( itk::ProgressEvent ) == typeid( event ) ) + { + itk::ProcessObject::ConstPointer process = + dynamic_cast< const itk::ProcessObject *>( caller ); + cout<< "B"<< process->GetProgress() <AddObserver( itk::ProgressEvent(), m_RedrawCommand.GetPointer() ); +} diff --git a/gSkullRemoval.h b/gSkullRemoval.h new file mode 100755 index 0000000..a098bcd --- /dev/null +++ b/gSkullRemoval.h @@ -0,0 +1,172 @@ +#ifndef GSKULLREMOVAL_H +#define GSKULLREMOVAL_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "itkQtAdaptor.h" + + + + const unsigned int Dimension = 3; + //typedef float InternalPixelType; + typedef signed short InternalPixelType; + typedef itk::Image< InternalPixelType, Dimension > InternalImageType; + typedef unsigned char OutputPixelType; + typedef itk::Image< OutputPixelType, Dimension > OutputImageType; + typedef short int writerPixelType; + typedef itk::Image< writerPixelType, Dimension > writerImageType; + typedef itk::CastImageFilter< InternalImageType, writerImageType > CastingwriterFilterType; + typedef itk::CastImageFilter< writerImageType, InternalImageType > CastingwriterINVFilterType; + typedef itk::ConnectedThresholdImageFilter< InternalImageType, InternalImageType > ConnectedFilterType; + typedef itk::CastImageFilter< InternalImageType, OutputImageType > CastingFilterType; + typedef itk::ImageFileReader< InternalImageType > ReaderType; + typedef itk::ImageFileWriter< OutputImageType > WriterType; + typedef itk::CurvatureFlowImageFilter< InternalImageType, InternalImageType > CurvatureFlowImageFilterType; + typedef itk::VTKImageImport ImportFilterType; + typedef itk::BinaryBallStructuringElement < unsigned char, 3 > StructuringElementType; + typedef itk::BinaryErodeImageFilter < OutputImageType, OutputImageType, StructuringElementType> ErodeFilterType; + typedef itk::BinaryDilateImageFilter < OutputImageType, OutputImageType, StructuringElementType> DilateFilterType; + typedef itk::MaskNegatedImageFilter MaskNegatedFilterType; +// typedef itk::ImageFileWriter< writerImageType > WriterTypeInternal; + typedef unsigned char MaskPixelType; + typedef itk::Image< MaskPixelType, Dimension > MaskImageType; + typedef itk::VTKImageExport< InternalImageType > ExportFilter1Type; + typedef itk::VTKImageExport< MaskImageType > ExportFilter2Type; + + template +void ConnectPipelines(ITK_Exporter exporter, VTK_Importer* importer) +{ + importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback()); + importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback()); + importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback()); + importer->SetSpacingCallback(exporter->GetSpacingCallback()); + importer->SetOriginCallback(exporter->GetOriginCallback()); + importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback()); + importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback()); + importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback()); + importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback()); + importer->SetDataExtentCallback(exporter->GetDataExtentCallback()); + importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback()); + importer->SetCallbackUserData(exporter->GetCallbackUserData()); +} + +/** + * This function will connect the given vtkImageExport filter to + * the given itk::VTKImageImport filter. + */ +template +void ConnectPipelines(VTK_Exporter* exporter, ITK_Importer importer) +{ + importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback()); + importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback()); + importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback()); + importer->SetSpacingCallback(exporter->GetSpacingCallback()); + importer->SetOriginCallback(exporter->GetOriginCallback()); + importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback()); + importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback()); + importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback()); + importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback()); + importer->SetDataExtentCallback(exporter->GetDataExtentCallback()); + importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback()); + importer->SetCallbackUserData(exporter->GetCallbackUserData()); +} + + + +class gSkullRemoval : public QObject +{ + Q_OBJECT + +public: + gSkullRemoval(); + ~gSkullRemoval(); + + + /*test*/ + + /** Command Class invoked for button redraw */ + typedef itk::MemberCommand< gSkullRemoval > RedrawCommandType; + /** Get Command */ + RedrawCommandType * GetRedrawCommand( void ) const; + + + /** Manage a Progress event */ + void ProcessEvent(itk::Object * caller, const itk::EventObject & event ); + void ConstProcessEvent(const itk::Object * caller, const itk::EventObject & event ); + + + /** Manage a Progress event */ + void Observe( itk::Object *caller ); + private: + + RedrawCommandType::Pointer m_RedrawCommand; + + /*ENDTEST*/ + public slots: + void runFilter(vtkImageData* inputVolume,double thr_low, double thr_up); + void abortSignal(); + +private: + vtkImageData *fixedVolume; + int dcmoutput; + bool aborted; + + +private: + vtkSmartPointer vtkImporter1; + vtkSmartPointer vtkExporter; + CurvatureFlowImageFilterType::Pointer smoothing; + ConnectedFilterType::Pointer connectedThreshold; + ErodeFilterType::Pointer binaryErodeFilter; + DilateFilterType::Pointer binaryDilateFilter; + ExportFilter1Type::Pointer itkExporter1; + CastingwriterINVFilterType::Pointer caster_writer_inv; + MaskNegatedFilterType::Pointer maskNegatedFilter; + ImportFilterType :: Pointer itkImporter; + writerImageType *importedITK; + InternalImageType *fixedITK; + CastingwriterFilterType::Pointer caster_writer ; + CastingFilterType::Pointer caster; + +signals: + void skull_mask_end(vtkImageData * fixedVolume); + void errMsg(QString msg); + void skull_mask_upd(QString msg, double val); + }; + + +#endif \ No newline at end of file diff --git a/icons/Thumbs.db b/icons/Thumbs.db new file mode 100755 index 0000000..e5d174d Binary files /dev/null and b/icons/Thumbs.db differ diff --git a/icons/ortoIco.png b/icons/ortoIco.png new file mode 100755 index 0000000..4e88815 Binary files /dev/null and b/icons/ortoIco.png differ diff --git a/icons/pb_load.png b/icons/pb_load.png new file mode 100755 index 0000000..b004e73 Binary files /dev/null and b/icons/pb_load.png differ diff --git a/icons/pb_quit.png b/icons/pb_quit.png new file mode 100755 index 0000000..9b4db0c Binary files /dev/null and b/icons/pb_quit.png differ diff --git a/icons/volrenIco.png b/icons/volrenIco.png new file mode 100755 index 0000000..9aa19c6 Binary files /dev/null and b/icons/volrenIco.png differ diff --git a/images.qrc b/images.qrc new file mode 100755 index 0000000..afd3f5a --- /dev/null +++ b/images.qrc @@ -0,0 +1,8 @@ + + + icons/pb_load.png + icons/pb_quit.png + icons/ortoIco.png + icons/volrenIco.png + + \ No newline at end of file diff --git a/itkQtAdaptor.h b/itkQtAdaptor.h new file mode 100755 index 0000000..551ae0e --- /dev/null +++ b/itkQtAdaptor.h @@ -0,0 +1,162 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: itkQtAdaptor.h + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 2002 Insight Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm 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 +#include "itkObject.h" +#include "itkObjectFactory.h" +#include "itkCommand.h" + + +namespace itk { + +/** Helper class that interface with Qt Signals and Slots */ +class QtTranslator : public QObject +{ + + Q_OBJECT + +public: + QtTranslator() {} + virtual ~QtTranslator() {} + +signals: + void Signal(); + +public slots: + virtual void Slot() {}; + virtual void Slot(int) {}; + virtual void Slot(double) {}; + +}; + + + +/** Helper class that interface Methods with Qt Slots */ +template +class QtSlotAdaptor : public QtTranslator +{ + typedef void (T::*TMemberFunctionVoidPointer)(); + typedef void (T::*TMemberFunctionIntPointer)(int); + typedef void (T::*TMemberFunctionDoublePointer)(double); + +public: + QtSlotAdaptor():m_MemberFunctionVoid(0), + m_MemberFunctionInt(0), + m_MemberFunctionDouble(0) {} + + virtual ~QtSlotAdaptor() {} + + /** Specify the callback function. */ + void SetCallbackFunction(T* object, + TMemberFunctionVoidPointer memberFunction) + { + m_This = object; + m_MemberFunctionVoid = memberFunction; + } + + /** Specify the callback function. */ + void SetCallbackFunction(T* object, + TMemberFunctionIntPointer memberFunction) + { + m_This = object; + m_MemberFunctionInt = memberFunction; + } + + /** Specify the callback function. */ + void SetCallbackFunction(T* object, + TMemberFunctionDoublePointer memberFunction) + { + m_This = object; + m_MemberFunctionDouble = memberFunction; + } + + /** Slot to be connected to Qt Signals. */ + void Slot() + { + if( m_MemberFunctionVoid ) + { + ((*m_This).*(m_MemberFunctionVoid))(); + } + } + + /** Slot to be connected to Qt Signals. */ + void Slot(int value) + { + if( m_MemberFunctionInt ) + { + ((*m_This).*(m_MemberFunctionInt))(value); + } + } + + /** Slot to be connected to Qt Signals. */ + void Slot(double value) + { + if( m_MemberFunctionDouble ) + { + ((*m_This).*(m_MemberFunctionDouble))(value); + } + } + + + +protected: + T* m_This; + TMemberFunctionVoidPointer m_MemberFunctionVoid; + TMemberFunctionIntPointer m_MemberFunctionInt; + TMemberFunctionDoublePointer m_MemberFunctionDouble; + + +}; + + + + + +/** Helper class that interface Observers with Qt Signals */ +class QtSignalAdaptor : public QtTranslator +{ + typedef SimpleMemberCommand CommandType; + +public: + QtSignalAdaptor() + { + m_Command = CommandType::New(); + m_Command->SetCallbackFunction( this, & QtSignalAdaptor::EmitSignal ); + } + + virtual ~QtSignalAdaptor() {} + + CommandType * GetCommand() + { + return m_Command; + } + + void EmitSignal() + { + emit Signal(); + } + +private: + CommandType::Pointer m_Command; +}; + + + + +} // end namespace diff --git a/main.cpp b/main.cpp new file mode 100755 index 0000000..dd4fcfb --- /dev/null +++ b/main.cpp @@ -0,0 +1,83 @@ + + +#include "mainw.h" +#include + #include "itkTextOutput.h" + +#include + + + +int main(int argc, char **argv) { + + std::cout << "Hello, world!" << std::endl; + + vtkObject::SetGlobalWarningDisplay(false); + itk::OutputWindow::SetInstance(itk::TextOutput::New()); + + QApplication app(argc,argv); + + if(!QFile("config.ini").exists()){ + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Icon::Critical); + msgBox.setText("gLocalize config file missing... Exiting."); + msgBox.setInformativeText("Please add config.ini file in the gLocalize path."); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setDefaultButton(QMessageBox::Ok); + int ret = msgBox.exec(); + cout<<"prequit" <value("Path/inDir").toString()).exists() || !QDir(config->value("Path/outDir").toString()).exists()){ + QString userMsg; + userMsg.clear(); + userMsg.append("Please check config.ini file parameters:\n"); + ( QDir(config->value("Path/inDir").toString()).exists() == true? "" : userMsg.append("- Patient directory : [Path]/inDir\n") ); + ( QDir(config->value("Path/outDir").toString()).exists() == true? "" : userMsg.append("- Output directory : [Path]/outDir\n") ); + + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Icon::Critical); + msgBox.setText("gLocalize configuration error... Exiting."); + msgBox.setInformativeText(userMsg); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setDefaultButton(QMessageBox::Ok); + + QSpacerItem* horizonatlSpacer= new QSpacerItem(300,0,QSizePolicy::Minimum,QSizePolicy::Expanding); + QGridLayout* layout = (QGridLayout*) msgBox.layout(); + layout->addItem(horizonatlSpacer, layout->rowCount(), 0 ,1 ,layout->columnCount()); + + int ret = msgBox.exec(); + cout<<"prequit" <show(); + int res= app.exec(); + + + + + + return 0; +} diff --git a/mainw.cpp b/mainw.cpp new file mode 100755 index 0000000..6dbff79 --- /dev/null +++ b/mainw.cpp @@ -0,0 +1,1043 @@ +#include "mainw.h" +#include + +#include + +#include + + void Ui_MainWindow::setupUi(QMainWindow *MainWindow) + { + if (MainWindow->objectName().isEmpty()) + MainWindow->setObjectName(QString::fromUtf8("MainWindow")); + MainWindow->resize(872, 737); + actionLoad = new QAction(MainWindow); + actionLoad->setObjectName(QString::fromUtf8("actionLoad")); + actionQuit = new QAction(MainWindow); + actionQuit->setObjectName(QString::fromUtf8("actionQuit")); + actionVolRen = new QAction(MainWindow); + actionVolRen->setObjectName(QString::fromUtf8("actionVolRen")); + actionVolRen->setCheckable(true); + actionOrthoslice = new QAction(MainWindow); + actionOrthoslice->setObjectName(QString::fromUtf8("actionOrthoslice")); + actionOrthoslice->setCheckable(true); + viewGroup = new QActionGroup(MainWindow); + viewGroup->addAction(actionVolRen); + viewGroup->addAction(actionOrthoslice); + actionOrthoslice->setChecked(true); + centralwidget = new QWidget(MainWindow); + centralwidget->setObjectName(QString::fromUtf8("centralwidget")); + horizontalLayout_8 = new QHBoxLayout(centralwidget); + horizontalLayout_8->setObjectName(QString::fromUtf8("horizontalLayout_8")); + widget = new QWidget(centralwidget); + widget->setObjectName(QString::fromUtf8("widget")); + widget->setMaximumSize(QSize(300, 16777215)); + widget->setMinimumSize(QSize(300, 0)); + verticalLayout_5 = new QVBoxLayout(widget); + verticalLayout_5->setObjectName(QString::fromUtf8("verticalLayout_5")); + frame_2 = new QFrame(widget); + frame_2->setObjectName(QString::fromUtf8("frame_2")); + frame_2->setFrameShape(QFrame::StyledPanel); + frame_2->setFrameShadow(QFrame::Raised); + verticalLayout_2 = new QVBoxLayout(frame_2); + verticalLayout_2->setObjectName(QString::fromUtf8("verticalLayout_2")); + formLayout_2 = new QFormLayout(); + formLayout_2->setObjectName(QString::fromUtf8("formLayout_2")); + label_6 = new QLabel(frame_2); + label_6->setObjectName(QString::fromUtf8("label_6")); + + formLayout_2->setWidget(0, QFormLayout::LabelRole, label_6); + + l_patientID = new QLabel(frame_2); + l_patientID->setObjectName(QString::fromUtf8("l_patientID")); + l_patientID->setMinimumSize(QSize(91, 0)); + + formLayout_2->setWidget(0, QFormLayout::FieldRole, l_patientID); + + label_8 = new QLabel(frame_2); + label_8->setObjectName(QString::fromUtf8("label_8")); + + formLayout_2->setWidget(1, QFormLayout::LabelRole, label_8); + + l_patientID_2 = new QLabel(frame_2); + l_patientID_2->setObjectName(QString::fromUtf8("l_patientID_2")); + l_patientID_2->setMinimumSize(QSize(91, 0)); + + formLayout_2->setWidget(1, QFormLayout::FieldRole, l_patientID_2); + + + label_12 = new QLabel(frame_2); + label_12->setObjectName(QString::fromUtf8("label_12")); + + formLayout_2->setWidget(5, QFormLayout::LabelRole, label_12); + + l_patientID_6 = new QLabel(frame_2); + l_patientID_6->setObjectName(QString::fromUtf8("l_patientID_6")); + l_patientID_6->setMinimumSize(QSize(91, 0)); + + formLayout_2->setWidget(5, QFormLayout::FieldRole, l_patientID_6); + + label_isoV = new QLabel(frame_2); + label_isoV->setObjectName(QString::fromUtf8("label_isoV")); + label_isoV->setText("Virtual Iso:"); + label_isoV->setMinimumSize(QSize(91, 0)); + formLayout_2->setWidget(6, QFormLayout::LabelRole, label_isoV); + + l_isoV = new QLabel(frame_2); + l_isoV->setObjectName(QString::fromUtf8("l_isoV")); + l_isoV->setText("N.a."); + l_isoV->setMinimumSize(QSize(91, 0)); + formLayout_2->setWidget(6, QFormLayout::FieldRole, l_isoV); + +#ifdef MULTIPLE_REF + a_DCMref=new QRadioButton(frame_2); + a_DCMref->setCheckable(true); + a_DCMref->setText("DCM"); + a_RTref=new QRadioButton(frame_2); + a_RTref->setCheckable(true); + a_RTref->setText("RT"); + a_OTSref=new QRadioButton(frame_2); + a_OTSref->setText("OTS"); + a_OTSref->setCheckable(true); + a_DCMref->setChecked(true); + + refGroup = new QButtonGroup(frame_2); + refGroup->addButton (a_DCMref); + refGroup->addButton(a_RTref); + refGroup->addButton(a_OTSref); + + QHBoxLayout* reflay=new QHBoxLayout; + reflay->addWidget(a_DCMref); + reflay->addWidget(a_RTref); + reflay->addWidget(a_OTSref); + + a_RTref->setDisabled(true); + + formLayout_2->setItem(6, QFormLayout::FieldRole, reflay); +#endif + verticalLayout_2->addLayout(formLayout_2); + + + verticalLayout_5->addWidget(frame_2); + + frame_5 = new QFrame(widget); + frame_5->setObjectName(QString::fromUtf8("frame_5")); + frame_5->setFrameShape(QFrame::StyledPanel); + frame_5->setFrameShadow(QFrame::Raised); + verticalLayout_4 = new QVBoxLayout(frame_5); + verticalLayout_4->setObjectName(QString::fromUtf8("verticalLayout_4")); + horizontalLayout_7 = new QHBoxLayout(); + horizontalLayout_7->setObjectName(QString::fromUtf8("horizontalLayout_7")); + label_7 = new QLabel(frame_5); + label_7->setObjectName(QString::fromUtf8("label_7")); + + horizontalLayout_7->addWidget(label_7); + + pushButton_5 = new QPushButton(frame_5); + pushButton_5->setObjectName(QString::fromUtf8("pushButton_5")); + pushButton_5->setEnabled(true); + + horizontalLayout_7->addWidget(pushButton_5); + + + verticalLayout_4->addLayout(horizontalLayout_7); + + + QHBoxLayout* manualMask_lay = new QHBoxLayout(); + manualMask_lay->setObjectName(QString::fromUtf8("manualMask_lay")); + QLabel* l_manualMask = new QLabel(frame_5); + l_manualMask->setObjectName(QString::fromUtf8("l_manualMask")); + l_manualMask->setText("Manual volume clip"); + + manualMask_lay->addWidget(l_manualMask); + + pb_manualMask = new QPushButton(frame_5); + pb_manualMask->setObjectName(QString::fromUtf8("pb_manualMask")); + pb_manualMask->setEnabled(true); + pb_manualMask->setText("View"); + pb_manualMask->setCheckable(true); + + manualMask_lay->addWidget(pb_manualMask); + verticalLayout_4->addLayout(manualMask_lay); + + + verticalLayout_5->addWidget(frame_5); + + frame_3 = new QFrame(widget); + frame_3->setObjectName(QString::fromUtf8("frame_3")); + frame_3->setEnabled(true); + frame_3->setFrameShape(QFrame::StyledPanel); + frame_3->setFrameShadow(QFrame::Raised); + verticalLayout = new QVBoxLayout(frame_3); + verticalLayout->setObjectName(QString::fromUtf8("verticalLayout")); + horizontalLayout = new QHBoxLayout(); + horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout")); + label = new QLabel(frame_3); + label->setObjectName(QString::fromUtf8("label")); + + horizontalLayout->addWidget(label); + + horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + horizontalLayout->addItem(horizontalSpacer); + + spinBox = new QSpinBox(frame_3); + spinBox->setObjectName(QString::fromUtf8("spinBox")); + spinBox->setMinimumSize(QSize(71, 0)); + spinBox->setMaximumSize(QSize(71, 16777215)); + spinBox->setMinimum(-1024); + spinBox->setMaximum(3000); + spinBox->setValue(1800); + + horizontalLayout->addWidget(spinBox); + + + verticalLayout->addLayout(horizontalLayout); + + horizontalLayout_2 = new QHBoxLayout(); + horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2")); + checkBox_2 = new QCheckBox(frame_3); + checkBox_2->setObjectName(QString::fromUtf8("checkBox_2")); + checkBox_2->setChecked(true); + + horizontalLayout_2->addWidget(checkBox_2); + + label_2 = new QLabel(frame_3); + label_2->setObjectName(QString::fromUtf8("label_2")); + + horizontalLayout_2->addWidget(label_2); + + horizontalSpacer_2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + horizontalLayout_2->addItem(horizontalSpacer_2); + + doubleSpinBox_2 = new QDoubleSpinBox(frame_3); + doubleSpinBox_2->setObjectName(QString::fromUtf8("doubleSpinBox_2")); + doubleSpinBox_2->setMinimumSize(QSize(71, 0)); + doubleSpinBox_2->setMaximumSize(QSize(71, 16777215)); + + horizontalLayout_2->addWidget(doubleSpinBox_2); + + doubleSpinBox_2bis = new QDoubleSpinBox(frame_3); + doubleSpinBox_2bis->setObjectName(QString::fromUtf8("doubleSpinBox_2bis")); + doubleSpinBox_2bis->setMinimumSize(QSize(71, 0)); + doubleSpinBox_2bis->setMaximumSize(QSize(71, 16777215)); + + horizontalLayout_2->addWidget(doubleSpinBox_2bis); + + + + verticalLayout->addLayout(horizontalLayout_2); + + horizontalLayout_3 = new QHBoxLayout(); + horizontalLayout_3->setObjectName(QString::fromUtf8("horizontalLayout_3")); + checkBox_3 = new QCheckBox(frame_3); + checkBox_3->setObjectName(QString::fromUtf8("checkBox_3")); + checkBox_3->setChecked(true); + + horizontalLayout_3->addWidget(checkBox_3); + + label_3 = new QLabel(frame_3); + label_3->setObjectName(QString::fromUtf8("label_3")); + + horizontalLayout_3->addWidget(label_3); + + horizontalSpacer_3 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + horizontalLayout_3->addItem(horizontalSpacer_3); + + doubleSpinBox_3 = new QDoubleSpinBox(frame_3); + doubleSpinBox_3->setObjectName(QString::fromUtf8("doubleSpinBox_3")); + doubleSpinBox_3->setMinimumSize(QSize(71, 0)); + doubleSpinBox_3->setMaximumSize(QSize(71, 16777215)); + doubleSpinBox_3->setMaximum(999999); + doubleSpinBox_3->setValue(22); + + horizontalLayout_3->addWidget(doubleSpinBox_3); + + + verticalLayout->addLayout(horizontalLayout_3); + + horizontalLayout_5 = new QHBoxLayout(); + horizontalLayout_5->setObjectName(QString::fromUtf8("horizontalLayout_5")); + checkBox_5 = new QCheckBox(frame_3); + checkBox_5->setObjectName(QString::fromUtf8("checkBox_5")); + checkBox_5->setChecked(true); + + horizontalLayout_5->addWidget(checkBox_5); + + label_5 = new QLabel(frame_3); + label_5->setObjectName(QString::fromUtf8("label_5")); + + horizontalLayout_5->addWidget(label_5); + + horizontalSpacer_5 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + horizontalLayout_5->addItem(horizontalSpacer_5); + + doubleSpinBox_5 = new QDoubleSpinBox(frame_3); + doubleSpinBox_5->setObjectName(QString::fromUtf8("doubleSpinBox_5")); + doubleSpinBox_5->setMinimumSize(QSize(71, 0)); + doubleSpinBox_5->setMaximumSize(QSize(71, 16777215)); + + horizontalLayout_5->addWidget(doubleSpinBox_5); + + + verticalLayout->addLayout(horizontalLayout_5); + + horizontalLayout_6 = new QHBoxLayout(); + horizontalLayout_6->setObjectName(QString::fromUtf8("horizontalLayout_6")); + pushButton_3 = new QPushButton(frame_3); + pushButton_3->setObjectName(QString::fromUtf8("pushButton_3")); + pushButton_3->setEnabled(true); + + horizontalLayout_6->addWidget(pushButton_3); + + pushButton_4 = new QPushButton(frame_3); + pushButton_4->setObjectName(QString::fromUtf8("pushButton_4")); + pushButton_4->setEnabled(false); + + horizontalLayout_6->addWidget(pushButton_4); + + + verticalLayout->addLayout(horizontalLayout_6); + + + verticalLayout_5->addWidget(frame_3); + + frame_4 = new QFrame(widget); + frame_4->setObjectName(QString::fromUtf8("frame_4")); + frame_4->setEnabled(true); + frame_4->setMaximumSize(QSize(16777215, 171)); + frame_4->setFrameShape(QFrame::StyledPanel); + frame_4->setFrameShadow(QFrame::Raised); + verticalLayout_3 = new QVBoxLayout(frame_4); + verticalLayout_3->setObjectName(QString::fromUtf8("verticalLayout_3")); + treeView = new QTreeView(frame_4); + //new QTreeWidgetItem(treeWidget); + treeView->setObjectName(QString::fromUtf8("treeView")); + treeView->setEnabled(true); + treeView->setFrameShape(QFrame::StyledPanel); + // treeView->setAlternatingRowColors(true); + treeView->setUniformRowHeights(true); + treeView->setSortingEnabled(false); + treeView->setAnimated(true); + treeView->setAllColumnsShowFocus(false); + //treeView->setColumnCount(5); + treeView->header()->setVisible(true); + treeView->header()->setCascadingSectionResizes(false); + treeView->header()->setHighlightSections(true); + treeView->header()->setStretchLastSection(true); + + verticalLayout_3->addWidget(treeView); + + formLayout = new QHBoxLayout(); + formLayout->setObjectName(QString::fromUtf8("formLayout")); + pushButton = new QPushButton(frame_4); + pushButton->setObjectName(QString::fromUtf8("pushButton")); + pushButton->setEnabled(false); + + formLayout->addWidget(pushButton); + + pushButton_2 = new QPushButton(frame_4); + pushButton_2->setObjectName(QString::fromUtf8("pushButton_2")); + pushButton_2->setEnabled(false); + + formLayout->addWidget(pushButton_2); + + pb_save= new QPushButton(frame_4); + pb_save->setObjectName(QString::fromUtf8("pb_save")); + pb_save->setText("Save .tac"); + formLayout->addWidget(pb_save); + pb_save->setEnabled(false); + + verticalLayout_3->addLayout(formLayout); + + verticalLayout_5->addWidget(frame_4); + + + horizontalLayout_8->addWidget(widget); + + frame = new QFrame(centralwidget); + frame->setObjectName(QString::fromUtf8("frame")); + frame->setMinimumSize(QSize(561, 0)); + frame->setFrameShape(QFrame::StyledPanel); + frame->setFrameShadow(QFrame::Raised); + + QHBoxLayout* renLay= new QHBoxLayout(frame); + qvtk= new QVTKWidget(frame); + renLay->addWidget(qvtk); + horizontalLayout_8->addWidget(frame); + + MainWindow->setCentralWidget(centralwidget); + statusbar = new QStatusBar(MainWindow); + statusbar->setObjectName(QString::fromUtf8("statusbar")); + MainWindow->setStatusBar(statusbar); + toolBar = new QToolBar(MainWindow); + toolBar->setObjectName(QString::fromUtf8("toolBar")); + MainWindow->addToolBar(Qt::TopToolBarArea, toolBar); + + toolBar->addAction(actionLoad); + toolBar->addSeparator(); + toolBar->addAction(actionVolRen); + toolBar->addAction(actionOrthoslice); + toolBar->addSeparator(); + QWidget *widget = new QWidget; + QHBoxLayout *spacerLayout = new QHBoxLayout; + QSpacerItem *spacer = + new QSpacerItem(1,1,QSizePolicy::Expanding,QSizePolicy::Minimum); + spacerLayout->addSpacerItem(spacer); + widget->setLayout(spacerLayout); + toolBar->addWidget(widget); + toolBar->addAction(actionQuit); + + progBar = new QProgressBar(MainWindow); + progBar->setMinimum(0); + progBar->setMaximum(100); + progBar->setMaximumHeight(15); + statusbar->addPermanentWidget(progBar); + + } // setupUi + + + +void MainWindow::onSkullMaskingUpdt(QString msg, double val){ + Ui->progBar->setValue(val*100); + QMetaObject::invokeMethod(Ui->statusbar, "showMessage", Qt::QueuedConnection, + Q_ARG(QString, msg ), + Q_ARG(int, 0)); +} + + +void MainWindow::call_quit(){ + + loadPatient_thread->quit(); + localize_thread->quit(); + skull_thread->quit(); + Sleep(100); + cout<< "Bye bye" <l_isoV->clear(); + (IsoV == true? Ui->l_isoV->setText("Yes") : Ui->l_isoV->setText("No") ); +} + +MainWindow::MainWindow(QString p_loadPath){ + + + + + Ui = new Ui_MainWindow; + Ui->setupUi(this); + this->retranslateUi(Ui,this); + this->connectUi(Ui); + Ui->actionVolRen->setEnabled(false); + Ui->actionOrthoslice->setEnabled(false); + Ui->pushButton_3->setEnabled(false); + Ui->pb_manualMask->setEnabled(false); + Ui->pushButton_5->setEnabled(false); + + Visualizer= new gRen(Ui->qvtk); + + loadPatient= new gLoadPatient; + loadPatient_thread = new QThread; + loadPatient->moveToThread(loadPatient_thread); + loadPatient_thread->start(); + + qRegisterMetaType< gPatientRTGeneralInfos* >("gPatientRTGeneralInfos *"); + qRegisterMetaType< std::vector >("std::vector"); + qRegisterMetaType< std::string >("std::string"); + qRegisterMetaType< vtkImageData* >("vtkImageData*"); + qRegisterMetaType < QList > ("QList"); + qRegisterMetaType < QList > ("QList"); + + connect(loadPatient, SIGNAL(loadEnd(vtkImageData*)), Visualizer,SLOT(loadVolume (vtkImageData* ))); + connect(loadPatient, SIGNAL(folderIsEmpty()),this,SLOT(onParsedEmptyFolder())); + connect(loadPatient, SIGNAL(parse_result(int , gPatientRTGeneralInfos* )),this,SLOT(onParsedOK(int , gPatientRTGeneralInfos* ))); + connect(loadPatient, SIGNAL(loadedRTIso(double*)),this,SLOT(onRTIsoAvailable(double*))); + connect(loadPatient, SIGNAL(loadedVolBBox(double*, double*, int*)),this,SLOT(onCTVolumeAvailable(double*,double*,int*))); + connect(loadPatient, SIGNAL(virtualIsoTested(bool)),this,SLOT(onVirtualIsoTested(bool))); + + + localize_thread = new QThread; + localize_marker = new gLocalize; + localize_marker->moveToThread(localize_thread); + localize_thread->start(); + connect(localize_marker,SIGNAL(localizationEnd(QList )),this,SLOT(onLocalizationEnd(QList ))); + connect(localize_marker,SIGNAL(localizationProgress(int)), this->Ui->progBar ,SLOT(setValue(int))); + + skullRemoval= new gSkullRemoval; + skull_thread= new QThread; + skullRemoval->moveToThread(skull_thread); + skull_thread->start(); + connect(skullRemoval, SIGNAL(skull_mask_end(vtkImageData *)),Visualizer,SLOT(onAutoSkullMaskEnd(vtkImageData* ))); + connect(skullRemoval, SIGNAL(skull_mask_end(vtkImageData *)),this,SLOT(onAutoSkullMaskEnd(vtkImageData* ))); + + connect(skullRemoval, SIGNAL(errMsg(QString)),this,SLOT(onAutoMaskError(QString ))); + connect(skullRemoval, SIGNAL(skull_mask_upd(QString , double )), this, SLOT(onSkullMaskingUpdt(QString,double))); + + + treeModel = new QStandardItemModel; + connect(treeModel,SIGNAL(itemChanged(QStandardItem*)),this,SLOT(onItemChanged(QStandardItem*))); + connect(Ui->viewGroup, SIGNAL(triggered(QAction*)), this, SLOT(onVisualizationTrigger(QAction* ))); + connect(Ui->pb_manualMask, SIGNAL(toggled ( bool )), this, SLOT(onManualMaskTrigger(bool))); +#ifdef MULTIPLE_REF + connect(Ui->refGroup, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(onRefTrigger(QAbstractButton*))); +#endif + loadDialog = new gLoadPatDialog; + connect(Visualizer, SIGNAL(PatientLoaded()),this,SLOT(onPatientlLoaded())); + + + QSettings *config = new QSettings ("config.ini",QSettings::IniFormat); + pathIn = config->value("Path/inDir").toString(); + pathOut = config->value("Path/outDir").toString(); + + /*default values*/ + Ui->spinBox->setValue(config->value("fiducialsLocalize/markerIntensity").toInt()); + Ui->doubleSpinBox_2->setValue(config->value("fiducialsLocalize/boxDiag_down").toDouble()); + Ui->doubleSpinBox_2bis->setValue(config->value("fiducialsLocalize/boxDiag_up").toDouble()); + Ui->doubleSpinBox_3->setValue(config->value("fiducialsLocalize/hausdDist").toDouble()); + Ui->doubleSpinBox_5->setValue(config->value("fiducialsLocalize/boxSidesDiff").toDouble()); + regGrownParameters[0]=config->value("skullMask/regGrow_up").toDouble(); + regGrownParameters[1]=config->value("skullMask/regGrow_down").toDouble(); + + + + delete config; + + + connect(localize_marker, SIGNAL(localizationAborted()), + this,SLOT(onLocalizationAborted())); + connect(loadPatient,SIGNAL(referenceChange(double, double, double )), + Visualizer,SLOT(onReferenceChange(double, double , double))); + connect(loadPatient,SIGNAL(referenceChange(double, double, double )), + this,SLOT(updateMarkerPos(double, double , double))); + + /*load passed workdir if any*/ + loadPath.clear(); + /*first check for argv [1]*/ + if(p_loadPath.isEmpty()) { + /*then check for ini inDir*/ + if(!pathIn.isEmpty()) + loadPath=pathIn; + } else + loadPath=p_loadPath; + + if(loadPath.isEmpty()){ + cout<< "loadpath is emty" <show(); + cout<< "loadPath: "< pippoReader= vtkSmartPointer::New(); + //pippoReader->SetDirectoryName("D:\\testIn"); + ////pippoReader->SetFileLowerLeft(1); + //pippoReader->Update(); + //pippoReader->Print(std::cout); + + //Visualizer->loadVolume(pippoReader->GetOutput()); + //cout<< "height" <GetHeight()<GetWidth()<GetOutput()->GetBounds(); + //cout<< "VolBounds: "<statusbar, "showMessage", Qt::QueuedConnection, + Q_ARG(QString, QString("Masking Done") ), + Q_ARG(int, 3000)); + + Ui->progBar->reset(); + QApplication::restoreOverrideCursor(); + + Ui->pb_manualMask->setEnabled(true); + Ui->pushButton_5->setEnabled(true); + Ui->frame_3->setEnabled(true); + Ui->frame_4->setEnabled(true); + +} + +void MainWindow::onPatientlLoaded(){ + QApplication::restoreOverrideCursor(); + + Ui->pushButton_5->setEnabled(true); + Ui->pb_manualMask->setEnabled(true); + Ui->actionVolRen->setEnabled(true); + Ui->actionOrthoslice->setEnabled(true); + Ui->pushButton_3->setEnabled(true); + + loadDialog->close(); + Ui->actionLoad->setEnabled(false); + + Ui->pb_manualMask->setEnabled(true); + Ui->pushButton_5->setEnabled(true); + Ui->pushButton_4->setEnabled(false); + Ui->pushButton_3->setEnabled(true); +} + +void MainWindow::onParsedEmptyFolder(){ + QApplication::restoreOverrideCursor(); + loadDialog->close(); + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Icon::Critical); + msgBox.setText("Load failed..."); + msgBox.setInformativeText("Parsed directory is empty or does not contain CT."); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setDefaultButton(QMessageBox::Ok); + int ret = msgBox.exec(); +} + +void MainWindow::setStatusMsg(QString msg, int timeout){ + QMetaObject::invokeMethod(Ui->statusbar, "showMessage", Qt::QueuedConnection, + Q_ARG(QString, msg ), + Q_ARG(int, timeout)); +} + +void MainWindow::retranslateUi(Ui_MainWindow* Ui, QMainWindow *MainWindow) { + MainWindow->setWindowTitle(QApplication::translate("MainWindow", "gLocalize - Fondazione CNAO - Politecnico di Milano - 2014", 0, QApplication::UnicodeUTF8)); + Ui->actionLoad->setText(QApplication::translate("MainWindow", "Load", 0, QApplication::UnicodeUTF8)); + Ui->actionLoad->setIcon(QIcon(":/icons/pb_load.png")); +#ifndef QT_NO_TOOLTIP + Ui->actionLoad->setToolTip(QApplication::translate("MainWindow", "Load patient data", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + Ui->actionQuit->setText(QApplication::translate("MainWindow", "Quit", 0, QApplication::UnicodeUTF8)); + Ui->actionQuit->setIcon(QIcon(":/icons/pb_quit.png")); +#ifndef QT_NO_TOOLTIP + Ui->actionQuit->setToolTip(QApplication::translate("MainWindow", "Quit application", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + Ui->actionVolRen->setText(QApplication::translate("MainWindow", "VolRen", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + Ui->actionVolRen->setToolTip(QApplication::translate("MainWindow", "Volume rendering", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + Ui->actionVolRen->setIcon(QIcon(":/icons/volrenIco.png")); + Ui->actionOrthoslice->setText(QApplication::translate("MainWindow", "Orthoslice", 0, QApplication::UnicodeUTF8)); + Ui->actionOrthoslice->setIcon(QIcon(":/icons/ortoIco.png")); + Ui->label_6->setText(QApplication::translate("MainWindow", "Patient ID:", 0, QApplication::UnicodeUTF8)); + Ui->l_patientID->setText(QString()); + Ui->label_8->setText(QApplication::translate("MainWindow", "Patient position:", 0, QApplication::UnicodeUTF8)); + Ui->l_patientID_2->setText(QString()); + Ui->label_12->setText(QApplication::translate("MainWindow", "RT Isocenter:", 0, QApplication::UnicodeUTF8)); + Ui->l_patientID_6->setText(QString()); + Ui->label_7->setText(QApplication::translate("MainWindow", "Automatic skull mask", 0, QApplication::UnicodeUTF8)); + Ui->pushButton_5->setText(QApplication::translate("MainWindow", "Execute", 0, QApplication::UnicodeUTF8)); + Ui->label->setText(QApplication::translate("MainWindow", "Marker intensity", 0, QApplication::UnicodeUTF8)); + Ui->checkBox_2->setText(QString()); + Ui->label_2->setText(QApplication::translate("MainWindow", "Box diagonal", 0, QApplication::UnicodeUTF8)); + Ui->checkBox_3->setText(QString()); + Ui->label_3->setText(QApplication::translate("MainWindow", "Hausdorff distance", 0, QApplication::UnicodeUTF8)); + Ui->checkBox_5->setText(QString()); + Ui->label_5->setText(QApplication::translate("MainWindow", "Box sides distance", 0, QApplication::UnicodeUTF8)); + Ui->pushButton_3->setText(QApplication::translate("MainWindow", "Localize", 0, QApplication::UnicodeUTF8)); + Ui->pushButton_4->setText(QApplication::translate("MainWindow", "Cancel", 0, QApplication::UnicodeUTF8)); + /* QTreeWidgetItem *___qtreewidgetitem = Ui->treeWidget->headerItem(); + ___qtreewidgetitem->setText(4, QApplication::translate("MainWindow", "Z", 0, QApplication::UnicodeUTF8)); + ___qtreewidgetitem->setText(3, QApplication::translate("MainWindow", "Y", 0, QApplication::UnicodeUTF8)); + ___qtreewidgetitem->setText(2, QApplication::translate("MainWindow", "X", 0, QApplication::UnicodeUTF8)); + ___qtreewidgetitem->setText(0, QApplication::translate("MainWindow", "ID", 0, QApplication::UnicodeUTF8));*/ + + /* const bool __sortingEnabled = Ui->treeWidget->isSortingEnabled(); + Ui->treeWidget->setSortingEnabled(false); + QTreeWidgetItem *___qtreewidgetitem1 = Ui->treeWidget->topLevelItem(0); + ___qtreewidgetitem1->setText(4, QApplication::translate("MainWindow", "0", 0, QApplication::UnicodeUTF8)); + ___qtreewidgetitem1->setText(3, QApplication::translate("MainWindow", "0", 0, QApplication::UnicodeUTF8)); + ___qtreewidgetitem1->setText(2, QApplication::translate("MainWindow", "0", 0, QApplication::UnicodeUTF8)); + ___qtreewidgetitem1->setText(0, QApplication::translate("MainWindow", "1", 0, QApplication::UnicodeUTF8)); + Ui->treeWidget->setSortingEnabled(__sortingEnabled); +*/ + Ui->pushButton->setText(QApplication::translate("MainWindow", "Select all", 0, QApplication::UnicodeUTF8)); + Ui->pushButton_2->setText(QApplication::translate("MainWindow", "Uncheck all", 0, QApplication::UnicodeUTF8)); + Ui->toolBar->setWindowTitle(QApplication::translate("MainWindow", "toolBar", 0, QApplication::UnicodeUTF8)); + + } // retranslateUi + + void MainWindow::connectUi(Ui_MainWindow* Ui){ + QObject::connect(Ui->pushButton_3, SIGNAL(released()), this, SLOT(call_localize_start())); + QObject::connect(Ui->pushButton_4, SIGNAL(released()), this, SLOT(call_localize_cancel())); + QObject::connect(Ui->pushButton, SIGNAL(released()), this, SLOT(call_visualize_all())); + QObject::connect(Ui->pushButton_2, SIGNAL(released()), this, SLOT(call_hide_all())); + QObject::connect(Ui->toolBar, SIGNAL(actionTriggered(QAction*)), this, SLOT(call_ToolbarAction(QAction*))); + QObject::connect(Ui->pushButton_5, SIGNAL(released()), this, SLOT(call_skullMask())); + QObject::connect(Ui->pb_save, SIGNAL(released()), this, SLOT(call_saveDotCtFile())); + + + QMetaObject::connectSlotsByName(this); + } + + + +void MainWindow::onLocalizationAborted(){ + Ui->pushButton_4->setEnabled(false); + Ui->pushButton_3->setEnabled(true); + Ui->progBar->reset(); + QMetaObject::invokeMethod(Ui->statusbar, "showMessage", Qt::QueuedConnection, + Q_ARG(QString, "Localization aborted..." ), + Q_ARG(int, 3000)); + +} + +void MainWindow::call_localize_start(){ + + //bool selected[3]; + QList selected; + selected.clear(); + selected.append(Ui->checkBox_2->isChecked()); + selected.append(Ui->checkBox_3->isChecked()); + selected.append(Ui->checkBox_5->isChecked()); + + + QMetaObject::invokeMethod(localize_marker, "localize", Qt::QueuedConnection, + Q_ARG(vtkImageData*, Visualizer->getVolume()), + Q_ARG(int,Ui->spinBox->text().toInt()), + Q_ARG(double,Ui->doubleSpinBox_2->text().toDouble()), + Q_ARG(double,Ui->doubleSpinBox_2bis->text().toDouble()), + Q_ARG(double,Ui->doubleSpinBox_3->text().toDouble()), + Q_ARG(double,Ui->doubleSpinBox_5->text().toDouble()), + Q_ARG(QList ,selected)); + + + QMetaObject::invokeMethod(Ui->statusbar, "showMessage", Qt::QueuedConnection, + Q_ARG(QString, "Localizing..." ), + Q_ARG(int, 0)); + Ui->pushButton_4->setEnabled(true); + Ui->pushButton_3->setEnabled(false); +} + +void MainWindow::call_localize_cancel(){ + + QMetaObject::invokeMethod(localize_marker, "callAbort", Qt::QueuedConnection); + Ui->pushButton_4->setEnabled(false); +} + +void MainWindow::onItemChanged(QStandardItem* item){ + + + QMetaObject::invokeMethod(Visualizer, "onSingleMarkerChange", Qt::QueuedConnection, + Q_ARG(int, item->text().toInt() ), + Q_ARG(bool, (item->checkState() == Qt::Checked ? true : false))); + +} + +void MainWindow::updateMarkerPos(double dx, double dy, double dz){ + treeModel->blockSignals(true); + for(int ii=0; ii< treeModel->rowCount() ; ii++){ + treeModel->item(ii,0)->child(0,0)->setText(QString::number( + treeModel->item(ii,0)->child(0,0)->text().toDouble()-dx)); + treeModel->item(ii,0)->child(1,0)->setText(QString::number( + treeModel->item(ii,0)->child(1,0)->text().toDouble()-dy)); + treeModel->item(ii,0)->child(2,0)->setText(QString::number( + treeModel->item(ii,0)->child(2,0)->text().toDouble()-dz)); + } + treeModel->blockSignals(false); +} + +void MainWindow::onLocalizationEnd(QList marker_list){ + + Ui->treeView->reset(); + treeModel->clear(); + Ui->pb_save->setEnabled(true); + Ui->pushButton_4->setEnabled(false); + Ui->pushButton_3->setEnabled(true); + + if(marker_list.size() == 0){ + Ui->pb_save->setEnabled(false); + QList marker_list; + QMetaObject::invokeMethod(Visualizer, "renderMarkers", Qt::QueuedConnection, + Q_ARG(QList,marker_list)); + + QMetaObject::invokeMethod(Ui->statusbar, "showMessage", Qt::QueuedConnection, + Q_ARG(QString, "Localization done. No markers found." ), + Q_ARG(int, 3000)); + + this->Ui->progBar->reset(); + this->Ui->pushButton->setEnabled(false); + this->Ui->pushButton_2->setEnabled(false); + + return; + } + + QStandardItem *parentItem = treeModel->invisibleRootItem(); + + for (int i = 0; i < marker_list.size() ; i++) { + QStandardItem *item = new QStandardItem(QString("%0").arg(i)); + item->setCheckable(true); + item->setCheckState(Qt::Checked); + item->setEditable(false); + + QList columnList; + columnList.clear(); + columnList.append(new QStandardItem(QString("%0").arg(marker_list.at(i).centroid.x*1000))); + columnList.append(new QStandardItem(QString("%0").arg(marker_list.at(i).centroid.y*1000))); + columnList.append(new QStandardItem(QString("%0").arg(marker_list.at(i).centroid.z*1000))); + item->appendRows(columnList); + +// cout<< "Scritto tree: " <appendRow(item); + treeModel->setItem(i, 0, item); + } + + Ui->treeView->setModel (treeModel); + Visualizer->renderMarkers(marker_list); + Ui->statusbar->showMessage("Localization done.",3); + + QMetaObject::invokeMethod(Ui->statusbar, "showMessage", Qt::QueuedConnection, + Q_ARG(QString, "Localization done." ), + Q_ARG(int, 3000)); + + this->Ui->progBar->reset(); + this->Ui->pushButton->setEnabled(true); + this->Ui->pushButton_2->setEnabled(true); +} + +void MainWindow::call_saveDotCtFile(){ + + /*QString filename = QFileDialog::getSaveFileName ( + this, + tr("Save .tac file"), + ".", + tr("Reference marker file (*.tac)") );*/ + + QString filename; + filename = pathOut + + "\\" + + Ui->l_patientID->text().split(" ").first() + + + ".tac"; + + QFile file(filename); + file.open(QIODevice::WriteOnly | QIODevice::Text); + QTextStream out(&file); +#ifdef MULTIPLE_REF + if(Ui->a_OTSref->isChecked() ){ +#endif + /*divide by volumeSpacing*/ + for(int ii=0; ii< treeModel->rowCount() ; ii++) + if( treeModel->item(ii,0)->checkState() == Qt::Checked) + out << treeModel->item(ii,0)->child(0,0)->text().toDouble()/Visualizer->getSpacing()[0]<<" " + << treeModel->item(ii,0)->child(1,0)->text().toDouble()/Visualizer->getSpacing()[1]<<" " + << treeModel->item(ii,0)->child(2,0)->text().toDouble()/Visualizer->getSpacing()[2]<rowCount() ; ii++) + if( treeModel->item(ii,0)->checkState() == Qt::Checked) + out << treeModel->item(ii,0)->child(0,0)->text()<<" " + << treeModel->item(ii,0)->child(1,0)->text()<<" " + << treeModel->item(ii,0)->child(2,0)->text()<l_isoV->text() == QString("Yes")) + out<< 1; + else if (Ui->l_isoV->text() == QString("No")) + out<< 0; + + // optional, as QFile destructor will already do it: + file.close(); + + + QMessageBox msgBox; + msgBox.setText("File saved"); + msgBox.setIcon(QMessageBox::Icon::Information); + msgBox.setInformativeText(filename); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setDefaultButton(QMessageBox::Ok); + msgBox.setFixedSize(400,150); + int ret = msgBox.exec(); +} + + +void MainWindow::call_visualize_all(){ +// //VISUALIZATION and Countour shift + for(int ii=0; ii< treeModel->rowCount() ; ii++) + treeModel->item(ii,0)->setCheckState(Qt::Checked); +} + +void MainWindow::call_hide_all(){ + for(int ii=0; ii< treeModel->rowCount() ; ii++) + treeModel->item(ii,0)->setCheckState(Qt::Unchecked); +} + +void MainWindow::call_ToolbarAction(QAction* action){ + + if(action == Ui->actionQuit) + this->call_quit(); +// QApplication::quit(); + + if(action == Ui->actionLoad){ + QString dirName = QFileDialog::getExistingDirectory(this,tr("Chose DICOM Directory"), "wrkDir",QFileDialog::ShowDirsOnly); + if(!dirName.isEmpty()) { + QMetaObject::invokeMethod(loadPatient, "load", Qt::QueuedConnection, + Q_ARG(QString, dirName)); + loadDialog->show(); + + QMetaObject::invokeMethod(Ui->statusbar, "showMessage", Qt::QueuedConnection, + Q_ARG(QString, "Loading patient..." ), + Q_ARG(int, 3000)); + + } + //patientLoader->parse(dirName); + } + + +} + +void MainWindow::call_skullMask(){ + + QApplication::setOverrideCursor(Qt::WaitCursor); + + QMetaObject::invokeMethod(Ui->statusbar, "showMessage", Qt::QueuedConnection, + Q_ARG(QString, "Skull masking..." ), + Q_ARG(int, 3000)); + + QMetaObject::invokeMethod(skullRemoval, "runFilter", Qt::QueuedConnection, + Q_ARG(vtkImageData*, Visualizer->getVolume()), + Q_ARG(double, regGrownParameters[1]), + Q_ARG(double,regGrownParameters[0])); + + Ui->pb_manualMask->setEnabled(false); + Ui->pushButton_5->setEnabled(false); + Ui->frame_3->setEnabled(false); + Ui->frame_4->setEnabled(false); + +} + + +void MainWindow::onAutoMaskError(QString msg){ + QApplication::restoreOverrideCursor(); + QMessageBox msgBox; + msgBox.setText("The automatic masking failed..."); + msgBox.setInformativeText("Manual volume clipping is the way to handle this error."); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setDefaultButton(QMessageBox::Ok); + int ret = msgBox.exec(); +} + +void MainWindow:: onRTIsoAvailable(double* iso){ + +#ifdef MULTIPLE_REF + Ui->a_RTref->setEnabled(true); +#endif + Ui->l_patientID_6->setText(QString("%0 %1 %2") + .arg(iso[0]) + .arg(iso[1]) + .arg(iso[2])); + +} + +void MainWindow:: onCTVolumeAvailable(double* bounds, double* spacing, int* dim){ + +} + +void MainWindow:: onParsedOK(int result, gPatientRTGeneralInfos* infos){ + + + if(result != NOERRORS) + return; + + if( QString(infos->PatientID).isEmpty() ) + Ui->l_patientID->setText(QString("RTPlan not available")); + else + Ui->l_patientID->setText(QString(infos->PatientID)); + + if( QString(infos->PatientOrientation).isEmpty() ) + Ui->l_patientID_2->setText(QString("RTPlan not available")); + else + Ui->l_patientID_2->setText(QString(infos->PatientOrientation)); + + + + QMetaObject::invokeMethod(Ui->statusbar, "showMessage", Qt::QueuedConnection, + Q_ARG(QString, "Dir parser: Ok." ), + Q_ARG(int, 3000)); + + //QMetaObject::invokeMethod(load2vtk, "loadInput", Qt::QueuedConnection, + // Q_ARG(std::vector, infos->CTfiles), + // Q_ARG(std::string,infos->rtIonPlanPath.toStdString()) + // ); + + +} + +void MainWindow::call_loadPatient(){ + + + +// Ui->gw_patientWidget->PatientAge->setText(infos->PatientAge); + +// QMetaObject::invokeMethod(load2vtk, "loadInput", Qt::QueuedConnection, +// Q_ARG(std::vector, infos->CTfiles), +// Q_ARG(std::string,infos->rtIonPlanPath.toStdString()) +// ); +// questo deve chiamare il loadVolume in Gren +} + + +#ifdef MULTIPLE_REF + +void MainWindow::onRefTrigger(QAbstractButton* trigger_button){ + + QRadioButton* clickedButton= reinterpret_cast (trigger_button); + + if(clickedButton == Ui->a_DCMref){ + QMetaObject::invokeMethod(loadPatient, "changeRef", Qt::QueuedConnection, + Q_ARG(int,0)); + } + + if(clickedButton == Ui->a_RTref){ + QMetaObject::invokeMethod(loadPatient, "changeRef", Qt::QueuedConnection, + Q_ARG(int,1)); + } + + if(clickedButton == Ui->a_OTSref){ + QMetaObject::invokeMethod(loadPatient, "changeRef", Qt::QueuedConnection, + Q_ARG(int,2)); + } + +} +#endif + +void MainWindow::onVisualizationTrigger(QAction* trigger_action){ + + if(trigger_action == Ui->actionOrthoslice ){ + this->Visualizer->onRequestRenderChange(1); + this->Ui->qvtk->GetInteractor()->Render(); + } + + if(trigger_action == Ui->actionVolRen ){ + this->Visualizer->onRequestRenderChange(0); + this->Ui->qvtk->GetInteractor()->Render(); + } + +} + + +void MainWindow::onManualMaskTrigger(bool state){ + + if(state){ + this->Visualizer->onRequestManualMask(0); + }else{ + this->Visualizer->onRequestManualMask(1); + } + +} + + diff --git a/mainw.h b/mainw.h new file mode 100755 index 0000000..2e42fca --- /dev/null +++ b/mainw.h @@ -0,0 +1,237 @@ +#ifndef _MAINW_H_ +#define _MAINW_H_ + +//#define MULTIPLE_REF + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +#include "gRen.h" + +//#include "wrkDirParser.h" +//#include "loadDCM2VTK.h" +#include "gPatientRTGeneralInfos.h" +#include "dicomUtils.h" +#include "connectITKVTK.h" +#include +#include "gLoadPatient.h" + +#include "gLocalize.h" + +#include +#include + +#include + +#include "gSkullRemoval.h" + +#include + +class gLoadPatDialog: public QDialog{ + public: + gLoadPatDialog(QWidget *parent = 0) + : QDialog(parent){ + QVBoxLayout * lay = new QVBoxLayout(this); + this->setModal(true); + + message = new QLabel(this); + lay->addWidget(message); + + message->setText("Loading patient from wrkDir... Please wait."); + }; + +private: + QLabel *message; + +}; + +class Ui_MainWindow { +public: + Ui_MainWindow(){}; + + QVTKWidget* qvtk; + QAction *actionLoad; + QAction *actionQuit; + QAction *actionVolRen; + QAction *actionOrthoslice; + QWidget *centralwidget; + QHBoxLayout *horizontalLayout_8; + QWidget *widget; + QVBoxLayout *verticalLayout_5; + QFrame *frame_2; + QVBoxLayout *verticalLayout_2; + QFormLayout *formLayout_2; + QLabel *label_6; + QLabel *l_patientID; + QLabel *label_8; + QLabel *l_patientID_2; + QLabel *label_12; + QLabel *l_patientID_6; + QLabel *label_isoV; + QLabel *l_isoV; + + + QFrame *frame_5; + QVBoxLayout *verticalLayout_4; + QHBoxLayout *horizontalLayout_7; + QLabel *label_7; + QPushButton *pushButton_5; + QFrame *frame_3; + QVBoxLayout *verticalLayout; + QHBoxLayout *horizontalLayout; + QLabel *label; + QSpacerItem *horizontalSpacer; + QSpinBox *spinBox; + QHBoxLayout *horizontalLayout_2; + QCheckBox *checkBox_2; + QLabel *label_2; + QSpacerItem *horizontalSpacer_2; + QDoubleSpinBox *doubleSpinBox_2; + QDoubleSpinBox *doubleSpinBox_2bis; + QHBoxLayout *horizontalLayout_3; + QCheckBox *checkBox_3; + QLabel *label_3; + QSpacerItem *horizontalSpacer_3; + QDoubleSpinBox *doubleSpinBox_3; + QHBoxLayout *horizontalLayout_4; + QSpacerItem *horizontalSpacer_4; + QHBoxLayout *horizontalLayout_5; + QCheckBox *checkBox_5; + QLabel *label_5; + QSpacerItem *horizontalSpacer_5; + QDoubleSpinBox *doubleSpinBox_5; + QHBoxLayout *horizontalLayout_6; + QPushButton *pushButton_3; + QPushButton *pushButton_4; + QFrame *frame_4; + QVBoxLayout *verticalLayout_3; + QTreeView *treeView; + QHBoxLayout *formLayout; + QPushButton *pushButton; + QPushButton *pushButton_2; + QFrame *frame; + QStatusBar *statusbar; + QToolBar *toolBar; + QProgressBar *progBar; + QActionGroup* viewGroup; + QPushButton* pb_manualMask; + QPushButton* pb_save; +#ifdef MULTIPLE_REF + QButtonGroup* refGroup; + QRadioButton* a_DCMref; + QRadioButton* a_RTref; + QRadioButton* a_OTSref; +#endif + void setupUi(QMainWindow *MainWindow); + +}; + + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(QString p_loadPath); + ~MainWindow(); + +private: + Ui_MainWindow* Ui; + void retranslateUi(Ui_MainWindow* Ui, QMainWindow *MainWindow); + void connectUi(Ui_MainWindow* Ui); + + gRen * Visualizer; + //gPatientLoader* patientLoader; + gLoadPatient* loadPatient; + QThread* loadPatient_thread; + + //loadDCM2VTK* load2vtk; + //QThread* load2VtkThread; + gLocalize* localize_marker; + QThread* localize_thread; + gSkullRemoval* skullRemoval; + QThread* skull_thread; + + QStandardItemModel* treeModel; + QString loadPath; + gLoadPatDialog* loadDialog; + + double regGrownParameters[2]; + + QString pathIn; + QString pathOut; + + + +private slots: + void call_localize_start(); + void call_localize_cancel(); + void call_visualize_all(); + void call_hide_all(); + void call_ToolbarAction(QAction* action); + void call_skullMask(); + void call_loadPatient(); + void call_saveDotCtFile(); + void call_quit(); + void call_quit_nothreads(); + + void onParsedOK(int result, gPatientRTGeneralInfos* data); + void onParsedEmptyFolder(); + void onLocalizationEnd(QList marker_list); + void onLocalizationAborted(); + void onVisualizationTrigger(QAction* trigger_action); + void onManualMaskTrigger(bool state); + void onAutoMaskError(QString msg); + void onItemChanged(QStandardItem* item); + void setStatusMsg(QString msg, int timeout); + void onVirtualIsoTested(bool IsoV); + + +#ifdef MULTIPLE_REF + void onRefTrigger(QAbstractButton* trigger_button); +#endif + void onPatientlLoaded(); + void onRTIsoAvailable(double* iso); + void onCTVolumeAvailable(double* bounds, double* spacing, int* dim); + void updateMarkerPos(double dx, double dy, double dz); + + void onSkullMaskingUpdt(QString msg, double val); + void onAutoSkullMaskEnd(vtkImageData* img); +}; + + + + +#endif \ No newline at end of file