First checkin for OpenMesh 2.0

git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@2 fdac6126-5c0c-442c-9429-916003d36597
This commit is contained in:
Jan Möbius
2009-02-06 13:37:46 +00:00
parent c3321ebdd9
commit 97f515985d
417 changed files with 76182 additions and 0 deletions

17
Tools/Utils/ACGMakefile Normal file
View File

@@ -0,0 +1,17 @@
#== SYSTEM PART -- DON'T TOUCH ==============================================
include $(ACGMAKE)/Config
#==============================================================================
SUBDIRS = $(call find-subdirs)
PACKAGES :=
PROJ_LIBS :=
MODULES := cxxlib
#== SYSTEM PART -- DON'T TOUCH ==============================================
include $(ACGMAKE)/Rules
#==============================================================================

57
Tools/Utils/Config.hh Normal file
View File

@@ -0,0 +1,57 @@
//=============================================================================
//
// OpenMesh
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
// www.openmesh.org
//
//-----------------------------------------------------------------------------
//
// License
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, version 2.1.
//
// 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//-----------------------------------------------------------------------------
//
// $Revision: 1802 $
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
//
//=============================================================================
/** \file Tools/Utils/Config.hh
*/
//=============================================================================
//
// Defines
//
//=============================================================================
#ifndef OPENMESH_UTILS_CONFIG_HH
#define OPENMESH_UTILS_CONFIG_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
//== NAMESPACES ===============================================================
#define BEGIN_NS_UTILS namespace Utils {
#define END_NS_UTILS }
//=============================================================================
#endif // OPENMESH_UTILS_CONFIG_HH defined
//=============================================================================

View File

@@ -0,0 +1,80 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2001-2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* 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 *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS newClass
//
//=============================================================================
#ifndef OPENMESH_UTILS_GLCONSTASSTRING_HH
#define OPENMESH_UTILS_GLCONSTASSTRING_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <GL/glut.h>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace Utils {
//== CLASS DEFINITION =========================================================
inline
const char *GLenum_as_string( GLenum _m )
{
#define MODE(M) case M:return #M
switch( _m )
{
MODE(GL_POINTS);
MODE(GL_LINES);
MODE(GL_LINE_STRIP);
MODE(GL_LINE_LOOP);
MODE(GL_TRIANGLES);
MODE(GL_TRIANGLE_STRIP);
MODE(GL_TRIANGLE_FAN);
MODE(GL_QUADS);
MODE(GL_QUAD_STRIP);
MODE(GL_POLYGON);
default: return "<unknown>";
}
#undef MODE
}
//=============================================================================
} // namespace Utils
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_UTILS_GLCONSTASSTRING_HH defined
//=============================================================================

498
Tools/Utils/Gnuplot.cc Normal file
View File

@@ -0,0 +1,498 @@
////////////////////////////////////////////
//
// A C++ interface to gnuplot.
//
// This is a direct translation from the C interface
// written by N. Devillard (which is available from
// http://ndevilla.free.fr/gnuplot/).
//
// As in the C interface this uses pipes and so wont
// run on a system that does'nt have POSIX pipe
// support
//
// Rajarshi Guha
// <rajarshi@presidency.com>
//
// 07/03/03
//
////////////////////////////////////////////
#include "Gnuplot.hh"
#include <stdarg.h>
#ifdef WIN32
# include <io.h>
#else
# include <fcntl.h> // X_OK
# include <unistd.h> // access
# define PATH_MAXNAMESZ 4096
#endif
#include <iostream>
#include <fstream>
#include <sstream>
#include <list>
#if defined(WIN32)
# define pclose _pclose
# define popen _popen
# define access _access
# define ACCESS_OK 0
# define PATH_SEP ";"
# define MKTEMP_AND_CHECK_FAILED(name) (_mktemp(name) == NULL)
#else
# define ACCESS_OK X_OK
# define PATH_SEP ":"
# define MKTEMP_AND_CHECK_FAILED(name) (mkstemp(name) == -1)
#endif
#ifndef WIN32
#include <stdlib.h>
#include <string.h>
#endif
using namespace std;
/////////////////////////////
//
// A string tokenizer taken from
// http://www.sunsite.ualberta.ca/
// Documentation/Gnu/libstdc++-2.90.8/html/21_strings/stringtok_std_h.txt
//
/////////////////////////////
template <typename Container>
void
stringtok (Container &container, string const &in,
const char * const delimiters = " \t\n")
{
const string::size_type len = in.length();
string::size_type i = 0;
while ( i < len )
{
// eat leading whitespace
i = in.find_first_not_of (delimiters, i);
if (i == string::npos)
return; // nothing left but white space
// find the end of the token
string::size_type j = in.find_first_of (delimiters, i);
// push token
if (j == string::npos)
{
container.push_back (in.substr(i));
return;
} else
container.push_back (in.substr(i, j-i));
// set up for next loop
i = j + 1;
}
}
// ----------------------------------------------------------------------------
#ifdef WIN32
std::string Gnuplot::gnuplot_executable_ = "pgnuplot.exe";
#else
std::string Gnuplot::gnuplot_executable_ = "gnuplot";
#endif
// ----------------------------------------------------------------------------
Gnuplot::Gnuplot(void)
{
init();
set_style("points");
}
// ----------------------------------------------------------------------------
Gnuplot::Gnuplot(const string &style)
{
init();
set_style(style);
}
// ----------------------------------------------------------------------------
Gnuplot::Gnuplot(const string &title,
const string &style,
const string &labelx, const string &labely,
vector<double> x, vector<double> y)
{
init();
if (x.size() == 0 || y.size() == 0)
throw GnuplotException("vectors too small");
if (style == "")
this->set_style("lines");
else
this->set_style(style);
if (labelx == "")
this->set_xlabel("X");
else
this->set_xlabel(labelx);
if (labely == "")
this->set_ylabel("Y");
else
this->set_ylabel(labely);
this->plot_xy(x,y,title);
cout << "Press enter to continue" << endl;
while (getchar() != '\n'){}
}
// ----------------------------------------------------------------------------
Gnuplot::Gnuplot(const string &title, const string &style,
const string &labelx, const string &labely,
vector<double> x)
{
init();
if (x.size() == 0)
throw GnuplotException("vector too small");
if (!this->gnucmd)
throw GnuplotException("Could'nt open connection to gnuplot");
if (style == "")
this->set_style("lines");
else
this->set_style(style);
if (labelx == "")
this->set_xlabel("X");
else
this->set_xlabel(labelx);
if (labely == "")
this->set_ylabel("Y");
else
this->set_ylabel(labely);
this->plot_x(x,title);
cout << "Press enter to continue" << endl;
while (getchar() != '\n'){}
}
// ----------------------------------------------------------------------------
Gnuplot::~Gnuplot()
{
if ((this->to_delete).size() > 0)
{
for (size_t i = 0; i < this->to_delete.size(); i++)
remove(this->to_delete[i].c_str());
}
if (pclose(this->gnucmd) == -1)
cerr << "Problem closing communication to gnuplot" << endl;
return;
}
// ----------------------------------------------------------------------------
bool Gnuplot::get_program_path(const string pname)
{
list<string> ls;
char *path;
path = getenv("PATH");
if (!path)
return false;
stringtok(ls, path, PATH_SEP);
for (list<string>::const_iterator i = ls.begin(); i != ls.end(); ++i)
{
string tmp = (*i) + "/" + pname;
if ( access(tmp.c_str(), ACCESS_OK) == 0 )
return true;
}
return false;
}
// ----------------------------------------------------------------------------
void Gnuplot::reset_plot(void)
{
if (this->to_delete.size() > 0)
{
for (size_t i = 0; i < this->to_delete.size(); i++)
remove(this->to_delete[i].c_str());
}
this->nplots = 0;
return;
}
// ----------------------------------------------------------------------------
void Gnuplot::set_style(const string &stylestr)
{
if (stylestr != "lines" &&
stylestr != "points" &&
stylestr != "linespoints" &&
stylestr != "impulses" &&
stylestr != "dots" &&
stylestr != "steps" &&
stylestr != "errorbars" &&
stylestr != "boxes" &&
stylestr != "boxerrorbars")
this->pstyle = string("points");
else
this->pstyle = stylestr;
}
// ----------------------------------------------------------------------------
void Gnuplot::cmd(const char *_cmd, ...)
{
va_list ap;
char local_cmd[GP_CMD_SIZE];
va_start(ap, _cmd);
vsprintf(local_cmd, _cmd, ap);
va_end(ap);
strcat(local_cmd,"\n");
fputs(local_cmd,this->gnucmd);
fflush(this->gnucmd);
return;
}
// ----------------------------------------------------------------------------
void Gnuplot::set_ylabel(const string &label)
{
ostringstream cmdstr;
cmdstr << "set xlabel \"" << label << "\"";
this->cmd(cmdstr.str().c_str());
return;
}
// ----------------------------------------------------------------------------
void Gnuplot::set_xlabel(const string &label)
{
ostringstream cmdstr;
cmdstr << "set xlabel \"" << label << "\"";
this->cmd(cmdstr.str().c_str());
return;
}
// ----------------------------------------------------------------------------
// Plots a linear equation (where you supply the
// slope and intercept)
//
void Gnuplot::plot_slope(double a, double b, const string &title)
{
ostringstream stitle;
ostringstream cmdstr;
if (title == "")
stitle << "no title";
else
stitle << title;
if (this->nplots > 0)
cmdstr << "replot " << a << " * x + " << b << " title \"" << stitle.str() << "\" with " << pstyle;
else
cmdstr << "plot " << a << " * x + " << b << " title \"" << stitle.str() << "\" with " << pstyle;
this->cmd(cmdstr.str().c_str());
this->nplots++;
return;
}
// ----------------------------------------------------------------------------
// Plot an equation which is supplied as a string
//
void Gnuplot::plot_equation(const string &equation, const string &title)
{
string titlestr, plotstr;
ostringstream cmdstr;
if (title == "")
titlestr = "no title";
else
titlestr = title;
if (this->nplots > 0)
plotstr = "replot";
else
plotstr = "plot";
cmdstr << plotstr << " " << equation << " " << "title \"" << titlestr << "\" with " << this->pstyle;
this->cmd(cmdstr.str().c_str());
this->nplots++;
return;
}
// ----------------------------------------------------------------------------
void Gnuplot::plot_x(vector<double> d, const string &title)
{
ofstream tmp;
ostringstream cmdstr;
#ifdef WIN32
char name[] = "gnuplotiXXXXXX";
#else
char name[] = "/tmp/gnuplotiXXXXXX";
#endif
if (this->to_delete.size() == GP_MAX_TMP_FILES - 1)
{
cerr << "Maximum number of temporary files reached (" << GP_MAX_TMP_FILES << "): cannot open more files" << endl;
return;
}
//
//open temporary files for output
#ifdef WIN32
if ( _mktemp(name) == NULL)
#else
if ( mkstemp(name) == -1 )
#endif
{
cerr << "Cannot create temporary file: exiting plot" << endl;
return;
}
tmp.open(name);
if (tmp.bad())
{
cerr << "Cannot create temorary file: exiting plot" << endl;
return;
}
//
// Save the temporary filename
//
this->to_delete.push_back(name);
//
// write the data to file
//
for (size_t i = 0; i < d.size(); i++)
tmp << d[i] << endl;
tmp.flush();
tmp.close();
//
// command to be sent to gnuplot
//
cmdstr << ( (this->nplots > 0) ? "replot " : "plot ");
if (title.empty())
cmdstr << "\"" << name << "\" with " << this->pstyle;
else
cmdstr << "\"" << name << "\" title \"" << title << "\" with "
<< this->pstyle;
//
// Do the actual plot
//
this->cmd(cmdstr.str().c_str());
this->nplots++;
return;
}
// ----------------------------------------------------------------------------
void Gnuplot::plot_xy(vector<double> x, vector<double> y, const string &title)
{
ofstream tmp;
ostringstream cmdstr;
#ifdef WIN32
char name[] = "gnuplotiXXXXXX";
#else
char name[] = "/tmp/gnuplotiXXXXXX";
#endif
// should raise an exception
if (x.size() != y.size())
return;
if ((this->to_delete).size() == GP_MAX_TMP_FILES - 1)
{
std::stringstream s;
s << "Maximum number of temporary files reached ("
<< GP_MAX_TMP_FILES << "): cannot open more files" << endl;
throw GnuplotException( s.str() );
}
//open temporary files for output
//
if (MKTEMP_AND_CHECK_FAILED(name))
throw GnuplotException("Cannot create temporary file: exiting plot");
tmp.open(name);
if (tmp.bad())
throw GnuplotException("Cannot create temorary file: exiting plot");
// Save the temporary filename
//
this->to_delete.push_back(name);
// Write the data to file
//
size_t N = std::min(x.size(), y.size());
for (size_t i = 0; i < N; i++)
tmp << x[i] << " " << y[i] << endl;
tmp.flush();
tmp.close();
//
// command to be sent to gnuplot
//
if (this->nplots > 0)
cmdstr << "replot ";
else cmdstr << "plot ";
if (title == "")
cmdstr << "\"" << name << "\" with " << this->pstyle;
else
cmdstr << "\"" << name << "\" title \"" << title << "\" with " << this->pstyle;
//
// Do the actual plot
//
this->cmd(cmdstr.str().c_str());
this->nplots++;
return;
}
// ----------------------------------------------------------------------------
void Gnuplot::init()
{
if (!this->get_program_path(gnuplot_executable_))
{
this->valid = false;
throw GnuplotException("Can't find gnuplot in your PATH");
}
this->gnucmd = popen(gnuplot_executable_.c_str(),"w");
if (!this->gnucmd)
{
this->valid = false;
throw GnuplotException("Couldn't open connection to gnuplot");
}
this->nplots = 0;
this->valid = true;
}
// ============================================================================

