DGtal  1.5.beta
Linearizer.ih
1 /**
2  * This program is free software: you can redistribute it and/or modify
3  * it under the terms of the GNU Lesser General Public License as
4  * published by the Free Software Foundation, either version 3 of the
5  * License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program. If not, see <http://www.gnu.org/licenses/>.
14  *
15  **/
16 
17 /**
18  * @file Linearizer.ih
19  * @author Roland Denis (\c roland.denis@univ-smb.fr )
20  * LAboratory of MAthematics - LAMA (CNRS, UMR 5127), University of Savoie, France
21  *
22  * @date 2015/06/18
23  *
24  * This file is part of the DGtal library.
25  */
26 
27 
28 //////////////////////////////////////////////////////////////////////////////
29 #include <cstddef>
30 //////////////////////////////////////////////////////////////////////////////
31 
32 ///////////////////////////////////////////////////////////////////////////////
33 // IMPLEMENTATION of inline methods.
34 ///////////////////////////////////////////////////////////////////////////////
35 
36 namespace DGtal
37 {
38 
39  /// Tools
40  namespace
41  {
42 
43  /** Helper that calculates the dimension index given the current linearization step.
44  *
45  * The step I is always decrementing from N-1 to 0.
46  *
47  * @tparam TStorageOrder Storage order (RowMajorStorage of ColMajorStorage).
48  * @tparam N Dimension of the space.
49  * @tparam I Current step.
50  */
51  template < typename TStorageOrder, std::size_t N, std::size_t I >
52  struct linearizer_helper;
53 
54  template < std::size_t N, std::size_t I >
55  struct linearizer_helper< RowMajorStorage, N, I >
56  {
57  enum { dim = I }; ///< Dimension index related to the step I.
58  };
59 
60  template < std::size_t N, std::size_t I >
61  struct linearizer_helper< ColMajorStorage, N, I >
62  {
63  enum { dim = N-1 - I }; ///< Dimension index related to the step I.
64  };
65 
66  /** Templated static structure for linearization of the coordinates of a point.
67  *
68  * @tparam TSize Type of the linearizared index.
69  * @tparam TStorageOrder Storage order (RowMajorStorage of ColMajorStorage).
70  * @tparam N Dimension of the space.
71  * @tparam I Current step.
72  */
73  template < typename TSize, typename TStorageOrder, std::size_t N, std::size_t I = N-1 >
74  struct linearizer_impl
75  {
76 
77  /**
78  * Return the linearized index from the coordinates of a point.
79  *
80  * @tparam TPoint Type of the point.
81  * @tparam TExtent Type of the domain's extent.
82  * @param[in] aPoint The point to linearize.
83  * @param[in] anExtent The extent of the domain.
84  * @return the linearized index of the point.
85  */
86  template < typename TPoint, typename TExtent >
87  static inline
88  TSize apply( TPoint const& aPoint, TExtent const& anExtent )
89  {
90  return
91  aPoint[ linearizer_helper<TStorageOrder, N, I>::dim ]
92  + anExtent[ linearizer_helper<TStorageOrder, N, I>::dim ] * linearizer_impl< TSize, TStorageOrder, N, I-1 >::apply( aPoint, anExtent );
93  }
94  };
95 
96  /**
97  * Specialization of the structure linearizer_impl for the last step.
98  *
99  * It is actually used as a terminate condition of the recursive process.
100  */
101  template < typename TSize, typename TStorageOrder, std::size_t N >
102  struct linearizer_impl< TSize, TStorageOrder, N, 0 >
103  {
104  template < typename TPoint, typename TExtent >
105  static inline
106  TSize apply( TPoint const& aPoint, TExtent const& /* anExtent */ )
107  {
108  return aPoint[ linearizer_helper<TStorageOrder, N, 0>::dim ];
109  }
110  };
111 
112  /** Templated static structure for de-linearization of a point index.
113  *
114  * @tparam TStorageOrder Storage order (RowMajorStorage of ColMajorStorage).
115  * @tparam N Dimension of the space.
116  * @tparam I Current step.
117  */
118  template < typename TStorageOrder, std::size_t N, std::size_t I = N-1 >
119  struct delinearizer_impl
120  {
121 
122  /**
123  * Return the de-linearized point from the linearized index of the point.
124  *
125  * @tparam TPoint Type of the point.
126  * @tparam TExtent Type of the domain's extent.
127  * @tparam TSize Type of the linearized index.
128  * @param[out] aPoint The point after de-linearization.
129  * @param[in] anExtent The extent of the domain.
130  * @param[in] anIndex The linearized index of the point.
131  */
132  template < typename TPoint, typename TExtent, typename TSize >
133  static inline
134  void apply( TPoint& aPoint, TExtent const& anExtent, TSize anIndex )
135  {
136  typename TExtent::Scalar const dim_extent = anExtent[ linearizer_helper<TStorageOrder, N, I>::dim ];
137  aPoint[ linearizer_helper<TStorageOrder, N, I>::dim ] = anIndex % dim_extent;
138  delinearizer_impl< TStorageOrder, N, I-1 >::apply( aPoint, anExtent, anIndex / dim_extent );
139  }
140  };
141 
142  /**
143  * Specialization of the structure delinearizer_impl for the last step.
144  *
145  * It is actually used as a terminate condition of the recursive process.
146  */
147  template < typename TStorageOrder, std::size_t N >
148  struct delinearizer_impl< TStorageOrder, N, 0 >
149  {
150  template < typename TPoint, typename TExtent, typename TSize >
151  static inline
152  void apply( TPoint& aPoint, TExtent const& /* anExtent */, TSize anIndex )
153  {
154  aPoint[ linearizer_helper<TStorageOrder, N, 0>::dim ] = anIndex;
155  }
156  };
157 
158  } // anonymous namespace
159 
160  /// Linearized index of a point, given the domain lower-bound and extent.
161  template <typename TSpace, typename TStorageOrder>
162  typename Linearizer< HyperRectDomain<TSpace>, TStorageOrder >::Size
163  Linearizer< HyperRectDomain<TSpace>, TStorageOrder >::
164  getIndex( Point aPoint, Point const& aLowerBound, Extent const& anExtent )
165  {
166  aPoint -= aLowerBound;
167  return linearizer_impl<Size, TStorageOrder, Domain::dimension>::apply(aPoint, anExtent);
168  }
169 
170  /// Linearized index of a point, given the domain extent.
171  template <typename TSpace, typename TStorageOrder>
172  typename Linearizer< HyperRectDomain<TSpace>, TStorageOrder >::Size
173  Linearizer< HyperRectDomain<TSpace>, TStorageOrder >::
174  getIndex( Point aPoint, Extent const& anExtent )
175  {
176  return linearizer_impl<Size, TStorageOrder, Domain::dimension>::apply(aPoint, anExtent);
177  }
178 
179  /// Linearized index of a point, given a domain.
180  template <typename TSpace, typename TStorageOrder>
181  typename Linearizer< HyperRectDomain<TSpace>, TStorageOrder >::Size
182  Linearizer< HyperRectDomain<TSpace>, TStorageOrder >::
183  getIndex( Point aPoint, Domain const& aDomain )
184  {
185  return linearizer_impl<Size, TStorageOrder, Domain::dimension>::apply(aPoint - aDomain.lowerBound(), aDomain.upperBound()-aDomain.lowerBound()+Point::diagonal(1));
186  }
187 
188  /// De-linearization of an index, given the domain lower-bound and extent.
189  template <typename TSpace, typename TStorageOrder>
190  typename Linearizer< HyperRectDomain<TSpace>, TStorageOrder >::Point
191  Linearizer< HyperRectDomain<TSpace>, TStorageOrder >::
192  getPoint( Size anIndex, Point const& aLowerBound, Extent const& anExtent )
193  {
194  Point point;
195  delinearizer_impl<TStorageOrder, Domain::dimension>::apply(point, anExtent, anIndex);
196  return point + aLowerBound;
197  }
198 
199  /// De-linearization of an index, given the domain extent.
200  template <typename TSpace, typename TStorageOrder>
201  typename Linearizer< HyperRectDomain<TSpace>, TStorageOrder >::Point
202  Linearizer< HyperRectDomain<TSpace>, TStorageOrder >::
203  getPoint( Size anIndex, Extent const& anExtent )
204  {
205  Point point;
206  delinearizer_impl<TStorageOrder, Domain::dimension>::apply(point, anExtent, anIndex);
207  return point;
208  }
209 
210  /// De-linearization of an index, given a domain.
211  template <typename TSpace, typename TStorageOrder>
212  typename Linearizer< HyperRectDomain<TSpace>, TStorageOrder >::Point
213  Linearizer< HyperRectDomain<TSpace>, TStorageOrder >::
214  getPoint( Size anIndex, Domain const& aDomain )
215  {
216  Point point;
217  delinearizer_impl<TStorageOrder, Domain::dimension>::apply(point, aDomain.upperBound()-aDomain.lowerBound()+Point::diagonal(1), anIndex);
218  return point + aDomain.lowerBound();
219  }
220 
221 } // namespace DGtal
222