Milena (Olena)
User documentation 2.0a Id
|
00001 // Copyright (C) 2009, 2010 EPITA Research and Development Laboratory 00002 // (LRDE) 00003 // 00004 // This file is part of Olena. 00005 // 00006 // Olena is free software: you can redistribute it and/or modify it under 00007 // the terms of the GNU General Public License as published by the Free 00008 // Software Foundation, version 2 of the License. 00009 // 00010 // Olena is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 // General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Olena. If not, see <http://www.gnu.org/licenses/>. 00017 // 00018 // As a special exception, you may use this file as part of a free 00019 // software project without restriction. Specifically, if other files 00020 // instantiate templates or use macros or inline functions from this 00021 // file, or you compile this file and link it with other files to produce 00022 // an executable, this file does not by itself cause the resulting 00023 // executable to be covered by the GNU General Public License. This 00024 // exception does not however invalidate any other reasons why the 00025 // executable file might be covered by the GNU General Public License. 00026 00030 00031 #ifndef MLN_GEOM_ROTATE_HH 00032 # define MLN_GEOM_ROTATE_HH 00033 00034 # include <mln/core/concept/image.hh> 00035 # include <mln/core/concept/site_set.hh> 00036 # include <mln/core/concept/box.hh> 00037 00038 # include <mln/core/routine/extend.hh> 00039 00040 # include <mln/core/image/imorph/tr_image.hh> 00041 00042 # include <mln/accu/shape/bbox.hh> 00043 00044 # include <mln/data/paste.hh> 00045 00046 # include <mln/geom/bbox.hh> 00047 00048 # include <mln/extension/duplicate.hh> 00049 00050 # include <mln/fun/x2x/composed.hh> 00051 # include <mln/fun/x2x/rotation.hh> 00052 # include <mln/fun/x2x/translation.hh> 00053 00054 # include <mln/literal/zero.hh> 00055 00056 # include <mln/math/pi.hh> 00057 00058 00059 namespace mln 00060 { 00061 00062 namespace geom 00063 { 00064 00079 // 00080 template <typename I, typename Ext, typename S> 00081 mln_concrete(I) 00082 rotate(const Image<I>& input, double angle, 00083 const Ext& extension, const Site_Set<S>& output_domain); 00084 00085 00087 template <typename I, typename Ext> 00088 mln_concrete(I) 00089 rotate(const Image<I>& input, double angle, const Ext& extension); 00090 00091 00094 template <typename I> 00095 mln_concrete(I) 00096 rotate(const Image<I>& input, double angle); 00097 00098 00103 // 00104 template <typename B> 00105 B 00106 rotate(const Box<B>& box_, double angle, const mln_site(B)& ref); 00107 00111 // 00112 template <typename B> 00113 B 00114 rotate(const Box<B>& box, double angle); 00115 00116 00117 00118 # ifndef MLN_INCLUDE_ONLY 00119 00120 00121 template <typename I, typename Ext, typename S> 00122 mln_concrete(I) 00123 rotate(const Image<I>& input_, double angle, 00124 const Ext& extension_, const Site_Set<S>& output_domain_) 00125 { 00126 trace::entering("geom::rotate"); 00127 00128 const I& input = exact(input_); 00129 const S& output_domain = exact(output_domain_); 00130 const mln_exact(Ext)& extension = exact(extension_); 00131 00132 // Do not check that output_domain_ is valid. If it is not, 00133 // further in this routine, we define a default domain. 00134 typedef mln_site(I) P; 00135 mln_precondition(P::dim == 2); 00136 mln_precondition(input.is_valid()); 00137 mln_precondition(angle >= -360.0f && angle <= 360.0f); 00138 // mlc_converts_to(mln_exact(Ext), mln_value(I))::check(); 00139 mlc_is_a(S,Box)::check(); 00140 // FIXME: A precondition is probably missing for the extension value. 00141 00142 extension::duplicate(input); 00143 00144 mln_site(I) c = geom::bbox(input).pcenter(); 00145 typedef fun::x2x::translation<2,double> trans_t; 00146 trans_t 00147 t(-1 * c.to_vec()), 00148 t_1(c.to_vec()); 00149 00150 typedef fun::x2x::rotation<2,double> rot_t; 00151 rot_t rot(math::pi * angle / 180.f, literal::origin); 00152 00153 typedef 00154 fun::x2x::composed<trans_t, fun::x2x::composed<rot_t, trans_t> > 00155 comp_transf_t; 00156 00157 comp_transf_t comp_transf = compose(t_1, compose(rot, t)); 00158 00159 S b = output_domain; 00160 // Automatically adjusting the output domain if needed. 00161 if (!output_domain.is_valid()) 00162 b = rotate(input.domain(), angle); 00163 00164 typedef 00165 typename mln::internal::extension_type<const I, mln_exact(Ext)>::result ext_t; 00166 00167 typedef 00168 tr_image<mln_box(I), ext_t, comp_transf_t> tr_t; 00169 00170 tr_t tr = transposed_image(b, ext_t(input, extension), comp_transf); 00171 00172 00173 mln_concrete(I) output; 00174 initialize(output, tr); 00175 00176 data::paste(tr, output); 00177 00178 trace::exiting("geom::rotate"); 00179 return output; 00180 } 00181 00182 00183 template <typename I, typename Ext> 00184 mln_concrete(I) 00185 rotate(const Image<I>& input, double angle, const Ext& extension) 00186 { 00187 // Old versions of GCC (including Apple GCC 4.0.1) do not parse 00188 // correctly `mln_box(I)()'. Hence, we need to typedef 00189 // `mln_box(I)' first. 00190 typedef mln_domain(I) domain_t; 00191 return rotate(input, angle, extension, domain_t()); 00192 } 00193 00194 00195 template <typename I> 00196 mln_concrete(I) 00197 rotate(const Image<I>& input, double angle) 00198 { 00199 return rotate(input, angle, literal::zero); 00200 } 00201 00202 00203 template <typename B> 00204 B 00205 rotate(const Box<B>& box_, double angle, const mln_site(B)& ref) 00206 { 00207 trace::entering("geom::rotate"); 00208 00209 const B& box = exact(box_); 00210 00211 typedef mln_site(B) P; 00212 mln_precondition(P::dim == 2); 00213 mln_precondition(box.is_valid()); 00214 mln_precondition(angle >= -360.0f && angle <= 360.0f); 00215 00216 typedef fun::x2x::translation<2,double> trans_t; 00217 trans_t 00218 t(-1 * ref.to_vec()), 00219 t_1(ref.to_vec()); 00220 00221 typedef fun::x2x::rotation<2,double> rot_t; 00222 rot_t rot(math::pi * angle / 180.f, literal::origin); 00223 00224 typedef 00225 fun::x2x::composed<trans_t, fun::x2x::composed<rot_t, trans_t> > 00226 comp_transf_t; 00227 00228 comp_transf_t comp_transf = compose(t_1, compose(rot, t)); 00229 00230 accu::shape::bbox<P> accu; 00231 00232 P 00233 top_right(box.pmin().row(), 00234 box.pmax().col()), 00235 bot_left(box.pmax().row(), 00236 box.pmin().col()); 00237 00238 accu.take(P(comp_transf(box.pmin().to_vec()))); 00239 accu.take(P(comp_transf(top_right.to_vec()))); 00240 accu.take(P(comp_transf(bot_left.to_vec()))); 00241 accu.take(P(comp_transf(box.pmax().to_vec()))); 00242 00243 B output = accu.to_result(); 00244 00245 trace::exiting("geom::rotate"); 00246 return output; 00247 } 00248 00249 00250 template <typename B> 00251 B 00252 rotate(const Box<B>& box, double angle) 00253 { 00254 return rotate(box, angle, exact(box).pcenter()); 00255 } 00256 00257 00258 00259 # endif // ! MLN_INCLUDE_ONLY 00260 00261 00262 } // end of namespace mln::geom 00263 00264 } // end of namespace mln 00265 00266 00267 #endif // ! MLN_GEOM_ROTATE_HH