From 967501f1488fe18fd03bddd7260e36e2330388db Mon Sep 17 00:00:00 2001 From: "eduardo.davila@creatis.insa-lyon.fr" Date: Sat, 17 Oct 2026 15:34:19 +0200 Subject: [PATCH] #3540 GetPropertiesBySlice box --- .../src/bbcreaVtkGetPropertiesBySlice.cxx | 223 ++++++++++-------- .../src/bbcreaVtkGetPropertiesBySlice.h | 2 +- .../src/bbcreaVtkMassProperties.cxx | 28 +-- .../src/bbcreaVtkMassProperties.h | 9 +- .../bbcreaVtkPolyDataConnectivityFilter.cxx | 21 +- .../src/bbcreaVtkPolyDataConnectivityFilter.h | 14 +- 6 files changed, 172 insertions(+), 125 deletions(-) diff --git a/bbtk_creaVtk_PKG/src/bbcreaVtkGetPropertiesBySlice.cxx b/bbtk_creaVtk_PKG/src/bbcreaVtkGetPropertiesBySlice.cxx index 0859085..a640a85 100644 --- a/bbtk_creaVtk_PKG/src/bbcreaVtkGetPropertiesBySlice.cxx +++ b/bbtk_creaVtk_PKG/src/bbcreaVtkGetPropertiesBySlice.cxx @@ -9,6 +9,7 @@ #include #include #include +#include namespace bbcreaVtk { @@ -20,29 +21,22 @@ BBTK_BLACK_BOX_IMPLEMENTATION(GetPropertiesBySlice,bbtk::AtomicBlackBox); //===== void GetPropertiesBySlice::Process() { - -// THE MAIN PROCESSING METHOD BODY -// Here we simply set the input 'In' value to the output 'Out' -// And print out the output value -// INPUT/OUTPUT ACCESSORS ARE OF THE FORM : -// void bbSet{Input|Output}NAME(const TYPE&) -// const TYPE& bbGet{Input|Output}NAME() const -// Where : -// * NAME is the name of the input/output -// (the one provided in the attribute 'name' of the tag 'input') -// * TYPE is the C++ type of the input/output -// (the one provided in the attribute 'type' of the tag 'input') - if (bbGetInputImage()!=NULL) { if (bbGetInputInPoint_pixel().size()==3) { - double spc[3]; - int dim[3]; - int ext[6]; - int voi[6]; - double range[2]; - double outPointDouble[3]; + double spc[3]; + int dim[3]; + int ext[6]; + int voi[6]; + double range[2]; + double outPointDouble[3]; + vtkImageData *outRegion = NULL; + vtkPolyData *flyingEdges= NULL; + outPointDouble[0] = 0; + outPointDouble[1] = 0; + outPointDouble[2] = 0; + bbGetInputImage()->GetSpacing(spc); bbGetInputImage()->GetExtent(ext); dim[0] = ext[1]-ext[0]+1; @@ -51,28 +45,53 @@ void GetPropertiesBySlice::Process() if (bbGetInputType()==1) // geometric center { std::vector outPointInt; - - //Crop + //Crop by slice vtkExtractVOI *crop = vtkExtractVOI::New(); crop->SetInputData( bbGetInputImage() ); crop->UpdateWholeExtent(); -// crop->Modified(); -// crop->Update(); -// vtkImageData *image2D = crop->GetOutput(); -// image2D->SetExtent( 0 , dim[0]-1 , 0 , dim[1]-1 , 0 , 0 ); + if (bbGetInputOrientation()==2) // xy + { + voi[0] = 0; + voi[1] = dim[0]-1; + voi[2] = 0; + voi[3] = dim[1]-1; + voi[4] = bbGetInputInPoint_pixel()[2]; + voi[5] = bbGetInputInPoint_pixel()[2]; + crop->SetVOI(voi); + } // if Orientation ==0 xy + if (bbGetInputOrientation()==1) // xz + { + voi[0] = 0; + voi[1] = dim[0]-1;; + voi[2] = bbGetInputInPoint_pixel()[1]; + voi[3] = bbGetInputInPoint_pixel()[1]; + voi[4] = 0; + voi[5] = dim[2]-1; + crop->SetVOI(voi); + } // if Orientation ==0 xy + if (bbGetInputOrientation()==0) // yz + { + voi[0] = bbGetInputInPoint_pixel()[0]; + voi[1] = bbGetInputInPoint_pixel()[0]; + voi[2] = 0; + voi[3] = dim[1]-1;; + voi[4] = 0; + voi[5] = dim[2]-1; + crop->SetVOI(voi); + } // if Orientation ==0 yz + crop->Update(); crop->GetOutput()->GetScalarRange( range ); - // Threshold vtkImageThreshold *thresh = vtkImageThreshold::New(); thresh->SetInValue(255); thresh->SetOutValue(0); thresh->SetOutputScalarTypeToUnsignedChar(); - thresh->ThresholdBetween( range[1]/2, range[1] ); thresh->SetInputData( crop->GetOutput() ); -// thresh->Update(); + thresh->Update(); - // Connectivity + /* + // SeedConnectivity vtkImageSeedConnectivity *connect = vtkImageSeedConnectivity::New(); connect->SetInputData( thresh->GetOutput() ); connect->SetInputConnectValue(255); @@ -81,39 +100,91 @@ void GetPropertiesBySlice::Process() connect->RemoveAllSeeds(); connect->SetOutputConnectedValue( 255 ); // connect->Update(); +*/ + // SeedConnectivityFilter all regions with different labels + vtkImageConnectivityFilter *connect2 = vtkImageConnectivityFilter::New(); + connect2->SetInputData( thresh->GetOutput() ); + connect2->SetScalarRange(255, 255); +// connect2->SetLabelModeToConstantValue(); +// connect2->SetLabelModeToSizeAndRank(); + connect2->SetExtractionModeToAllRegions(); + connect2->Update(); + // Nearest point of al sub regions + double tmpPointA[3]; + double tmpPointB[3]; + double rx,ry,rz,dist; + double minDist = 1000000; + int iRegion,regionSize = connect2->GetNumberOfExtractedRegions(); + // Choosing the most neer mass point to the Input point + for ( iRegion=1; iRegion<=regionSize; iRegion++ ) + { + //thresholdRegion + vtkImageThreshold *threshRegion = vtkImageThreshold::New(); + threshRegion->SetInValue(255); + threshRegion->SetOutValue(0); + threshRegion->SetOutputScalarTypeToUnsignedChar(); + threshRegion->ThresholdBetween( iRegion, iRegion ); // <<<< for each region.... + threshRegion->SetInputData( connect2->GetOutput() ); + threshRegion->Update(); - //Geometric center + //vtkPolyData perimeter + vtkDiscreteFlyingEdges2D *discreteflyingedges2d = vtkDiscreteFlyingEdges2D::New(); + discreteflyingedges2d->SetInputData( threshRegion->GetOutput() ); + discreteflyingedges2d->Update(); - //vtkPolyData perimeter - - vtkDiscreteFlyingEdges2D *discreteflyingedges2d = vtkDiscreteFlyingEdges2D::New(); - discreteflyingedges2d->SetInputData( connect->GetOutput() ); -// discreteflyingedges2d->Update(); - - //vtkCenterOfMass - vtkCenterOfMass *centerofmass = vtkCenterOfMass::New(); - centerofmass->SetUseScalarsAsWeights(false); - - centerofmass->SetInputData( discreteflyingedges2d->GetOutput() ); -// centerofmass->Update(); + //vtkCenterOfMass + vtkCenterOfMass *centerofmass = vtkCenterOfMass::New(); + centerofmass->SetUseScalarsAsWeights(false); + centerofmass->SetInputData( discreteflyingedges2d->GetOutput() ); + centerofmass->Update(); + centerofmass->GetCenter( tmpPointA ); + + if (bbGetInputOrientation()==2) // xy + { + tmpPointB[0] = (int) round(tmpPointA[0]/spc[0]) ; + tmpPointB[1] = (int) round(tmpPointA[1]/spc[1]) ; + tmpPointB[2] = (int) round(tmpPointA[2]/spc[2]) ; + } // if Orientation ==0 xy - connect->AddSeed( bbGetInputInPoint_pixel()[0] , bbGetInputInPoint_pixel()[1] , bbGetInputInPoint_pixel()[2] ); + if (bbGetInputOrientation()==1) // xz + { + tmpPointB[0] = (int) round(tmpPointA[0]/spc[0]) ; + tmpPointB[1] = (int) round(tmpPointA[2]/spc[2]) ; + tmpPointB[2] = (int) round(tmpPointA[1]/spc[1]) ; + } // if Orientation ==0 xy + if (bbGetInputOrientation()==0) // yz + { + tmpPointB[0] = (int) round(tmpPointA[2]/spc[2]) ; + tmpPointB[1] = (int) round(tmpPointA[0]/spc[0]) ; + tmpPointB[2] = (int) round(tmpPointA[1]/spc[1]) ; + } // if Orientation ==0 yz + + rx = tmpPointB[0] - bbGetInputInPoint_pixel()[0] ; + ry = tmpPointB[1] - bbGetInputInPoint_pixel()[1] ; + rz = tmpPointB[2] - bbGetInputInPoint_pixel()[2] ; + dist = sqrt ( rx*rx + ry*ry + rz*rz ); + + if ( (iRegion==1) || (distGetOutput(); + flyingEdges = discreteflyingedges2d->GetOutput(); + } // + + } // for iRegion + +// connect->AddSeed( bbGetInputInPoint_pixel()[0] , bbGetInputInPoint_pixel()[1] , bbGetInputInPoint_pixel()[2] ); + + outPointInt.push_back( (int) round(outPointDouble[0]) ); + outPointInt.push_back( (int) round(outPointDouble[1]) ); + outPointInt.push_back( (int) round(outPointDouble[2]) ); +/* if (bbGetInputOrientation()==2) // xy { - voi[0] = 0; - voi[1] = dim[0]-1; - voi[2] = 0; - voi[3] = dim[1]-1; - voi[4] = bbGetInputInPoint_pixel()[2]; - voi[5] = bbGetInputInPoint_pixel()[2]; - crop->SetVOI(voi); - crop -> Update(); - thresh -> Update(); - connect -> Update(); - discreteflyingedges2d -> Update(); - centerofmass -> Update(); - centerofmass->GetCenter( outPointDouble ); outPointInt.push_back( (int) round(outPointDouble[0]/spc[0]) ); outPointInt.push_back( (int) round(outPointDouble[1]/spc[1]) ); outPointInt.push_back( (int) round(outPointDouble[2]/spc[2]) ); @@ -121,19 +192,6 @@ void GetPropertiesBySlice::Process() if (bbGetInputOrientation()==1) // xz { - voi[0] = 0; - voi[1] = dim[0]-1;; - voi[2] = bbGetInputInPoint_pixel()[1]; - voi[3] = bbGetInputInPoint_pixel()[1]; - voi[4] = 0; - voi[5] = dim[2]-1; - crop->SetVOI(voi); - crop -> Update(); - thresh -> Update(); - connect -> Update(); - discreteflyingedges2d -> Update(); - centerofmass -> Update(); - centerofmass->GetCenter( outPointDouble ); outPointInt.push_back( (int) round(outPointDouble[0]/spc[0]) ); outPointInt.push_back( (int) round(outPointDouble[2]/spc[2]) ); outPointInt.push_back( (int) round(outPointDouble[1]/spc[1]) ); @@ -141,34 +199,13 @@ void GetPropertiesBySlice::Process() if (bbGetInputOrientation()==0) // yz { - voi[0] = bbGetInputInPoint_pixel()[0]; - voi[1] = bbGetInputInPoint_pixel()[0]; - voi[2] = 0; - voi[3] = dim[1]-1;; - voi[4] = 0; - voi[5] = dim[2]-1; - crop->SetVOI(voi); - crop -> Update(); - thresh -> Update(); - connect -> Update(); - discreteflyingedges2d -> Update(); - centerofmass -> Update(); - centerofmass->GetCenter( outPointDouble ); outPointInt.push_back( (int) round(outPointDouble[2]/spc[2]) ); outPointInt.push_back( (int) round(outPointDouble[0]/spc[0]) ); outPointInt.push_back( (int) round(outPointDouble[1]/spc[1]) ); } // if Orientation ==0 yz - - //Clean Memory -/* - crop -> Delete(); - thresh -> Delete(); - connect -> Delete(); - discreteflyingedges2d -> Delete(); - centerofmass -> Delete(); -*/ - bbSetOutputImageConnected2D( connect->GetOutput() ); - bbSetOutputPolyDataDiscreteflyingedges2D( discreteflyingedges2d->GetOutput() ); + */ + bbSetOutputImageConnected2D( outRegion ); + bbSetOutputPolyDataDiscreteflyingedges2D( flyingEdges ); bbSetOutputValue( bbGetInputImage()->GetScalarComponentAsDouble( outPointInt[0],outPointInt[1],outPointInt[2], 0) ); bbSetOutputOutPoint_pixel( outPointInt ); } // if type == 1 geometric center diff --git a/bbtk_creaVtk_PKG/src/bbcreaVtkGetPropertiesBySlice.h b/bbtk_creaVtk_PKG/src/bbcreaVtkGetPropertiesBySlice.h index 0c564b2..8e48f2b 100644 --- a/bbtk_creaVtk_PKG/src/bbcreaVtkGetPropertiesBySlice.h +++ b/bbtk_creaVtk_PKG/src/bbcreaVtkGetPropertiesBySlice.h @@ -44,7 +44,7 @@ BBTK_BEGIN_DESCRIBE_BLACK_BOX(GetPropertiesBySlice,bbtk::AtomicBlackBox); BBTK_DESCRIPTION("No Description."); BBTK_CATEGORY("empty"); BBTK_INPUT(GetPropertiesBySlice,Image,"Input image",vtkImageData*,""); - BBTK_INPUT(GetPropertiesBySlice,Orientation,"(default 0) Orientation 0=xy 1=yz 2=xz",int,""); + BBTK_INPUT(GetPropertiesBySlice,Orientation,"(default 0) Orientation 0=yz 1=xz 2=xy",int,""); BBTK_INPUT(GetPropertiesBySlice,Type,"(default 0) 0=nothing 1=Geometric center",int,""); BBTK_INPUT(GetPropertiesBySlice,InPoint_pixel,"In point in pixel units",std::vector,""); BBTK_OUTPUT(GetPropertiesBySlice,OutPoint_pixel,"Out point in pixel units",std::vector,""); diff --git a/bbtk_creaVtk_PKG/src/bbcreaVtkMassProperties.cxx b/bbtk_creaVtk_PKG/src/bbcreaVtkMassProperties.cxx index f35bd91..9e394bf 100644 --- a/bbtk_creaVtk_PKG/src/bbcreaVtkMassProperties.cxx +++ b/bbtk_creaVtk_PKG/src/bbcreaVtkMassProperties.cxx @@ -11,12 +11,12 @@ namespace bbcreaVtk BBTK_ADD_BLACK_BOX_TO_PACKAGE(creaVtk,MassProperties) BBTK_BLACK_BOX_IMPLEMENTATION(MassProperties,bbtk::AtomicBlackBox); -//===== + +//===== // Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost) //===== void MassProperties::Process() { - // THE MAIN PROCESSING METHOD BODY // Here we simply set the input 'In' value to the output 'Out' // And print out the output value @@ -30,13 +30,13 @@ void MassProperties::Process() // (the one provided in the attribute 'type' of the tag 'input') // bbSetOutputOut( bbGetInputIn() ); // std::cout << "Output value = " <SetInputData( bbGetInputIn() ); massproperties->Update(); bbSetOutputSurfaceArea( massproperties->GetSurfaceArea() ); + bbSetOutputVolume( massproperties->GetVolume() ); bbSetOutputVolumeX( massproperties->GetVolumeX() ); bbSetOutputVolumeY( massproperties->GetVolumeY() ); bbSetOutputVolumeZ( massproperties->GetVolumeZ() ); @@ -45,43 +45,39 @@ void MassProperties::Process() bbSetOutputNormalizedShapeIndex( massproperties->GetNormalizedShapeIndex() ); } // if In !NULL } -//===== + +//===== // Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost) //===== void MassProperties::bbUserSetDefaultValues() { - // SET HERE THE DEFAULT INPUT/OUTPUT VALUES OF YOUR BOX // Here we initialize the input 'In' to 0 bbSetInputIn(NULL); - } -//===== + +//===== // Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost) //===== void MassProperties::bbUserInitializeProcessing() { - // THE INITIALIZATION METHOD BODY : // Here does nothing // but this is where you should allocate the internal/output pointers -// if any - - +// if any } -//===== + +//===== // Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost) //===== void MassProperties::bbUserFinalizeProcessing() { - // THE FINALIZATION METHOD BODY : // Here does nothing // but this is where you should desallocate the internal/output pointers // if any - } -} -// EO namespace bbcreaVtk + +}// EO namespace bbcreaVtk diff --git a/bbtk_creaVtk_PKG/src/bbcreaVtkMassProperties.h b/bbtk_creaVtk_PKG/src/bbcreaVtkMassProperties.h index f92702d..b760cdb 100644 --- a/bbtk_creaVtk_PKG/src/bbcreaVtkMassProperties.h +++ b/bbtk_creaVtk_PKG/src/bbcreaVtkMassProperties.h @@ -23,6 +23,7 @@ class bbcreaVtk_EXPORT MassProperties //===== BBTK_DECLARE_INPUT(In, vtkPolyData*); BBTK_DECLARE_OUTPUT(SurfaceArea,double); + BBTK_DECLARE_OUTPUT(Volume,double); BBTK_DECLARE_OUTPUT(VolumeX,double); BBTK_DECLARE_OUTPUT(VolumeY,double); BBTK_DECLARE_OUTPUT(VolumeZ,double); @@ -43,13 +44,13 @@ BBTK_BEGIN_DESCRIBE_BLACK_BOX(MassProperties,bbtk::AtomicBlackBox); BBTK_CATEGORY("empty"); BBTK_INPUT(MassProperties,In,"Mesh PolyData",vtkPolyData*,""); BBTK_OUTPUT(MassProperties,SurfaceArea,"Surface Area",double,""); - BBTK_OUTPUT(MassProperties,VolumeX,"VolumeX",double,""); - BBTK_OUTPUT(MassProperties,VolumeY,"VolumeY",double,""); - BBTK_OUTPUT(MassProperties,VolumeZ,"VolumeZ",double,""); + BBTK_OUTPUT(MassProperties,Volume,"Volume",double,""); + BBTK_OUTPUT(MassProperties,VolumeX,"VolumeX Compute and return the volume projected on to each axis aligned plane.",double,""); + BBTK_OUTPUT(MassProperties,VolumeY,"VolumeY Compute and return the volume projected on to each axis aligned plane.",double,""); + BBTK_OUTPUT(MassProperties,VolumeZ,"VolumeZ Compute and return the volume projected on to each axis aligned plane.",double,""); BBTK_OUTPUT(MassProperties,MinCellArea,"MinCellArea",double,""); BBTK_OUTPUT(MassProperties,MaxCellArea,"MaxCellArea",double,""); BBTK_OUTPUT(MassProperties,NormalizedShapeIndex,"NormalizedShapeIndex",double,""); - BBTK_END_DESCRIBE_BLACK_BOX(MassProperties); //===== // Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost) diff --git a/bbtk_creaVtk_PKG/src/bbcreaVtkPolyDataConnectivityFilter.cxx b/bbtk_creaVtk_PKG/src/bbcreaVtkPolyDataConnectivityFilter.cxx index b2becd1..df2fbdc 100644 --- a/bbtk_creaVtk_PKG/src/bbcreaVtkPolyDataConnectivityFilter.cxx +++ b/bbtk_creaVtk_PKG/src/bbcreaVtkPolyDataConnectivityFilter.cxx @@ -35,7 +35,8 @@ void PolyDataConnectivityFilter::Process() return; } - if(bbGetInputType() == 1){ + if(bbGetInputType() == 1) // Extract all connected regions + { connFilter->SetInputData( bbGetInputIn() ); connFilter->SetExtractionModeToSpecifiedRegions(); connFilter->Update(); @@ -49,10 +50,20 @@ void PolyDataConnectivityFilter::Process() component->DeepCopy(connFilter->GetOutput()); output.push_back(component); connFilter->DeleteSpecifiedRegion(i); - } - - bbSetOutputOut(output); - } + } // for i + } // Type == 1 + if(bbGetInputType() == 5) // Extract the region closest to the specified point + { + if (bbGetInputPoint().size()==3) + { + connFilter->SetInputData( bbGetInputIn() ); + connFilter->SetExtractionModeToClosestPointRegion(); + connFilter->SetClosestPoint(bbGetInputPoint()[0], bbGetInputPoint()[1], bbGetInputPoint()[2] ); + connFilter->Update(); + output.push_back( connFilter->GetOutput() ); + } + } // Type == 5 + bbSetOutputOut(output); } //===== // Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost) diff --git a/bbtk_creaVtk_PKG/src/bbcreaVtkPolyDataConnectivityFilter.h b/bbtk_creaVtk_PKG/src/bbcreaVtkPolyDataConnectivityFilter.h index d9547d4..aa481eb 100644 --- a/bbtk_creaVtk_PKG/src/bbcreaVtkPolyDataConnectivityFilter.h +++ b/bbtk_creaVtk_PKG/src/bbcreaVtkPolyDataConnectivityFilter.h @@ -21,11 +21,12 @@ class bbcreaVtk_EXPORT PolyDataConnectivityFilter //===== // Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost) //===== - BBTK_DECLARE_INPUT(In,vtkPolyData*); - BBTK_DECLARE_INPUT(Type,int); - BBTK_DECLARE_OUTPUT(Out,std::vector); - BBTK_PROCESS(Process); - void Process(); + BBTK_DECLARE_INPUT(In,vtkPolyData*); + BBTK_DECLARE_INPUT(Type,int); + BBTK_DECLARE_INPUT(Point,std::vector); + BBTK_DECLARE_OUTPUT(Out,std::vector); + BBTK_PROCESS(Process); + void Process(); vtkPolyDataConnectivityFilter *connFilter; //===== @@ -39,7 +40,8 @@ BBTK_AUTHOR("InfoDev"); BBTK_DESCRIPTION("No Description."); BBTK_CATEGORY("empty"); BBTK_INPUT(PolyDataConnectivityFilter,In,"Input polydata",vtkPolyData*,""); -BBTK_INPUT(PolyDataConnectivityFilter,Type,"0: nothing, 1: Extract all connected regions",int,""); +BBTK_INPUT(PolyDataConnectivityFilter,Type,"0: nothing, 1: Extract all connected regions, 5: Extract the region closest to the specified point",int,""); +BBTK_INPUT(PolyDataConnectivityFilter,Point,"(Type 5) Input point",std::vector,""); BBTK_OUTPUT(PolyDataConnectivityFilter,Out,"output polydatas",std::vector,""); BBTK_END_DESCRIBE_BLACK_BOX(PolyDataConnectivityFilter); //===== -- 2.56.0