184
Tools/Utils/Gnuplot.hh Normal file
View File

@@ -0,0 +1,184 @@
////////////////////////////////////////////
//
// A C++ interface to gnuplot.
//
// This is a direct translation from the C interface
// written by N. Devillard (which is available from
// http://ndevilla.free.fr/gnuplot/).
//
// As in the C interface this uses pipes and so wont
// run on a system that doesn't have POSIX pipe
// support
//
// Rajarshi Guha
// <rajarshi@presidency.com>
//
// 07/03/03
//
////////////////////////////////////////////
//
// A little correction for Win32 compatibility
// and MS VC 6.0 done by V.Chyzhdzenka
//
// Notes:
// 1. Added private method Gnuplot::init().
// 2. Temporary file is created in th current
// folder but not in /tmp.
// 3. Added #indef WIN32 e.t.c. where is needed.
// 4. Added private member m_sGNUPlotFileName is
// a name of executed GNUPlot file.
//
// Viktor Chyzhdzenka
// e-mail: chyzhdzenka@mail.ru
//
// 20/05/03
//
////////////////////////////////////////////
#ifndef _GNUPLOT_HH
#define _GNUPLOT_HH
#include <OpenMesh/Core/System/config.hh>
// #ifndef WIN32
// # include <unistd.h>
// #else
// # pragma warning (disable : 4786) // Disable 4786 warning for MS VC 6.0
// #endif
#if defined(OM_CC_MIPS)
# include <stdio.h>
#else
# include <cstdio>
#endif
#include <string>
#include <vector>
#include <stdexcept>
// ----------------------------------------------------------------------------
#ifdef WIN32
# define GP_MAX_TMP_FILES 27 //27 temporary files it's Microsoft restriction
#else
# define GP_MAX_TMP_FILES 64
# define GP_TMP_NAME_SIZE 512
# define GP_TITLE_SIZE 80
#endif
#define GP_CMD_SIZE 1024
// ----------------------------------------------------------------------------
using namespace std;
// ----------------------------------------------------------------------------
/// Exception thrown by class Gnuplot
class GnuplotException : public runtime_error
{
public:
GnuplotException(const string &msg) : runtime_error(msg){}
};
// ----------------------------------------------------------------------------
/** Utility class interfacing with Gnuplot.
*
* \note The plot will be visible as long as the object is not destructed.
*
* \author Rajarshi Guha (C++ API based on the C API by Nicolas Devillard)
*
* \see <a
* href="http://ndevilla.free.fr/gnuplot/">http://ndevilla.free.fr/gnuplot/</a>
* more information.
*/
class Gnuplot
{
private:
FILE *gnucmd;
string pstyle;
vector<string> to_delete;
int nplots;
bool get_program_path(const string);
bool valid;
// Name of executed GNUPlot file
static string gnuplot_executable_;
void init();
public:
/// \name Constructors
//@{
/// Default constructor.
Gnuplot();
/// Set a style during construction.
Gnuplot(const string & _style);
/// Constructor calling plot_xy().
Gnuplot(const string & _title,
const string & _style,
const string & _xlabel,
const string & _ylabel,
vector<double> _x, vector<double> _y);
/// Constructor calling plot_x().
Gnuplot(const string &_title,
const string &_style,
const string &_xlabel,
const string &_ylabel,
vector<double> _x);
//@}
~Gnuplot();
/// Send a command to gnuplot (low-level function use by all plot functions.)
void cmd(const char *_cmd, ...);
/// \name Gnuplot settings
//@{
void set_style(const string & _style); ///< set line style
void set_ylabel(const string & _ylabel); ///< set x axis label
void set_xlabel(const string & _xlabel); ///< set x axis label
//@}
/// \name plot functions
//@{
/// Plot a single vector
void plot_x(vector<double> _x, const string &_title);
/// Plot x,y pairs
void plot_xy(vector<double> _x, vector<double> _y, const string &_title);
/// Plot an equation of the form: y = ax + b
/// You supply a and b
void plot_slope(
double _a,
double _b,
const string & _title
);
/// Plot an equation supplied as a string
void plot_equation(
const string & _equation,
const string & _title
);
/// If multiple plots are present it will clear the plot area
void reset_plot(void);
//@}
/// Is \c Self valid?
bool is_valid(void) const { return valid; }
/// Is \c Self active, i.e. does it have an active plot?
bool is_active(void) const { return this->nplots > 0; }
};
// ----------------------------------------------------------------------------
#endif // _GNUPLOT_HH
// ============================================================================

353
Tools/Utils/HeapT.hh Normal file
View File

