1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 
19 #ifndef itkImageToRectilinearFEMObjectFilter_h
20 #define itkImageToRectilinearFEMObjectFilter_h
21 
22 #include "vnl/vnl_vector.h"
23 #include "itkFEMObject.h"
24 #include "itkProcessObject.h"
25 
26 namespace itk
27 {
28 namespace fem
29 {
30 /**
31  * \class ImageToRectilinearFEMObjectFilter
32  * \brief Generate a rectilinar mesh from an image. The result is stored
33  *        in a FEMObject
34  *
35  * This class generates a Mesh consiting of quadrilateral elements in 2D
36  * and hexahedral elements in 3D. The resulting meshes can be used with
37  * specific elements for solving membrane or linear elasticity problems.
38  *
39  * \ingroup ITKFEM
40  */
41 
42 template <typename TInputImage>
43 class ITK_TEMPLATE_EXPORT ImageToRectilinearFEMObjectFilter : public ProcessObject
44 {
45 public:
46   ITK_DISALLOW_COPY_AND_ASSIGN(ImageToRectilinearFEMObjectFilter);
47 
48   /** Standard class type aliases. */
49   using Self = ImageToRectilinearFEMObjectFilter;
50   using Superclass = ProcessObject;
51   using Pointer = SmartPointer<Self>;
52   using ConstPointer = SmartPointer<const Self>;
53 
54   /** Method for creation through the object factory. */
55   itkNewMacro(Self);
56 
57   /** Run-time type information (and related methods). */
58   itkTypeMacro(ImageToRectilinearFEMObjectFilter, ProcessObject);
59 
60   static constexpr unsigned int NDimensions = TInputImage::ImageDimension;
61 
62   /** Typedefs for Input Image */
63   using InputImageType = TInputImage;
64   using ImagePointer = typename InputImageType::Pointer;
65   using ImageConstPointer = typename InputImageType::ConstPointer;
66   using ImageRegionType = typename InputImageType::RegionType;
67   using ImageSizeType = typename InputImageType::SizeType;
68   using ImagePointType = typename InputImageType::PointType;
69   using ImageIndexType = typename InputImageType::IndexType;
70 
71   /** Typedefs for Output FEMObject */
72   using FEMObjectType = typename itk::fem::FEMObject<NDimensions>;
73   using FEMObjectPointer = typename FEMObjectType::Pointer;
74   using FEMObjectConstPointer = typename FEMObjectType::ConstPointer;
75   using DataObjectPointer = typename DataObject::Pointer;
76 
77   /** Some convenient type alias. */
78   using MaterialType = itk::fem::MaterialLinearElasticity;
79   using MaterialPointerType = MaterialType::Pointer;
80   // using QuadElementBaseType = itk::fem::Element2DC0LinearQuadrilateral;
81   // using HexElementBaseType = itk::fem::Element3DC0LinearHexahedron;
82   using ElementBaseType = itk::fem::Element;
83   using ElementBasePointerType = itk::fem::Element::ConstPointer;
84 
85 #ifdef ITK_USE_CONCEPT_CHECKING
86   // Begin concept checking
87 //  itkConceptMacro(SameDimensionOrMinusOne,
88 //    (Concept::SameDimensionOrMinusOne<NDimensions, 3>));
89 // End concept checking
90 #endif
91 
92   /**Get/Set the number of voxels/pixels in each dimension used
93     *during the mesh generation
94     */
95   itkGetMacro(PixelsPerElement, vnl_vector<unsigned int> );
96   itkSetMacro(PixelsPerElement, vnl_vector<unsigned int> );
SetPixelsPerElement(unsigned int numPixels)97   void SetPixelsPerElement( unsigned int numPixels )
98   {
99     this->m_PixelsPerElement.fill( numPixels );
100   }
101 
102   /**Get the number of element in each dimension of the generated mesh*/
103   itkGetMacro(NumberOfElements, vnl_vector<unsigned int> );
104 
105   /**Get/Set the material used for the mesh */
106   itkGetMacro(Material, MaterialPointerType);
107   itkSetMacro(Material, MaterialPointerType);
108 
109   /**Get/Set the element type used to generate the mesh */
110   itkGetMacro(Element, ElementBasePointerType);
111   itkSetMacro(Element, ElementBasePointerType);
112 
113   /** Set/Get the image input of this process object.  */
114   using Superclass::SetInput;
115   void SetInput( InputImageType *image);
116 
117   void SetInput( unsigned int, InputImageType *image);
118 
119   InputImageType * GetInput();
120 
121   InputImageType * GetInput(unsigned int idx);
122 
123   /** Make a DataObject of the correct type to be used as the specified
124    * output. */
125   using DataObjectPointerArraySizeType = ProcessObject::DataObjectPointerArraySizeType;
126   using Superclass::MakeOutput;
127   DataObjectPointer MakeOutput(DataObjectPointerArraySizeType idx) override;
128 
129   /** Get the output data of this process object.  The output of this
130    * function is not valid until an appropriate Update() method has
131    * been called, either explicitly or implicitly.  Both the filter
132    * itself and the data object have Update() methods, and both
133    * methods update the data.
134    *
135    * For Filters which have multiple outputs of different types, the
136    * GetOutput() method assumes the output is of OutputImageType. For
137    * the GetOutput(unsigned int) method, a dynamic_cast is performed
138    * incase the filter has outputs of different types or image
139    * types. Derived classes should have names get methods for these
140    * outputs.
141    */
142   FEMObjectType * GetOutput();
143 
144   FEMObjectType * GetOutput(unsigned int idx);
145 
146 protected:
147   ImageToRectilinearFEMObjectFilter();
~ImageToRectilinearFEMObjectFilter()148   ~ImageToRectilinearFEMObjectFilter() override {}
149   void PrintSelf(std::ostream& os, Indent indent) const override;
150 
151   /** Method invoked by the pipeline in order to trigger mesh generation */
152   void  GenerateData() override;
153 
154   void Generate2DRectilinearMesh();
155 
156   void Generate3DRectilinearMesh();
157 
158 private:
159   vnl_vector<unsigned int> m_NumberOfElements;
160   vnl_vector<unsigned int> m_PixelsPerElement;
161   MaterialPointerType      m_Material;
162   ElementBasePointerType   m_Element;
163 };
164 } // end namespace fem
165 } // end namespace itk
166 
167 #ifndef ITK_MANUAL_INSTANTIATION
168 #include "itkImageToRectilinearFEMObjectFilter.hxx"
169 #endif
170 
171 #endif // itkImageToRectilinearFEMObjectFilter_h
172