/* -*- mona-c++ -*-
* Copyright (c) Leipzig, Madrid 2004 - 2008
* Max-Planck-Institute for Human Cognitive and Brain Science
* Max-Planck-Institute for Evolutionary Anthropology
* BIT, ETSI Telecomunicacion, UPM
*
* This program 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; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
// $Id: meshstats.cc 938 2006-07-11 11:57:01Z write1 $
/*! \brief mona-meshstats -- computes surface area and enclosed volume of a (closed) mesh
\par Description
\b mona-meshstats expects a surface mesh on input (\c --in-file)
and computes the surface area and its enclosed volume,
which are printed as ascii on output (\c --out-file).
Note, the mesh should contain an enclosed manifold.
\par Usage
<code>mona-meshstats --usage</code> (or <code>mona-meshstats --help</code>)
\param --in-file input image holding the mesh
\param --out-file acii output of the area and volume
\param --verbose give some verbose information
(e.g., Euler number)
\par Examples
-# Output the statistics of a VISTA mesh
\code
user> mona-meshstats -i mesh.v -o stats.dat
\endcode
Note, the mesh format can be anything covered by the io plugins included in \a libmona.
-# Ditto, but being used in a pipe, printing to stdout and outputs some verbose informations
\code
user> ... | mona-meshstats -i - -o - -v | ...
\endcode
\par Known bugs
If the mesh doesnt't contain a closed manifold, the program results
with strange values.
\todo Include checking for manifold closure (gtscheck like)
\sa meshconvert.cc
\file meshstats.cc
\author Gert Wollny & M. Tittgemeyer, tittge@cbs.mpg.de, 2004
*/
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <fstream>
#include <string>
#include <algorithm>
// MONA specific
#include <mona.hh>
using namespace std;
using namespace mona;
/*! \brief Fuctor to compute volume and surface area of a mesh
The functor class is initialised by a mesh.
The class is derived from the image filterbase, that solely defines a result type.
Whenever using in an image filter, the result_type is specified by
<code>typename Filter::result_type</code> that needs to be resolved here.
*/
class CMeshStats {
public:
CMeshStats(const CTriangleMesh& m):
_M_mesh(m),
_M_volume(0.0),
_M_area(0.0)
{
}
void operator() ( const CTriangleMesh::triangle_type& face ) {
_M_volume += calc_fvolume(_M_mesh.vertex_at( face[2] ),
_M_mesh.vertex_at( face[1] ),
_M_mesh.vertex_at( face[0] ));
_M_area += calc_farea(_M_mesh.vertex_at( face[0] ),
_M_mesh.vertex_at( face[1] ));
}
double get_volume() const {
return _M_volume / 6.0;
}
double get_area() const {
return _M_area / 2.0;
}
private:
double calc_fvolume(const CTriangleMesh::vertex_type& a, const CTriangleMesh::vertex_type& b, const CTriangleMesh::vertex_type& c) {
return (a.x * (b.y * c.z - b.z * c.y) +
b.x * (c.y * a.z - c.z * a.y) +
c.x * (a.y * b.z - a.z * b.y));
}
double calc_farea(const CTriangleMesh::vertex_type& a, const CTriangleMesh::vertex_type& b) {
C3DFVector n(a.y * b.z - a.z * b.y,
a.z * b.x - a.x * b.z,
a.x * b.y - a.y * b.x);
return n.norm();
}
const CTriangleMesh& _M_mesh;
double _M_volume;
double _M_area;
};
/* A function to calcultate the surface area and the volume of a mesh.
The volume is only valid, if the mesh is a closed and oriented manifold.
\param m the mesh
\retval volume the volume encosed by the mesh
\retval area the surface area
*/
void VMeshVolumeAndArea(const CTriangleMesh& m, double *volume, double *area) {
CMeshStats operateOnMesh(m);
CTriangleMesh::trianglefield_type::const_iterator iTriangle = m.triangles_begin();
for ( ; iTriangle != m.triangles_end(); ++iTriangle )
operateOnMesh(*iTriangle);
*volume = operateOnMesh.get_volume();
if (*volume < 0)
*volume = - *volume;
*area = operateOnMesh.get_area();
}
namespace options {
string in_filename;
bool verbose = false;
}
namespace {
void get_options( int argc, const char *argv[] )
{
popt::COptions opts;
opts.push_back(popt::option( options::in_filename, "in-file", 'i',
"input mesh of the data to calculate", "" ));
vector<string> non_options;
popt::parse_options(argc, argv, opts, non_options);
// what to do with unrecognized options
if ( non_options.size() > 0 )
throw invalid_argument("unknown options");
// required options (anything that has no default value)
if ( options::in_filename.empty() )
throw mona_runtime_error("'--in-file' ('i') option required");
}
} // anonymous namespace
int main(int argc, const char *argv[])
{
using namespace std;
using namespace mona;
try {
get_options(argc, argv);
#ifdef DEBUG
error_report.set_level( vstream::ml_debug );
#endif
CIOMeshPluginHandler meshio;
// get the mesh
auto_ptr<CTriangleMesh> mesh_ptr( meshio.load(options::in_filename) );
if ( !mesh_ptr->get_available_data() ) {
string not_found = ("No supported data found in ") + options::in_filename;
throw mona_runtime_error(not_found);
}
double volume;
double area;
VMeshVolumeAndArea(*mesh_ptr, &volume, &area);
cout << "Volume: " << volume << ", Surface Area: " << area << endl;
return EXIT_SUCCESS;
}
catch (const mona_runtime_error& e){
cerr << argv[0] << " error: " << e.what() << endl;
}
catch (const mona_fatal_error& e){
cerr << argv[0] << " fatal: " << e.what() << endl;
}
catch (const mona_exception& e){
cerr << argv[0] << " error: " << e.what() << endl;
}
catch (const invalid_argument &e){
cerr << argv[0] << " error: " << e.what() << endl;
}
catch (const exception& e){
cerr << argv[0] << " error: " << e.what() << endl;
}
catch (...){
cerr << argv[0] << " unknown exception" << endl;
}
return EXIT_FAILURE;
}
/*
$Log$
Revision 1.9 2005/06/29 13:32:02 wollny
move to libmona-version 0.7
Revision 1.3 2005/06/02 13:33:23 gerddie
adapt code to new plugin handling
Revision 1.2 2005/04/05 14:00:37 gerddie
bug fix
Revision 1.8 2005/04/05 13:58:34 wollny
bug fix
Revision 1.7 2005/01/19 11:10:07 wollny
adapted to new verbose handling of libmona
Revision 1.6 2005/01/18 12:28:21 tittge
adjusted documetation
Revision 1.5 2004/11/01 16:24:54 wollny
move from old error-report to cverb
Revision 1.4 2004/10/22 15:03:04 tittge
remove some memory problems (by consitently using auto_ptr's)
Revision 1.3 2004/10/20 14:32:09 tittge
new tool to calc mesh volume and surface area
Revision 1.2 2004/06/03 09:57:45 wollny
Changed (hopefully) all instancable class names to Cxxxxx
Revision 1.1 2004/04/05 08:45:08 tittge
initial
*/