From: eduardo.davila@creatis.insa-lyon.fr Date: Mon, 16 Feb 2026 17:25:13 +0000 (+0100) Subject: #3544 ThinningImageFilter3D X-Git-Url: http://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=1d5f6851994334fa6630cbf6db1a95f7351436b7;p=bbtk.git #3544 ThinningImageFilter3D --- diff --git a/kernel/src/bbtkBlackBox.cxx b/kernel/src/bbtkBlackBox.cxx index 6d0afbb..b74d65a 100644 --- a/kernel/src/bbtkBlackBox.cxx +++ b/kernel/src/bbtkBlackBox.cxx @@ -774,7 +774,7 @@ namespace bbtk ( (bbBoxProcessModeIsManual()==true)&&(bbLetRecursiveExecuteManualMode==true) ) ) { - + // printf("EED BlackBox::bbRecursiveExecute bbProcess start %s \n", bbGetFullName().c_str() ); //auto start = std::chrono::high_resolution_clock::now(); @@ -1041,41 +1041,33 @@ namespace bbtk std::string v; // Looks for the adaptor if (bbGetOutputType(output).name() != typeid(std::string).name() ) - { - // Look for factory - Package::Pointer p = bbGetDescriptor()->GetPackage(); - if ((p != 0) && ( ! p->GetFactorySet().empty() ) ) - { - Factory::Pointer f = p->GetFactorySet().begin()->lock(); - BlackBox::Pointer a; - try - { - a = f->NewAdaptor( - bbGetOutputType(output), - typeid(std::string), - ""); - } catch (bbtk::Exception e) - { - } - if (a){ - // bbUpdate(); - a->bbSetInput("In",bbGetOutput(output)); - a->bbExecute(); - v = a->bbGetOutput("Out").unsafe_get() ; - } else { - v="? (no adaptor found)"; - } - } - else - { - v="? (no factory found)"; - } - } - else - { - // bbUpdate(); - v = bbGetOutput(output).unsafe_get() ; - } + { + // Look for factory + Package::Pointer p = bbGetDescriptor()->GetPackage(); + if ((p != 0) && ( ! p->GetFactorySet().empty() ) ) + { + Factory::Pointer f = p->GetFactorySet().begin()->lock(); + BlackBox::Pointer a; + try { + a = f->NewAdaptor( bbGetOutputType(output), typeid(std::string), ""); + } catch (bbtk::Exception e) { + } + if (a) + { + // bbUpdate(); + a->bbSetInput("In",bbGetOutput(output)); + a->bbExecute(); + v = a->bbGetOutput("Out").unsafe_get() ; + } else { + v="? (no adaptor found)"; + } // if a + } else { + v="? (no factory found)"; + } // if p + } else { + // bbUpdate(); + v = bbGetOutput(output).unsafe_get() ; + } // name return v; } //========================================================================= diff --git a/kernel/src/bbtkConnection.cxx b/kernel/src/bbtkConnection.cxx index 9624cea..f3d5a9f 100644 --- a/kernel/src/bbtkConnection.cxx +++ b/kernel/src/bbtkConnection.cxx @@ -442,13 +442,11 @@ Connection::Connection(BlackBox::Pointer from, const std::string& output, mTo->bbSetInput( mInput, mFrom->bbGetOutput(mOutput), false); - } - else - { + } else { // 2) Look for an adaptor bbtk::BlackBox::Pointer adaptor; try - { + { adaptor = mFactory.lock() ->NewAdaptor(mFrom->bbGetOutput(mOutput).type(), mTo->bbGetInputType(mInput), diff --git a/kernel/src/bbtkFactory.cxx b/kernel/src/bbtkFactory.cxx index 368275a..3b8e915 100644 --- a/kernel/src/bbtkFactory.cxx +++ b/kernel/src/bbtkFactory.cxx @@ -110,20 +110,20 @@ namespace bbtk pkgname, path); if (p!=0) - { - //=================================================================== - bbtkMessage("output",2,p->GetName()<<" " + { + //=================================================================== + bbtkMessage("output",2,p->GetName()<<" " <GetVersion() <<" " <GetAuthor() << " Category(s) :" <GetCategory() <GetDescription()<AddFactory(GetThisPointer()); - mPackageMap[pkgname] = p; - return true; - } + bbtkMessage("output",2,p->GetDescription()<AddFactory(GetThisPointer()); + mPackageMap[pkgname] = p; + return true; + } // if p return false; } @@ -641,27 +641,20 @@ namespace bbtk <second->NewAdaptor(typein,typeout,name); - if (b) break; - } - if (!b) - { - bbtkError("no "<second->NewAdaptor(typein,typeout,name); + if (b) break; + } if (!b) { + bbtkError("no "< with name BlackBox::Pointer Factory::NewWidgetAdaptor(const DataInfo& typein, diff --git a/kernel/src/bbtkPackage.cxx b/kernel/src/bbtkPackage.cxx index bcb8308..4b97e16 100644 --- a/kernel/src/bbtkPackage.cxx +++ b/kernel/src/bbtkPackage.cxx @@ -728,14 +728,13 @@ printf("EED Package::OpenDynamicLibrary %s %s \n", libname.c_str(), package_n <second.lock()->NewBlackBox(name); bbtkDebugDecTab("kernel",8); return bb; @@ -844,11 +843,11 @@ printf("EED Package::OpenDynamicLibrary %s %s \n", libname.c_str(), package_n DescriptorMapType::iterator i = mDescriptorMap.find(d->GetTypeName()); if (i!=mDescriptorMap.end()) - { - bbtkWarning("Package<"< : Trying to register box type <" + { + bbtkWarning("Package<"< : Trying to register box type <" <GetTypeName()<<"> which is already in the package"); - return false; - } + return false; + } mDescriptorMap[d->GetTypeName()] = d; // d->Reference(); @@ -856,34 +855,31 @@ printf("EED Package::OpenDynamicLibrary %s %s \n", libname.c_str(), package_n // If it is a default adaptor, also register it in the adaptors map if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_ADAPTOR ) - { - bbtkDebugMessage("kernel",8,"Package<"<::Register(\""<GetTypeName()<<"\") : The box is an adaptor, inserting it in adaptors map ..."<::Register(\""<GetTypeName()<<"\") : The box is an adaptor, inserting it in adaptors map ..."<GetInputDescriptor("In")->GetTypeInfo(); - TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo(); - DataInfo infoin(typein,d->GetInputDescriptor("In")->GetNature()); - DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature()); - AdaptorKey key(infoin,infoout,d->GetKind()); + TypeInfo typein = d->GetInputDescriptor("In")->GetTypeInfo(); + TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo(); + DataInfo infoin(typein,d->GetInputDescriptor("In")->GetNature()); + DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature()); + AdaptorKey key(infoin,infoout,d->GetKind()); - AdaptorMapType::const_iterator i; - i = mAdaptorMap.find(key); - if (i == mAdaptorMap.end()) - { - mAdaptorMap[key] = d; - } - // If already an adaptor registered : error - else - { - if (i->second.lock()->GetTypeName() != d->GetTypeName()) - { - bbtkError("Package <"< : trying to register black box <" - <GetTypeName() - <<"> as default adaptor but there is already a default adaptor registered (<" - <second.lock()->GetTypeName()<<">)"); - } - } - } + AdaptorMapType::const_iterator i; + i = mAdaptorMap.find(key); + if (i == mAdaptorMap.end()) + { + mAdaptorMap[key] = d; + } else { // If already an adaptor registered : error + if (i->second.lock()->GetTypeName() != d->GetTypeName()) + { + bbtkError("Package <"< : trying to register black box <" + <GetTypeName() + <<"> as default adaptor but there is already a default adaptor registered (<" + <second.lock()->GetTypeName()<<">)"); + } // if name + }// if i + } // if kind // If it is a default adaptor, also register it in the adaptors map else if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_GUI) { diff --git a/packages/itk/bbs/appli/exampleThinningImageFilter3D.bbg b/packages/itk/bbs/appli/exampleThinningImageFilter3D.bbg new file mode 100644 index 0000000..751a986 --- /dev/null +++ b/packages/itk/bbs/appli/exampleThinningImageFilter3D.bbg @@ -0,0 +1,56 @@ +# ---------------------------------- +# - BBTKGEditor v 1.6 BBG BlackBox Diagram file +# - /Users/davila/Creatis/C23/creatools_source/bbtk/packages/itk/bbs/appli/exampleThinningImageFilter3D.bbg +# ---------------------------------- + +APP_START +CATEGORY: +DESCRIPTION:Description ?? +AUTHOR:Author ?? +EXPORTFORMAT:0 +COMPLEXBOX:FALSE +COMPLEXINPUTS:0 +BOXES:5 +BOX +vtk:LoadHola:Box00 +ISEXEC:FALSE +-10.742698:32.159670:-900.000000 +10.807302:29.659670:-900.000000 +FIN_BOX +BOX +creaMaracasVisu:ImageChangeInformation:Box01 +ISEXEC:FALSE +-11.837496:23.127593:-900.000000 +11.312504:20.627593:-900.000000 +FIN_BOX +BOX +itk:TubularStructures_Sato:Box02 +ISEXEC:FALSE +-21.074848:6.431934:-900.000000 +1.720152:3.931934:-900.000000 +FIN_BOX +BOX +vtk:RescaleSlopeIntercept:Box03 +ISEXEC:FALSE +-17.379907:13.958665:-900.000000 +5.445093:11.458665:-900.000000 +PORT +OutputFormat:"VTK_DOUBLE" +FIN_BOX +BOX +creaMaracasVisu:ViewerNV:Box04 +ISEXEC:TRUE +-21.348547:-6.979333:-900.000000 +20.771453:-9.479333:-900.000000 +FIN_BOX +CONNECTIONS:3 +CONNECTION +Box00:Out:Box01:In +NumberOfControlPoints:0 +CONNECTION +Box01:Out:Box03:In +NumberOfControlPoints:0 +CONNECTION +Box03:Out:Box02:In +NumberOfControlPoints:0 +APP_END diff --git a/packages/itk/bbs/appli/exampleThinningImageFilter3D.bbs b/packages/itk/bbs/appli/exampleThinningImageFilter3D.bbs new file mode 100644 index 0000000..72ee917 --- /dev/null +++ b/packages/itk/bbs/appli/exampleThinningImageFilter3D.bbs @@ -0,0 +1,40 @@ +# ---------------------------------- +# - BBTKGEditor v 1.6 BBS BlackBox Script +# - /Users/davila/Creatis/C23/creatools_source/bbtk/packages/itk/bbs/appli/exampleThinningImageFilter3D.bbs +# ---------------------------------- + +# BBTK GEditor Script +# ---------------------- + +include std +include itkvtk +include vtk +include creaMaracasVisu +include itk + +author "Author ??" +description "Description ??" +category "" + +new vtk:LoadHola Box00 + +new creaMaracasVisu:ImageChangeInformation Box01 + +new itk:TubularStructures_Sato Box02 + +new vtk:RescaleSlopeIntercept Box03 + set Box03.OutputFormat "VTK_DOUBLE" + +new creaMaracasVisu:ViewerNV Box04 + + +connect Box00.Out Box01.In + +connect Box01.Out Box03.In + +connect Box03.Out Box02.In + + + +# Complex input ports +exec Box04 diff --git a/packages/itk/src/bbitkThinningImageFilter3D.cxx b/packages/itk/src/bbitkThinningImageFilter3D.cxx new file mode 100644 index 0000000..5eaf4a7 --- /dev/null +++ b/packages/itk/src/bbitkThinningImageFilter3D.cxx @@ -0,0 +1,12 @@ +//===== +// 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) +//===== +#include "bbitkThinningImageFilter3D.h" +#include "bbitkPackage.h" +namespace bbitk +{ + BBTK_ADD_BLACK_BOX_TO_PACKAGE(itk,ThinningImageFilter3D) + BBTK_BLACK_BOX_IMPLEMENTATION(ThinningImageFilter3D,bbtk::AtomicBlackBox); +}// EO namespace bbitk + + diff --git a/packages/itk/src/bbitkThinningImageFilter3D.h b/packages/itk/src/bbitkThinningImageFilter3D.h new file mode 100644 index 0000000..0cebb5b --- /dev/null +++ b/packages/itk/src/bbitkThinningImageFilter3D.h @@ -0,0 +1,169 @@ +//===== +// 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) +//===== +#ifndef __bbitkThinningImageFilter3D_h_INCLUDED__ +#define __bbitkThinningImageFilter3D_h_INCLUDED__ + +#include "bbitk_EXPORT.h" +#include "bbtkAtomicBlackBox.h" +#include "iostream" + +#include "itkBinaryThinningImageFilter3D.hxx" + +#include "bbitkImage.h" + +namespace bbitk +{ + +class bbitk_EXPORT ThinningImageFilter3D +: +public bbtk::AtomicBlackBox +{ + BBTK_BLACK_BOX_INTERFACE(ThinningImageFilter3D,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) + //===== + BBTK_DECLARE_INPUT(In,anyImagePointer); + BBTK_DECLARE_OUTPUT(Out,anyImagePointer); + + BBTK_PROCESS(ProcessSwitch); + private : + inline void ProcessSwitch(); + template void Process(); + itk::Object *mOutput; + + //===== + // 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_BEGIN_DESCRIBE_BLACK_BOX(ThinningImageFilter3D,bbtk::AtomicBlackBox); + BBTK_NAME("ThinningImageFilter3D"); + BBTK_AUTHOR("InfoDev"); + BBTK_DESCRIPTION("No Description."); + BBTK_CATEGORY("empty"); + BBTK_INPUT(ThinningImageFilter3D,In,"Image (SHORT format)",anyImagePointer,""); + BBTK_OUTPUT(ThinningImageFilter3D,Out,"Output image ",anyImagePointer,""); +BBTK_END_DESCRIBE_BLACK_BOX(ThinningImageFilter3D); +//===== +// 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 ThinningImageFilter3D::ProcessSwitch() +{ + bbtk::TypeInfo t = bbGetInputIn().type(); +// BBTK_TEMPLATE_ITK_IMAGE_SWITCH(t, this->Process); +// BBTK_TEMPLATE_ITK_IMAGE_DIM_3_SWITCH(t, this->Process , "Error format. (you need 3D short,float,double)") ; + + BBTK_BEGIN_TEMPLATE_SWITCH(t) +// BBTK_SWITCH_ITK_IMAGE_short_3(t,this->Process,) + BBTK_SWITCH_ITK_IMAGE_int16_t_3(t,this->Process,) +// BBTK_SWITCH_ITK_IMAGE_float_3(t,this->Process,) +// BBTK_SWITCH_ITK_IMAGE_double_3(t,this->Process,) + BBTK_END_TEMPLATE_SWITCH(t) +} + +//===== +// 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) +//===== +template +void ThinningImageFilter3D::Process() +{ + // + // https://github.com/thewtex/ITKBinaryThinningImageFilter3D + // + printf("EED ThinningImageFilter3D::Process Start\n"); + + // Verify the number of parameters in the command line +// if (argc <= 2) +// { +// std::cerr << "Usage: " << std::endl; +// std::cerr << argv[0] << " inputImageFile outputImageFile" << std::endl; +// return EXIT_FAILURE; +// } +// char *infilename = argv[1]; +// char *outfilename = argv[2]; +// + const unsigned int Dimension = 3; + typedef signed short PixelType; // must be signed for CT since Hounsfield units can be < 0 + typedef itk::Image ImageType; + +// // Read image +// typedef itk::ImageFileReader ReaderType; +// ReaderType::Pointer reader = ReaderType::New(); +// reader->SetFileName(infilename); +// try +// { +// reader->Update(); +// } +// catch (itk::ExceptionObject &ex) +// { +// std::cout << ex << std::endl; +// return EXIT_FAILURE; +// } +// cout << infilename << " sucessfully read." << endl; + + // Define the thinning filter + typedef itk::BinaryThinningImageFilter3D ThinningFilterType; + ThinningFilterType::Pointer thinningFilter = ThinningFilterType::New(); + + T* inputImage = this->bbGetInputIn().get(); +// thinningFilter->SetInput( reader->GetOutput() ); + thinningFilter->SetInput( inputImage ); + + thinningFilter->Update(); + thinningFilter->GetOutput()->Register(); + + +// // output to file +// typedef itk::ImageFileWriter WriterType; +// WriterType::Pointer writer = WriterType::New(); +// writer->SetInput(thinningFilter->GetOutput()); +// writer->SetFileName(outfilename); +// +// try +// { +// writer->Update(); +// } +// catch (itk::ExceptionObject &ex) +// { +// std::cout << ex << std::endl; +// return EXIT_FAILURE; +// } +// cout << outfilename << " sucessfully written." << endl; + +// cout << "Program terminated normally." << endl; +// return EXIT_SUCCESS; + + if (mOutput) mOutput->UnRegister(); + this->bbSetOutputOut( thinningFilter->GetOutput() ); + mOutput = thinningFilter->GetOutput(); + printf("EED ThinningImageFilter3D::Process End\n"); +} + +//===== +// 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 ThinningImageFilter3D::bbUserSetDefaultValues() +{ + mOutput = 0; +} + +//===== +// 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 ThinningImageFilter3D::bbUserInitializeProcessing() +{ +} + +//===== +// 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 ThinningImageFilter3D::bbUserFinalizeProcessing() +{ +} + +}// EO namespace bbitk +#endif // __bbitkThinningImageFilter3D_h_INCLUDED__ + diff --git a/packages/itk/src/itkBinaryThinningImageFilter3D.h b/packages/itk/src/itkBinaryThinningImageFilter3D.h new file mode 100644 index 0000000..8441ce1 --- /dev/null +++ b/packages/itk/src/itkBinaryThinningImageFilter3D.h @@ -0,0 +1,172 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ +#ifndef itkBinaryThinningImageFilter3D_h +#define itkBinaryThinningImageFilter3D_h + +#include +#include +#include +#include + +namespace itk +{ +/** \class BinaryThinningImageFilter3D +* +* \brief This filter computes one-pixel-wide skeleton of a 3D input image. +* +* This class is parametrized over the type of the input image +* and the type of the output image. +* +* The input is assumed to be a binary image. All non-zero valued voxels +* are set to 1 internally to simplify the computation. The filter will +* produce a skeleton of the object. The output background values are 0, +* and the foreground values are 1. +* +* A 26-neighbourhood configuration is used for the foreground and a +* 6-neighbourhood configuration for the background. Thinning is performed +* symmetrically in order to guarantee that the skeleton lies medial within +* the object. +* +* This filter is a parallel thinning algorithm and is an implementation +* of the algorithm described in: +* +* T.C. Lee, R.L. Kashyap, and C.N. Chu. +* Building skeleton models via 3-D medial surface/axis thinning algorithms. +* Computer Vision, Graphics, and Image Processing, 56(6):462--478, 1994. +* +* To do: Make use of multi-threading. +* +* \author Hanno Homann, Oxford University, Wolfson Medical Vision Lab, UK. +* +* \sa MorphologyImageFilter +* \ingroup ImageEnhancement MathematicalMorphologyImageFilters BinaryThinningImageFilter3D +*/ + +template +class BinaryThinningImageFilter3D : public ImageToImageFilter +{ +public: + /** Standard class typedefs. */ + typedef BinaryThinningImageFilter3D Self; + typedef ImageToImageFilter Superclass; + typedef SmartPointer Pointer; + typedef SmartPointer ConstPointer; + + /** Method for creation through the object factory */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(BinaryThinningImageFilter3D, ImageToImageFilter); + + /** Type for input image. */ + typedef TInputImage InputImageType; + + /** Type for output image: Skelenton of the object. */ + typedef TOutputImage OutputImageType; + + /** Type for the region of the input image. */ + typedef typename InputImageType::RegionType RegionType; + + /** Type for the index of the input image. */ + typedef typename RegionType::IndexType IndexType; + + /** Type for the pixel type of the input image. */ + typedef typename InputImageType::PixelType InputImagePixelType; + + /** Type for the pixel type of the input image. */ + typedef typename OutputImageType::PixelType OutputImagePixelType; + + /** Type for the size of the input image. */ + typedef typename RegionType::SizeType SizeType; + + /** Pointer Type for input image. */ + typedef typename InputImageType::ConstPointer InputImagePointer; + + /** Pointer Type for the output image. */ + typedef typename OutputImageType::Pointer OutputImagePointer; + + /** Boundary condition type for the neighborhood iterator */ + typedef ConstantBoundaryCondition ConstBoundaryConditionType; + + /** Neighborhood iterator type */ + typedef NeighborhoodIterator NeighborhoodIteratorType; + + /** Neighborhood type */ + typedef typename NeighborhoodIteratorType::NeighborhoodType NeighborhoodType; + + /** Get Skelenton by thinning image. */ + OutputImageType *GetThinning(void); + + /** ImageDimension enumeration */ + itkStaticConstMacro(InputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + TOutputImage::ImageDimension); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ + itkConceptMacro(SameDimensionCheck, + (Concept::SameDimension)); + itkConceptMacro(SameTypeCheck, + (Concept::SameType)); + itkConceptMacro(InputAdditiveOperatorsCheck, + (Concept::AdditiveOperators)); + itkConceptMacro(InputConvertibleToIntCheck, + (Concept::Convertible)); + itkConceptMacro(IntConvertibleToInputCheck, + (Concept::Convertible)); + itkConceptMacro(InputIntComparableCheck, + (Concept::Comparable)); + /** End concept checking */ +#endif + +protected: + BinaryThinningImageFilter3D(); + virtual ~BinaryThinningImageFilter3D(){}; + void PrintSelf(std::ostream &os, Indent indent) const; + + /** Compute thinning Image. */ + void GenerateData(); + + /** Prepare data. */ + void PrepareData(); + + /** Compute thinning Image. */ + void ComputeThinImage(); + + /** isEulerInvariant [Lee94] */ + bool isEulerInvariant(NeighborhoodType neighbors, int *LUT); + void fillEulerLUT(int *LUT); + /** isSimplePoint [Lee94] */ + bool isSimplePoint(NeighborhoodType neighbors); + /** Octree_labeling [Lee94] */ + void Octree_labeling(int octant, int label, int *cube); + +private: + BinaryThinningImageFilter3D(const Self &); //purposely not implemented + void operator=(const Self &); //purposely not implemented + +}; // end of BinaryThinningImageFilter3D class + +} //end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkBinaryThinningImageFilter3D.hxx" +#endif + +#endif // itkBinaryThinningImageFilter3D_h diff --git a/packages/itk/src/itkBinaryThinningImageFilter3D.hxx b/packages/itk/src/itkBinaryThinningImageFilter3D.hxx new file mode 100644 index 0000000..bd7e9e4 --- /dev/null +++ b/packages/itk/src/itkBinaryThinningImageFilter3D.hxx @@ -0,0 +1,965 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ +#ifndef itkBinaryThinningImageFilter3D_hxx +#define itkBinaryThinningImageFilter3D_hxx + +#include + +#include "itkBinaryThinningImageFilter3D.h" +#include "itkImageRegionConstIterator.h" +#include "itkImageRegionIterator.h" +#include "itkNeighborhoodIterator.h" +#include + +namespace itk +{ +/** + * Constructor + */ +template +BinaryThinningImageFilter3D::BinaryThinningImageFilter3D() +{ + + this->SetNumberOfRequiredOutputs(1); + + OutputImagePointer thinImage = OutputImageType::New(); + this->SetNthOutput(0, thinImage.GetPointer()); +} + +/** + * Return the thinning Image pointer + */ +template +typename BinaryThinningImageFilter3D< + TInputImage, TOutputImage>::OutputImageType * +BinaryThinningImageFilter3D::GetThinning(void) +{ + return dynamic_cast( + this->ProcessObject::GetOutput(0)); +} + +/** + * Prepare data for computation + * Copy the input image to the output image, changing from the input + * type to the output type. + */ +template +void BinaryThinningImageFilter3D::PrepareData(void) +{ + + itkDebugMacro(<< "PrepareData Start"); + OutputImagePointer thinImage = GetThinning(); + + InputImagePointer inputImage = + dynamic_cast(ProcessObject::GetInput(0)); + + thinImage->SetBufferedRegion(thinImage->GetRequestedRegion()); + thinImage->Allocate(); + + typename OutputImageType::RegionType region = thinImage->GetRequestedRegion(); + + ImageRegionConstIterator it(inputImage, region); + ImageRegionIterator ot(thinImage, region); + + it.GoToBegin(); + ot.GoToBegin(); + + itkDebugMacro(<< "PrepareData: Copy input to output"); + + // Copy the input to the output, changing all foreground pixels to + // have value 1 in the process. + while (!ot.IsAtEnd()) + { + if (it.Get()) + { + ot.Set(NumericTraits::One); + } + else + { + ot.Set(NumericTraits::Zero); + } + ++it; + ++ot; + } + itkDebugMacro(<< "PrepareData End"); +} + +/** + * Post processing for computing thinning + */ +template +void BinaryThinningImageFilter3D::ComputeThinImage() +{ + itkDebugMacro(<< "ComputeThinImage Start"); + OutputImagePointer thinImage = GetThinning(); + + typename OutputImageType::RegionType region = thinImage->GetRequestedRegion(); + + ConstBoundaryConditionType boundaryCondition; + boundaryCondition.SetConstant(0); + + typename NeighborhoodIteratorType::RadiusType radius; + radius.Fill(1); + NeighborhoodIteratorType ot(radius, thinImage, region); + ot.SetBoundaryCondition(boundaryCondition); + + std::vector simpleBorderPoints; + typename std::vector::iterator simpleBorderPointsIt; + + // Define offsets + typedef typename NeighborhoodIteratorType::OffsetType OffsetType; + OffsetType N = {{0, -1, 0}}; // north + OffsetType S = {{0, 1, 0}}; // south + OffsetType E = {{1, 0, 0}}; // east + OffsetType W = {{-1, 0, 0}}; // west + OffsetType U = {{0, 0, 1}}; // up + OffsetType B = {{0, 0, -1}}; // bottom + + // prepare Euler LUT [Lee94] + int eulerLUT[256]; + fillEulerLUT(eulerLUT); + // Loop through the image several times until there is no change. + int unchangedBorders = 0; + while (unchangedBorders < 6) // loop until no change for all the six border types + { + unchangedBorders = 0; + for (int currentBorder = 1; currentBorder <= 6; currentBorder++) + { + // Loop through the image. + for (ot.GoToBegin(); !ot.IsAtEnd(); ++ot) + { + // check if point is foreground + if (ot.GetCenterPixel() != 1) + { + continue; // current point is already background + } + // check 6-neighbors if point is a border point of type currentBorder + bool isBorderPoint = false; + if (currentBorder == 1 && ot.GetPixel(N) <= 0) + isBorderPoint = true; + if (currentBorder == 2 && ot.GetPixel(S) <= 0) + isBorderPoint = true; + if (currentBorder == 3 && ot.GetPixel(E) <= 0) + isBorderPoint = true; + if (currentBorder == 4 && ot.GetPixel(W) <= 0) + isBorderPoint = true; + if (currentBorder == 5 && ot.GetPixel(U) <= 0) + isBorderPoint = true; + if (currentBorder == 6 && ot.GetPixel(B) <= 0) + isBorderPoint = true; + if (!isBorderPoint) + { + continue; // current point is not deletable + } + // check if point is the end of an arc + int numberOfNeighbors = -1; // -1 and not 0 because the center pixel will be counted as well + for (int i = 0; i < 27; i++) // i = 0..26 + if (ot.GetPixel(i) == 1) + numberOfNeighbors++; + + if (numberOfNeighbors == 1) + { + continue; // current point is not deletable + } + + // check if point is Euler invariant + if (!isEulerInvariant(ot.GetNeighborhood(), eulerLUT)) + { + continue; // current point is not deletable + } + + // check if point is simple (deletion does not change connectivity in the 3x3x3 neighborhood) + if (!isSimplePoint(ot.GetNeighborhood())) + { + continue; // current point is not deletable + } + + // add all simple border points to a list for sequential re-checking + simpleBorderPoints.push_back(ot.GetIndex()); + } // end image iteration loop + + // sequential re-checking to preserve connectivity when + // deleting in a parallel way + bool noChange = true; + for (simpleBorderPointsIt = simpleBorderPoints.begin(); simpleBorderPointsIt != simpleBorderPoints.end(); simpleBorderPointsIt++) + { + // 1. Set simple border point to 0 + thinImage->SetPixel(*simpleBorderPointsIt, NumericTraits::Zero); + // 2. Check if neighborhood is still connected + ot.SetLocation(*simpleBorderPointsIt); + if (!isSimplePoint(ot.GetNeighborhood())) + { + // we cannot delete current point, so reset + thinImage->SetPixel(*simpleBorderPointsIt, NumericTraits::One); + } + else + { + noChange = false; + } + } + if (noChange) + unchangedBorders++; + + simpleBorderPoints.clear(); + } // end currentBorder for loop + } // end unchangedBorders while loop + + itkDebugMacro(<< "ComputeThinImage End"); +} + +/** + * Generate ThinImage + */ +template +void BinaryThinningImageFilter3D::GenerateData() +{ + + this->PrepareData(); + + itkDebugMacro(<< "GenerateData: Computing Thinning Image"); + this->ComputeThinImage(); +} // end GenerateData() + +/** + * Fill the Euler look-up table (LUT) for later check of the Euler invariance. (see [Lee94]) + */ +template +void BinaryThinningImageFilter3D::fillEulerLUT(int *LUT) +{ + LUT[1] = 1; + LUT[3] = -1; + LUT[5] = -1; + LUT[7] = 1; + LUT[9] = -3; + LUT[11] = -1; + LUT[13] = -1; + LUT[15] = 1; + LUT[17] = -1; + LUT[19] = 1; + LUT[21] = 1; + LUT[23] = -1; + LUT[25] = 3; + LUT[27] = 1; + LUT[29] = 1; + LUT[31] = -1; + LUT[33] = -3; + LUT[35] = -1; + LUT[37] = 3; + LUT[39] = 1; + LUT[41] = 1; + LUT[43] = -1; + LUT[45] = 3; + LUT[47] = 1; + LUT[49] = -1; + LUT[51] = 1; + + LUT[53] = 1; + LUT[55] = -1; + LUT[57] = 3; + LUT[59] = 1; + LUT[61] = 1; + LUT[63] = -1; + LUT[65] = -3; + LUT[67] = 3; + LUT[69] = -1; + LUT[71] = 1; + LUT[73] = 1; + LUT[75] = 3; + LUT[77] = -1; + LUT[79] = 1; + LUT[81] = -1; + LUT[83] = 1; + LUT[85] = 1; + LUT[87] = -1; + LUT[89] = 3; + LUT[91] = 1; + LUT[93] = 1; + LUT[95] = -1; + LUT[97] = 1; + LUT[99] = 3; + LUT[101] = 3; + LUT[103] = 1; + + LUT[105] = 5; + LUT[107] = 3; + LUT[109] = 3; + LUT[111] = 1; + LUT[113] = -1; + LUT[115] = 1; + LUT[117] = 1; + LUT[119] = -1; + LUT[121] = 3; + LUT[123] = 1; + LUT[125] = 1; + LUT[127] = -1; + LUT[129] = -7; + LUT[131] = -1; + LUT[133] = -1; + LUT[135] = 1; + LUT[137] = -3; + LUT[139] = -1; + LUT[141] = -1; + LUT[143] = 1; + LUT[145] = -1; + LUT[147] = 1; + LUT[149] = 1; + LUT[151] = -1; + LUT[153] = 3; + LUT[155] = 1; + + LUT[157] = 1; + LUT[159] = -1; + LUT[161] = -3; + LUT[163] = -1; + LUT[165] = 3; + LUT[167] = 1; + LUT[169] = 1; + LUT[171] = -1; + LUT[173] = 3; + LUT[175] = 1; + LUT[177] = -1; + LUT[179] = 1; + LUT[181] = 1; + LUT[183] = -1; + LUT[185] = 3; + LUT[187] = 1; + LUT[189] = 1; + LUT[191] = -1; + LUT[193] = -3; + LUT[195] = 3; + LUT[197] = -1; + LUT[199] = 1; + LUT[201] = 1; + LUT[203] = 3; + LUT[205] = -1; + LUT[207] = 1; + + LUT[209] = -1; + LUT[211] = 1; + LUT[213] = 1; + LUT[215] = -1; + LUT[217] = 3; + LUT[219] = 1; + LUT[221] = 1; + LUT[223] = -1; + LUT[225] = 1; + LUT[227] = 3; + LUT[229] = 3; + LUT[231] = 1; + LUT[233] = 5; + LUT[235] = 3; + LUT[237] = 3; + LUT[239] = 1; + LUT[241] = -1; + LUT[243] = 1; + LUT[245] = 1; + LUT[247] = -1; + LUT[249] = 3; + LUT[251] = 1; + LUT[253] = 1; + LUT[255] = -1; +} + +/** + * Check for Euler invariance. (see [Lee94]) + */ +template +bool BinaryThinningImageFilter3D::isEulerInvariant(NeighborhoodType neighbors, int *LUT) +{ + // calculate Euler characteristic for each octant and sum up + int EulerChar = 0; + unsigned char n; + // Octant SWU + n = 1; + if (neighbors[24] == 1) + n |= 128; + if (neighbors[25] == 1) + n |= 64; + if (neighbors[15] == 1) + n |= 32; + if (neighbors[16] == 1) + n |= 16; + if (neighbors[21] == 1) + n |= 8; + if (neighbors[22] == 1) + n |= 4; + if (neighbors[12] == 1) + n |= 2; + EulerChar += LUT[n]; + // Octant SEU + n = 1; + if (neighbors[26] == 1) + n |= 128; + if (neighbors[23] == 1) + n |= 64; + if (neighbors[17] == 1) + n |= 32; + if (neighbors[14] == 1) + n |= 16; + if (neighbors[25] == 1) + n |= 8; + if (neighbors[22] == 1) + n |= 4; + if (neighbors[16] == 1) + n |= 2; + EulerChar += LUT[n]; + // Octant NWU + n = 1; + if (neighbors[18] == 1) + n |= 128; + if (neighbors[21] == 1) + n |= 64; + if (neighbors[9] == 1) + n |= 32; + if (neighbors[12] == 1) + n |= 16; + if (neighbors[19] == 1) + n |= 8; + if (neighbors[22] == 1) + n |= 4; + if (neighbors[10] == 1) + n |= 2; + EulerChar += LUT[n]; + // Octant NEU + n = 1; + if (neighbors[20] == 1) + n |= 128; + if (neighbors[23] == 1) + n |= 64; + if (neighbors[19] == 1) + n |= 32; + if (neighbors[22] == 1) + n |= 16; + if (neighbors[11] == 1) + n |= 8; + if (neighbors[14] == 1) + n |= 4; + if (neighbors[10] == 1) + n |= 2; + EulerChar += LUT[n]; + // Octant SWB + n = 1; + if (neighbors[6] == 1) + n |= 128; + if (neighbors[15] == 1) + n |= 64; + if (neighbors[7] == 1) + n |= 32; + if (neighbors[16] == 1) + n |= 16; + if (neighbors[3] == 1) + n |= 8; + if (neighbors[12] == 1) + n |= 4; + if (neighbors[4] == 1) + n |= 2; + EulerChar += LUT[n]; + // Octant SEB + n = 1; + if (neighbors[8] == 1) + n |= 128; + if (neighbors[7] == 1) + n |= 64; + if (neighbors[17] == 1) + n |= 32; + if (neighbors[16] == 1) + n |= 16; + if (neighbors[5] == 1) + n |= 8; + if (neighbors[4] == 1) + n |= 4; + if (neighbors[14] == 1) + n |= 2; + EulerChar += LUT[n]; + // Octant NWB + n = 1; + if (neighbors[0] == 1) + n |= 128; + if (neighbors[9] == 1) + n |= 64; + if (neighbors[3] == 1) + n |= 32; + if (neighbors[12] == 1) + n |= 16; + if (neighbors[1] == 1) + n |= 8; + if (neighbors[10] == 1) + n |= 4; + if (neighbors[4] == 1) + n |= 2; + EulerChar += LUT[n]; + // Octant NEB + n = 1; + if (neighbors[2] == 1) + n |= 128; + if (neighbors[1] == 1) + n |= 64; + if (neighbors[11] == 1) + n |= 32; + if (neighbors[10] == 1) + n |= 16; + if (neighbors[5] == 1) + n |= 8; + if (neighbors[4] == 1) + n |= 4; + if (neighbors[14] == 1) + n |= 2; + EulerChar += LUT[n]; + if (EulerChar == 0) + return true; + else + return false; +} + +/** + * Check if current point is a Simple Point. + * This method is named 'N(v)_labeling' in [Lee94]. + * Outputs the number of connected objects in a neighborhood of a point + * after this point would have been removed. + */ +template +bool BinaryThinningImageFilter3D::isSimplePoint(NeighborhoodType neighbors) +{ + // copy neighbors for labeling + int cube[26]; + int i; + for (i = 0; i < 13; i++) // i = 0..12 -> cube[0..12] + cube[i] = neighbors[i]; + // i != 13 : ignore center pixel when counting (see [Lee94]) + for (i = 14; i < 27; i++) // i = 14..26 -> cube[13..25] + cube[i - 1] = neighbors[i]; + // set initial label + int label = 2; + // for all points in the neighborhood + for (int i = 0; i < 26; i++) + { + if (cube[i] == 1) // voxel has not been labelled yet + { + // start recursion with any octant that contains the point i + switch (i) + { + case 0: + case 1: + case 3: + case 4: + case 9: + case 10: + case 12: + Octree_labeling(1, label, cube); + break; + case 2: + case 5: + case 11: + case 13: + Octree_labeling(2, label, cube); + break; + case 6: + case 7: + case 14: + case 15: + Octree_labeling(3, label, cube); + break; + case 8: + case 16: + Octree_labeling(4, label, cube); + break; + case 17: + case 18: + case 20: + case 21: + Octree_labeling(5, label, cube); + break; + case 19: + case 22: + Octree_labeling(6, label, cube); + break; + case 23: + case 24: + Octree_labeling(7, label, cube); + break; + case 25: + Octree_labeling(8, label, cube); + break; + } + label++; + if (label - 2 >= 2) + { + return false; + } + } + } + //return label-2; in [Lee94] if the number of connected compontents would be needed + return true; +} + +/** + * Octree_labeling [Lee94] + * This is a recursive method that calulates the number of connected + * components in the 3D neighbourhood after the center pixel would + * have been removed. + */ +template +void BinaryThinningImageFilter3D::Octree_labeling(int octant, int label, int *cube) +{ + // check if there are points in the octant with value 1 + if (octant == 1) + { + // set points in this octant to current label + // and recurseive labeling of adjacent octants + if (cube[0] == 1) + cube[0] = label; + if (cube[1] == 1) + { + cube[1] = label; + Octree_labeling(2, label, cube); + } + if (cube[3] == 1) + { + cube[3] = label; + Octree_labeling(3, label, cube); + } + if (cube[4] == 1) + { + cube[4] = label; + Octree_labeling(2, label, cube); + Octree_labeling(3, label, cube); + Octree_labeling(4, label, cube); + } + if (cube[9] == 1) + { + cube[9] = label; + Octree_labeling(5, label, cube); + } + if (cube[10] == 1) + { + cube[10] = label; + Octree_labeling(2, label, cube); + Octree_labeling(5, label, cube); + Octree_labeling(6, label, cube); + } + if (cube[12] == 1) + { + cube[12] = label; + Octree_labeling(3, label, cube); + Octree_labeling(5, label, cube); + Octree_labeling(7, label, cube); + } + } + if (octant == 2) + { + if (cube[1] == 1) + { + cube[1] = label; + Octree_labeling(1, label, cube); + } + if (cube[4] == 1) + { + cube[4] = label; + Octree_labeling(1, label, cube); + Octree_labeling(3, label, cube); + Octree_labeling(4, label, cube); + } + if (cube[10] == 1) + { + cube[10] = label; + Octree_labeling(1, label, cube); + Octree_labeling(5, label, cube); + Octree_labeling(6, label, cube); + } + if (cube[2] == 1) + cube[2] = label; + if (cube[5] == 1) + { + cube[5] = label; + Octree_labeling(4, label, cube); + } + if (cube[11] == 1) + { + cube[11] = label; + Octree_labeling(6, label, cube); + } + if (cube[13] == 1) + { + cube[13] = label; + Octree_labeling(4, label, cube); + Octree_labeling(6, label, cube); + Octree_labeling(8, label, cube); + } + } + if (octant == 3) + { + if (cube[3] == 1) + { + cube[3] = label; + Octree_labeling(1, label, cube); + } + if (cube[4] == 1) + { + cube[4] = label; + Octree_labeling(1, label, cube); + Octree_labeling(2, label, cube); + Octree_labeling(4, label, cube); + } + if (cube[12] == 1) + { + cube[12] = label; + Octree_labeling(1, label, cube); + Octree_labeling(5, label, cube); + Octree_labeling(7, label, cube); + } + if (cube[6] == 1) + cube[6] = label; + if (cube[7] == 1) + { + cube[7] = label; + Octree_labeling(4, label, cube); + } + if (cube[14] == 1) + { + cube[14] = label; + Octree_labeling(7, label, cube); + } + if (cube[15] == 1) + { + cube[15] = label; + Octree_labeling(4, label, cube); + Octree_labeling(7, label, cube); + Octree_labeling(8, label, cube); + } + } + if (octant == 4) + { + if (cube[4] == 1) + { + cube[4] = label; + Octree_labeling(1, label, cube); + Octree_labeling(2, label, cube); + Octree_labeling(3, label, cube); + } + if (cube[5] == 1) + { + cube[5] = label; + Octree_labeling(2, label, cube); + } + if (cube[13] == 1) + { + cube[13] = label; + Octree_labeling(2, label, cube); + Octree_labeling(6, label, cube); + Octree_labeling(8, label, cube); + } + if (cube[7] == 1) + { + cube[7] = label; + Octree_labeling(3, label, cube); + } + if (cube[15] == 1) + { + cube[15] = label; + Octree_labeling(3, label, cube); + Octree_labeling(7, label, cube); + Octree_labeling(8, label, cube); + } + if (cube[8] == 1) + cube[8] = label; + if (cube[16] == 1) + { + cube[16] = label; + Octree_labeling(8, label, cube); + } + } + if (octant == 5) + { + if (cube[9] == 1) + { + cube[9] = label; + Octree_labeling(1, label, cube); + } + if (cube[10] == 1) + { + cube[10] = label; + Octree_labeling(1, label, cube); + Octree_labeling(2, label, cube); + Octree_labeling(6, label, cube); + } + if (cube[12] == 1) + { + cube[12] = label; + Octree_labeling(1, label, cube); + Octree_labeling(3, label, cube); + Octree_labeling(7, label, cube); + } + if (cube[17] == 1) + cube[17] = label; + if (cube[18] == 1) + { + cube[18] = label; + Octree_labeling(6, label, cube); + } + if (cube[20] == 1) + { + cube[20] = label; + Octree_labeling(7, label, cube); + } + if (cube[21] == 1) + { + cube[21] = label; + Octree_labeling(6, label, cube); + Octree_labeling(7, label, cube); + Octree_labeling(8, label, cube); + } + } + if (octant == 6) + { + if (cube[10] == 1) + { + cube[10] = label; + Octree_labeling(1, label, cube); + Octree_labeling(2, label, cube); + Octree_labeling(5, label, cube); + } + if (cube[11] == 1) + { + cube[11] = label; + Octree_labeling(2, label, cube); + } + if (cube[13] == 1) + { + cube[13] = label; + Octree_labeling(2, label, cube); + Octree_labeling(4, label, cube); + Octree_labeling(8, label, cube); + } + if (cube[18] == 1) + { + cube[18] = label; + Octree_labeling(5, label, cube); + } + if (cube[21] == 1) + { + cube[21] = label; + Octree_labeling(5, label, cube); + Octree_labeling(7, label, cube); + Octree_labeling(8, label, cube); + } + if (cube[19] == 1) + cube[19] = label; + if (cube[22] == 1) + { + cube[22] = label; + Octree_labeling(8, label, cube); + } + } + if (octant == 7) + { + if (cube[12] == 1) + { + cube[12] = label; + Octree_labeling(1, label, cube); + Octree_labeling(3, label, cube); + Octree_labeling(5, label, cube); + } + if (cube[14] == 1) + { + cube[14] = label; + Octree_labeling(3, label, cube); + } + if (cube[15] == 1) + { + cube[15] = label; + Octree_labeling(3, label, cube); + Octree_labeling(4, label, cube); + Octree_labeling(8, label, cube); + } + if (cube[20] == 1) + { + cube[20] = label; + Octree_labeling(5, label, cube); + } + if (cube[21] == 1) + { + cube[21] = label; + Octree_labeling(5, label, cube); + Octree_labeling(6, label, cube); + Octree_labeling(8, label, cube); + } + if (cube[23] == 1) + cube[23] = label; + if (cube[24] == 1) + { + cube[24] = label; + Octree_labeling(8, label, cube); + } + } + if (octant == 8) + { + if (cube[13] == 1) + { + cube[13] = label; + Octree_labeling(2, label, cube); + Octree_labeling(4, label, cube); + Octree_labeling(6, label, cube); + } + if (cube[15] == 1) + { + cube[15] = label; + Octree_labeling(3, label, cube); + Octree_labeling(4, label, cube); + Octree_labeling(7, label, cube); + } + if (cube[16] == 1) + { + cube[16] = label; + Octree_labeling(4, label, cube); + } + if (cube[21] == 1) + { + cube[21] = label; + Octree_labeling(5, label, cube); + Octree_labeling(6, label, cube); + Octree_labeling(7, label, cube); + } + if (cube[22] == 1) + { + cube[22] = label; + Octree_labeling(6, label, cube); + } + if (cube[24] == 1) + { + cube[24] = label; + Octree_labeling(7, label, cube); + } + if (cube[25] == 1) + cube[25] = label; + } +} + +/** + * Print Self + */ +template +void BinaryThinningImageFilter3D::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "Thinning image: " << std::endl; +} + +} // end namespace itk + +#endif // itkBinaryThinningImageFilter3D_hxx diff --git a/packages/std/src/bbstdCastVector.h b/packages/std/src/bbstdCastVector.h index c7bb20d..160ce65 100644 --- a/packages/std/src/bbstdCastVector.h +++ b/packages/std/src/bbstdCastVector.h @@ -76,9 +76,6 @@ namespace bbstd }; //================================================================= - - - //================================================================= // BlackBox description BBTK_BEGIN_DESCRIBE_TEMPLATE2_BLACK_BOX(CastVector,bbtk::AtomicBlackBox); @@ -95,10 +92,17 @@ namespace bbstd BBTK_END_DESCRIBE_TEMPLATE2_BLACK_BOX(CastVector); //================================================================= - template void CastVector< T , U >::bbUserSetDefaultValues() {} - template void CastVector< T , U >::bbUserInitializeProcessing() {} - template void CastVector< T , U >::bbUserFinalizeProcessing() {} - + template + void CastVector< T , U >::bbUserSetDefaultValues() + {} + + template + void CastVector< T , U >::bbUserInitializeProcessing() + {} + + template + void CastVector< T , U >::bbUserFinalizeProcessing() + {} } // namespace bbstd diff --git a/packages/std/src/bbstdDoubleToInt.cxx b/packages/std/src/bbstdDoubleToInt.cxx index 6c41981..6968af7 100644 --- a/packages/std/src/bbstdDoubleToInt.cxx +++ b/packages/std/src/bbstdDoubleToInt.cxx @@ -8,12 +8,12 @@ namespace bbstd BBTK_ADD_BLACK_BOX_TO_PACKAGE(std,DoubleToInt) BBTK_BLACK_BOX_IMPLEMENTATION(DoubleToInt,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 DoubleToInt::Process() { - // THE MAIN PROCESSING METHOD BODY // Here we simply set the input 'In' value to the output 'Out' // And print out the output value @@ -25,46 +25,41 @@ void DoubleToInt::Process() // (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') - bbSetOutputOut( (int)bbGetInputIn() ); - + bbSetOutputOut( (int)bbGetInputIn() ); } + //===== // 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 DoubleToInt::bbUserSetDefaultValues() { - // SET HERE THE DEFAULT INPUT/OUTPUT VALUES OF YOUR BOX // Here we initialize the input 'In' to 0 - bbSetInputIn(0); - + bbSetInputIn(0); } + //===== // 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 DoubleToInt::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 DoubleToInt::bbUserFinalizeProcessing() { - // THE FINALIZATION METHOD BODY : // Here does nothing // but this is where you should desallocate the internal/output pointers -// if any - +// if any } -} -// EO namespace bbstd + +}// EO namespace bbstd diff --git a/packages/std/src/bbstdDoubleToInt.h b/packages/std/src/bbstdDoubleToInt.h index 83df9df..4a30efc 100644 --- a/packages/std/src/bbstdDoubleToInt.h +++ b/packages/std/src/bbstdDoubleToInt.h @@ -28,18 +28,17 @@ class bbstd_EXPORT DoubleToInt }; BBTK_BEGIN_DESCRIBE_BLACK_BOX(DoubleToInt,bbtk::AtomicBlackBox); -BBTK_NAME("DoubleToInt"); -BBTK_AUTHOR("Claire Mouton"); -BBTK_DESCRIPTION("Converts a double to an int"); -BBTK_CATEGORY(""); -BBTK_INPUT(DoubleToInt,In,"Double input",double,""); -BBTK_OUTPUT(DoubleToInt,Out,"Int output",int,""); + BBTK_NAME("DoubleToInt"); + BBTK_AUTHOR("Claire Mouton"); + BBTK_DESCRIPTION("Converts a double to an int"); + BBTK_CATEGORY(""); + BBTK_INPUT(DoubleToInt,In,"Double input",double,""); + BBTK_OUTPUT(DoubleToInt,Out,"Int output",int,""); BBTK_END_DESCRIBE_BLACK_BOX(DoubleToInt); //===== // 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) //===== -} -// EO namespace bbstd +}// EO namespace bbstd #endif // __bbstdDoubleToInt_h_INCLUDED__ diff --git a/packages/std/src/bbstdNumericalVectorToStringVector.cxx b/packages/std/src/bbstdNumericalVectorToStringVector.cxx new file mode 100644 index 0000000..3ed784a --- /dev/null +++ b/packages/std/src/bbstdNumericalVectorToStringVector.cxx @@ -0,0 +1,26 @@ +//===== +// 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) +//===== +#include "bbstdNumericalVectorToStringVector.h" +#include "bbstdPackage.h" +namespace bbstd +{ + +BBTK_BLACK_BOX_TEMPLATE_IMPLEMENTATION(NumericalVectorToStringVector,bbtk::AtomicBlackBox); + +BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(std,NumericalVectorToStringVector,int8_t); +BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(std,NumericalVectorToStringVector,uint8_t); +BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(std,NumericalVectorToStringVector,int16_t); +BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(std,NumericalVectorToStringVector,uint16_t); +BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(std,NumericalVectorToStringVector,int32_t); +BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(std,NumericalVectorToStringVector,uint32_t); +BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(std,NumericalVectorToStringVector,long); +BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(std,NumericalVectorToStringVector,float); +BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(std,NumericalVectorToStringVector,double); + +//typedef std::string string; +// BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(std,NumericalVectorToStringVector,string); + +} // EO namespace bbstd + + diff --git a/packages/std/src/bbstdNumericalVectorToStringVector.h b/packages/std/src/bbstdNumericalVectorToStringVector.h new file mode 100644 index 0000000..87f995d --- /dev/null +++ b/packages/std/src/bbstdNumericalVectorToStringVector.h @@ -0,0 +1,71 @@ +//===== +// 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) +//===== +#ifndef __bbstdNumericalVectorToStringVector_h_INCLUDED__ +#define __bbstdNumericalVectorToStringVector_h_INCLUDED__ + +#include "bbstd_EXPORT.h" +#include "bbtkAtomicBlackBox.h" +#include + +namespace bbstd +{ + +template +class bbstd_EXPORT NumericalVectorToStringVector + : + public bbtk::AtomicBlackBox +{ + BBTK_TEMPLATE_BLACK_BOX_INTERFACE(NumericalVectorToStringVector,bbtk::AtomicBlackBox,T); +//===== +// 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,std::vector); + BBTK_DECLARE_OUTPUT(Out,std::vector); + BBTK_PROCESS(DoIt); + void DoIt(); +// T decode_item(const std::string&); +//===== +// 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_BEGIN_DESCRIBE_TEMPLATE_BLACK_BOX(NumericalVectorToStringVector,bbtk::AtomicBlackBox); + BBTK_NAME(bbtk::HumanTypeName >() +"ToStringVector"); + BBTK_AUTHOR("InfoDev"); + BBTK_DEFAULT_ADAPTOR(); + BBTK_DESCRIPTION("Converts the content of the input " + +bbtk::HumanTypeName >() + +" ("+bbtk::TypeName >()+") to string vector "); + typedef std::vector Tvector; + BBTK_TEMPLATE_INPUT(NumericalVectorToStringVector,In,"Input",Tvector); + BBTK_TEMPLATE_OUTPUT(NumericalVectorToStringVector,Out,"Output",std::vector); +BBTK_END_DESCRIBE_TEMPLATE_BLACK_BOX(NumericalVectorToStringVector); + +template +void NumericalVectorToStringVector::bbUserSetDefaultValues() +{} + +template +void NumericalVectorToStringVector::bbUserInitializeProcessing() +{} + +template +void NumericalVectorToStringVector::bbUserFinalizeProcessing() +{} + +template +void NumericalVectorToStringVector::DoIt() +{ + typedef T type; + bbmOutputOut.clear(); + int lgt = bbGetInputIn().size(); + for (int i=0; i,""); BBTK_INPUT(VectorFilterDouble,In0,"Input vector",std::vector,""); BBTK_INPUT(VectorFilterDouble,In1,"Input vector",std::vector,""); diff --git a/packages/std/src/bbstdVectorToString.h b/packages/std/src/bbstdVectorToString.h index 2bfa7c9..17e2e7d 100644 --- a/packages/std/src/bbstdVectorToString.h +++ b/packages/std/src/bbstdVectorToString.h @@ -58,14 +58,14 @@ namespace bbstd //================================================================= // BlackBox description BBTK_BEGIN_DESCRIBE_TEMPLATE_BLACK_BOX(VectorToString,bbtk::AtomicBlackBox); - BBTK_NAME(bbtk::HumanTypeName >()+"ToString"); - BBTK_AUTHOR("laurent.guigues@creatis.insa-lyon.fr"); - BBTK_DEFAULT_ADAPTOR(); - BBTK_DESCRIPTION("Converts the content of the input vector ("+bbtk::TypeName >()+") to a string in which each item is separated by the value of the input 'Separator'"); + BBTK_NAME(bbtk::HumanTypeName >()+"ToString"); + BBTK_AUTHOR("laurent.guigues@creatis.insa-lyon.fr"); + BBTK_DEFAULT_ADAPTOR(); + BBTK_DESCRIPTION("Converts the content of the input vector ("+bbtk::TypeName >()+") to a string in which each item is separated by the value of the input 'Separator'"); typedef std::vector Tvector; - BBTK_TEMPLATE_INPUT(VectorToString, In,"Input",Tvector); - BBTK_TEMPLATE_INPUT(VectorToString, Separator,"Separator of item in the output string. Default is whitespace.",std::string); - BBTK_TEMPLATE_OUTPUT(VectorToString, Out,"Output",std::string); + BBTK_TEMPLATE_INPUT(VectorToString, In,"Input",Tvector); + BBTK_TEMPLATE_INPUT(VectorToString, Separator,"Separator of item in the output string. Default is whitespace.",std::string); + BBTK_TEMPLATE_OUTPUT(VectorToString, Out,"Output",std::string); BBTK_END_DESCRIBE_TEMPLATE_BLACK_BOX(VectorToString); //=================================================================