* apps/papers/levillain.09.ismm/graph.cc: Misc. changes.
(mln::influence_zones)
(mln::io::neato::save):
Move functions...
* apps/papers/levillain.09.ismm/influence_zones.hh,
* apps/papers/levillain.09.ismm/io.hh:
...here (new files).
* apps/papers/levillain.09.ismm/Makefile.am (noinst_HEADERS):
Add io.hh and influence_zones.hh
---
milena/ChangeLog | 14 +
milena/apps/papers/levillain.09.ismm/Makefile.am | 7 +-
milena/apps/papers/levillain.09.ismm/graph.cc | 259 +-------------------
.../papers/levillain.09.ismm/influence_zones.hh} | 85 ++++----
milena/apps/papers/levillain.09.ismm/io.hh | 242 ++++++++++++++++++
5 files changed, 315 insertions(+), 292 deletions(-)
copy milena/{mln/literal/black.hh => apps/papers/levillain.09.ismm/influence_zones.hh}
(55%)
create mode 100644 milena/apps/papers/levillain.09.ismm/io.hh
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 544cc30..d79c220 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,19 @@
2011-10-04 Roland Levillain <roland(a)lrde.epita.fr>
+ Split apps/papers/levillain.09.ismm/graph.cc.
+
+ * apps/papers/levillain.09.ismm/graph.cc: Misc. changes.
+ (mln::influence_zones)
+ (mln::io::neato::save):
+ Move functions...
+ * apps/papers/levillain.09.ismm/influence_zones.hh,
+ * apps/papers/levillain.09.ismm/io.hh:
+ ...here (new files).
+ * apps/papers/levillain.09.ismm/Makefile.am (noinst_HEADERS):
+ Add io.hh and influence_zones.hh
+
+2011-10-04 Roland Levillain <roland(a)lrde.epita.fr>
+
Handle the case of filling an empty border.
* mln/border/fill.hh (mln::border::impl::fill_size_1): Here.
diff --git a/milena/apps/papers/levillain.09.ismm/Makefile.am
b/milena/apps/papers/levillain.09.ismm/Makefile.am
index ec5d328..ac583f8 100644
--- a/milena/apps/papers/levillain.09.ismm/Makefile.am
+++ b/milena/apps/papers/levillain.09.ismm/Makefile.am
@@ -1,4 +1,5 @@
-# Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE).
+# Copyright (C) 2008, 2009, 2011 EPITA Research and Development
+# Laboratory (LRDE).
#
# This file is part of Olena.
#
@@ -22,7 +23,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/milena -I$(top_builddir)/milena
APPS_CXXFLAGS = @APPS_CXXFLAGS@
AM_CXXFLAGS = $(APPS_CXXFLAGS)
-noinst_HEADERS = chain.hh
+noinst_HEADERS = chain.hh io.hh influence_zones.hh
noinst_PROGRAMS = image2d graph complex
image2d_SOURCES = image2d.cc
@@ -37,6 +38,8 @@ dist_noinst_DATA = seeds.pgm m283-c.off
noinst_DATA = lena-s.ppm graph-s.png m283-s.off
MOSTLYCLEANFILES = $(noinst_DATA) graph-s.neato
+# FIXME: Also generate intermediate images (gradients, etc.).
+
lena-s.ppm: $(top_srcdir)/milena/img/lena.pgm image2d$(EXEEXT)
./image2d$(EXEEXT) $< 1000 $@
diff --git a/milena/apps/papers/levillain.09.ismm/graph.cc
b/milena/apps/papers/levillain.09.ismm/graph.cc
index bd6f983..714037d 100644
--- a/milena/apps/papers/levillain.09.ismm/graph.cc
+++ b/milena/apps/papers/levillain.09.ismm/graph.cc
@@ -24,16 +24,16 @@
// executable file might be covered by the GNU General Public License.
#include <iostream>
-#include <iomanip>
#include <vector>
#include <mln/core/image/image2d.hh>
-#include <mln/core/routine/duplicate.hh>
#include <mln/core/alias/neighb2d.hh>
-#include <mln/core/site_set/p_queue_fast.hh>
+
#include <mln/labeling/blobs.hh>
#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/data/stretch.hh>
#include <mln/debug/println.hh>
#include <mln/draw/line.hh>
#include <mln/pw/all.hh>
@@ -57,251 +57,11 @@
#include <mln/morpho/gradient.hh>
#include <mln/labeling/colorize.hh>
+#include "io.hh"
+#include "influence_zones.hh"
#include "chain.hh"
-// FIXME: Copied and adjusted from pics/graph.cc; factor.
-
-namespace mln
-{
-
- template <typename I, typename N>
- mln_concrete(I)
- influence_zones(const I& input, const N& nbh)
- {
- mln_concrete(I) output = duplicate(input);
-
- p_queue_fast<mln_site(I)> q;
-
- {
- // Initialization.
- mln_piter(I) p(input.domain());
- mln_niter(N) n(nbh, p);
- for_all(p)
- if (input(p) != 0)
- for_all(n) if (input.has(n))
- if (input(n) == 0)
- {
- q.push(p);
- break;
- }
- }
- {
- // Body.
- mln_site(I) p;
- mln_niter(N) n(nbh, p);
- while (! q.is_empty())
- {
- p = q.pop_front();
- mln_invariant(output(p) != 0);
- for_all(n) if (input.has(n))
- if (output(n) == 0)
- {
- output(n) = output(p);
- q.push(n);
- }
- }
- }
-
- return output;
-
- }
-
-
- namespace io
- {
-
- namespace neato
- {
-
- /* FIXME: This is just the gray-level version. Handle other value
- types as well. */
- void
- save(const complex_image<1, discrete_plane_1complex_geometry,
- value::int_u8>& ima,
- const std::string& filename,
- const std::string& bgcolor = "#0000C0",
- const std::string& fontcolor = "#0000C0",
- bool empty_vertex_label = true)
- {
- typedef value::int_u8 V;
- typedef complex_image<1, discrete_plane_1complex_geometry, V> I;
- const unsigned D = 1;
- typedef discrete_plane_1complex_geometry G;
-
- std::ofstream g(filename.c_str());
- g << "graph wst" << std::endl
- << "{" << std::endl
- << " graph [bgcolor = \"" << bgcolor <<
"\"]" << std::endl
- << " edge [color = \"#FFFFFF\"]" << std::endl
- << " node [color = \"#FFFFFF\", height=\"5\",
width=\"5\","
- << " fontsize=\"100\", fontcolor = \"" <<
fontcolor << "\"]"
- << std::endl;
-
- // Vertices.
- p_n_faces_fwd_piter<D, G> v(ima.domain(), 0);
- typedef complex_higher_neighborhood<D, G> e_nbh_t;
- e_nbh_t e_nbh;
- for_all(v)
- {
- V vertex_color = ima(v);
- std::ostringstream vertex_color_str;
- // FIXME: Only valid for gray-level images.
- vertex_color_str << '#'
- << std::hex
- << std::setfill('0')
- << std::setw(2) << vertex_color
- << std::setw(2) << vertex_color
- << std::setw(2) << vertex_color
- << std::dec;
-
- g << " v" << v.unproxy_().face_id()
- << " [pos = \""
- << std::fixed << std::setprecision(1)
- << (float)v.to_site().front()[1] << ", "
- << -(float)v.to_site().front()[0]
- << "\", color = \"" << vertex_color_str.str()
- << "\", fillcolor = \"" << vertex_color_str.str()
- << "\", pin = \"true\",
style=\"filled,setlinewidth(3)\"";
- if (empty_vertex_label)
- g << ", label = \"\"";
- g << "];"
- << std::endl;
- }
-
- // Edges.
- p_n_faces_fwd_piter<D, G> e(ima.domain(), 1);
- typedef complex_lower_neighborhood<D, G> v_nbh_t;
- v_nbh_t v_nbh;
- mln_niter_(v_nbh_t) adj_v(v_nbh, e);
- for_all(e)
- {
- V edge_color = ima(e);
- std::ostringstream edge_color_str;
- edge_color_str << '#'
- << std::hex
- << std::setfill('0')
- << std::setw(2) << edge_color
- << std::setw(2) << edge_color
- << std::setw(2) << edge_color
- << std::dec;
-
- // Adjacent vertices.
- adj_v.start();
- topo::face<1> v1 = adj_v.unproxy_().face();
- point2d p1 = adj_v.to_site().front();
- adj_v.next();
- topo::face<1> v2 = adj_v.unproxy_().face();
- point2d p2 = adj_v.to_site().front();
- adj_v.next();
- mln_invariant(!adj_v.is_valid());
-
- g << " v" << v1.face_id() << " -- v" <<
v2.face_id() << " ";
- g << "[color = \"" << edge_color_str.str()
- << "\", style=\"setlinewidth(10)\"];" <<
std::endl;
- }
-
- g << "}" << std::endl;
- g.close();
- }
-
- // FIXME: Factor with the previous version.
- void
- save(const complex_image<1, discrete_plane_1complex_geometry,
- value::rgb8>& ima,
- const std::string& filename,
- const std::string& bgcolor = "#0000C0",
- const std::string& fontcolor = "#0000C0",
- bool empty_vertex_label = true)
- {
- typedef value::rgb8 V;
- typedef complex_image<1, discrete_plane_1complex_geometry, V> I;
- const unsigned D = 1;
- typedef discrete_plane_1complex_geometry G;
-
- std::ofstream g(filename.c_str());
- g << "graph wst" << std::endl
- << "{" << std::endl
- << " graph [bgcolor = \"" << bgcolor <<
"\"]" << std::endl
- << " edge [color = \"#FFFFFF\"]" << std::endl
- << " node [color = \"#FFFFFF\", height=\"5\",
width=\"5\","
- << " fontsize=\"100\", fontcolor = \"" <<
fontcolor << "\"]"
- << std::endl;
-
- // Vertices.
- p_n_faces_fwd_piter<D, G> v(ima.domain(), 0);
- typedef complex_higher_neighborhood<D, G> e_nbh_t;
- e_nbh_t e_nbh;
- for_all(v)
- {
- V vertex_color = ima(v);
- std::ostringstream vertex_color_str;
- // FIXME: Only valid for gray-level images.
- vertex_color_str << '#'
- << std::hex
- << std::setfill('0')
- << std::setw(2) << vertex_color.red()
- << std::setw(2) << vertex_color.green()
- << std::setw(2) << vertex_color.blue()
- << std::dec;
-
- g << " v" << v.unproxy_().face_id()
- << " [pos = \""
- << std::fixed << std::setprecision(1)
- << (float)v.to_site().front()[1] << ", "
- << -(float)v.to_site().front()[0]
- << "\", color = \"" << vertex_color_str.str()
- << "\", fillcolor = \"" << vertex_color_str.str()
- << "\", pin = \"true\",
style=\"filled,setlinewidth(3)\"";
- if (empty_vertex_label)
- g << ", label = \"\"";
- g << "];"
- << std::endl;
- }
-
- // Edges.
- p_n_faces_fwd_piter<D, G> e(ima.domain(), 1);
- typedef complex_lower_neighborhood<D, G> v_nbh_t;
- v_nbh_t v_nbh;
- mln_niter_(v_nbh_t) adj_v(v_nbh, e);
- for_all(e)
- {
- V edge_color = ima(e);
- std::ostringstream edge_color_str;
- edge_color_str << '#'
- << std::hex
- << std::setfill('0')
- << std::setw(2) << edge_color.red()
- << std::setw(2) << edge_color.green()
- << std::setw(2) << edge_color.blue()
- << std::dec;
-
- // Adjacent vertices.
- adj_v.start();
- topo::face<1> v1 = adj_v.unproxy_().face();
- point2d p1 = adj_v.to_site().front();
- adj_v.next();
- topo::face<1> v2 = adj_v.unproxy_().face();
- point2d p2 = adj_v.to_site().front();
- adj_v.next();
- mln_invariant(!adj_v.is_valid());
-
- g << " v" << v1.face_id() << " -- v" <<
v2.face_id() << " ";
- g << "[color = \"" << edge_color_str.str()
- << "\", style=\"setlinewidth(10)\"];" <<
std::endl;
- }
-
- g << "}" << std::endl;
- g.close();
- }
-
- } // end of namespace mln::io::neato
-
- } // end of namespace mln::io
-
-} // end of namespace mln
-
-
// FIXME: Clean up and move into Milena?
mln::int_u8_1complex_image2d
make_complex_image(const mln::image2d<mln::value::int_u8>& input)
@@ -331,6 +91,9 @@ make_complex_image(const mln::image2d<mln::value::int_u8>&
input)
data::paste(iz, IZ);
}
+#if 0
+ io::pgm::save (data::stretch(mln::value::int_u8(), iz), "iz.pgm");
+#endif
// Make graph/complex.
@@ -480,14 +243,16 @@ int main(int argc, char* argv[])
// Input image computed from the graph of influence zones (IZ) of seeds.
typedef int_u8_graph_image2d ima_t;
ima_t ima = make_complex_image(seeds);
- io::neato::save(ima, "apps/graph.neato");
+#if 0
+ io::neato::save(ima, "graph.neato");
+#endif
// Gradient.
input g = morpho::gradient(ima, make_elt_win(ima));
#if 0
// FIXME: get the name as argument.
- io::neato::save(g, "apps/graph-g.neato");
+ io::neato::save(g, "graph-g.neato");
#endif
// Chain.
diff --git a/milena/mln/literal/black.hh
b/milena/apps/papers/levillain.09.ismm/influence_zones.hh
similarity index 55%
copy from milena/mln/literal/black.hh
copy to milena/apps/papers/levillain.09.ismm/influence_zones.hh
index ab05cae..353b16e 100644
--- a/milena/mln/literal/black.hh
+++ b/milena/apps/papers/levillain.09.ismm/influence_zones.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2007, 2008, 2009 EPITA Research and Development
+// Copyright (C) 2008, 2009, 2011 EPITA Research and Development
// Laboratory (LRDE)
//
// This file is part of Olena.
@@ -24,62 +24,61 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#ifndef MLN_LITERAL_BLACK_HH
-# define MLN_LITERAL_BLACK_HH
-
/// \file
-/// \brief Definition of the 'black' literal.
+/// \brief Computation of the influence zones of the objects of an
+/// image.
+
+// FIXME: Refactor and move into the library.
-# include <mln/core/concept/literal.hh>
+#include <mln/core/routine/duplicate.hh>
+
+#include <mln/core/site_set/p_queue_fast.hh>
namespace mln
{
- namespace literal
+ // FIXME: Add Image and Neighborhood concept constraints.
+ template <typename I, typename N>
+ inline
+ mln_concrete(I)
+ influence_zones(const I& input, const N& nbh)
{
+ mln_concrete(I) output = duplicate(input);
- /// Type of literal black.
- struct black_t : public Literal<black_t>
- {
-# ifdef MLN_NEW_VALUE_TYPES
- operator float() const;
- operator double() const;
-# endif // MLN_NEW_VALUE_TYPES
- };
-
-
- /// Literal black.
- extern const black_t& black;
-
-
-# ifndef MLN_INCLUDE_ONLY
+ p_queue_fast<mln_site(I)> q;
-# ifndef MLN_WO_GLOBAL_VARS
-
- const black_t& black = black_t();
-
-# endif
-
-# ifdef MLN_NEW_VALUE_TYPES
- inline
- black_t::operator float() const
{
- return 0.f;
+ // Initialization.
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ if (input(p) != 0)
+ for_all(n) if (input.has(n))
+ if (input(n) == 0)
+ {
+ q.push(p);
+ break;
+ }
}
-
- inline
- black_t::operator double() const
{
- return 0.;
+ // Body.
+ mln_site(I) p;
+ mln_niter(N) n(nbh, p);
+ while (! q.is_empty())
+ {
+ p = q.pop_front();
+ mln_invariant(output(p) != 0);
+ for_all(n) if (input.has(n))
+ if (output(n) == 0)
+ {
+ output(n) = output(p);
+ q.push(n);
+ }
+ }
}
-# endif // MLN_NEW_VALUE_TYPES
-# endif // ! MLN_INCLUDE_ONLY
-
- } // end of namespace mln::literal
+ return output;
+ }
} // end of namespace mln
-
-
-#endif // ! MLN_LITERAL_BLACK_HH
diff --git a/milena/apps/papers/levillain.09.ismm/io.hh
b/milena/apps/papers/levillain.09.ismm/io.hh
new file mode 100644
index 0000000..d39aae6
--- /dev/null
+++ b/milena/apps/papers/levillain.09.ismm/io.hh
@@ -0,0 +1,242 @@
+// Copyright (C) 2008, 2009, 2011 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.
+
+/// \file
+/// \brief Some neato (Graphviz) I/O routines.
+
+// FIXME: Refactor and move into the library.
+
+#include <fstream>
+#include <sstream>
+#include <iomanip>
+
+#include <string>
+
+#include <mln/core/image/complex_image.hh>
+#include <mln/core/alias/complex_geometry.hh>
+
+#include <mln/core/image/complex_neighborhoods.hh>
+#include <mln/core/image/complex_neighborhood_piter.hh>
+
+#include <mln/value/int_u8.hh>
+
+
+namespace mln
+{
+
+ namespace io
+ {
+
+ namespace neato
+ {
+
+ /* FIXME: This is just the gray-level version. Handle other value
+ types as well. */
+ // FIXME: Use an alias instead of the long type name.
+ void
+ save(const complex_image<1, discrete_plane_1complex_geometry,
+ value::int_u8>& ima,
+ const std::string& filename,
+ const std::string& bgcolor = "#0000C0",
+ const std::string& fontcolor = "#0000C0",
+ bool empty_vertex_label = true)
+ {
+ typedef value::int_u8 V;
+ typedef complex_image<1, discrete_plane_1complex_geometry, V> I;
+ const unsigned D = 1;
+ typedef discrete_plane_1complex_geometry G;
+
+ std::ofstream g(filename.c_str());
+ g << "graph wst" << std::endl
+ << "{" << std::endl
+ << " graph [bgcolor = \"" << bgcolor <<
"\"]" << std::endl
+ << " edge [color = \"#FFFFFF\"]" << std::endl
+ << " node [color = \"#FFFFFF\", height=\"5\",
width=\"5\","
+ << " fontsize=\"100\", fontcolor = \"" <<
fontcolor << "\"]"
+ << std::endl;
+
+ // Vertices.
+ p_n_faces_fwd_piter<D, G> v(ima.domain(), 0);
+ typedef complex_higher_neighborhood<D, G> e_nbh_t;
+ e_nbh_t e_nbh;
+ for_all(v)
+ {
+ V vertex_color = ima(v);
+ std::ostringstream vertex_color_str;
+ // FIXME: Only valid for gray-level images.
+ vertex_color_str << '#'
+ << std::hex
+ << std::setfill('0')
+ << std::setw(2) << vertex_color
+ << std::setw(2) << vertex_color
+ << std::setw(2) << vertex_color
+ << std::dec;
+
+ g << " v" << v.unproxy_().face_id()
+ << " [pos = \""
+ << std::fixed << std::setprecision(1)
+ << (float)v.to_site().front()[1] << ", "
+ << -(float)v.to_site().front()[0]
+ << "\", color = \"" << vertex_color_str.str()
+ << "\", fillcolor = \"" << vertex_color_str.str()
+ << "\", pin = \"true\",
style=\"filled,setlinewidth(3)\"";
+ if (empty_vertex_label)
+ g << ", label = \"\"";
+ g << "];"
+ << std::endl;
+ }
+
+ // Edges.
+ p_n_faces_fwd_piter<D, G> e(ima.domain(), 1);
+ typedef complex_lower_neighborhood<D, G> v_nbh_t;
+ v_nbh_t v_nbh;
+ mln_niter_(v_nbh_t) adj_v(v_nbh, e);
+ for_all(e)
+ {
+ V edge_color = ima(e);
+ std::ostringstream edge_color_str;
+ edge_color_str << '#'
+ << std::hex
+ << std::setfill('0')
+ << std::setw(2) << edge_color
+ << std::setw(2) << edge_color
+ << std::setw(2) << edge_color
+ << std::dec;
+
+ // Adjacent vertices.
+ adj_v.start();
+ topo::face<1> v1 = adj_v.unproxy_().face();
+ point2d p1 = adj_v.to_site().front();
+ adj_v.next();
+ topo::face<1> v2 = adj_v.unproxy_().face();
+ point2d p2 = adj_v.to_site().front();
+ adj_v.next();
+ mln_invariant(!adj_v.is_valid());
+
+ g << " v" << v1.face_id() << " -- v" <<
v2.face_id() << " ";
+ g << "[color = \"" << edge_color_str.str()
+ << "\", style=\"setlinewidth(10)\"];" <<
std::endl;
+ }
+
+ g << "}" << std::endl;
+ g.close();
+ }
+
+ // FIXME: Factor with the previous version.
+ void
+ save(const complex_image<1, discrete_plane_1complex_geometry,
+ value::rgb8>& ima,
+ const std::string& filename,
+ const std::string& bgcolor = "#0000C0",
+ const std::string& fontcolor = "#0000C0",
+ bool empty_vertex_label = true)
+ {
+ typedef value::rgb8 V;
+ typedef complex_image<1, discrete_plane_1complex_geometry, V> I;
+ const unsigned D = 1;
+ typedef discrete_plane_1complex_geometry G;
+
+ std::ofstream g(filename.c_str());
+ g << "graph wst" << std::endl
+ << "{" << std::endl
+ << " graph [bgcolor = \"" << bgcolor <<
"\"]" << std::endl
+ << " edge [color = \"#FFFFFF\"]" << std::endl
+ << " node [color = \"#FFFFFF\", height=\"5\",
width=\"5\","
+ << " fontsize=\"100\", fontcolor = \"" <<
fontcolor << "\"]"
+ << std::endl;
+
+ // Vertices.
+ p_n_faces_fwd_piter<D, G> v(ima.domain(), 0);
+ typedef complex_higher_neighborhood<D, G> e_nbh_t;
+ e_nbh_t e_nbh;
+ for_all(v)
+ {
+ V vertex_color = ima(v);
+ std::ostringstream vertex_color_str;
+ // FIXME: Only valid for gray-level images.
+ vertex_color_str << '#'
+ << std::hex
+ << std::setfill('0')
+ << std::setw(2) << vertex_color.red()
+ << std::setw(2) << vertex_color.green()
+ << std::setw(2) << vertex_color.blue()
+ << std::dec;
+
+ g << " v" << v.unproxy_().face_id()
+ << " [pos = \""
+ << std::fixed << std::setprecision(1)
+ << (float)v.to_site().front()[1] << ", "
+ << -(float)v.to_site().front()[0]
+ << "\", color = \"" << vertex_color_str.str()
+ << "\", fillcolor = \"" << vertex_color_str.str()
+ << "\", pin = \"true\",
style=\"filled,setlinewidth(3)\"";
+ if (empty_vertex_label)
+ g << ", label = \"\"";
+ g << "];"
+ << std::endl;
+ }
+
+ // Edges.
+ p_n_faces_fwd_piter<D, G> e(ima.domain(), 1);
+ typedef complex_lower_neighborhood<D, G> v_nbh_t;
+ v_nbh_t v_nbh;
+ mln_niter_(v_nbh_t) adj_v(v_nbh, e);
+ for_all(e)
+ {
+ V edge_color = ima(e);
+ std::ostringstream edge_color_str;
+ edge_color_str << '#'
+ << std::hex
+ << std::setfill('0')
+ << std::setw(2) << edge_color.red()
+ << std::setw(2) << edge_color.green()
+ << std::setw(2) << edge_color.blue()
+ << std::dec;
+
+ // Adjacent vertices.
+ adj_v.start();
+ topo::face<1> v1 = adj_v.unproxy_().face();
+ point2d p1 = adj_v.to_site().front();
+ adj_v.next();
+ topo::face<1> v2 = adj_v.unproxy_().face();
+ point2d p2 = adj_v.to_site().front();
+ adj_v.next();
+ mln_invariant(!adj_v.is_valid());
+
+ g << " v" << v1.face_id() << " -- v" <<
v2.face_id() << " ";
+ g << "[color = \"" << edge_color_str.str()
+ << "\", style=\"setlinewidth(10)\"];" <<
std::endl;
+ }
+
+ g << "}" << std::endl;
+ g.close();
+ }
+
+ } // end of namespace mln::io::neato
+
+ } // end of namespace mln::io
+
+} // end of namespace mln
--
1.7.2.5