@@ -0,0 +1,353 @@
//=============================================================================
//
// OpenMesh
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
// www.openmesh.org
//
//-----------------------------------------------------------------------------
//
// License
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, version 2.1.
//
// 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//-----------------------------------------------------------------------------
//
// $Revision: 1802 $
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
//
//=============================================================================
/** \file HeapT.hh
A generic heap class
**/
/** Martin, 26.12.2004:
1) replaced resize(size()-1) with pop_back(), since the later is more efficient
2) replaced interface_.set_heap_position(entry(0), -1); with reset_heap_position()
3) added const modifier to various functions
TODO: in the moment the heap does not conform to the HeapInterface specification,
i.e., copies are passed instead of references. This is especially important
for set_heap_position(), where the reference argument is non-const. The
specification should be changed to reflect that the heap actually (only?)
works when the heap entry is nothing more but a handle.
TODO: change the specification of HeapInterface to make less(), greater() and
get_heap_position() const. Needs changing DecimaterT. Might break
someone's code.
*/
//=============================================================================
//
// CLASS HeapT
//
//=============================================================================
#ifndef OPENMESH_UTILS_HEAPT_HH
#define OPENMESH_UTILS_HEAPT_HH
//== INCLUDES =================================================================
#include "Config.hh"
#include <vector>
#include <OpenMesh/Core/System/omstream.hh>
//== NAMESPACE ================================================================
namespace OpenMesh { // BEGIN_NS_OPENMESH
namespace Utils { // BEGIN_NS_UTILS
//== CLASS DEFINITION =========================================================
/** This class demonstrates the HeapInterface's interface. If you
* want to build your customized heap you will have to specity a heap
* interface class and use this class as a template parameter for the
* class HeapT. This class defines the interface that this heap
* interface has to implement.
*
* \see HeapT
*/
template <class HeapEntry>
struct HeapInterfaceT
{
/// Comparison of two HeapEntry's: strict less
bool less(const HeapEntry& _e1, const HeapEntry& _e2);
/// Comparison of two HeapEntry's: strict greater
bool greater(const HeapEntry& _e1, const HeapEntry& _e2);
/// Get the heap position of HeapEntry _e
int get_heap_position(const HeapEntry& _e);
/// Set the heap position of HeapEntry _e
void set_heap_position(HeapEntry& _e, int _i);
};
/** \class HeapT HeapT.hh <OSG/Utils/HeapT.hh>
*
* An efficient, highly customizable heap.
*
* The main difference (and performace boost) of this heap compared
* to e.g. the heap of the STL is that here to positions of the
* heap's elements are accessible from the elements themself.
* Therefore if one changes the priority of an element one does not
* have to remove and re-insert this element, but can just call the
* update(HeapEntry) method.
*
* This heap class is parameterized by two template arguments:
* \li the class \c HeapEntry, that will be stored in the heap
* \li the HeapInterface telling the heap how to compare heap entries and
* how to store the heap positions in the heap entries.
*
* As an example how to use the class see declaration of class
* Decimater::DecimaterT.
*
* \see HeapInterfaceT
*/
template <class HeapEntry, class HeapInterface=HeapEntry>
class HeapT : private std::vector<HeapEntry>
{
private:
typedef std::vector<HeapEntry> Base;
public:
/// Constructor
HeapT() : HeapVector() {}
/// Construct with a given \c HeapIterface.
HeapT(const HeapInterface& _interface)
: HeapVector(), interface_(_interface)
{}
/// Destructor.
~HeapT(){};
/// clear the heap
void clear() { HeapVector::clear(); }
/// is heap empty?
bool empty() const { return HeapVector::empty(); }
/// returns the size of heap
unsigned int size() const { return HeapVector::size(); }
/// reserve space for _n entries
void reserve(unsigned int _n) { HeapVector::reserve(_n); }
/// reset heap position to -1 (not in heap)
void reset_heap_position(HeapEntry _h)
{ interface_.set_heap_position(_h, -1); }
/// is an entry in the heap?
bool is_stored(HeapEntry _h)
{ return interface_.get_heap_position(_h) != -1; }
/// insert the entry _h
void insert(HeapEntry _h)
{
push_back(_h);
upheap(size()-1);
}
/// get the first entry
HeapEntry front() const
{
assert(!empty());
return entry(0);
}
/// delete the first entry
void pop_front()
{
assert(!empty());
reset_heap_position(entry(0));
if (size() > 1)
{
entry(0, entry(size()-1));
Base::pop_back();
downheap(0);
}
else
{
Base::pop_back();
}
}
/// remove an entry
void remove(HeapEntry _h)
{
int pos = interface_.get_heap_position(_h);
reset_heap_position(_h);
assert(pos != -1);
assert((unsigned int) pos < size());
// last item ?
if ((unsigned int) pos == size()-1)
{
Base::pop_back();
}
else
{
entry(pos, entry(size()-1)); // move last elem to pos
Base::pop_back();
downheap(pos);
upheap(pos);
}
}
/** update an entry: change the key and update the position to
reestablish the heap property.
*/
void update(HeapEntry _h)
{
int pos = interface_.get_heap_position(_h);
assert(pos != -1);
assert((unsigned int)pos < size());
downheap(pos);
upheap(pos);
}
/// check heap condition
bool check()
{
bool ok(true);
unsigned int i, j;
for (i=0; i<size(); ++i)
{
if (((j=left(i))<size()) && interface_.greater(entry(i), entry(j)))
{
omerr() << "Heap condition violated\n";
ok=false;
}
if (((j=right(i))<size()) && interface_.greater(entry(i), entry(j)))
{
omerr() << "Heap condition violated\n";
ok=false;
}
}
return ok;
}
protected:
/// Instance of HeapInterface
HeapInterface interface_;
private:
// typedef
typedef std::vector<HeapEntry> HeapVector;
/// Upheap. Establish heap property.
void upheap(unsigned int _idx);
/// Downheap. Establish heap property.
void downheap(unsigned int _idx);
/// Get the entry at index _idx
inline HeapEntry entry(unsigned int _idx) const
{
assert(_idx < size());
return (Base::operator[](_idx));
}
/// Set entry _h to index _idx and update _h's heap position.
inline void entry(unsigned int _idx, HeapEntry _h)
{
assert(_idx < size());
Base::operator[](_idx) = _h;
interface_.set_heap_position(_h, _idx);
}
/// Get parent's index
inline unsigned int parent(unsigned int _i) { return (_i-1)>>1; }
/// Get left child's index
inline unsigned int left(unsigned int _i) { return (_i<<1)+1; }
/// Get right child's index
inline unsigned int right(unsigned int _i) { return (_i<<1)+2; }
};
//== IMPLEMENTATION ==========================================================
template <class HeapEntry, class HeapInterface>
void
HeapT<HeapEntry, HeapInterface>::
upheap(unsigned int _idx)
{
HeapEntry h = entry(_idx);
unsigned int parentIdx;
while ((_idx>0) &&
interface_.less(h, entry(parentIdx=parent(_idx))))
{
entry(_idx, entry(parentIdx));
_idx = parentIdx;
}
entry(_idx, h);
}
//-----------------------------------------------------------------------------
template <class HeapEntry, class HeapInterface>
void
HeapT<HeapEntry, HeapInterface>::
downheap(unsigned int _idx)
{
HeapEntry h = entry(_idx);
unsigned int childIdx;
unsigned int s = size();
while(_idx < s)
{
childIdx = left(_idx);
if (childIdx >= s) break;
if ((childIdx+1 < s) &&
(interface_.less(entry(childIdx+1), entry(childIdx))))
++childIdx;
if (interface_.less(h, entry(childIdx))) break;
entry(_idx, entry(childIdx));
_idx = childIdx;
}
entry(_idx, h);
}
//=============================================================================
} // END_NS_UTILS
} // END_NS_OPENMESH
//=============================================================================
#endif // OSG_HEAP_HH defined
//=============================================================================

222
Tools/Utils/MeshCheckerT.cc Normal file
View File

