• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List

save.hh

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

Generated on Tue Oct 4 2011 15:24:23 for Milena (Olena) by  doxygen 1.7.1