2850: Add a program adding curvature information to OFF files.

* apps/statues/mesh-curv.cc: New. * apps/statues/io.hh (write_faces_asc_float, write_off_float): New functions. * apps/statues/Makefile.am (bin_PROGRAMS): Add mesh-curv. (mesh_curv_SOURCES): New. --- milena/ChangeLog | 10 +++ milena/apps/statues/Makefile.am | 4 +- milena/apps/statues/io.hh | 48 ++++++++++++++ milena/apps/statues/mesh-curv.cc | 131 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 192 insertions(+), 1 deletions(-) create mode 100644 milena/apps/statues/mesh-curv.cc diff --git a/milena/ChangeLog b/milena/ChangeLog index a64a5a5..bd9bf01 100644 --- a/milena/ChangeLog +++ b/milena/ChangeLog @@ -1,5 +1,15 @@ 2008-11-12 Roland Levillain <roland@lrde.epita.fr> + Add a program adding curvature information to OFF files. + + * apps/statues/mesh-curv.cc: New. + * apps/statues/io.hh (write_faces_asc_float, write_off_float): + New functions. + * apps/statues/Makefile.am (bin_PROGRAMS): Add mesh-curv. + (mesh_curv_SOURCES): New. + +2008-11-12 Roland Levillain <roland@lrde.epita.fr> + Exercise mln::io::load on OFF file (with float data). * tests/io/off/load_float.cc: New test. diff --git a/milena/apps/statues/Makefile.am b/milena/apps/statues/Makefile.am index 00b3865..9b07a62 100644 --- a/milena/apps/statues/Makefile.am +++ b/milena/apps/statues/Makefile.am @@ -14,7 +14,9 @@ AM_LDFLAGS = $(GLFLAGS) LDADD = -L$(top_builddir)/external/trimesh/libsrc -ltrimesh $(GLLIBS) -bin_PROGRAMS = mesh-segm mesh-skel +bin_PROGRAMS = mesh-curv mesh-segm mesh-skel + +mesh_curv_SOURCES = mesh-curv.cc io.hh mesh_segm_SOURCES = mesh-segm.cc io.hh mesh_skel_SOURCES = mesh-skel.cc io.hh diff --git a/milena/apps/statues/io.hh b/milena/apps/statues/io.hh index 4f8fd5e..04ce871 100644 --- a/milena/apps/statues/io.hh +++ b/milena/apps/statues/io.hh @@ -35,6 +35,8 @@ #include <TriMesh.h> +#include <mln/value/rgb8.hh> + /// Taken from TriMesh_io.cc /// \{ @@ -83,6 +85,11 @@ inline void write_verts_asc(TriMesh *mesh, FILE *f, /// Taken and adapted from TriMesh_io.cc /// \{ + +/*----------------------. +| OFF with color data. | +`----------------------*/ + /// Write a bunch of faces to an ASCII file with colors. inline void write_faces_asc_colored(TriMesh *mesh, const std::vector<mln::value::rgb8>& colors, @@ -115,9 +122,50 @@ inline void write_off_colored(TriMesh *mesh, write_verts_asc(mesh, f, "", 0, 0, false, 0, ""); write_faces_asc_colored(mesh, colors, f, "3 ", ""); } + +/*----------------------. +| OFF with float data. | +`----------------------*/ + +/// Write a bunch of faces to an ASCII file with colors. +inline void write_faces_asc_float(TriMesh *mesh, + const std::vector<float>& values, + FILE *f, + const char *before_face, + const char *after_line) +{ + mesh->need_faces(); + for (int i = 0; i < mesh->faces.size(); i++) + { + // Vertices Color + // -------- ------------ + // V0 V1 V2 R G B A + fprintf(f, "%s%d %d %d %f %f %f 1.0%s\n", + before_face, + mesh->faces[i][0], mesh->faces[i][1], mesh->faces[i][2], + values[i], values[i], values[i], + after_line); + } +} + +/// Write an off file with floating-point values. +inline void write_off_float(TriMesh *mesh, const std::vector<float>& values, + FILE *f) +{ + fprintf(f, "OFF\n"); + mesh->need_faces(); + fprintf(f, "%lu %lu 0\n", (unsigned long) mesh->vertices.size(), + (unsigned long) mesh->faces.size()); + write_verts_asc(mesh, f, "", 0, 0, false, 0, ""); + write_faces_asc_float(mesh, values, f, "3 ", ""); +} /// \} +/*---------------------------------------. +| OFF without data (``binary values''). | +`---------------------------------------*/ + /// Taken and adapted from TriMesh_io.cc /// \{ /// Write a bunch of faces to an ASCII file, removing the ones tagged diff --git a/milena/apps/statues/mesh-curv.cc b/milena/apps/statues/mesh-curv.cc new file mode 100644 index 0000000..bba4d38 --- /dev/null +++ b/milena/apps/statues/mesh-curv.cc @@ -0,0 +1,131 @@ +// 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-curv.cc +/// \brief A program computing the mean curvature at each (2-)face of +/// a mesh. + +#include <cstdlib> +#include <cmath> + +#include <algorithm> +#include <vector> +#include <iostream> +#include <utility> + +#include <TriMesh.h> + +#include <mln/accu/min_max.hh> +#include <mln/fun/v2v/linear.hh> +#include <mln/math/abs.hh> + +#include "io.hh" + + +// Doesn't C++ have a better way to express Pi? +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; + exit(1); + } + + std::string input_filename = argv[1]; + std::string output_filename = argv[2]; + + + // TriMesh is a pain: it systematically allocates on the heap. + // Introduce another name to manipulate the mesh as a (non-pointer) + // object. + TriMesh* mesh_ptr = TriMesh::read(input_filename.c_str()); + if (!mesh_ptr) + exit(2); + TriMesh& mesh = *mesh_ptr; + + // Computes faces (triangles). + mesh.need_faces(); + // Computation of the mean curvature on each vertex of the mesh. + mesh.need_curvatures(); + std::vector<float> vertex_h_inv(mesh.vertices.size(), 0.f); + for (unsigned v = 0; v < mesh.vertices.size(); ++v) + { + float h = (mesh.curv1[v] + mesh.curv2[v]) / 2; + float h_inv = 1 / pi * atan(-h) + pi / 2; + vertex_h_inv[v] = h_inv; + } + // For each face of the mesh, computean an average curvature value + // from the mean curvature at its vertices. + std::vector<float> face_h_inv(mesh.faces.size(), 42.f); + mln::accu::min_max<float> acc; + for (unsigned f = 0; f < mesh.faces.size(); ++f) + { + float h_inv = (vertex_h_inv[mesh.faces[f][0]] + + vertex_h_inv[mesh.faces[f][1]] + + vertex_h_inv[mesh.faces[f][2]]) / 3; + face_h_inv[f] = h_inv; + acc.take(h_inv); + } + + /* Shrink the values of FACE_H_INV into the range 0..1, as these are + the only values accepted a an RGB floating-point component in the + OFF file format. */ + std::vector<float> normalized_face_h_inv(face_h_inv.size(), 0.0f); + 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; + // Don't normalize actually if the curvature is constants (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); + std::transform(face_h_inv.begin(), face_h_inv.end(), + normalized_face_h_inv.begin(), f); + } + + // Taken and adapted from TriMesh_io.cc + FILE* f_out = fopen(output_filename.c_str(), "wb"); + if (!f_out) + { + std::cerr << "Error opening " << output_filename.c_str() + << " for writing." << std::endl; + exit(2); + } + write_off_float(mesh_ptr, normalized_face_h_inv, f_out); + fclose(f_out); + + delete mesh_ptr; +} -- 1.6.0.1
participants (1)
-
Roland Levillain