@@ -0,0 +1,222 @@
//=============================================================================
//
// OpenMesh
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
// www.openmesh.org
//
//-----------------------------------------------------------------------------
//
// License
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, version 2.1.
//
// 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//-----------------------------------------------------------------------------
//
// $Revision: 2433 $
// $Date: 2008-08-27 13:43:05 +0200 (Mi, 27. Aug 2008) $
//
//=============================================================================
#define OPENMESH_MESHCHECKER_C
//== INCLUDES =================================================================
#include <OpenMesh/Tools/Utils/MeshCheckerT.hh>
//== NAMESPACES ==============================================================
namespace OpenMesh {
namespace Utils {
//== IMPLEMENTATION ==========================================================
template <class Mesh>
bool
MeshCheckerT<Mesh>::
check(unsigned int _targets, std::ostream& _os)
{
bool ok(true);
//--- vertex checks ---
if (_targets & CHECK_VERTICES)
{
typename Mesh::ConstVertexIter v_it(mesh_.vertices_begin()),
v_end(mesh_.vertices_end());
typename Mesh::VertexHandle vh;
typename Mesh::ConstVertexVertexIter vv_it;
typename Mesh::HalfedgeHandle heh;
unsigned int count;
const unsigned int max_valence(10000);
for (; v_it != v_end; ++v_it)
{
if (!is_deleted(v_it))
{
vh = v_it.handle();
/* The outgoing halfedge of a boundary vertex has to be a
boundary halfedge */
heh = mesh_.halfedge_handle(vh);
if (heh.is_valid() && !mesh_.is_boundary(heh))
{
for (typename Mesh::ConstVertexOHalfedgeIter vh_it(mesh_, vh);
vh_it; ++vh_it)
{
if (mesh_.is_boundary(vh_it.handle()))
{
_os << "MeshChecker: vertex " << vh
<< ": outgoing halfedge not on boundary error\n";
ok = false;
}
}
}
// outgoing halfedge has to refer back to vertex
if (mesh_.halfedge_handle(vh).is_valid() &&
mesh_.from_vertex_handle(mesh_.halfedge_handle(vh)) != vh)
{
_os << "MeshChecker: vertex " << vh
<< ": outgoing halfedge does not reference vertex\n";
ok = false;
}
// check whether circulators are still in order
vv_it = mesh_.cvv_iter(vh);
for (count=0; vv_it && (count < max_valence); ++vv_it, ++count) {};
if (count == max_valence)
{
_os << "MeshChecker: vertex " << vh
<< ": ++circulator problem, one ring corrupt\n";
ok = false;
}
vv_it = mesh_.cvv_iter(vh);
for (count=0; vv_it && (count < max_valence); --vv_it, ++count) {};
if (count == max_valence)
{
_os << "MeshChecker: vertex " << vh
<< ": --circulator problem, one ring corrupt\n";
ok = false;
}
}
}
}
//--- halfedge checks ---
if (_targets & CHECK_EDGES)
{
typename Mesh::ConstHalfedgeIter h_it(mesh_.halfedges_begin()),
h_end(mesh_.halfedges_end());
typename Mesh::HalfedgeHandle hh, hstart, hhh;
unsigned int count, n_halfedges = 2*mesh_.n_edges();
for (; h_it != h_end; ++h_it)
{
if (!is_deleted(mesh_.edge_handle(h_it.handle())))
{
hh = h_it.handle();
// degenerated halfedge ?
if (mesh_.from_vertex_handle(hh) == mesh_.to_vertex_handle(hh))
{
_os << "MeshChecker: halfedge " << hh
<< ": to-vertex == from-vertex\n";
ok = false;
}
// next <-> prev check
if (mesh_.next_halfedge_handle(mesh_.prev_halfedge_handle(hh)) != hh)
{
_os << "MeshChecker: halfedge " << hh
<< ": prev->next != this\n";
ok = false;
}
// halfedges should form a cycle
count=0; hstart=hhh=hh;
do
{
hhh = mesh_.next_halfedge_handle(hhh);
++count;
} while (hhh != hstart && count < n_halfedges);
if (count == n_halfedges)
{
_os << "MeshChecker: halfedges starting from " << hh
<< " do not form a cycle\n";
ok = false;
}
}
}
}
//--- face checks ---
if (_targets & CHECK_FACES)
{
typename Mesh::ConstFaceIter f_it(mesh_.faces_begin()),
f_end(mesh_.faces_end());
typename Mesh::FaceHandle fh;
typename Mesh::ConstFaceHalfedgeIter fh_it;
for (; f_it != f_end; ++f_it)
{
if (!is_deleted(f_it))
{
fh = f_it.handle();
for (fh_it=mesh_.cfh_iter(fh); fh_it; ++fh_it)
{
if (mesh_.face_handle(fh_it.handle()) != fh)
{
_os << "MeshChecker: face " << fh
<< ": its halfedge does not reference face\n";
ok = false;
}
}
}
}
}
return ok;
}
//=============================================================================
} // naespace Utils
} // namespace OpenMesh
//=============================================================================

114
Tools/Utils/MeshCheckerT.hh Normal file
View File

@@ -0,0 +1,114 @@
//=============================================================================
//
// OpenMesh
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
// www.openmesh.org
//
//-----------------------------------------------------------------------------
//
// License
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, version 2.1.
//
// 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//-----------------------------------------------------------------------------
//
// $Revision: 1802 $
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
//
//=============================================================================
#ifndef OPENMESH_MESHCHECKER_HH
#define OPENMESH_MESHCHECKER_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/Utils/GenProg.hh>
#include <OpenMesh/Core/Mesh/Attributes.hh>
#include <iostream>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace Utils {
//== CLASS DEFINITION =========================================================
/** Check integrity of mesh.
*
* This class provides several functions to check the integrity of a mesh.
*/
template <class Mesh>
class MeshCheckerT
{
public:
/// constructor
MeshCheckerT(const Mesh& _mesh) : mesh_(_mesh) {}
/// destructor
~MeshCheckerT() {}
/// what should be checked?
enum CheckTargets
{
CHECK_EDGES = 1,
CHECK_VERTICES = 2,
CHECK_FACES = 4,
CHECK_ALL = 255,
};
/// check it, return true iff ok
bool check( unsigned int _targets=CHECK_ALL,
std::ostream& _os= omerr());
private:
bool is_deleted(typename Mesh::VertexHandle _vh)
{ return (mesh_.has_vertex_status() ? mesh_.status(_vh).deleted() : false); }
bool is_deleted(typename Mesh::EdgeHandle _eh)
{ return (mesh_.has_edge_status() ? mesh_.status(_eh).deleted() : false); }
bool is_deleted(typename Mesh::FaceHandle _fh)
{ return (mesh_.has_face_status() ? mesh_.status(_fh).deleted() : false); }
// ref to mesh
const Mesh& mesh_;
};
//=============================================================================
} // namespace Utils
} // namespace OpenMesh
//=============================================================================
#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_MESHCHECKER_C)
#define OPENMESH_MESHCHECKER_TEMPLATES
#include "MeshCheckerT.cc"
#endif
//=============================================================================
#endif // OPENMESH_MESHCHECKER_HH defined
//=============================================================================

136
Tools/Utils/NumLimitsT.hh Normal file
View File

@@ -0,0 +1,136 @@
//=============================================================================
//
// OpenMesh
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
// www.openmesh.org
//
//-----------------------------------------------------------------------------
//
// License
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, version 2.1.
//
// 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//-----------------------------------------------------------------------------
//
// $Revision: 4254 $
// $Date: 2009-01-12 14:44:00 +0100 (Mo, 12. Jan 2009) $
//
//=============================================================================
/** \file NumLimitsT.hh
Temporary solution until std::numeric_limits is standard.
*/
//=============================================================================
//
// CLASS NumLimitsT
//
//=============================================================================
#ifndef OPENMESH_UTILS_NUMLIMITS_HH
#define OPENMESH_UTILS_NUMLIMITS_HH
//== INCLUDES =================================================================
#include "Config.hh"
#include <limits.h>
#include <float.h>
//== NAMESPEACES ==============================================================
namespace OpenMesh { // BEGIN_NS_OPENMESH
namespace Utils { // BEGIN_NS_UTILS
//== CLASS DEFINITION =========================================================
/** \class NumLimitsT NumLimitsT.hh <OpenMesh/Utils/NumLimitsT.hh
This class provides the maximum and minimum values a certain
scalar type (\cint, \c float, or \double) can store. You can
use it like this:
\code
#include <OpenMesh/Utils/NumLimitsT.hh>
int float_min = OpenMesh::NumLimitsT<float>::min();
float double_max = OpenMesh::NumLimitsT<double>::max();
\endcode
\note This functionality should be provided by
std::numeric_limits. This template does not exist on gcc <=
2.95.3. The class template NumLimitsT is just a workaround.
**/
template <typename Scalar>
class NumLimitsT
{
public:
/// Return the smallest \em absolte value a scalar type can store.
static inline Scalar min() { return 0; }
/// Return the maximum \em absolte value a scalar type can store.
static inline Scalar max() { return 0; }
static inline bool is_float() { return false; }
static inline bool is_integer() { return !NumLimitsT<Scalar>::is_float(); }
static inline bool is_signed() { return true; }
};
// is_float
template<>
inline bool NumLimitsT<float>::is_float() { return true; }
template<>
inline bool NumLimitsT<double>::is_float() { return true; }
template<>
inline bool NumLimitsT<long double>::is_float() { return true; }
// is_signed
template<>
inline bool NumLimitsT<unsigned char>::is_signed() { return false; }
template<>
inline bool NumLimitsT<unsigned short>::is_signed() { return false; }
template<>
inline bool NumLimitsT<unsigned int>::is_signed() { return false; }
template<>
inline bool NumLimitsT<unsigned long>::is_signed() { return false; }
template<>
inline bool NumLimitsT<unsigned long long>::is_signed() { return false; }
// min/max
template<> inline int NumLimitsT<int>::min() { return INT_MIN; }
template<> inline int NumLimitsT<int>::max() { return INT_MAX; }
template<> inline float NumLimitsT<float>::min() { return FLT_MIN; }
template<> inline float NumLimitsT<float>::max() { return FLT_MAX; }
template<> inline double NumLimitsT<double>::min() { return DBL_MIN; }
template<> inline double NumLimitsT<double>::max() { return DBL_MAX; }
//=============================================================================
} // END_NS_UTILS
} // END_NS_OPENMESH
//=============================================================================
#endif // OPENMESH_NUMLIMITS_HH defined
//=============================================================================

253
Tools/Utils/StripifierT.cc Normal file
View File

