Milena (Olena)  User documentation 2.0a Id
save.hh
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
 All Classes Namespaces Functions Variables Typedefs Enumerator