
* apps/graph-morpho/convert.hh, * apps/graph-morpho/debug.hh: New files. * apps/graph-morpho/io.hh (println): Remove function. * apps/graph-morpho/samples-image2d.cc, * apps/graph-morpho/samples-complex1d.cc: Adjust clients. * apps/graph-morpho/Makefile.am (noinst_HEADERS): Add convert.hh and debug.hh. --- milena/ChangeLog | 14 +++ milena/apps/graph-morpho/Makefile.am | 2 +- milena/apps/graph-morpho/convert.hh | 117 +++++++++++++++++++++++++ milena/apps/graph-morpho/debug.hh | 99 +++++++++++++++++++++ milena/apps/graph-morpho/io.hh | 81 ----------------- milena/apps/graph-morpho/samples-complex1d.cc | 39 ++++---- milena/apps/graph-morpho/samples-image2d.cc | 38 ++++---- 7 files changed, 269 insertions(+), 121 deletions(-) create mode 100644 milena/apps/graph-morpho/convert.hh create mode 100644 milena/apps/graph-morpho/debug.hh diff --git a/milena/ChangeLog b/milena/ChangeLog index 669d4f9..dcad3c7 100644 --- a/milena/ChangeLog +++ b/milena/ChangeLog @@ -1,3 +1,17 @@ +2009-10-01 Roland Levillain <roland@lrde.epita.fr> + + Clean up some conversion and pretty-printing routines in graph-morpho. + + * apps/graph-morpho/convert.hh, + * apps/graph-morpho/debug.hh: + New files. + * apps/graph-morpho/io.hh (println): Remove function. + * apps/graph-morpho/samples-image2d.cc, + * apps/graph-morpho/samples-complex1d.cc: + Adjust clients. + * apps/graph-morpho/Makefile.am (noinst_HEADERS): + Add convert.hh and debug.hh. + 2009-09-30 Roland Levillain <roland@lrde.epita.fr> Generic vertices-edges combinator in apps/graph-morpho/. diff --git a/milena/apps/graph-morpho/Makefile.am b/milena/apps/graph-morpho/Makefile.am index 70e177e..76fb7d7 100644 --- a/milena/apps/graph-morpho/Makefile.am +++ b/milena/apps/graph-morpho/Makefile.am @@ -20,7 +20,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/milena -I$(top_builddir)/milena APPS_CXXFLAGS = @APPS_CXXFLAGS@ AM_CXXFLAGS = $(APPS_CXXFLAGS) -noinst_HEADERS = io.hh morpho.hh make_complex2d.hh +noinst_HEADERS = convert.hh debug.hh io.hh morpho.hh make_complex2d.hh noinst_PROGRAMS = samples-complex1d samples-image2d asf-complex1d asf-image2d samples_complex1d_SOURCES = samples-complex1d.cc diff --git a/milena/apps/graph-morpho/convert.hh b/milena/apps/graph-morpho/convert.hh new file mode 100644 index 0000000..e51b4ac --- /dev/null +++ b/milena/apps/graph-morpho/convert.hh @@ -0,0 +1,117 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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 APPS_GRAPH_MORPHO_CONVERT_HH +# define APPS_GRAPH_MORPHO_CONVERT_HH + +/// \file +/// \brief Conversion between various graph/complex image types. + +# include <mln/core/alias/complex_image.hh> +# include <mln/core/image/image2d.hh> + + +namespace convert +{ + + /// Convert an mln::bin_1complex_image2d to an mln::image2d<bool>. + inline + mln::image2d<bool> + to_image2d(const mln::bin_1complex_image2d& input) + { + using namespace mln; + + const unsigned dim = 1; + typedef geom::complex_geometry<dim, point2d> geom_t; + + // Compute the bounding box of the domain of FROM. + accu::shape::bbox<point2d> bbox; + p_n_faces_fwd_piter<dim, geom_t> v(input.domain(), 0); + for_all(v) + { + mln_site_(geom_t) s(v); + // Site S is point2d multi-site and should be a singleton (since V + // iterates on vertices). + mln_invariant(s.size() == 1); + point2d p = s.front(); + bbox.take(p); + } + mln::box2d support = bbox; + + image2d<bool> output(box2d(point2d(support.pmin().row() * 2, + support.pmin().col() * 2), + point2d(support.pmax().row() * 2, + support.pmax().col() * 2))); + data::fill(output, false); + + // Iterate on vertices. + for_all(v) + { + mln_site_(geom_t) s(v); + // Site S is point2d multi-site and should be a singleton (since V + // iterates on vertices). + mln_invariant(s.size() == 1); + point2d p_in = s.front(); + point2d p_out(p_in.row() * 2, p_in.col() * 2); + output(p_out) = input(v); + } + + // Iterate on edges. + p_n_faces_fwd_piter<dim, geom_t> e(input.domain(), 1); + for_all(e) + { + mln_site_(geom_t) s(e); + // Site S is point2d multi-site and should be a pair (since E + // iterates on vertices). + mln_invariant(s.size() == 2); + point2d p1 = s[0]; + point2d p2 = s[1]; + if (p1.row() == p2.row()) + { + // Horizontal edge. + point2d p_out(p1.row() * 2, + p1.col() + p2.col()); + output(p_out) = input(e); + } + else if (p1.col() == p2.col()) + { + // Vertical edge. + point2d p_out(p1.row() + p2.row(), + p1.col() * 2); + output(p_out) = input(e); + } + else + { + // Edge not fitting in the 2D regular grid canvas, aborting. + abort(); + } + } + return output; + } + +} // end of namespace convert + + +#endif // ! APPS_GRAPH_MORPHO_CONVERT_HH diff --git a/milena/apps/graph-morpho/debug.hh b/milena/apps/graph-morpho/debug.hh new file mode 100644 index 0000000..5ad3045 --- /dev/null +++ b/milena/apps/graph-morpho/debug.hh @@ -0,0 +1,99 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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 APPS_GRAPH_MORPHO_DEBUG_HH +# define APPS_GRAPH_MORPHO_DEBUG_HH + +/// \file +/// \brief Pretty-printing between graph/complex image types. + +# include <mln/core/alias/complex_image.hh> +# include <mln/core/image/image2d.hh> + +# include <mln/debug/println.hh> + +# include "apps/graph-morpho/convert.hh" + + +namespace debug +{ + + /// Pretty print an mln::image2d<bool> viewed as a graph. + void + println_graph(const std::string& message, const mln::image2d<bool>& input) + { + // INPUT must have odd numbers of rows and columns. + mln_precondition(input.nrows() % 2 == 1); + mln_precondition(input.ncols() % 2 == 1); + + mln::image2d<char> output; + mln::initialize(output, input); + for (int row = input.domain().pmin().row(); + row <= input.domain().pmax().row(); ++row) + { + if (row % 2 == 0) + // Even row: line with vertices and horizontal edges. + for (int col = input.domain().pmin().col(); + col <= input.domain().pmax().col(); ++col) + { + mln::point2d p(row, col); + if (col % 2 == 0) + // Even column: vertex. + output(p) = input(p) ? 'O' : '.'; + else + // Odd column: horizontal edge. + output(p) = input(p) ? '-' : ' '; + } + else + // Odd row: line with vertical edges and inter-edge spaces + // (squares). + for (int col = input.domain().pmin().col(); + col <= input.domain().pmax().col(); ++col) + { + mln::point2d p(row, col); + if (col % 2 == 0) + // Even column: vertical edge. + output(p) = input(p) ? '|' : ' '; + else + // Odd column: space. + output(p) = ' '; + } + } + mln::debug::println(message, output); + } + + + /// Pretty-print an mln::bin_1complex_image2d viewed as a graph. + void + println_graph(const std::string& message, + const mln::bin_1complex_image2d& input) + { + println_graph(message, convert::to_image2d(input)); + } + +} // end of namespace debug + + +#endif // ! APPS_GRAPH_MORPHO_DEBUG_HH diff --git a/milena/apps/graph-morpho/io.hh b/milena/apps/graph-morpho/io.hh index cdc54bb..8c92949 100644 --- a/milena/apps/graph-morpho/io.hh +++ b/milena/apps/graph-morpho/io.hh @@ -153,85 +153,4 @@ make_regular_complex1d_image(const mln::Image<I>& input_) } -inline -void -println(const std::string& message, const mln::bin_1complex_image2d& ima, - const mln::box2d& support) -{ - using namespace mln; - - // These are admittedly loose preconditions, but we cannot check - // much anyway. - mln_precondition(ima.domain().nfaces_of_dim(0) == support.nsites()); - - image2d<bool> vertices(support); - image2d<bool> h_edges(box2d(support.pmin(), support.pmax() - dpoint2d(0, 1))); - image2d<bool> v_edges(box2d(support.pmin(), support.pmax() - dpoint2d(1, 0))); - - const unsigned dim = 1; - typedef geom::complex_geometry<dim, point2d> geom_t; - - // Iterator on vertices. - p_n_faces_fwd_piter<dim, geom_t> v(ima.domain(), 0); - for_all(v) - { - mln_site_(geom_t) s(v); - // Site S is point2d multi-site and should be a singleton (since V - // iterates on vertices). - mln_invariant(s.size() == 1); - point2d p = s.front(); - vertices(p) = ima(v); - } - - // Iterator on edges. - p_n_faces_fwd_piter<dim, geom_t> e(ima.domain(), 1); - for_all(e) - { - mln_site_(geom_t) s(e); - // Site S is point2d multi-site and should be a pair (since E - // iterates on vertices). - mln_invariant(s.size() == 2); - point2d p1 = s[0]; - point2d p2 = s[1]; - if (p1.row() == p2.row()) - { - // Horizontal edge. - h_edges(p1) = ima(e); - } - else - { - // Vertical edge. - mln_assertion(p1.col() == p2.col()); - v_edges(p1) = ima(e); - } - } - - std::cout << message << std::endl; - for (int row = vertices.domain().pmin().row(); - row <= vertices.domain().pmax().row(); ++row) - { - for (int col = vertices.domain().pmin().col(); - col <= vertices.domain().pmax().col(); ++col) - { - point2d p(row, col); - // Vertex. - std::cout << (vertices(p) ? "O" : "."); - // Potential horizontal edge on the right of the vertex. - if (col != vertices.domain().pmax().col()) - std::cout << (h_edges(p) ? " - " : " "); - } - std::cout << std::endl; - - // Potential vertical edge below the vertices of the current ROW. - if (row != vertices.domain().pmax().row()) - for (int col = vertices.domain().pmin().col(); - col <= vertices.domain().pmax().col(); ++col) - { - point2d p(row, col); - std::cout << (v_edges(p) ? "| " : " "); - } - std::cout << std::endl; - } -} - #endif // ! APPS_GRAPH_MORPHO_IO_HH diff --git a/milena/apps/graph-morpho/samples-complex1d.cc b/milena/apps/graph-morpho/samples-complex1d.cc index bc8f21b..0b32236 100644 --- a/milena/apps/graph-morpho/samples-complex1d.cc +++ b/milena/apps/graph-morpho/samples-complex1d.cc @@ -35,6 +35,8 @@ #include "apps/graph-morpho/morpho.hh" #include "apps/graph-morpho/io.hh" +#include "apps/graph-morpho/debug.hh" + #include "apps/data.hh" @@ -57,20 +59,19 @@ int main() paper from Jean Cousty et al. */ image2d<bool> x_pbm = io::pbm::load(MLN_APPS_DIR "/graph-morpho/x.pbm"); ima_t x = make_regular_complex1d_image(x_pbm); - box2d x_box(x_pbm.nrows() / 2 + 1, x_pbm.ncols() / 2 + 1); - println("x:", x, x_box); + ::debug::println_graph("x:", x); - println("dilation_e2v(x):", dilation_e2v(x), x_box); - println("erosion_v2e(x):", erosion_v2e(x), x_box); + ::debug::println_graph("dilation_e2v(x):", dilation_e2v(x)); + ::debug::println_graph("erosion_v2e(x):", erosion_v2e(x)); - println("erosion_e2v(x):", erosion_e2v(x), x_box); - println("dilation_v2e(x):", dilation_v2e(x), x_box); + ::debug::println_graph("erosion_e2v(x):", erosion_e2v(x)); + ::debug::println_graph("dilation_v2e(x):", dilation_v2e(x)); - println("dilation_graph(x):", dilation_graph(x), x_box); - println("erosion_graph(x):", erosion_graph(x), x_box); + ::debug::println_graph("dilation_graph(x):", dilation_graph(x)); + ::debug::println_graph("erosion_graph(x):", erosion_graph(x)); - println("alpha3(x):", alpha3(x), x_box); - println("beta3(x):", beta3(x), x_box); + ::debug::println_graph("alpha3(x):", alpha3(x)); + ::debug::println_graph("beta3(x):", beta3(x)); // --------- // // Filters. // @@ -79,20 +80,18 @@ int main() // Create an image corresponding to the graph Y. image2d<bool> y_pbm = io::pbm::load(MLN_APPS_DIR "/graph-morpho/y.pbm"); ima_t y = make_regular_complex1d_image(y_pbm); - box2d y_box(y_pbm.nrows() / 2 + 1, y_pbm.ncols() / 2 + 1); - println("y:", y, y_box); + ::debug::println_graph("y:", y); - println("opening_graph(y):", opening_graph(y), y_box); - println("half_opening_graph(y):", half_opening_graph(y), y_box); - println("beta3(alpha3(y)):", beta3(alpha3(y)), y_box); + ::debug::println_graph("opening_graph(y):", opening_graph(y)); + ::debug::println_graph("half_opening_graph(y):", half_opening_graph(y)); + ::debug::println_graph("beta3(alpha3(y)):", beta3(alpha3(y))); // Create an image corresponding to the graph Z. image2d<bool> z_pbm = io::pbm::load(MLN_APPS_DIR "/graph-morpho/z.pbm"); ima_t z = make_regular_complex1d_image(z_pbm); - box2d z_box(z_pbm.nrows() / 2 + 1, z_pbm.ncols() / 2 + 1); - println("z:", z, z_box); + ::debug::println_graph("z:", z); - println("closing_graph(z):", closing_graph(z), z_box); - println("half_closing_graph(z):", half_closing_graph(z), z_box); - println("alpha3(beta3(z)):", alpha3(beta3(z)), z_box); + ::debug::println_graph("closing_graph(z):", closing_graph(z)); + ::debug::println_graph("half_closing_graph(z):", half_closing_graph(z)); + ::debug::println_graph("alpha3(beta3(z)):", alpha3(beta3(z))); } diff --git a/milena/apps/graph-morpho/samples-image2d.cc b/milena/apps/graph-morpho/samples-image2d.cc index 455a147..76d5f7f 100644 --- a/milena/apps/graph-morpho/samples-image2d.cc +++ b/milena/apps/graph-morpho/samples-image2d.cc @@ -29,11 +29,11 @@ #include <mln/io/pbm/load.hh> -#include <mln/debug/println.hh> - #include "apps/graph-morpho/morpho.hh" #include "apps/graph-morpho/io.hh" +#include "apps/graph-morpho/debug.hh" + #include "apps/data.hh" @@ -58,19 +58,19 @@ int main() /* Create an image corresponding to the graph X of the ISMM 2009 paper from Jean Cousty et al. */ image2d<bool> x = io::pbm::load(MLN_APPS_DIR "/graph-morpho/x.pbm"); - debug::println("x:", x); + ::debug::println_graph("x:", x); - debug::println("dilation_e2v(x):", dilation_e2v(x)) ; - debug::println("erosion_v2e(x):", erosion_v2e(x)); + ::debug::println_graph("dilation_e2v(x):", dilation_e2v(x)) ; + ::debug::println_graph("erosion_v2e(x):", erosion_v2e(x)); - debug::println("erosion_e2v(x):", erosion_e2v(x)); - debug::println("dilation_v2e(x):", dilation_v2e(x)); + ::debug::println_graph("erosion_e2v(x):", erosion_e2v(x)); + ::debug::println_graph("dilation_v2e(x):", dilation_v2e(x)); - debug::println("dilation_graph(x):", dilation_graph(x)); - debug::println("erosion_graph(x):", erosion_graph(x)); + ::debug::println_graph("dilation_graph(x):", dilation_graph(x)); + ::debug::println_graph("erosion_graph(x):", erosion_graph(x)); - debug::println("alpha3(x):", alpha3(x)); - debug::println("beta3(x):", beta3(x)); + ::debug::println_graph("alpha3(x):", alpha3(x)); + ::debug::println_graph("beta3(x):", beta3(x)); // --------- // // Filters. // @@ -78,17 +78,17 @@ int main() // Create an image corresponding to the graph Y. image2d<bool> y = io::pbm::load(MLN_APPS_DIR "/graph-morpho/y.pbm"); - debug::println("y:", y); + ::debug::println_graph("y:", y); - debug::println("opening_graph(y):", opening_graph(y)); - debug::println("half_opening_graph(y):", half_opening_graph(y)); - debug::println("beta3(alpha3(y)):", beta3(alpha3(y))); + ::debug::println_graph("opening_graph(y):", opening_graph(y)); + ::debug::println_graph("half_opening_graph(y):", half_opening_graph(y)); + ::debug::println_graph("beta3(alpha3(y)):", beta3(alpha3(y))); // Create an image corresponding to the graph Z. image2d<bool> z = io::pbm::load(MLN_APPS_DIR "/graph-morpho/z.pbm"); - debug::println("z:", z); + ::debug::println_graph("z:", z); - debug::println("closing_graph(z):", closing_graph(z)); - debug::println("half_closing_graph(z):", half_closing_graph(z)); - debug::println("alpha3(beta3(z)):", alpha3(beta3(z))); + ::debug::println_graph("closing_graph(z):", closing_graph(z)); + ::debug::println_graph("half_closing_graph(z):", half_closing_graph(z)); + ::debug::println_graph("alpha3(beta3(z)):", alpha3(beta3(z))); } -- 1.6.3.1