$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
rotate.hh
1 // Copyright (C) 2009, 2010, 2012 EPITA Research and Development
2 // Laboratory (LRDE)
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
30 
31 #ifndef MLN_GEOM_ROTATE_HH
32 # define MLN_GEOM_ROTATE_HH
33 
34 # include <mln/core/concept/image.hh>
35 # include <mln/core/concept/site_set.hh>
36 # include <mln/core/concept/box.hh>
37 
38 # include <mln/core/routine/extend.hh>
39 
40 # include <mln/core/image/imorph/tr_image.hh>
41 
42 # include <mln/accu/shape/bbox.hh>
43 
44 # include <mln/data/paste.hh>
45 
46 # include <mln/geom/bbox.hh>
47 # include <mln/geom/top_right.hh>
48 # include <mln/geom/bottom_left.hh>
49 
50 # include <mln/extension/duplicate.hh>
51 
52 # include <mln/fun/x2x/composed.hh>
53 # include <mln/fun/x2x/rotation.hh>
54 # include <mln/fun/x2x/translation.hh>
55 
56 # include <mln/literal/zero.hh>
57 
58 # include <mln/math/pi.hh>
59 
60 
61 namespace mln
62 {
63 
64  namespace geom
65  {
66 
84  template <typename I, typename Ext, typename S>
85  mln_concrete(I)
86  rotate(const Image<I>& input, double angle,
87  const Ext& extension, const Site_Set<S>& output_domain);
88 
89 
94  template <typename I, typename Ext>
95  mln_concrete(I)
96  rotate(const Image<I>& input, double angle, const Ext& extension);
97 
98 
104  template <typename I>
105  mln_concrete(I)
106  rotate(const Image<I>& input, double angle);
107 
108 
116  template <typename B>
117  B
118  rotate(const Box<B>& box_, double angle, const mln_site(B)& ref);
119 
126  template <typename B>
127  B
128  rotate(const Box<B>& box, double angle);
129 
130 
131 
132 # ifndef MLN_INCLUDE_ONLY
133 
134 
135  template <typename I, typename Ext, typename S>
136  mln_concrete(I)
137  rotate(const Image<I>& input_, double angle,
138  const Ext& extension_, const Site_Set<S>& output_domain_)
139  {
140  mln_trace("geom::rotate");
141 
142  const I& input = exact(input_);
143  const S& output_domain = exact(output_domain_);
144  const mln_exact(Ext)& extension = exact(extension_);
145 
146  // Do not check that output_domain_ is valid. If it is not,
147  // further in this routine, we define a default domain.
148  typedef mln_site(I) P;
149  mln_precondition(input.is_valid());
150  mln_precondition(angle >= -360.0f && angle <= 360.0f);
151 // mlc_converts_to(mln_exact(Ext), mln_value(I))::check();
152  mlc_is_a(S,Box)::check();
153  // FIXME: A precondition is probably missing for the extension value.
154 
155  extension::duplicate(input);
156 
157  mln_site(I) c = geom::bbox(input).pcenter();
158  typedef fun::x2x::translation<P::dim,double> trans_t;
159  trans_t
160  t(-1 * c.to_vec()),
161  t_1(c.to_vec());
162 
163  typedef fun::x2x::rotation<P::dim,double> rot_t;
164  rot_t rot(math::pi * angle / 180.f, literal::origin);
165 
166  typedef
167  fun::x2x::composed<trans_t, fun::x2x::composed<rot_t, trans_t> >
168  comp_transf_t;
169 
170  comp_transf_t comp_transf = compose(t_1, compose(rot, t));
171 
172  S b = output_domain;
173  // Automatically adjusting the output domain if needed.
174  if (!output_domain.is_valid())
175  b = rotate(input.domain(), angle);
176 
177  typedef
178  typename mln::internal::extension_type<const I, mln_exact(Ext)>::result ext_t;
179 
180  typedef
181  tr_image<mln_box(I), ext_t, comp_transf_t> tr_t;
182 
183  tr_t tr = transposed_image(b, ext_t(input, extension), comp_transf);
184 
185 
186  mln_concrete(I) output;
187  initialize(output, tr);
188 
189  data::paste(tr, output);
190 
191  return output;
192  }
193 
194 
195  template <typename I, typename Ext>
196  mln_concrete(I)
197  rotate(const Image<I>& input, double angle, const Ext& extension)
198  {
199  // Old versions of GCC (including Apple GCC 4.0.1) do not parse
200  // correctly `mln_box(I)()'. Hence, we need to typedef
201  // `mln_box(I)' first.
202  typedef mln_domain(I) domain_t;
203  return rotate(input, angle, extension, domain_t());
204  }
205 
206 
207  template <typename I>
208  mln_concrete(I)
209  rotate(const Image<I>& input, double angle)
210  {
211  return rotate(input, angle, literal::zero);
212  }
213 
214 
215  template <typename B>
216  B
217  rotate(const Box<B>& box_, double angle, const mln_site(B)& ref)
218  {
219  mln_trace("geom::rotate");
220 
221  const B& box = exact(box_);
222 
223  typedef mln_site(B) P;
224  mln_precondition(box.is_valid());
225  mln_precondition(angle >= -360.0f && angle <= 360.0f);
226 
227  typedef fun::x2x::translation<P::dim,double> trans_t;
228  trans_t
229  t(-1 * ref.to_vec()),
230  t_1(ref.to_vec());
231 
232  typedef fun::x2x::rotation<P::dim,double> rot_t;
233  rot_t rot(math::pi * angle / 180.f, literal::origin);
234 
235  typedef
236  fun::x2x::composed<trans_t, fun::x2x::composed<rot_t, trans_t> >
237  comp_transf_t;
238 
239  comp_transf_t comp_transf = compose(t_1, compose(rot, t));
240 
241  accu::shape::bbox<P> accu;
242 
243  P
244  top_right = geom::top_right(box),
245  bot_left = geom::bottom_left(box);
246 
247  accu.take(P(comp_transf(box.pmin().to_vec())));
248  accu.take(P(comp_transf(top_right.to_vec())));
249  accu.take(P(comp_transf(bot_left.to_vec())));
250  accu.take(P(comp_transf(box.pmax().to_vec())));
251 
252  B output = accu.to_result();
253 
254  return output;
255  }
256 
257 
258  template <typename B>
259  B
260  rotate(const Box<B>& box, double angle)
261  {
262  return rotate(box, angle, exact(box).pcenter());
263  }
264 
265 
266 
267 # endif // ! MLN_INCLUDE_ONLY
268 
269 
270  } // end of namespace mln::geom
271 
272 } // end of namespace mln
273 
274 
275 #endif // ! MLN_GEOM_ROTATE_HH