* mln/io/off/save.hh: New.
---
milena/ChangeLog | 6 ++
milena/mln/io/off/save.hh | 197 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 203 insertions(+), 0 deletions(-)
create mode 100644 milena/mln/io/off/save.hh
diff --git a/milena/ChangeLog b/milena/ChangeLog
index cfd2a4f..50ba108 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -24,6 +24,12 @@
2008-10-22 Roland Levillain <roland(a)lrde.epita.fr>
+ Add a routine to save a complex-based image to an OFF file.
+
+ * mln/io/off/save.hh: New.
+
+2008-10-22 Roland Levillain <roland(a)lrde.epita.fr>
+
Enrich the interface of mln::util::multi_site.
* mln/util/multi_site.hh (mln::util::multi_site<P>::front):
diff --git a/milena/mln/io/off/save.hh b/milena/mln/io/off/save.hh
new file mode 100644
index 0000000..eba2aeb
--- /dev/null
+++ b/milena/mln/io/off/save.hh
@@ -0,0 +1,197 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_IO_OFF_SAVE_HH
+# define MLN_IO_OFF_SAVE_HH
+
+/// \file mln/io/off/save.hh
+/// \brief Input saving function for OFF files.
+///
+/// \see
http://shape.cs.princeton.edu/benchmark/documentation/off_format.html
+
+# include <cstdlib>
+
+# include <iostream>
+# include <fstream>
+# include <sstream>
+
+# include <string>
+
+# include <mln/core/alias/bin_2complex_image3df.hh>
+# include <mln/core/image/complex_neighborhoods.hh>
+# include <mln/core/image/complex_neighborhood_piter.hh>
+
+
+namespace mln
+{
+
+ namespace io
+ {
+
+ namespace off
+ {
+
+ /** \brief Save a (binary) OFF image into a complex image.
+
+ \param[in] ima The image to save.
+ \param[in] filename The name of the file where to save the image.
+
+ The image is said binary since data only represent the
+ existence of faces. */
+ void save(const bin_2complex_image3df& ima, const std::string& filename);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ void save(const bin_2complex_image3df& ima, const std::string& filename)
+ {
+ const std::string me = "mln::io::off::save";
+
+ std::ofstream ostr(filename.c_str());
+ if (!ostr)
+ {
+ std::cerr << me << ": `" << filename << "'
invalid file."
+ << std::endl;
+ /* FIXME: Too violent. We should allow the use of
+ exceptions, at least to have Milena's code behave
+ correctly in interpreted environments (std::exit() or
+ std::abort() causes the termination of a Python
+ interpreter, for instance!). */
+ std::exit(1);
+ }
+
+ /*---------.
+ | Header. |
+ `---------*/
+
+ /* ``The .off files in the Princeton Shape Benchmark conform
+ to the following standard. */
+
+ /* OFF files are all ASCII files beginning with the keyword
+ OFF. '' */
+ ostr << "OFF" << std::endl;
+
+ // A comment.
+ ostr << "# Generated by Milena 1.0
http://olena.lrde.epita.fr\n"
+ << "# EPITA Research and Development Laboratory (LRDE)"
+ << std::endl;
+
+ /* ``The next line states the number of vertices, the number
+ of faces, and the number of edges. The number of edges can
+ be safely ignored.'' */
+ /* FIXME: This is too long. We shall be able to write
+
+ ima.domain().nfaces<0>()
+
+ or even
+
+ ima.nfaces<0>().
+ */
+ ostr << ima.domain().cplx().nfaces<0>() << ' '
+ << ima.domain().cplx().nfaces<1>() << ' '
+ << ima.domain().cplx().nfaces<2>() << std::endl;
+
+ /*-------.
+ | Data. |
+ `-------*/
+
+ // --------- //
+ // Complex. //
+ // --------- //
+
+ typedef mln::bin_2complex_image3df I;
+ const unsigned D = I::dim;
+ typedef mln_geom_(I) G;
+
+ // ------------------------------------------ //
+ // Vertices & geometry (vertices locations). //
+ // ------------------------------------------ //
+
+ /* ``The vertices are listed with x, y, z coordinates, written
+ one per line. */
+
+ // Traverse the 0-faces (vertices).
+ p_n_faces_fwd_piter<D, G> v(ima.domain(), 0);
+ for_all(v)
+ {
+ mln_invariant(v.to_site().size() == 1);
+ ostr << v.to_site().front()[0] << ' '
+ << v.to_site().front()[1] << ' '
+ << v.to_site().front()[2] << std::endl;
+ }
+
+ // --------------- //
+ // Faces & edges. //
+ // --------------- //
+
+ /* After the list of vertices, the faces are listed, with one
+ face per line. For each face, the number of vertices is
+ specified, followed by indices into the list of
+ vertices.'' */
+
+ // Traverse the 2-faces (polygons).
+ p_n_faces_fwd_piter<D, G> f(ima.domain(), 2);
+
+ typedef complex_m_face_neighborhood<D, G> nbh_t;
+ // A neighborhood where neighbors are the set of 0-faces
+ // transitively adjacent to the reference point.
+ nbh_t nbh;
+ mln_fwd_niter_(nbh_t) u(nbh, f);
+ /* FIXME: We should be able to pas this value (m) either at
+ the construction of the neighborhood or at the construction
+ of the iterator. */
+ u.iter().set_m(0);
+
+ // For each (2-)face, iterate on (transitively) ajacent
+ // vertices (0-faces).
+ for_all(f)
+ {
+ unsigned nvertices = 0;
+ std::ostringstream vertices;
+ for_all(u)
+ {
+ // FIXME: Likewise, this is a bit too long...
+ vertices << ' ' << u.unproxy_().face().face_id();
+ ++nvertices;
+ }
+ ostr << nvertices << vertices.str() << std::endl;
+ }
+
+ ostr.close();
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::io::off
+
+ } // end of namespace mln::io
+
+} // end of namespace mln
+
+
+#endif // ! MLN_IO_OFF_SAVE_HH
--
1.6.0.1