* apps/statues/mesh-complex-max-curv.cc: New.
* test-mesh-complex-max-curv.in: New test.
* apps/statues/Makefile.am (bin_PROGRAMS): Add
mesh-complex-max-curv.
(mesh_complex_max_curv_SOURCES): New.
---
milena/ChangeLog | 10 ++
milena/apps/statues/Makefile.am | 18 ++-
milena/apps/statues/mesh-complex-max-curv.cc | 165 +++++++++++++++++++++
milena/apps/statues/test-mesh-complex-max-curv.in | 7 +
4 files changed, 197 insertions(+), 3 deletions(-)
create mode 100644 milena/apps/statues/mesh-complex-max-curv.cc
create mode 100644 milena/apps/statues/test-mesh-complex-max-curv.in
diff --git a/milena/ChangeLog b/milena/ChangeLog
index f08a8d9..02fe7c1 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,15 @@
2008-12-30 Roland Levillain <roland(a)lrde.epita.fr>
+ Exercise the curvature computation routines ported from Trimesh.
+
+ * apps/statues/mesh-complex-max-curv.cc: New.
+ * test-mesh-complex-max-curv.in: New test.
+ * apps/statues/Makefile.am (bin_PROGRAMS): Add
+ mesh-complex-max-curv.
+ (mesh_complex_max_curv_SOURCES): New.
+
+2008-12-30 Roland Levillain <roland(a)lrde.epita.fr>
+
Port Trimesh's curvature computation routines to Milena.
* apps/statues/trimesh/: New directory.
diff --git a/milena/apps/statues/Makefile.am b/milena/apps/statues/Makefile.am
index 8dd7199..d493628 100644
--- a/milena/apps/statues/Makefile.am
+++ b/milena/apps/statues/Makefile.am
@@ -21,6 +21,11 @@ LDADD_trimesh = -L$(top_builddir)/external/trimesh/libsrc -ltrimesh
$(GLLIBS)
# FIXME: Have program names embed the type of structure used (either
# graph or complex).
+bin_PROGRAMS =
+TESTS =
+
+## FIXME: Programs' names should reflect a dependency on Trimesh, if any.
+
## ------------------------------------------------ ##
## Graph-based applications, depending on Trimesh. ##
## ------------------------------------------------ ##
@@ -31,6 +36,8 @@ LDADD_trimesh = -L$(top_builddir)/external/trimesh/libsrc -ltrimesh
$(GLLIBS)
# mesh_segm_CPPFLAGS = $(AM_CPPFLAGS) $(CPPFLAGS_trimesh)
# mesh_segm_LDFLAGS = $(LDFLAGS_trimesh)
# mesh_segm_LDADD = $(LDADD_trimesh)
+#
+# TESTS += test-mesh-segm
# mesh_skel_SOURCES = mesh-skel.cc io.hh
# mesh_skel_CPPFLAGS = $(AM_CPPFLAGS) $(CPPFLAGS_trimesh)
@@ -60,8 +67,13 @@ mesh_max_curv_LDADD = $(LDADD_trimesh)
noinst_HEADERS = trimesh/misc.hh
EXTRA_DIST = trimesh/README
+# A small test exercising the curvature computation routines ported
+# from Trimesh to Milena.
+bin_PROGRAMS += mesh-complex-max-curv
+mesh_complex_max_curv_SOURCES = mesh-complex-max-curv.cc
+TESTS += test-mesh-complex-max-curv
+
+# Segmentation program working on precomputed meshes with curvatures data.
bin_PROGRAMS += mesh-complex-segm
mesh_complex_segm_SOURCES = mesh-complex-segm.cc
-
-
-TESTS = test-mesh-segm test-mesh-complex-segm
+TESTS += test-mesh-complex-segm
diff --git a/milena/apps/statues/mesh-complex-max-curv.cc
b/milena/apps/statues/mesh-complex-max-curv.cc
new file mode 100644
index 0000000..0a75da5
--- /dev/null
+++ b/milena/apps/statues/mesh-complex-max-curv.cc
@@ -0,0 +1,165 @@
+// 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.
+
+/// \file apps/statues/mesh-complex-max-curv.cc
+/// \brief A program computing the max curvature at each (2-)face of
+/// the surface of the (triangle) mesh of a statue, using a
+/// complex-based image.
+
+#include <cstdlib>
+#include <cmath>
+
+#include <utility>
+#include <iostream>
+
+#include <mln/core/image/complex_image.hh>
+#include <mln/core/image/complex_neighborhoods.hh>
+
+#include <mln/morpho/closing_area.hh>
+#include <mln/morpho/meyer_wst.hh>
+
+#include <mln/level/fill.hh>
+#include <mln/literal/zero.hh>
+
+#include <mln/math/max.hh>
+#include <mln/math/sqr.hh>
+#include <mln/accu/min_max.hh>
+#include <mln/fun/v2v/linear.hh>
+#include <mln/level/transform.hh>
+
+#include <mln/literal/white.hh>
+
+#include <mln/io/off/load.hh>
+#include <mln/io/off/save.hh>
+
+#include "trimesh/misc.hh"
+
+
+// Doesn't C++ have a better way to express Pi?
+static const float pi = 4 * atanf(1);
+
+
+int main(int argc, char* argv[])
+{
+ if (argc != 3)
+ {
+ std::cerr << "usage: " << argv[0] << " input.off
output.off"
+ << std::endl;
+ std::exit(1);
+ }
+
+ std::string input_filename = argv[1];
+ std::string output_filename = argv[2];
+
+ /*----------------.
+ | Complex image. |
+ `----------------*/
+
+ // Image type.
+ typedef mln::float_2complex_image3df ima_t;
+ // Dimension of the image (and therefore of the complex).
+ static const unsigned D = ima_t::dim;
+ // Geometry of the image.
+ typedef mln_geom_(ima_t) G;
+
+ mln::bin_2complex_image3df input;
+ mln::io::off::load(input, input_filename);
+
+// // ------------------------------------------------------------
+// // FIXME: TEST.
+// mln::complex_image< 2, mln::space_2complex_geometry, mln::algebra::vec<3,
float> >
+// normal = mesh_normal(input.domain());
+// mln::p_n_faces_fwd_piter<D, G> v_(normal.domain(), 0);
+// for_all(v_)
+// std::cout << normal(v_) << std::endl;
+// std::exit(0);
+// // ------------------------------------------------------------
+
+ std::pair<ima_t, ima_t> curv = mln::geom::mesh_curvature(input.domain());
+
+ // Compute the max curvature at each vertex.
+ ima_t max_curv(input.domain());
+ mln::level::fill(max_curv, mln::literal::zero);
+ mln::p_n_faces_fwd_piter<D, G> v(max_curv.domain(), 0);
+ for_all(v)
+ max_curv(v) = mln::math::max(mln::math::sqr(curv.first(v)),
+ mln::math::sqr(curv.second(v)));
+
+ // Propagate these values on triangles.
+ mln::p_n_faces_fwd_piter<D, G> t(max_curv.domain(), 2);
+ typedef mln::complex_m_face_neighborhood<D, G> adj_vertices_nbh_t;
+ adj_vertices_nbh_t adj_vertices_nbh;
+ mln_niter_(adj_vertices_nbh_t) adj_v(adj_vertices_nbh, t);
+ /* FIXME: Not really user friendly! The `m' value should pass at
+ the construction of ADJ_V. */
+ adj_v.iter().set_m(0);
+ mln::accu::min_max<float> acc;
+ // Iterate on triangles (2-faces).
+ for_all(t)
+ {
+ float s = 0.0f;
+ unsigned n = 0;
+ // Iterate on vertices (0-faces).
+ for_all(adj_v)
+ {
+ s += max_curv(adj_v);
+ ++n;
+ }
+ float m = s / n;
+ max_curv(t) = m;
+ acc.take(m);
+ // A triangle should be adjacent to exactly three vertices.
+ mln_invariant(n <= 3);
+ }
+
+ // Normalize values between 0 and 1.
+ /* Shrink the values of FACE_M into the range 0..1, as these are
+ the only values accepted a an RGB floating-point component in the
+ OFF file format. */
+ ima_t output(max_curv.domain());
+ mln::level::fill(output, mln::literal::zero);
+ std::pair<float, float> min_max(acc);
+ // FIXME: Taken from mln/level/stretch.hh (this should be factored).
+ float min = min_max.first;
+ float max = min_max.second;
+ std::cout << min << std::endl;
+ std::cout << max << std::endl;
+ // Don't normalize actually if the curvature is constant (i.e.,
+ // if min == max).
+ if (min != max)
+ {
+ float m = 0.0f;
+ float M = 1.0f;
+ float a = (M - m) / (max - min);
+ float b = (m * max - M * min) / (max - min);
+ mln::fun::v2v::linear<float, float, float> f(a, b);
+ output = mln::level::transform(max_curv, f);
+ }
+
+ // Output.
+ mln::io::off::save(output, output_filename);
+}
diff --git a/milena/apps/statues/test-mesh-complex-max-curv.in
b/milena/apps/statues/test-mesh-complex-max-curv.in
new file mode 100644
index 0000000..e138a12
--- /dev/null
+++ b/milena/apps/statues/test-mesh-complex-max-curv.in
@@ -0,0 +1,7 @@
+#! /bin/sh
+
+set -ex
+
+mesh_dir=@top_srcdir@/milena/mesh
+
+time ./mesh-complex-max-curv $mesh_dir/teapot.off teapot-complex-max-curv.off
--
1.6.0.4