* 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(a)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(a)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