* apps/generic-skel/image3d-skel.hh: Aesthetic changes.
(save_vtk_polygons): New function.
Use it...
* apps/generic-skel/image3d-skel-unconstrained.cc,
* apps/generic-skel/image3d-skel-with-end-points.cc:
...here, to save images in VTK format.
* apps/generic-skel/Makefile.am (MOSTLYCLEANFILES):
Add image3d-skel-unconstrained-input.vtk,
image3d-skel-unconstrained-skel.vtk,
image3d-skel-with-end-points-input.vtk and
image3d-skel-with-end-points-skel.vtk,
---
milena/ChangeLog | 16 +++
milena/apps/generic-skel/Makefile.am | 4 +
.../generic-skel/image3d-skel-unconstrained.cc | 2 +
.../generic-skel/image3d-skel-with-end-points.cc | 2 +
milena/apps/generic-skel/image3d-skel.hh | 108 +++++++++++++++++++-
5 files changed, 129 insertions(+), 3 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index cebc7f6..52e8f97 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,21 @@
2011-07-11 Roland Levillain <roland(a)lrde.epita.fr>
+ Add a VTK output routine in apps/generic-skel.
+
+ * apps/generic-skel/image3d-skel.hh: Aesthetic changes.
+ (save_vtk_polygons): New function.
+ Use it...
+ * apps/generic-skel/image3d-skel-unconstrained.cc,
+ * apps/generic-skel/image3d-skel-with-end-points.cc:
+ ...here, to save images in VTK format.
+ * apps/generic-skel/Makefile.am (MOSTLYCLEANFILES):
+ Add image3d-skel-unconstrained-input.vtk,
+ image3d-skel-unconstrained-skel.vtk,
+ image3d-skel-with-end-points-input.vtk and
+ image3d-skel-with-end-points-skel.vtk,
+
+2011-07-11 Roland Levillain <roland(a)lrde.epita.fr>
+
Use package metadata macros instead of hard-coded strings in I/Os.
* mln/io/fld/write_header.hh (mln::io::fld::write_header)
diff --git a/milena/apps/generic-skel/Makefile.am b/milena/apps/generic-skel/Makefile.am
index 425668c..ad89544 100644
--- a/milena/apps/generic-skel/Makefile.am
+++ b/milena/apps/generic-skel/Makefile.am
@@ -79,9 +79,13 @@ TESTS += \
# FIXME: Rename all outputs to have their names use their generator as prefix.
MOSTLYCLEANFILES = \
image3d-skel-unconstrained-input.raw \
+ image3d-skel-unconstrained-input.vtk \
image3d-skel-unconstrained-skel.raw \
+ image3d-skel-unconstrained-skel.vtk \
image3d-skel-with-end-points-input.raw \
+ image3d-skel-with-end-points-input.vtk \
image3d-skel-with-end-points-skel.raw \
+ image3d-skel-with-end-points-skel.vtk \
picasso-skel-unconstrained.pbm \
picasso-skel-with-end-points.pbm \
tiny-skel-unconstrained.pbm \
diff --git a/milena/apps/generic-skel/image3d-skel-unconstrained.cc
b/milena/apps/generic-skel/image3d-skel-unconstrained.cc
index 954c00c..65ef1c1 100644
--- a/milena/apps/generic-skel/image3d-skel-unconstrained.cc
+++ b/milena/apps/generic-skel/image3d-skel-unconstrained.cc
@@ -76,6 +76,7 @@ int main()
std::cerr << input.domain() << std::endl;
save_raw_3d(input, "image3d-skel-unconstrained-input.raw");
+ save_vtk_polygons(input, "image3d-skel-unconstrained-input.vtk");
// FIXME: Debug.
unsigned n_fg_comps;
@@ -101,4 +102,5 @@ int main()
is_simple,
detach);
save_raw_3d(output, "image3d-skel-unconstrained-skel.raw");
+ save_vtk_polygons(output, "image3d-skel-unconstrained-skel.vtk");
}
diff --git a/milena/apps/generic-skel/image3d-skel-with-end-points.cc
b/milena/apps/generic-skel/image3d-skel-with-end-points.cc
index f692cde..e5c3774 100644
--- a/milena/apps/generic-skel/image3d-skel-with-end-points.cc
+++ b/milena/apps/generic-skel/image3d-skel-with-end-points.cc
@@ -77,6 +77,7 @@ int main()
std::cerr << input.domain() << std::endl;
save_raw_3d(input, "image3d-skel-with-end-points-input.raw");
+ save_vtk_polygons(input, "image3d-skel-with-end-points-input.vtk");
// FIXME: Debug.
unsigned n_fg_comps;
@@ -109,4 +110,5 @@ int main()
detach,
constraint);
save_raw_3d(output, "image3d-skel-with-end-points-skel.raw");
+ save_vtk_polygons(output, "image3d-skel-with-end-points-skel.vtk");
}
diff --git a/milena/apps/generic-skel/image3d-skel.hh
b/milena/apps/generic-skel/image3d-skel.hh
index ed8f7ae..7abf4fb 100644
--- a/milena/apps/generic-skel/image3d-skel.hh
+++ b/milena/apps/generic-skel/image3d-skel.hh
@@ -30,14 +30,24 @@
#ifndef APPS_GENERIC_SKEL_IMAGE3D_SKEL_HH
# define APPS_GENERIC_SKEL_IMAGE3D_SKEL_HH
+#include <mln/version.hh>
+
#include <mln/core/image/image3d.hh>
#include <mln/math/sqr.hh>
#include <mln/math/sqrt.hh>
+/*------.
+| I/O. |
+`------*/
+
// FIXME: Do not use a dedicated I/O routines. Either convert the data
-// to another format, or move this routine into mln/io.
+// to another format, or move thess routines into mln/io.
+
+// -------------------- //
+// PGM (3D extension). //
+// -------------------- //
mln::image3d<bool>
load_pgm_3d(const std::string& filename)
@@ -81,6 +91,10 @@ load_pgm_3d(const std::string& filename)
return ima;
}
+// ------------- //
+// Raw 3D data. //
+// ------------- //
+
void
save_raw_3d(const mln::image3d<bool>& ima, const std::string& filename)
{
@@ -90,6 +104,94 @@ save_raw_3d(const mln::image3d<bool>& ima, const
std::string& filename)
file << static_cast<char>(ima(p) ? 0xff : 0x00);
}
+// ----- //
+// VTK. //
+// ----- //
+
+// Save a binary 3D image as a VTK file where each voxel is
+// represented by a cube decomposed in 6 square faces.
+void
+save_vtk_polygons(const mln::image3d<bool>& ima,
+ const std::string& filename)
+{
+ std::ofstream file(filename.c_str());
+
+ // Header.
+ file
+ << "# vtk DataFile Version 2.0" << std::endl
+ << "Generated by " OLN_PACKAGE_STRING " (" OLN_PACKAGE_URL
")" << std::endl
+ << "ASCII" << std::endl
+ << std::endl;
+
+ // Number of object (foreground) sites to represent as a cube.
+ unsigned ncubes = 0;
+ mln_piter_(mln::image3d<bool>) p(ima.domain());
+ for_all(p)
+ if (ima(p))
+ ++ncubes;
+
+ /* FIXME: The current approach duplicates some of the vertices (when
+ they are shared by two cubes or more). */
+
+ // Points (locations).
+ file << "DATASET POLYDATA" << std::endl;
+ // Each site (voxel) is defined by the location of its 8 corners.
+ file << "POINTS " << ncubes * 8 << " float"
<< std::endl;
+
+ // ``Radius'' (half-length) of a cube.
+ float r = 0.5;
+
+ // Cubes (voxels).
+ for_all(p)
+ if (ima(p))
+ file << p[0] - r << ' ' << p[1] - r << ' '
<< p[2] - r << " "
+ << p[0] + r << ' ' << p[1] - r << ' '
<< p[2] - r << " "
+ << p[0] + r << ' ' << p[1] + r << ' '
<< p[2] - r << " "
+ << p[0] - r << ' ' << p[1] + r << ' '
<< p[2] - r << " "
+ << p[0] - r << ' ' << p[1] - r << ' '
<< p[2] + r << " "
+ << p[0] + r << ' ' << p[1] - r << ' '
<< p[2] + r << " "
+ << p[0] + r << ' ' << p[1] + r << ' '
<< p[2] + r << " "
+ << p[0] - r << ' ' << p[1] + r << ' '
<< p[2] + r
+ << std::endl;
+ file << std::endl;
+
+ /* FIXME: The current approach duplicates some of the faces (when
+ they are shared by two squares). */
+
+ // Decompose each cube as a set of squares (polygons).
+ file << "POLYGONS "
+ // Each square has 6 faces
+ << ncubes * 6 << ' '
+ /* Each square face requires 5 parameters: 1 for the number of
+ vertices of the polygon (always `4'), and 4 for the indices of
+ the vertices of this polygon. */
+ << ncubes * 6 * (1 + 4) << std::endl;
+
+ // ``Draw'' the 6 faces of each cube.
+ for (unsigned i = 0; i < ncubes; ++i)
+ {
+ /* Vertices. The 8 vertices of associated with the `i'-th cube
+ have indices `8 * i' to `8 * i + 7'. */
+ unsigned v[8] =
+ { 8 * i + 0, 8 * i + 1, 8 * i + 2, 8 * i + 3,
+ 8 * i + 4, 8 * i + 5, 8 * i + 6, 8 * i + 7 };
+ // Square faces.
+ file
+ << "4 " << v[0] << ' ' << v[1] <<
' ' << v[2] << ' ' << v[3] << '\n'
+ << "4 " << v[4] << ' ' << v[5] <<
' ' << v[6] << ' ' << v[7] << '\n'
+ << "4 " << v[0] << ' ' << v[1] <<
' ' << v[5] << ' ' << v[4] << '\n'
+ << "4 " << v[2] << ' ' << v[3] <<
' ' << v[7] << ' ' << v[6] << '\n'
+ << "4 " << v[0] << ' ' << v[4] <<
' ' << v[7] << ' ' << v[3] << '\n'
+ << "4 " << v[1] << ' ' << v[2] <<
' ' << v[6] << ' ' << v[5] << '\n'
+ << std::flush;
+ }
+}
+
+
+/*--------------.
+| Subsampling. |
+`--------------*/
+
// FIXME: Again, this is a dedicated routine. Use something from
// subsample.
mln::image3d<bool>
@@ -97,11 +199,11 @@ subsampling_3d(const mln::image3d<bool>& input, unsigned
factor)
{
using namespace mln;
typedef image3d<bool> I;
- /* This subsampling procedure may not tak into account pixels at the
+ /* This subsampling procedure may not take into account pixels at the
end of each sloce/row/column if the corresponding dimension is
not a multiple of FACTOR. */
I output(input.nslices() / factor,
- input.nrows() / factor,
+ input.nrows() / factor,
input.ncols() / factor);
mln_piter_(I) po(output.domain());
for_all(po)
--
1.7.2.5