Milena (Olena)
User documentation 2.0a Id
|
00001 // Copyright (C) 2008, 2009, 2011 EPITA Research and Development 00002 // Laboratory (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 00027 #ifndef MLN_IO_OFF_SAVE_HH 00028 # define MLN_IO_OFF_SAVE_HH 00029 00035 00036 # include <cstdlib> 00037 00038 # include <iostream> 00039 # include <fstream> 00040 # include <sstream> 00041 00042 # include <string> 00043 00044 # include <mln/core/alias/complex_image.hh> 00045 # include <mln/core/image/complex_neighborhoods.hh> 00046 # include <mln/core/image/complex_neighborhood_piter.hh> 00047 00048 00049 namespace mln 00050 { 00051 00052 namespace io 00053 { 00054 00055 namespace off 00056 { 00057 00065 void save(const bin_2complex_image3df& ima, 00066 const std::string& filename); 00067 00075 void save(const int_u8_2complex_image3df& ima, 00076 const std::string& filename); 00077 00086 void save(const float_2complex_image3df& ima, 00087 const std::string& filename); 00088 00096 void save(const rgb8_2complex_image3df& ima, 00097 const std::string& filename); 00098 00099 00100 namespace internal 00101 { 00102 00103 template <typename I, typename E> 00104 struct off_saver : public Object<E> 00105 { 00107 typedef mln_value(I) value; 00108 00110 static const unsigned D = 2; 00111 00113 off_saver(); 00114 00116 void operator()(const I& ima, const std::string& filename) const; 00117 }; 00118 00119 00120 struct bin_off_saver 00121 : public off_saver< bin_2complex_image3df, bin_off_saver > 00122 { 00126 void write_face_data(std::ostream& ostr, const value& v) const; 00127 }; 00128 00129 struct int_u8_off_saver 00130 : public off_saver< int_u8_2complex_image3df, int_u8_off_saver > 00131 { 00133 void write_face_data(std::ostream& ostr, const value& v) const; 00134 }; 00135 00136 00137 /* FIXME: We should turn float_off_saver into a 00138 float01_off_saver (see FIXME/comment in implementation 00139 below). */ 00140 struct float_off_saver 00141 : public off_saver< float_2complex_image3df, float_off_saver > 00142 { 00144 void write_face_data(std::ostream& ostr, const value& v) const; 00145 }; 00146 00147 00148 struct rgb8_off_saver 00149 : public off_saver< rgb8_2complex_image3df, rgb8_off_saver > 00150 { 00152 void write_face_data(std::ostream& ostr, const value& v) const; 00153 }; 00154 00155 } // end of namespace mln::io::off::internal 00156 00157 00158 00159 # ifndef MLN_INCLUDE_ONLY 00160 00161 /*----------. 00162 | Facades. | 00163 `----------*/ 00164 00165 inline 00166 void 00167 save(const bin_2complex_image3df& ima, const std::string& filename) 00168 { 00169 trace::entering("mln::io::off::save"); 00170 internal::bin_off_saver()(ima, filename); 00171 trace::exiting("mln::io::off::save"); 00172 } 00173 00174 inline 00175 void 00176 save(const int_u8_2complex_image3df& ima, const std::string& filename) 00177 { 00178 trace::entering("mln::io::off::save"); 00179 internal::int_u8_off_saver()(ima, filename); 00180 trace::exiting("mln::io::off::save"); 00181 } 00182 00183 inline 00184 void 00185 save(const float_2complex_image3df& ima, const std::string& filename) 00186 { 00187 trace::entering("mln::io::off::save"); 00188 internal::float_off_saver()(ima, filename); 00189 trace::exiting("mln::io::off::save"); 00190 } 00191 00192 inline 00193 void 00194 save(const rgb8_2complex_image3df& ima, const std::string& filename) 00195 { 00196 trace::entering("mln::io::off::save"); 00197 internal::rgb8_off_saver()(ima, filename); 00198 trace::exiting("mln::io::off::save"); 00199 } 00200 00201 00202 /*-------------------------. 00203 | Actual implementations. | 00204 `-------------------------*/ 00205 00206 // -------- // 00207 // Canvas. // 00208 // -------- // 00209 00210 namespace internal 00211 { 00212 00213 template <typename I, typename E> 00214 off_saver<I, E>::off_saver() 00215 { 00216 // Concept checking. 00217 void (E::*m1)(std::ostream&, const value&) const = 00218 &E::write_face_data; 00219 m1 = 0; 00220 } 00221 00222 00223 template <typename I, typename E> 00224 void 00225 off_saver<I, E>::operator()(const I& ima, 00226 const std::string& filename) const 00227 { 00228 const std::string me = "mln::io::off::save"; 00229 00230 std::ofstream ostr(filename.c_str()); 00231 if (!ostr) 00232 { 00233 std::cerr << me << ": `" << filename << "' invalid file." 00234 << std::endl; 00235 /* FIXME: Too violent. We should allow the use of 00236 exceptions, at least to have Milena's code behave 00237 correctly in interpreted environments (std::exit() or 00238 std::abort() causes the termination of a Python 00239 interpreter, for instance!). */ 00240 std::exit(1); 00241 } 00242 00243 /*---------. 00244 | Header. | 00245 `---------*/ 00246 00247 /* ``The .off files in the Princeton Shape Benchmark conform 00248 to the following standard.'' */ 00249 00250 /* ``OFF files are all ASCII files beginning with the 00251 keyword OFF. '' */ 00252 ostr << "OFF" << std::endl; 00253 00254 // A comment. 00255 ostr << "# Generated by Milena 1.0 http://olena.lrde.epita.fr\n" 00256 << "# EPITA Research and Development Laboratory (LRDE)" 00257 << std::endl; 00258 00259 /* ``The next line states the number of vertices, the number 00260 of faces, and the number of edges. The number of edges can 00261 be safely ignored.'' */ 00262 /* FIXME: This is too long. We shall be able to write 00263 00264 ima.domain().template nfaces_of_static_dim<0>() 00265 00266 or even 00267 00268 ima.template nfaces_of_static_dim<0>(). 00269 */ 00270 ostr << ima.domain().cplx().template nfaces_of_static_dim<0>() << ' ' 00271 << ima.domain().cplx().template nfaces_of_static_dim<2>() << ' ' 00272 << ima.domain().cplx().template nfaces_of_static_dim<1>() 00273 << std::endl; 00274 00275 /*-------. 00276 | Data. | 00277 `-------*/ 00278 00279 // --------- // 00280 // Complex. // 00281 // --------- // 00282 00283 typedef mln_geom(I) G; 00284 00285 // ------------------------------------------ // 00286 // Vertices & geometry (vertices locations). // 00287 // ------------------------------------------ // 00288 00289 /* ``The vertices are listed with x, y, z coordinates, written 00290 one per line.'' */ 00291 00292 // Traverse the 0-faces (vertices). 00293 p_n_faces_fwd_piter<D, G> v(ima.domain(), 0); 00294 for_all(v) 00295 { 00296 mln_invariant(v.to_site().size() == 1); 00297 ostr << v.to_site().front()[0] << ' ' 00298 << v.to_site().front()[1] << ' ' 00299 << v.to_site().front()[2] << std::endl; 00300 } 00301 00302 // --------------- // 00303 // Faces & edges. // 00304 // --------------- // 00305 00306 /* ``After the list of vertices, the faces are listed, with one 00307 face per line. For each face, the number of vertices is 00308 specified, followed by indices into the list of 00309 vertices.'' */ 00310 00311 // Traverse the 2-faces (polygons). 00312 p_n_faces_fwd_piter<D, G> f(ima.domain(), 2); 00313 00314 typedef complex_m_face_neighborhood<D, G> nbh_t; 00315 // A neighborhood where neighbors are the set of 0-faces 00316 // transitively adjacent to the reference point. 00317 nbh_t nbh; 00318 mln_fwd_niter(nbh_t) u(nbh, f); 00319 /* FIXME: We should be able to pas this value (m) either at 00320 the construction of the neighborhood or at the construction 00321 of the iterator. */ 00322 u.iter().set_m(0); 00323 00324 // For each (2-)face, iterate on (transitively) ajacent 00325 // vertices (0-faces). 00326 for_all(f) 00327 { 00328 unsigned nvertices = 0; 00329 std::ostringstream vertices; 00330 for_all(u) 00331 { 00332 // FIXME: Likewise, this is a bit too long... 00333 vertices << ' ' << u.unproxy_().face().face_id(); 00334 ++nvertices; 00335 } 00336 ostr << nvertices << vertices.str(); 00337 // Possibly save a value (depends on the actual format). 00338 exact(this)->write_face_data(ostr, ima(f)); 00339 ostr << std::endl; 00340 } 00341 00342 ostr.close(); 00343 } 00344 00345 // ---------------- // 00346 // Specific parts. // 00347 // ---------------- // 00348 00388 inline 00389 void 00390 bin_off_saver::write_face_data(std::ostream& /* ostr */, 00391 const value& /* v */) const 00392 { 00393 // Do nothing (no data associated to faces). 00394 } 00395 00396 inline 00397 void 00398 int_u8_off_saver::write_face_data(std::ostream& ostr, 00399 const value& v) const 00400 { 00401 /* Using RGBA colors to represent an 8-bit integer value. 00402 00403 Each channel (R, G, B) of the color V is an integer in 00404 the range 0..255. A fourth channel, A, controls the 00405 transparency. 00406 00407 We just set the same value for each channel, as the OFF 00408 file format does not support gray-level values as-is. */ 00409 ostr << ' ' << v << ' ' << v << ' ' << v 00410 << ' ' << 1.0f << std::endl; 00411 } 00412 00413 /* FIXME: We should turn float_off_saver into a 00414 float01_off_saver to avoid the assertions below. */ 00415 inline 00416 void 00417 float_off_saver::write_face_data(std::ostream& ostr, 00418 const value& v) const 00419 { 00420 /* Using RGBA colors to represent a floating-point value. 00421 00422 Each channel (R, G, B) of the color V is a floating-point 00423 number in the range 0..1. A fourth channel, A, controls 00424 the transparency. 00425 00426 We just set the same value for each channel, as the OFF 00427 file format does not support gray-level values as 00428 such. */ 00429 mln_assertion(0.0f <= v); 00430 mln_assertion(v <= 1.0f); 00431 ostr << ' ' << v << ' ' << v << ' ' << v 00432 << ' ' << 1.0f; 00433 } 00434 00435 inline 00436 void 00437 rgb8_off_saver::write_face_data(std::ostream& ostr, 00438 const value& v) const 00439 { 00440 /* RGBA color. 00441 00442 Each channel (R, G, B) of the color V is an integer in 00443 the range 0..255. A fourth channel, A, controls the 00444 transparency. */ 00445 ostr << ' ' << v.red() << ' ' << v.green() << ' ' << v.blue() 00446 << ' ' << 1.0f; 00447 } 00448 /* \} */ 00449 00450 } // end of namespace mln::io::off::internal 00451 00452 00453 # endif // ! MLN_INCLUDE_ONLY 00454 00455 } // end of namespace mln::io::off 00456 00457 } // end of namespace mln::io 00458 00459 } // end of namespace mln 00460 00461 00462 #endif // ! MLN_IO_OFF_SAVE_HH