last-svn-commit-277-gc7ca4da 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, --- 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@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@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
participants (1)
-
Roland Levillain