3104: 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. --- 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@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@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
participants (1)
-
Roland Levillain