KWStyle - itkPhasedArray3DSpecialCoordinatesImage.h
 
Matrix View
Description

1 /*=========================================================================
2
3   Program:   Insight Segmentation & Registration Toolkit
4   Module:    $RCSfile: itkPhasedArray3DSpecialCoordinatesImage.h.html,v $
5   Language:  C++
6   Date:      $Date: 2006/01/17 19:15:43 $
7   Version:   $Revision: 1.4 $
8
9   Copyright (c) Insight Software Consortium. All rights reserved.
10   See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11
12      This software is distributed WITHOUT ANY WARRANTY; without even
13      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14      PURPOSE.  See the above copyright notices for more information.
15
16 =========================================================================*/
17 #ifndef __itkPhasedArray3DSpecialCoordinatesImage_h
18 #define __itkPhasedArray3DSpecialCoordinatesImage_h
19
20 #include "itkSpecialCoordinatesImage.h"
21 #include "itkImageRegion.h"
22 #include "itkPoint.h"
23 #include "itkContinuousIndex.h"
24 #include "vnl/vnl_math.h"
25
26
27 namespace itk
28 {
29
30 /** \class PhasedArray3DSpecialCoordinatesImage
31 LEN  *  \brief Templated 3D nonrectilinear-coordinate image class for phased-array "range" images.
32  *
33  * y-axis <--------------------+
34  *                             |\
35  *                          /  | \ 
36  *                          `~-|  \
37  *                       /     |   \
38  *                        ele- |    \
39  *                    / vation |     \
40  * projection                  |      v x-axis
41  * to y-z plane -> o           |
42  *                             v z-axis
43  * 
44  * 
45  * In a phased array "range" image, a point in space is represented by the angle
46  * between its projection onto the x-z plane and the z-axis (the azimuth
47  * coordinate), the angle between its projection onto the y-z plane and the
48  * z-axis (the elevation coordinate), and by its distance from the origin
49  * (the radius).  See the diagram above, which illustrates elevation.
50  * 
51  * The equations form performing the conversion from Cartesian coordinates to
52  * 3D phased array coordinates are as follows:
53  * 
54  * azimuth = arctan(x/y)
55  * elevation = arctan(y/z)
56  * radius = sqrt(x^2 + y^2 + z^2)
57  * 
58  * The reversed transforms are: 
59  * 
60  * z = radius / sqrt( 1 + (tan(azimuth))^2 + (tan(elevation))^2 );
61  * x = z * tan(azimuth)
62  * y = z * tan(elevation)
63  * 
64  * PhasedArray3DSpecialCoordinatesImages are templated over a pixel type and
65  * follow the SpecialCoordinatesImage interface.  The data in an image is
66  * arranged in a 1D array as [radius-index][elevation-index][azimuth-index] with
67  * azimuth-index varying most rapidly.  The Index type reverses the order so
68  * that Index[0] = azimuth-index, Index[1] = elevation-index, and
69  * Index[2] = radius-index.
70  * 
71  * Azimuth is discretized into m_AzimuthAngularSeparation intervals per angular
72  * voxel, the most negative azimuth interval containing data is then mapped to
73  * azimuth-index=0, and the largest azimuth interval containing data is then
74  * mapped to azimuth-index=( number of samples along azimuth axis - 1 ).
75  * Elevation is discretized in the same manner.  This way, the mapping to
76  * Cartesian space is symmetric about the z axis such that the line defined by
77  * azimuth/2,elevation/2 = z-axis.  Radius is discretized into
78  * m_RadiusSampleSize units per angular voxel.  The smallest range interval
79  * containing data is then mapped to radius-index=0, such that
80  * radius = m_FirstSampleDistance + (radius-index * m_RadiusSampleSize).
81  *
82  * \sa SpecialCoordinatesImage
83  *
84  * \ingroup ImageObjects */
85 template <class TPixel>
86 class ITK_EXPORT PhasedArray3DSpecialCoordinatesImage :
87 public SpecialCoordinatesImage<TPixel,3>
88 {
89 public:
90   /** Standard class typedefs */
91   typedef PhasedArray3DSpecialCoordinatesImage            Self;
92 TDA   typedef SpecialCoordinatesImage<TPixel,3> Superclass;
93 TDA   typedef SmartPointer<Self>  Pointer;
94 TDA   typedef SmartPointer<const Self>  ConstPointer;
95 TDA   typedef WeakPointer<const Self>  ConstWeakPointer;
96
97   /** Method for creation through the object factory. */
98   itkNewMacro(Self);
99
100   /** Run-time type information (and related methods). */
101   itkTypeMacro(PhasedArray3DSpecialCoordinatesImage, SpecialCoordinatesImage);
102
103   /** Pixel typedef support. Used to declare pixel type in filters
104    * or other operations. */
105   typedef TPixel PixelType;
106
107   /** Typedef alias for PixelType */
108 SEM   typedef TPixel ValueType ;
109
110   /** Internal Pixel representation. Used to maintain a uniform API
111    * with Image Adaptors and allow to keep a particular internal
112    * representation of data while showing a different external
113    * representation. */
114   typedef TPixel InternalPixelType;
115
116   typedef typename Superclass::IOPixelType   IOPixelType;
117   
118   /** Accessor type that convert data between internal and external
119    *  representations.  */
120   typedef DefaultPixelAccessor< PixelType > AccessorType;
121   
122   /** Accessor functor to choose between accessors: DefaultPixelAccessor for
123    * the Image, and DefaultVectorPixelAccessor for the vector image. The 
124    * functor provides a generic API between the two accessors.*/
125   typedef DefaultPixelAccessorFunctor< Self > AccessorFunctorType;
126
127   /** Dimension of the image.  This constant is used by functions that are
128    * templated over image type (as opposed to being templated over pixel type
129    * and dimension) when they need compile time access to the dimension of
130    * the image. */
131   itkStaticConstMacro(ImageDimension, unsigned int, 3);
132
133   /** Container used to store pixels in the image. */
134   typedef ImportImageContainer<unsigned long, PixelType> PixelContainer;
135
136   /** Index typedef support. An index is used to access pixel values. */
137   typedef typename Superclass::IndexType  IndexType;
138
139   /** Offset typedef support. An offset is used to access pixel values. */
140   typedef typename Superclass::OffsetType OffsetType;
141
142   /** Size typedef support. A size is used to define region bounds. */
143   typedef typename Superclass::SizeType   SizeType;
144
145 LEN   /** Region typedef support. A region is used to specify a subset of an image. */
146   typedef typename Superclass::RegionType RegionType;
147
148   /** Spacing typedef support.  Spacing holds the "fake" size of a pixel, making
149    * each pixel look like a 1 unit hyper-cube to filters that were designed for
150    * normal images and that therefore use m_Spacing.  The spacing is the
151    * geometric distance between image samples. */
152   typedef typename Superclass::SpacingType SpacingType;
153
154   /** Origin typedef support.  The origin is the "fake" geometric coordinates
155    * of the index (0,0).  Also for use w/ filters designed for normal images. */
156   typedef typename Superclass::PointType PointType;
157
158   /** A pointer to the pixel container. */
159   typedef typename PixelContainer::Pointer PixelContainerPointer;
160 TDA   typedef typename PixelContainer::ConstPointer PixelContainerConstPointer;
161
162   /** \brief Get the continuous index from a physical point
163    *
164    * Returns true if the resulting index is within the image, false otherwise.
165    * \sa Transform */
166   template<class TCoordRep>
167   bool TransformPhysicalPointToContinuousIndex(
168               const Point<TCoordRep, 3>& point,
169               ContinuousIndex<TCoordRep, 3>& index   ) const
170     {
171     RegionType region = this->GetLargestPossibleRegion();
172     double maxAzimuth =    region.GetSize(0) - 1;
173     double maxElevation =  region.GetSize(1) - 1;
174     
175     // Convert Cartesian coordinates into angular coordinates
176     TCoordRep azimuth   = atan(point[0] / point[2]);
177     TCoordRep elevation = atan(point[1] / point[2]);
178     TCoordRep radius    = sqrt( point[0] * point[0]
179                               + point[1] * point[1]
180                               + point[2] * point[2] );
181     
182     // Convert the "proper" angular coordinates into index format
183     index[0] = static_cast<TCoordRep>( (azimuth/m_AzimuthAngularSeparation)
184 IND ***************************************+ (maxAzimuth/2.0)   );
185     index[1] = static_cast<TCoordRep>( (elevation/m_ElevationAngularSeparation)
186 IND ***************************************+ (maxElevation/2.0) );
187     index[2] = static_cast<TCoordRep>( ( (radius-m_FirstSampleDistance)
188 IND **********************************************/ m_RadiusSampleSize) );
189     
190     // Now, check to see if the index is within allowed bounds
191     const bool isInside = region.IsInside( index );
192
193     return isInside;
194     }
195
196   /** Get the index (discrete) from a physical point.
197    * Floating point index results are truncated to integers.
198    * Returns true if the resulting index is within the image, false otherwise
199    * \sa Transform */
200   template<class TCoordRep>
201   bool TransformPhysicalPointToIndex(
202             const Point<TCoordRep, 3>& point,
203             IndexType & index                                ) const
204     {
205     typedef typename IndexType::IndexValueType IndexValueType;
206     
207     RegionType region = this->GetLargestPossibleRegion();
208     double maxAzimuth =    region.GetSize(0) - 1;
209     double maxElevation =  region.GetSize(1) - 1;
210     
211     // Convert Cartesian coordinates into angular coordinates
212     TCoordRep azimuth   = atan(point[0] / point[2]);
213     TCoordRep elevation = atan(point[1] / point[2]);
214     TCoordRep radius    = sqrt( point[0] * point[0]
215                                 + point[1] * point[1]
216                                 + point[2] * point[2] );
217     
218     // Convert the "proper" angular coordinates into index format
219     index[0] = static_cast<IndexValueType>( (azimuth/m_AzimuthAngularSeparation)
220 IND ********************************************+ (maxAzimuth/2.0) );
221 LEN     index[1] = static_cast<IndexValueType>( (elevation/m_ElevationAngularSeparation)
222 IND ********************************************+ (maxElevation/2.0) );
223     index[2] = static_cast<IndexValueType>( ( (radius-m_FirstSampleDistance)
224 IND **************************************************/ m_RadiusSampleSize ) );
225     
226     // Now, check to see if the index is within allowed bounds
227     const bool isInside = region.IsInside( index );
228
229     return isInside;
230     }
231
232   /** Get a physical point (in the space which
233    * the origin and spacing infomation comes from)
234    * from a continuous index (in the index space)
235    * \sa Transform */
236   template<class TCoordRep>
237   void TransformContinuousIndexToPhysicalPoint(
238             const ContinuousIndex<TCoordRep, 3>& index,
239             Point<TCoordRep, 3>& point        ) const
240     {
241     RegionType region = this->GetLargestPossibleRegion();
242     double maxAzimuth =    region.GetSize(0) - 1;
243     double maxElevation =  region.GetSize(1) - 1;
244     
245     // Convert the index into proper angular coordinates
246     TCoordRep azimuth   = ( index[0] - (maxAzimuth/2.0) )
247 IND *************************** m_AzimuthAngularSeparation;
248     TCoordRep elevation = ( index[1] - (maxElevation/2.0) )
249 IND *************************** m_ElevationAngularSeparation;
250     TCoordRep radius    = (index[2]*m_RadiusSampleSize)+m_FirstSampleDistance;
251     
252     // Convert the angular coordinates into Cartesian coordinates
253     TCoordRep tanOfAzimuth    = tan(azimuth);
254     TCoordRep tanOfElevation  = tan(elevation);
255     point[2] = static_cast<TCoordRep>( radius /
256            sqrt(1 + tanOfAzimuth*tanOfAzimuth + tanOfElevation*tanOfElevation));
257     point[1] = static_cast<TCoordRep>( point[2] * tanOfElevation );
258     point[0] = static_cast<TCoordRep>( point[2] * tanOfAzimuth );
259     }
260
261   /** Get a physical point (in the space which
262    * the origin and spacing infomation comes from)
263    * from a discrete index (in the index space)
264    *
265    * \sa Transform */
266   template<class TCoordRep>
267   void TransformIndexToPhysicalPoint(
268                       const IndexType & index,
269                       Point<TCoordRep, 3>& point ) const
270     {
271     RegionType region = this->GetLargestPossibleRegion();
272     double maxAzimuth =    region.GetSize(0) - 1;
273     double maxElevation =  region.GetSize(1) - 1;
274     
275     // Convert the index into proper angular coordinates
276     TCoordRep azimuth   = ( static_cast<double>(index[0]) - (maxAzimuth/2.0) )
277 IND *************************** m_AzimuthAngularSeparation;
278     TCoordRep elevation = ( static_cast<double>(index[1]) - (maxElevation/2.0) )
279 IND *************************** m_ElevationAngularSeparation;
280     TCoordRep radius    = (static_cast<double>(index[2]) * m_RadiusSampleSize)
281 IND **************************+ m_FirstSampleDistance;
282     
283     // Convert the angular coordinates into Cartesian coordinates
284     TCoordRep tanOfAzimuth    = tan(azimuth);
285     TCoordRep tanOfElevation  = tan(elevation);
286     point[2] = static_cast<TCoordRep>( radius / sqrt(
287             1.0 + tanOfAzimuth*tanOfAzimuth + tanOfElevation*tanOfElevation) );
288     point[1] = static_cast<TCoordRep>( point[2] * tanOfElevation );
289     point[0] = static_cast<TCoordRep>( point[2] * tanOfAzimuth );
290     }
291   
292   
293   /**  Set the number of radians between each azimuth unit.   **/
294   itkSetMacro(AzimuthAngularSeparation, double);
295   
296   /**  Set the number of radians between each elevation unit.   **/
297   itkSetMacro(ElevationAngularSeparation, double);
298   
299   /**  Set the number of cartesian units between each unit along the R .  **/
300   itkSetMacro(RadiusSampleSize, double);
301   
302   /**  Set the distance to add to the radius. */
303   itkSetMacro(FirstSampleDistance, double);
304   
305 protected:
306   PhasedArray3DSpecialCoordinatesImage()
307     {
308     m_RadiusSampleSize = 1;
309     m_AzimuthAngularSeparation =    1 * (2.0*vnl_math::pi/360.0); // 1 degree
310     m_ElevationAngularSeparation =  1 * (2.0*vnl_math::pi/360.0); // 1 degree
311     m_FirstSampleDistance = 0;
312     }
313   virtual ~PhasedArray3DSpecialCoordinatesImage() {};
314   void PrintSelf(std::ostream& os, Indent indent) const;
315   
316 private:
317   PhasedArray3DSpecialCoordinatesImage(const Self&); //purposely not implemented
318   void operator=(const Self&); //purposely not implemented
319   
320   double  m_AzimuthAngularSeparation;   // in radians
321   double  m_ElevationAngularSeparation; // in radians
322   double  m_RadiusSampleSize;
323   double  m_FirstSampleDistance;
324   
325 };
326 #ifdef ITK_EXPLICIT_INSTANTIATION
327 IND ***extern template class PhasedArray3DSpecialCoordinatesImage<float         >;
328 IND ***extern template class PhasedArray3DSpecialCoordinatesImage<double        >;
329 IND ***extern template class PhasedArray3DSpecialCoordinatesImage<unsigned char >;
330 IND ***extern template class PhasedArray3DSpecialCoordinatesImage<unsigned short>;
331 IND ***extern template class PhasedArray3DSpecialCoordinatesImage<unsigned int  >;
332 IND ***extern template class PhasedArray3DSpecialCoordinatesImage<signed char   >;
333 IND ***extern template class PhasedArray3DSpecialCoordinatesImage<signed short  >;
334 IND ***extern template class PhasedArray3DSpecialCoordinatesImage<signed int    >;
335 #endif
336 // end namespace itk
337 #ifndef ITK_MANUAL_INSTANTIATION
338 #include "itkPhasedArray3DSpecialCoordinatesImage.txx"
339 #endif
340
341 #endif
342
343 EOF

Generated by KWStyle 1.0b on Tuesday January,17 at 02:14:38PM
© Kitware Inc.