@@ -0,0 +1,253 @@
//=============================================================================
//
// OpenMesh
// Copyright (C) 2001-2003 by Computer Graphics Group, RWTH Aachen
// www.openmesh.org
//
//-----------------------------------------------------------------------------
//
// License
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, version 2.1.
//
// 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//-----------------------------------------------------------------------------
//
// $Revision: 1802 $
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
//
//=============================================================================
//=============================================================================
//
// CLASS StripifierT - IMPLEMENTATION
//
//=============================================================================
#define OPENMESH_STRIPIFIERT_C
//== INCLUDES =================================================================
#include <OpenMesh/Tools/Utils/StripifierT.hh>
#include <list>
//== NAMESPACES ===============================================================
namespace OpenMesh {
//== IMPLEMENTATION ==========================================================
template <class Mesh>
unsigned int
StripifierT<Mesh>::
stripify()
{
// preprocess: add new properties
mesh_.add_property( processed_ );
mesh_.add_property( used_ );
mesh_.request_face_status();
// build strips
clear();
build_strips();
// postprocess: remove properties
//mesh_.remove_property(processed_);
//mesh_.remove_property(used_);
//mesh_.release_face_status();
return n_strips();
}
//-----------------------------------------------------------------------------
template <class Mesh>
void
StripifierT<Mesh>::
build_strips()
{
Strip experiments[3];
typename Mesh::HalfedgeHandle h[3];
unsigned int best_idx, best_length, length;
FaceHandles faces[3];
typename FaceHandles::iterator fh_it, fh_end;
typename Mesh::FaceIter f_it, f_end=mesh_.faces_end();
// init faces to be un-processed and un-used
// deleted or hidden faces are marked processed
if (mesh_.has_face_status())
{
for (f_it=mesh_.faces_begin(); f_it!=f_end; ++f_it)
if (mesh_.status(f_it).hidden() || mesh_.status(f_it).deleted())
processed(f_it) = used(f_it) = true;
else
processed(f_it) = used(f_it) = false;
}
else
{
for (f_it=mesh_.faces_begin(); f_it!=f_end; ++f_it)
processed(f_it) = used(f_it) = false;
}
for (f_it=mesh_.faces_begin(); true; )
{
// find start face
for (; f_it!=f_end; ++f_it)
if (!processed(f_it))
break;
if (f_it==f_end) break; // stop if all have been processed
// collect starting halfedges
h[0] = mesh_.halfedge_handle(f_it.handle());
h[1] = mesh_.next_halfedge_handle(h[0]);
h[2] = mesh_.next_halfedge_handle(h[1]);
// build 3 strips, take best one
best_length = best_idx = 0;
for (unsigned int i=0; i<3; ++i)
{
build_strip(h[i], experiments[i], faces[i]);
if ((length = experiments[i].size()) > best_length)
{
best_length = length;
best_idx = i;
}
for (fh_it=faces[i].begin(), fh_end=faces[i].end();
fh_it!=fh_end; ++fh_it)
used(*fh_it) = false;
}
// update processed status
fh_it = faces[best_idx].begin();
fh_end = faces[best_idx].end();
for (; fh_it!=fh_end; ++fh_it)
processed(*fh_it) = true;
// add best strip to strip-list
strips_.push_back(experiments[best_idx]);
}
}
//-----------------------------------------------------------------------------
template <class Mesh>
void
StripifierT<Mesh>::
build_strip(typename Mesh::HalfedgeHandle _start_hh,
Strip& _strip,
FaceHandles& _faces)
{
std::list<unsigned int> strip;
typename Mesh::HalfedgeHandle hh;
typename Mesh::FaceHandle fh;
// reset face list
_faces.clear();
// init strip
strip.push_back(mesh_.from_vertex_handle(_start_hh).idx());
strip.push_back(mesh_.to_vertex_handle(_start_hh).idx());
// walk along the strip: 1st direction
hh = mesh_.prev_halfedge_handle(mesh_.opposite_halfedge_handle(_start_hh));
while (1)
{
// go right
hh = mesh_.next_halfedge_handle(hh);
hh = mesh_.opposite_halfedge_handle(hh);
hh = mesh_.next_halfedge_handle(hh);
if (mesh_.is_boundary(hh)) break;
fh = mesh_.face_handle(hh);
if (processed(fh) || used(fh)) break;
_faces.push_back(fh);
used(fh) = true;
strip.push_back(mesh_.to_vertex_handle(hh).idx());
// go left
hh = mesh_.opposite_halfedge_handle(hh);
hh = mesh_.next_halfedge_handle(hh);
if (mesh_.is_boundary(hh)) break;
fh = mesh_.face_handle(hh);
if (processed(fh) || used(fh)) break;
_faces.push_back(fh);
used(fh) = true;
strip.push_back(mesh_.to_vertex_handle(hh).idx());
}
// walk along the strip: 2nd direction
bool flip(false);
hh = mesh_.prev_halfedge_handle(_start_hh);
while (1)
{
// go right
hh = mesh_.next_halfedge_handle(hh);
hh = mesh_.opposite_halfedge_handle(hh);
hh = mesh_.next_halfedge_handle(hh);
if (mesh_.is_boundary(hh)) break;
fh = mesh_.face_handle(hh);
if (processed(fh) || used(fh)) break;
_faces.push_back(fh);
used(fh) = true;
strip.push_front(mesh_.to_vertex_handle(hh).idx());
flip = true;
// go left
hh = mesh_.opposite_halfedge_handle(hh);
hh = mesh_.next_halfedge_handle(hh);
if (mesh_.is_boundary(hh)) break;
fh = mesh_.face_handle(hh);
if (processed(fh) || used(fh)) break;
_faces.push_back(fh);
used(fh) = true;
strip.push_front(mesh_.to_vertex_handle(hh).idx());
flip = false;
}
if (flip) strip.push_front(strip.front());
// copy final strip to _strip
_strip.clear();
_strip.reserve(strip.size());
std::copy(strip.begin(), strip.end(), std::back_inserter(_strip));
}
//=============================================================================
} // namespace OpenMesh
//=============================================================================

141
Tools/Utils/StripifierT.hh Normal file
View File

@@ -0,0 +1,141 @@
//=============================================================================
//
// OpenMesh
// Copyright (C) 2001-2003 by Computer Graphics Group, RWTH Aachen
// www.openmesh.org
//
//-----------------------------------------------------------------------------
//
// License
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, version 2.1.
//
// 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//-----------------------------------------------------------------------------
//
// $Revision: 1802 $
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
//
//=============================================================================
//=============================================================================
//
// CLASS StripifierT
//
//=============================================================================
#ifndef OPENMESH_STRIPIFIERT_HH
#define OPENMESH_STRIPIFIERT_HH
//== INCLUDES =================================================================
#include <vector>
#include <OpenMesh/Core/Utils/Property.hh>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace OpenMesh {
//== CLASS DEFINITION =========================================================
/** \class StripifierT StripifierT.hh <OpenMesh/Tools/Utils/StripifierT.hh>
This class decomposes a triangle mesh into several triangle strips.
*/
template <class Mesh>
class StripifierT
{
public:
typedef unsigned int Index;
typedef std::vector<Index> Strip;
typedef typename Strip::const_iterator IndexIterator;
typedef std::vector<Strip> Strips;
typedef typename Strips::const_iterator StripsIterator;
/// Default constructor
StripifierT(Mesh& _mesh) : mesh_(_mesh) {}
/// Destructor
~StripifierT() {}
/// Compute triangle strips, returns number of strips
unsigned int stripify();
/// delete all strips
void clear() { Strips().swap(strips_); }
/// returns number of strips
unsigned int n_strips() const { return strips_.size(); }
/// are strips computed?
bool is_valid() const { return !strips_.empty(); }
/// Access strips
StripsIterator begin() const { return strips_.begin(); }
/// Access strips
StripsIterator end() const { return strips_.end(); }
private:
typedef std::vector<typename Mesh::FaceHandle> FaceHandles;
/// this method does the main work
void build_strips();
/// build a strip from a given halfedge (in both directions)
void build_strip(typename Mesh::HalfedgeHandle _start_hh,
Strip& _strip,
FaceHandles& _faces);
FPropHandleT<bool>::reference processed(typename Mesh::FaceHandle _fh) {
return mesh_.property(processed_, _fh);
}
FPropHandleT<bool>::reference used(typename Mesh::FaceHandle _fh) {
return mesh_.property(used_, _fh);
}
private:
Mesh& mesh_;
Strips strips_;
FPropHandleT<bool> processed_, used_;
};
//=============================================================================
} // namespace OpenMesh
//=============================================================================
#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_STRIPIFIERT_C)
#define OPENMESH_STRIPIFIERT_TEMPLATES
#include "StripifierT.cc"
#endif
//=============================================================================
#endif // OPENMESH_STRIPIFIERT_HH defined
//=============================================================================

View File

@@ -0,0 +1,330 @@
// ============================================================================
// $Id: TestingFramework.hh,v 1.1.1.1 2006-10-25 16:14:15 habbecke Exp $
// ----------------------------------------------------------------------------
#ifndef TESTINGFRAMEWORK_HH
#define TESTINGFRAMEWORK_HH
// ----------------------------------------------------------------------------
/** \file TestingFramework.hh
This file contains a little framework for test programms
*/
// ----------------------------------------------------------------------------
#include "Config.hh"
#include <iosfwd>
#include <sstream>
#include <vector>
#include <algorithm>
#include <stdexcept>
#include <OpenMesh/Core/Utils/Noncopyable.hh>
// ------------------------------------------------------------- namespace ----
namespace OpenMesh { // BEGIN_NS_OPENMESH
namespace Utils { // BEGIN_NS_UTILS
// ----------------------------------------------------------------- class ----
//
// Usage Example
//
// #include <iostream>
// #include <.../TestingFramework.hh>
//
// struct test_func : public TestingFramework::TestFunc
// {
// typedef test_func Self;
//
// // define ctor and copy-ctor
// test_func( TestingFramework& _th, std::string _n ) : TestingFramework::TestFunc( _th, _n ) { }
// test_func( Self& _cpy ) : TestingFramework::TestFunc(_cpy) { }
//
// // overload body()
// void body()
// {
//
// // Do the tests
// // direct call to verify
// verify( testResult, expectedResult, "additional information" );
//
// // or use the define TH_VERIFY. The test-expression will be used as the message string
// TH_VERIFY( testResult, expectedResult );
//
// ...
// }
// };
//
// int main(...)
// {
// TestingFramework testSuite(std::cout); // send output to stdout
//
// new test_func(testSuite); // create new test instance. It registers with testSuite.
// return testSuite.run();
// }
//
//
#define TH_VERIFY( expr, expt ) \
verify( expr, expt, #expr )
//
#define TH_VERIFY_X( expr, expt ) \
verify_x( expr, expt, #expr )
/** Helper class for test programms.
\internal
*/
class TestingFramework : Noncopyable
{
public:
typedef TestingFramework Self;
typedef std::logic_error verify_error;
#ifndef DOXY_IGNORE_THIS
class TestFunc
{
public:
TestFunc( TestingFramework& _th, const std::string& _n )
: th_(_th), name_(_n)
{
th_.reg(this);
}
virtual ~TestFunc()
{ }
void operator() ( void )
{
prolog();
try
{
body();
}
catch( std::exception& x )
{
std::cerr << "<<Error>>: Cannot proceed test due to failure of last"
<< " test: " << x.what() << std::endl;
}
catch(...)
{
std::cerr << "Fatal: cannot proceed test due to unknown error!"
<< std::endl;
}
epilog();
}
const TestingFramework& testHelper() const { return th_; }
protected:
virtual void prolog(void)
{
begin(name_);
}
virtual void body(void) = 0;
virtual void epilog(void)
{
end();
}
protected:
TestingFramework& testHelper() { return th_; }
TestFunc( const TestFunc& _cpy ) : th_(_cpy.th_), name_(_cpy.name_) { }
// Use the following method in prolog()
TestFunc& begin(std::string _title, const std::string& _info = "")
{ th_.begin(_title,_info); return *this; }
// Use the following method in epilog()
TestFunc& end(void)
{ th_.end(); return *this; }
// Use the followin methods in body()
template <typename ValueType>
bool
verify( const ValueType& _rc, const ValueType& _expected,
std::string _info )
{ return th_.verify( _rc, _expected, _info ); }
template <typename ValueType>
void
verify_x( const ValueType& _rc, const ValueType& _expected,
std::string _info )
{
if ( !verify(_rc, _expected, _info) )
throw verify_error(_info);
}
TestFunc& info(const std::string& _info)
{ th_.info(_info); return *this; }
TestFunc& info(const std::ostringstream& _ostr)
{ th_.info(_ostr); return *this; }
private:
TestFunc();
protected:
TestingFramework& th_;
std::string name_;
};
#endif
typedef TestFunc* TestFuncPtr;
typedef std::vector<TestFuncPtr> TestSet;
public:
TestingFramework(std::ostream& _os)
: errTotal_(0), errCount_(0),
verifyTotal_(0), verifyCount_(0),
testTotal_(0), testCount_(0),
os_(_os)
{ }
protected:
#ifndef DOXY_IGNORE_THIS
struct TestDeleter
{
void operator() (TestFuncPtr _tfptr) { delete _tfptr; }
};
#endif
public:
virtual ~TestingFramework()
{
std::for_each(tests_.begin(), tests_.end(), TestDeleter() );
}
public:
template <typename ValueType>
bool verify(const ValueType& _rc,
const ValueType& _expected,
const std::string& _info)
{
++verifyTotal_;
if ( _rc == _expected )
{
os_ << " " << _info << ", result: " << _rc << ", OK!" << std::endl;
return true;
}
++errTotal_;
os_ << " " << _info << ", result: " << _rc << " != " << _expected
<< " <<ERROR>>" << std::endl;
return false;
}
Self& begin(std::string _title, const std::string& _info = "")
{
std::ostringstream ostr;
testTitle_ = _title;
errCount_ = errTotal_;
++testTotal_;
ostr << _title;
if ( !_info.empty() )
ostr << " ["<< _info << "]";
testTitle_ = ostr.str();
os_ << "Begin " << testTitle_ << std::endl;
return *this;
}
Self& end()
{
if (errorCount()==0)
++testCount_;
os_ << "End " << testTitle_ << ": " << errorCount() << " Error(s)." << std::endl;
return *this;
}
Self& info(const std::string& _info)
{
os_ << " + " << _info << std::endl;
return *this;
}
Self& info(const std::ostringstream& _ostr)
{
os_ << " + " << _ostr.str() << std::endl;
return *this;
}
size_t errorTotal() const { return errTotal_; }
size_t errorCount() const { return errTotal_ - errCount_; }
size_t verifyTotal() const { return verifyTotal_; }
size_t verifyCount() const { return verifyTotal_ - verifyCount_; }
size_t goodTotal() const { return verifyTotal() - errorTotal(); }
size_t goodCount() const { return verifyCount() - errorCount(); }
size_t testTotal() const { return testTotal_; }
size_t testCount() const { return testCount_; }
public:
int run(void)
{
os_ << "Test started\n";
TestRunner executer;
std::for_each(tests_.begin(), tests_.end(), executer );
os_ << std::endl;
os_ << "All tests completed" << std::endl
<< " #Tests: " << testCount() << "/" << testTotal() << std::endl
<< " #Errors: " << errorTotal() << "/" << verifyTotal() << std::endl;
return errorTotal();
}
protected:
#ifndef DOXY_IGNORE_THIS
struct TestRunner
{
void operator() (TestFuncPtr _tfptr) { (*_tfptr)(); }
};
#endif
int reg(TestFuncPtr _tfptr)
{
tests_.push_back(_tfptr);
return true;
}
friend class TestFunc;
private:
size_t errTotal_;
size_t errCount_;
size_t verifyTotal_;
size_t verifyCount_;
size_t testTotal_; // #Tests
size_t testCount_; // #Tests ohne Fehler
std::string testTitle_;
std::ostream& os_;
TestSet tests_;
};
// ============================================================================
} // END_NS_UTILS
} // END_NS_OPENMESH
// ============================================================================
#endif // TESTINGFRMEWORK_HH
// ============================================================================

397
Tools/Utils/Timer.cc Normal file
View File

@@ -0,0 +1,397 @@
// ============================================================================
// $Id: Timer.cc,v 1.1.1.1 2006-10-25 16:14:15 habbecke Exp $
// ----------------------------------------------------------------------------
#ifndef DOXY_IGNORE_THIS
// ----------------------------------------------------------------------------
#include <OpenMesh/Core/System/config.h>
#if defined(OM_CC_MIPS)
# include <math.h>
# include <stdio.h>
#else
# include <cmath>
# include <cstdio>
#endif
#include "Timer.hh"
// ----------------------------------------------------------------------------
// ------------------------------------------------------------- namespace ----
namespace OpenMesh {
namespace Utils {
// ----------------------------------------------------------------------------
using namespace std;
// -------------------------------------------------------------- TimerImpl ----
// just a base class for the implementation
class TimerImpl
{
protected:
public:
TimerImpl() { ; }
virtual ~TimerImpl() { ; }
virtual void reset(void) = 0;
virtual void start(void) = 0;
virtual void stop(void) = 0;
virtual void cont(void) = 0;
virtual double seconds(void) const = 0;
};
// compiler and os dependent implementation
// ------------------------------------------------------------- windows 32 ----
#if defined(WIN32) && (defined(_MSC_VER) || defined(__INTEL_COMPILER))
#include <windows.h>
class TimerImplWin32 : public TimerImpl
{
protected:
LARGE_INTEGER freq_;
LARGE_INTEGER count_;
LARGE_INTEGER start_;
public:
TimerImplWin32(void);
~TimerImplWin32(void) { ; }
virtual void reset(void);
virtual void start(void);
virtual void stop(void);
virtual void cont(void);
virtual double seconds(void) const;
};
TimerImplWin32::TimerImplWin32(void)
{
if (QueryPerformanceFrequency(&freq_)==FALSE)
throw std::runtime_error("Performance counter of of stock!");
reset();
}
void TimerImplWin32::reset(void)
{
memset(&count_,0,sizeof(count_));
memset(&start_,0,sizeof(count_));
}
void TimerImplWin32::start(void)
{
reset();
QueryPerformanceCounter(&start_);
}
void TimerImplWin32::stop(void)
{
LARGE_INTEGER stop_;
QueryPerformanceCounter(&stop_);
count_.QuadPart += stop_.QuadPart - start_.QuadPart;
}
void TimerImplWin32::cont(void)
{
QueryPerformanceCounter(&start_);
}
double TimerImplWin32::seconds(void) const
{
return (double)count_.QuadPart/(double)freq_.QuadPart;
}
// ------------------------------------------------------------- posix time ----
#elif defined(__GNUC__) && defined(__POSIX__)
# include <time.h>
template <clockid_t N>
class TimerImplPosix : public TimerImpl
{
public:
TimerImplPosix() : id_(N), seconds_(0.0)
{ }
~TimerImplPosix()
{ }
virtual void reset(void) { seconds_ = 0.0; }
virtual void start(void) { seconds_ = 0.0; clock_gettime( id_, &start_ ); }
virtual void stop(void)
{
timespec stop;
clock_gettime( id_, &stop );
seconds_ += ( stop.tv_sec - start_.tv_sec );
seconds_ += ( (double(stop.tv_nsec-start_.tv_nsec)*1e-9) );
}
virtual void cont(void) { clock_gettime( id_, &start_ ); }
virtual double seconds() const { return seconds_; }
protected:
clockid_t id_;
double seconds_;
timespec start_;
};
// ----------------------------------------------------------- gettimeofday ----
#elif defined(__GNUC__) || (defined(__INTEL_COMPILER) && !defined(WIN32))
# include <sys/time.h>
# include <sys/resource.h>
# include <unistd.h>
class TimerImplGToD: public TimerImpl
{
public:
TimerImplGToD() : seconds_(0.0)
{ }
~TimerImplGToD()
{ }
virtual void reset(void) { seconds_ = 0.0; }
virtual void start(void) { seconds_ = 0.0; gettimeofday( &start_, &tz_ ); }
virtual void stop(void)
{
gettimeofday( &stop_, &tz_ );
seconds_ += (double)(stop_.tv_sec - start_.tv_sec);
seconds_ += (double)(stop_.tv_usec- start_.tv_usec)*1e-6;
}
virtual void cont(void) { gettimeofday( &start_, &tz_); }
virtual double seconds() const { return seconds_; }
private:
struct timeval start_, stop_;
struct timezone tz_;
double seconds_;
};
#else // ---------------------------------------- standard implementation ----
#include <time.h>
static const unsigned long clockticks = CLOCKS_PER_SEC;
class TimerImplStd : public TimerImpl
{
public:
TimerImplStd() : freq_(clockticks) { reset(); }
~TimerImplStd() { ; }
virtual void reset(void) { count_ = 0; }
virtual void start(void) { count_ = 0; start_ = clock(); }
virtual void stop(void);
virtual void cont(void) { start_ = clock(); }
virtual double seconds(void) const { return (double)count_/(double)freq_; }
protected:
unsigned long freq_;
unsigned long count_;
unsigned long start_;
};
void TimerImplStd::stop(void)
{
unsigned long stop_ = clock();
count_ += stop_-start_;
}
#endif
// ----------------------------------------------------------------- Timer ----
Timer::Timer(void)
{
#if defined(WIN32) && defined(_MSC_VER)
impl_ = new TimerImplWin32;
#elif defined(__GNUC__) && defined(__POSIX__)
// CLOCK_REALTIME
// CLOCK_MONOTONIC - ?
// CLOCK_REALTIME_HR - RTlinux
// CLOCK_MONOTONIC_HR - ?
# if defined(CLOCK_REALTIME_HR)
impl_ = new TimerImplPosix<CLOCK_REALTIME_HR>;
# else
impl_ = new TimerImplPosix<CLOCK_REALTIME>;
# endif
#elif defined(__GNUC__) || (defined(__INTEL_COMPILER) && !defined(WIN32))
impl_ = new TimerImplGToD;
#else
impl_ = new TimerImplStd;
#endif
state_ = Stopped;
}
Timer::~Timer(void)
{
delete impl_;
state_ = Stopped;
}
void Timer::reset(void)
{
state_ = Stopped;
impl_->reset();
}
void Timer::start(void)
{
state_ = Running;
impl_->start();
}
void Timer::stop(void)
{
impl_->stop();
state_ = Stopped;
}
void Timer::cont(void)
{
impl_->cont();
state_ = Running;
}
double Timer::seconds(void) const
{
return state_==Stopped ? impl_->seconds() : 0.0;
}
std::string Timer::as_string(Timer::Format format)
{
if (state_ == Running)
return "Running";
return as_string(impl_->seconds(),format);
}
std::string Timer::as_string(double seconds, Timer::Format format)
{
char string[32];
double fraction;
double integer;
unsigned long t;
// double rest;
short hour,min,sec;
bool negative = false;
if ( seconds < 0 )
{
negative = true;
seconds *= -1;
}
fraction = modf(seconds,&integer);
t = (unsigned long)integer;
hour = short( t / 3600L );
t %= 3600L;
min = short( t / 60L );
t %= 60L;
sec = short( t );
// rest = (double)t + fraction;
char *ptr = string;
if (negative)
*ptr++ = '-';
switch(format)
{
case Timer::Automatic:
if (hour)
ptr += sprintf(ptr,"%02dh:",hour);
if (min)
ptr += sprintf(ptr,"%02dm:",min);
else if (ptr>string && hour)
ptr += sprintf(ptr,"00m:");
if (sec)
ptr += sprintf(ptr,"%02d",sec);
else if (ptr>string && min)
ptr += sprintf(ptr,"00");
if (!hour && !min) // higher resolution necessary
{
if (ptr > string && sec)
{
sprintf(ptr,".%.3fs",fraction);
ptr++;
while(*(ptr+2))
{
*ptr = *(ptr+2);
ptr++;
}
*ptr = '\0';
}
else if ( fraction * 1e2 > 0.1)
sprintf(ptr,"%.3fcs",fraction*1.e2);
else if ( fraction * 1e3 > 0.1)
sprintf(ptr,"%.3fms",fraction*1.e3);
else if ( fraction * 1e6 > 0.1)
sprintf(ptr,"%.1f\xb5s",fraction*1.e6);
else if ( fraction * 1e9 > 0.1)
sprintf(ptr,"%.1fns",fraction*1.e9);
else
sprintf(ptr,"%.1fps",fraction*1.e12);
} else // append a 's' for seconds!
{
ptr[0] = 's';
ptr[1] = '\0';
}
break;
case Timer::Long:
ptr += sprintf(ptr,"%02dh:%02dm:%02d",hour,min,sec);
sprintf(ptr,".%.12fs",fraction);
ptr++;
while(*(ptr+2))
{
*ptr = *(ptr+2);
ptr++;
}
*ptr = '\0';
break;
case Timer::Hours:
sprintf(ptr,"%02dh:%02dm:%02ds",hour,min,sec); break;
case Timer::Minutes:
ptr += sprintf(ptr,"%02dm:%02d", min, sec);
sprintf(ptr,".%.2fs",fraction);
ptr++;
while(*(ptr+2))
{
*ptr = *(ptr+2);
ptr++;
}
*ptr = '\0';
break;
case Timer::Seconds: sprintf(ptr,"%.3fs",seconds); break;
case Timer::HSeconds: sprintf(ptr,"%.3fcs",seconds*1e2); break;
case Timer::MSeconds: sprintf(ptr,"%.3fms",seconds*1e3); break;
case Timer::MicroSeconds: sprintf(ptr,"%.1f\xb5s",seconds*1e6); break;
case Timer::NanoSeconds: sprintf(ptr,"%.1fns",seconds*1e9); break;
}
return string;
}
// ============================================================================
} // END_NS_UTILS
} // END_NS_OPENMESH
// ----------------------------------------------------------------------------
#endif // DOXY_IGNORE_THIS
// ============================================================================
// end of file Timer.cc
// ============================================================================

169
Tools/Utils/Timer.hh Normal file
View File

@@ -0,0 +1,169 @@
// ============================================================================
// $Id: Timer.hh,v 1.1.1.1 2006-10-25 16:14:15 habbecke Exp $
// ----------------------------------------------------------------------------
#ifndef TIMER_HH
#define TIMER_HH
// ----------------------------------------------------------------------------
/** \file Timer.hh
A timer class
*/
// ----------------------------------------------------------------------------
#include <OpenMesh/Core/System/config.hh>
//
#include <iostream>
#include <string>
#if defined(OM_CC_MIPS)
# include <assert.h>
#else
# include <cassert>
#endif
// ------------------------------------------------------------- namespace ----
namespace OpenMesh {
namespace Utils {
// -------------------------------------------------------------- forwards ----
class TimerImpl;
// ----------------------------------------------------------------- class ----
/** Timer class
*/
class Timer
{
public:
/// Formatting options for member Timer::as_string()
enum Format {
Automatic,
Long,
Hours,
Minutes,
Seconds,
HSeconds,
MSeconds,
MicroSeconds,
NanoSeconds
};
Timer(void);
~Timer(void);
/// Returns true if self is in a valid state!
bool is_valid() const { return state_!=Invalid; }
bool is_stopped() const { return state_==Stopped; }
/// Reset the timer
void reset(void);
/// Start measurement
void start(void);
/// Stop measurement
void stop(void);
/// Continue measurement
void cont(void);
/// Give resolution of timer. Depends on the underlying measurement method.
float resolution() const;
/// Returns measured time in seconds, if the timer is in state 'Stopped'
double seconds(void) const;
/// Returns measured time in hundredth seconds, if the timer is in state 'Stopped'
double hseconds(void) const { return seconds()*1e2; }
/// Returns measured time in milli seconds, if the timer is in state 'Stopped'
double mseconds(void) const { return seconds()*1e3; }
/// Returns measured time in micro seconds, if the timer is in state 'Stopped'
double useconds(void) const { return seconds()*1e6; }
/** Returns the measured time as a string. Use the format flags to specify
a wanted resolution.
*/
std::string as_string(Format format = Automatic);
/** Returns a given measured time as a string. Use the format flags to
specify a wanted resolution.
*/
static std::string as_string(double seconds, Format format = Automatic);
public:
//@{
/// Compare timer values
bool operator < (const Timer& t2) const
{
assert( is_stopped() && t2.is_stopped() );
return (seconds() < t2.seconds());
}
bool operator > (const Timer& t2) const
{
assert( is_stopped() && t2.is_stopped() );
return (seconds() > t2.seconds());
}
bool operator == (const Timer& t2) const
{
assert( is_stopped() && t2.is_stopped() );
return (seconds() == t2.seconds());
}
bool operator <= (const Timer& t2) const
{
assert( is_stopped() && t2.is_stopped() );
return (seconds() <= t2.seconds());
}
bool operator >=(const Timer& t2) const
{
assert( is_stopped() && t2.is_stopped() );
return (seconds() >= t2.seconds());
}
//@}
protected:
TimerImpl *impl_;
enum {
Invalid = -1,
Stopped = 0,
Running = 1
} state_;
};
/** Write seconds to output stream.
* Timer must be stopped before.
* \relates Timer
*/
inline std::ostream& operator << (std::ostream& _o, const Timer& _t)
{
return (_o << _t.seconds());
}
// ============================================================================
} // END_NS_UTILS
} // END_NS_OPENMESH
// ============================================================================
#endif
// end of Timer.hh
// ===========================================================================

183
Tools/Utils/conio.cc Normal file
View File

@@ -0,0 +1,183 @@
// ============================================================================
#include <OpenMesh/Core/System/config.hh>
#include <OpenMesh/Tools/Utils/conio.hh>
// ----------------------------------------------------------------- Win32 ----
#ifdef WIN32
#include <conio.h>
namespace OpenMesh {
namespace Utils {
int kbhit() { return ::kbhit(); }
int getch() { return ::getch(); }
int getche() { return ::getche(); }
} // Tools
} // AS
// ----------------------------------------------------------------- Other ----
#else
// Based on code published by Floyd Davidson in a newsgroup.
#include <stdio.h> /* stdout, fflush() */
#if !defined(POSIX_1003_1_2001)
# include <fcntl.h>
# include <unistd.h>
#else
# include <select.h> /* select() */
#endif
#include <termios.h> /* tcsetattr() */
#include <sys/ioctl.h> /* ioctl() */
#include <sys/time.h> /* struct timeval */
namespace OpenMesh {
namespace Utils {
#ifdef CTIME
# undef CTIME
#endif
#define CTIME 1
#define CMIN 1
int kbhit(void)
{
int cnt = 0;
int error;
static struct termios Otty, Ntty;
tcgetattr(0, &Otty);
Ntty = Otty;
Ntty.c_iflag = 0; /* input mode */
Ntty.c_oflag = 0; /* output mode */
Ntty.c_lflag &= ~ICANON; /* raw mode */
Ntty.c_cc[VMIN] = CMIN; /* minimum chars to wait for */
Ntty.c_cc[VTIME] = CTIME; /* minimum wait time */
if (0 == (error = tcsetattr(0, TCSANOW, &Ntty)))
{
struct timeval tv;
error += ioctl(0, FIONREAD, &cnt);
error += tcsetattr(0, TCSANOW, &Otty);
tv.tv_sec = 0;
tv.tv_usec = 100; /* insert at least a minimal delay */
select(1, NULL, NULL, NULL, &tv);
}
return (error == 0 ? cnt : -1 );
}
int getch(void)
{
char ch;
int error;
static struct termios Otty, Ntty;
fflush(stdout);
tcgetattr(0, &Otty);
Ntty = Otty;
Ntty.c_iflag = 0; // input mode
Ntty.c_oflag = 0; // output mode
Ntty.c_lflag &= ~ICANON; // line settings
Ntty.c_lflag &= ~ECHO; // enable echo
Ntty.c_cc[VMIN] = CMIN; // minimum chars to wait for
Ntty.c_cc[VTIME] = CTIME; // minimum wait time
// Conditionals allow compiling with or without flushing pre-existing
// existing buffered input before blocking.
#if 1
// use this to flush the input buffer before blocking for new input
# define FLAG TCSAFLUSH
#else
// use this to return a char from the current input buffer, or block if
// no input is waiting.
# define FLAG TCSANOW
#endif
if (0 == (error = tcsetattr(0, FLAG, &Ntty)))
{
error = read(0, &ch, 1 ); // get char from stdin
error += tcsetattr(0, FLAG, &Otty); // restore old settings
}
return (error == 1 ? (int) ch : -1 );
}
int getche(void)
{
char ch;
int error;
static struct termios Otty, Ntty;
fflush(stdout);
tcgetattr(0, &Otty);
Ntty = Otty;
Ntty.c_iflag = 0; // input mode
Ntty.c_oflag = 0; // output mode
Ntty.c_lflag &= ~ICANON; // line settings
Ntty.c_lflag |= ECHO; // enable echo
Ntty.c_cc[VMIN] = CMIN; // minimum chars to wait for
Ntty.c_cc[VTIME] = CTIME; // minimum wait time
// Conditionals allow compiling with or without flushing pre-existing
// existing buffered input before blocking.
#if 1
// use this to flush the input buffer before blocking for new input
# define FLAG TCSAFLUSH
#else
// use this to return a char from the current input buffer, or block if
// no input is waiting.
# define FLAG TCSANOW
#endif
if (0 == (error = tcsetattr(0, FLAG, &Ntty))) {
error = read(0, &ch, 1 ); // get char from stdin
error += tcsetattr(0, FLAG, &Otty); // restore old settings
}
return (error == 1 ? (int) ch : -1 );
}
} // namespace Tools
} // namespace AS
// ----------------------------------------------------------------------------
#endif // System dependent parts
// ============================================================================
//#define Test
#if defined(Test)
#include <ctype.h>
int main (void)
{
char msg[] = "press key to continue...";
char *ptr = msg, tmp;
while ( !OpenMesh::Utils::kbhit() )
{
tmp = *ptr;
*ptr = islower(tmp) ? toupper(tmp) : tolower(tmp);
printf("\r%s", msg); fflush(stdout);
*ptr = (char)tmp;
if (!*(++ptr))
ptr = msg;
usleep(20000);
}
printf("\r%s.", msg); fflush(stdout);
OpenMesh::Utils::getch();
printf("\r%s..", msg); fflush(stdout);
OpenMesh::Utils::getche();
return 0;
}
#endif // Test
// ============================================================================

37
Tools/Utils/conio.hh Normal file
View File

@@ -0,0 +1,37 @@
#ifndef OPENMESH_UTILS_CONIO_HH
#define OPENMESH_UTILS_CONIO_HH
// ----------------------------------------------------------------------------
namespace OpenMesh {
namespace Utils {
// ----------------------------------------------------------------------------
/** Check if characters a pending in stdin.
*
* \return Number of characters available to read.
*
* \see getch(), getche()
*/
int kbhit(void);
/** A blocking single character input from stdin
*
* \return Character, or -1 if an input error occurs.
*
* \see getche(), kbhit()
*/
int getch(void);
/** A blocking single character input from stdin with echo.
*
* \return Character, or -1 if an input error occurs.
* \see getch(), kbhit()
*/
int getche(void);
// ----------------------------------------------------------------------------
} // namespace Utils
} // namespace OpenMesh
// ----------------------------------------------------------------------------
#endif // OPENMESH_UTILS_CONIO_HH
// ============================================================================

116
Tools/Utils/getopt.c Normal file
View File

@@ -0,0 +1,116 @@
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "getopt.h"
int opterr = 1, /* if error message should be printed */
optind = 1, /* index into parent argv vector */
optopt, /* character checked for validity */
optreset; /* reset getopt */
char *optarg; /* argument associated with option */
#define BADCH (int)'?'
#define BADARG (int)':'
#define EMSG ""
/*
* getopt --
* Parse argc/argv argument vector.
*/
int
getopt(int nargc, char * const *nargv, const char *ostr)
{
# define __progname nargv[0]
static char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc || *(place = nargv[optind]) != '-') {
place = EMSG;
return (-1);
}
if (place[1] && *++place == '-') { /* found "--" */
++optind;
place = EMSG;
return (-1);
}
} /* option letter okay? */
if ((optopt = (int)*place++) == (int)':' ||
!(oli = strchr(ostr, optopt))) {
/*
* if the user didn't specify '-' as an option,
* assume it means -1.
*/
if (optopt == (int)'-')
return (-1);
if (!*place)
++optind;
if (opterr && *ostr != ':')
(void)fprintf(stderr,
"%s: illegal option -- %c\n", __progname, optopt);
return (BADCH);
}
if (*++oli != ':') { /* don't need argument */
optarg = NULL;
if (!*place)
++optind;
}
else { /* need an argument */
if (*place) /* no white space */
optarg = place;
else if (nargc <= ++optind) { /* no arg */
place = EMSG;
if (*ostr == ':')
return (BADARG);
if (opterr)
(void)fprintf(stderr,
"%s: option requires an argument -- %c\n",
__progname, optopt);
return (BADCH);
}
else /* white space */
optarg = nargv[optind];
place = EMSG;
++optind;
}
return (optopt); /* dump back option letter */
}

26
Tools/Utils/getopt.h Normal file
View File

@@ -0,0 +1,26 @@
#ifndef _GETOPT_H_
#define _GETOPT_H_
#include <OpenMesh/Core/System/compiler.hh>
#if defined(WIN32)
#if defined(__cplusplus)
extern "C" {
extern int opterr;
extern int optind;
extern int optopt;
extern int optreset;
extern char *optarg;
extern int getopt(int nargc, char * const *nargv, const char *ostr);
}
# endif
#else
# include <getopt.h>
#endif
#endif /* _GETOPT_H_ */