2004-02-13 03:18:57 +01:00
|
|
|
/****************************************************************************
|
|
|
|
* VCGLib o o *
|
|
|
|
* Visual and Computer Graphics Library o o *
|
|
|
|
* _ O _ *
|
|
|
|
* Copyright(C) 2004 \/)\/ *
|
|
|
|
* Visual Computing Lab /\/| *
|
|
|
|
* ISTI - Italian National Research Council | *
|
|
|
|
* \ *
|
|
|
|
* All rights reserved. *
|
|
|
|
* *
|
make point2 derived Eigen's Matrix, and a set of minimal fixes to make meshlab compile
with both old and new version. The fixes include:
- dot product: vec0 * vec1 => vec0.dot(vec1) (I added .dot() to the old Point classes too)
- Transpose: Transpose is an Eigen type, so we cannot keep it if Eigen is used. Therefore
I added a .tranpose() to old matrix classes, and modified most of the Transpose() to transpose()
both in vcg and meshlab. In fact, transpose() are free with Eigen, it simply returns a transpose
expression without copies. On the other be carefull: m = m.transpose() won't work as expected,
here me must evaluate to a temporary: m = m.transpose().eval(); However, this operation in very
rarely needed: you transpose at the same sime you set m, or you use m.transpose() directly.
- the last issue is Normalize which both modifies *this and return a ref to it. This behavior
don't make sense anymore when using expression template, e.g., in (a+b).Normalize(), the type
of a+b if not a Point (or whatever Vector types), it an expression of the addition of 2 points,
so we cannot modify the value of *this, since there is no value. Therefore I've already changed
all those .Normalize() of expressions to the Eigen's version .normalized().
- Finally I've changed the Zero to SetZero in the old Point classes too.
2008-10-28 01:59:46 +01:00
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
2004-02-13 03:18:57 +01:00
|
|
|
* 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 (http://www.gnu.org/licenses/gpl.txt) *
|
|
|
|
* for more details. *
|
|
|
|
* *
|
|
|
|
****************************************************************************/
|
2004-02-09 14:32:16 +01:00
|
|
|
/****************************************************************************
|
|
|
|
History
|
|
|
|
|
2004-02-13 03:18:57 +01:00
|
|
|
$Log: not supported by cvs2svn $
|
2007-07-24 09:09:17 +02:00
|
|
|
Revision 1.21 2007/01/08 09:23:49 pietroni
|
|
|
|
added explicit cast in function inline float Sqrt(const int v) in order to avoid warnings
|
|
|
|
|
2007-01-08 10:23:49 +01:00
|
|
|
Revision 1.20 2006/10/13 13:14:50 cignoni
|
|
|
|
Added two sqrt templates for resolving ambiguity of sqrt(int)
|
|
|
|
|
2006-10-13 15:14:50 +02:00
|
|
|
Revision 1.19 2005/12/01 01:03:37 cignoni
|
|
|
|
Removed excess ';' from end of template functions, for gcc compiling
|
|
|
|
|
2005-12-01 02:03:37 +01:00
|
|
|
Revision 1.18 2004/08/31 15:42:59 fasano
|
|
|
|
Aggiunte macro sin/cos/atan per C++ Builder
|
|
|
|
|
2004-08-31 17:42:59 +02:00
|
|
|
Revision 1.17 2004/05/10 13:00:14 ganovelli
|
|
|
|
limits function cancelled
|
|
|
|
|
2004-05-10 15:00:14 +02:00
|
|
|
Revision 1.16 2004/05/03 08:38:08 ganovelli
|
|
|
|
correction on templates
|
|
|
|
|
2004-05-03 10:38:08 +02:00
|
|
|
Revision 1.15 2004/04/15 09:36:59 ganovelli
|
|
|
|
Min and Max changed from const members to static class function
|
|
|
|
Use: Value<float>::Min()
|
|
|
|
|
2004-04-15 11:36:59 +02:00
|
|
|
Revision 1.14 2004/03/31 12:41:55 tarini
|
|
|
|
debugged Max and Min const values (to make them linkable)
|
|
|
|
|
2004-03-31 14:41:55 +02:00
|
|
|
Revision 1.13 2004/03/31 10:09:19 cignoni
|
|
|
|
int64 -> long long for GCC compatibility
|
|
|
|
|
2004-03-31 12:09:19 +02:00
|
|
|
Revision 1.12 2004/03/16 00:23:50 tarini
|
|
|
|
- added VoidType - added "static_assert"
|
|
|
|
|
2004-03-16 01:23:50 +01:00
|
|
|
Revision 1.11 2004/03/10 17:37:54 tarini
|
|
|
|
Added Atan2.
|
|
|
|
Added common utilities: Max, Min, Swap, Sort(a,b), Sort(a,b,c).
|
|
|
|
Changed Max values syntax. example: Value<float>::Max
|
|
|
|
|
2004-03-10 18:37:54 +01:00
|
|
|
Revision 1.10 2004/03/10 16:54:57 tarini
|
|
|
|
Added Atan2.
|
|
|
|
Added common utilities: Max, Min, Swap, Sort(a,b), Sort(a,b,c).
|
|
|
|
Changed Max values syntax. example: Value<float>::Max
|
|
|
|
|
2004-03-08 20:40:48 +01:00
|
|
|
Revision 1.7 2004/03/08 19:38:29 tarini
|
2004-03-16 01:23:50 +01:00
|
|
|
Added Min e Max. usage: Min<float>::Value (tarini)
|
2004-03-08 20:40:48 +01:00
|
|
|
|
2004-03-08 20:38:29 +01:00
|
|
|
Revision 1.6 2004/03/08 14:49:37 ponchio
|
|
|
|
Aggiunti un po di inline davanti alle funzioni
|
|
|
|
|
2004-03-08 15:49:37 +01:00
|
|
|
Revision 1.5 2004/03/04 00:21:00 ponchio
|
|
|
|
added Acos e Asin
|
|
|
|
|
2004-03-04 01:21:00 +01:00
|
|
|
Revision 1.4 2004/03/03 22:51:49 cignoni
|
|
|
|
changed math from class to template
|
|
|
|
|
2004-02-19 16:28:01 +01:00
|
|
|
Revision 1.2 2004/02/13 02:18:57 cignoni
|
|
|
|
Edited Comments and GPL license
|
|
|
|
|
2004-02-09 14:32:16 +01:00
|
|
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#ifndef __VCGLIB_MATH_BASE
|
|
|
|
#define __VCGLIB_MATH_BASE
|
|
|
|
|
2011-10-05 17:04:40 +02:00
|
|
|
#include <float.h>
|
2004-02-09 14:32:16 +01:00
|
|
|
#include <math.h>
|
|
|
|
#include <assert.h>
|
2008-09-30 13:41:04 +02:00
|
|
|
#include <limits>
|
2013-07-26 09:01:21 +02:00
|
|
|
#include <algorithm>
|
2004-02-09 14:32:16 +01:00
|
|
|
|
2004-03-16 01:23:50 +01:00
|
|
|
|
2004-02-09 14:32:16 +01:00
|
|
|
#ifdef __BORLANDC__
|
|
|
|
float sqrtf (float v) {return sqrt(v);}
|
|
|
|
float fabsf (float v) {return fabs(v);}
|
2004-08-31 17:42:59 +02:00
|
|
|
float cosf (float v) {return cos(v);}
|
|
|
|
float sinf (float v) {return sin(v);}
|
|
|
|
float acosf (float v) {return acos(v);}
|
|
|
|
float asinf (float v) {return asin(v);}
|
|
|
|
float atan2f (float v0, float v1) {return atan2(v0,v1);}
|
|
|
|
#endif
|
2004-02-09 14:32:16 +01:00
|
|
|
|
|
|
|
namespace vcg {
|
2004-03-16 01:23:50 +01:00
|
|
|
|
2004-03-03 23:51:49 +01:00
|
|
|
namespace math {
|
2004-02-09 14:32:16 +01:00
|
|
|
|
make point2 derived Eigen's Matrix, and a set of minimal fixes to make meshlab compile
with both old and new version. The fixes include:
- dot product: vec0 * vec1 => vec0.dot(vec1) (I added .dot() to the old Point classes too)
- Transpose: Transpose is an Eigen type, so we cannot keep it if Eigen is used. Therefore
I added a .tranpose() to old matrix classes, and modified most of the Transpose() to transpose()
both in vcg and meshlab. In fact, transpose() are free with Eigen, it simply returns a transpose
expression without copies. On the other be carefull: m = m.transpose() won't work as expected,
here me must evaluate to a temporary: m = m.transpose().eval(); However, this operation in very
rarely needed: you transpose at the same sime you set m, or you use m.transpose() directly.
- the last issue is Normalize which both modifies *this and return a ref to it. This behavior
don't make sense anymore when using expression template, e.g., in (a+b).Normalize(), the type
of a+b if not a Point (or whatever Vector types), it an expression of the addition of 2 points,
so we cannot modify the value of *this, since there is no value. Therefore I've already changed
all those .Normalize() of expressions to the Eigen's version .normalized().
- Finally I've changed the Zero to SetZero in the old Point classes too.
2008-10-28 01:59:46 +01:00
|
|
|
template <class SCALAR>
|
2004-03-03 23:51:49 +01:00
|
|
|
class MagnitudoComparer
|
2004-02-09 14:32:16 +01:00
|
|
|
{
|
|
|
|
public:
|
2013-03-22 17:43:59 +01:00
|
|
|
inline bool operator() ( const SCALAR a, const SCALAR b ) { return fabs(a)>fabs(b); }
|
2004-02-09 14:32:16 +01:00
|
|
|
};
|
make point2 derived Eigen's Matrix, and a set of minimal fixes to make meshlab compile
with both old and new version. The fixes include:
- dot product: vec0 * vec1 => vec0.dot(vec1) (I added .dot() to the old Point classes too)
- Transpose: Transpose is an Eigen type, so we cannot keep it if Eigen is used. Therefore
I added a .tranpose() to old matrix classes, and modified most of the Transpose() to transpose()
both in vcg and meshlab. In fact, transpose() are free with Eigen, it simply returns a transpose
expression without copies. On the other be carefull: m = m.transpose() won't work as expected,
here me must evaluate to a temporary: m = m.transpose().eval(); However, this operation in very
rarely needed: you transpose at the same sime you set m, or you use m.transpose() directly.
- the last issue is Normalize which both modifies *this and return a ref to it. This behavior
don't make sense anymore when using expression template, e.g., in (a+b).Normalize(), the type
of a+b if not a Point (or whatever Vector types), it an expression of the addition of 2 points,
so we cannot modify the value of *this, since there is no value. Therefore I've already changed
all those .Normalize() of expressions to the Eigen's version .normalized().
- Finally I've changed the Zero to SetZero in the old Point classes too.
2008-10-28 01:59:46 +01:00
|
|
|
|
2006-10-13 15:14:50 +02:00
|
|
|
inline float Sqrt(const short v) { return sqrtf(v); }
|
2007-01-08 10:23:49 +01:00
|
|
|
inline float Sqrt(const int v) { return sqrtf((float)v); }
|
make point2 derived Eigen's Matrix, and a set of minimal fixes to make meshlab compile
with both old and new version. The fixes include:
- dot product: vec0 * vec1 => vec0.dot(vec1) (I added .dot() to the old Point classes too)
- Transpose: Transpose is an Eigen type, so we cannot keep it if Eigen is used. Therefore
I added a .tranpose() to old matrix classes, and modified most of the Transpose() to transpose()
both in vcg and meshlab. In fact, transpose() are free with Eigen, it simply returns a transpose
expression without copies. On the other be carefull: m = m.transpose() won't work as expected,
here me must evaluate to a temporary: m = m.transpose().eval(); However, this operation in very
rarely needed: you transpose at the same sime you set m, or you use m.transpose() directly.
- the last issue is Normalize which both modifies *this and return a ref to it. This behavior
don't make sense anymore when using expression template, e.g., in (a+b).Normalize(), the type
of a+b if not a Point (or whatever Vector types), it an expression of the addition of 2 points,
so we cannot modify the value of *this, since there is no value. Therefore I've already changed
all those .Normalize() of expressions to the Eigen's version .normalized().
- Finally I've changed the Zero to SetZero in the old Point classes too.
2008-10-28 01:59:46 +01:00
|
|
|
|
2004-03-08 15:49:37 +01:00
|
|
|
inline float Sqrt(const float v) { return sqrtf(v); }
|
|
|
|
inline float Abs(const float v) { return fabsf(v); }
|
|
|
|
inline float Cos(const float v) { return cosf(v); }
|
|
|
|
inline float Sin(const float v) { return sinf(v); }
|
|
|
|
inline float Acos(const float v) { return acosf(v); }
|
|
|
|
inline float Asin(const float v) { return asinf(v); }
|
2004-03-10 17:54:57 +01:00
|
|
|
inline float Atan2(const float v0,const float v1) { return atan2f(v0,v1); }
|
2004-03-03 23:51:49 +01:00
|
|
|
|
2004-03-08 15:49:37 +01:00
|
|
|
inline double Sqrt(const double v) { return sqrt(v); }
|
|
|
|
inline double Abs(const double v) { return fabs(v); }
|
|
|
|
inline double Cos(const double v) { return cos(v); }
|
|
|
|
inline double Sin(const double v) { return sin(v); }
|
|
|
|
inline double Acos(const double v) { return acos(v); }
|
|
|
|
inline double Asin(const double v) { return asin(v); }
|
2004-03-10 17:54:57 +01:00
|
|
|
inline double Atan2(const double v0,const double v1) { return atan2(v0,v1); }
|
make point2 derived Eigen's Matrix, and a set of minimal fixes to make meshlab compile
with both old and new version. The fixes include:
- dot product: vec0 * vec1 => vec0.dot(vec1) (I added .dot() to the old Point classes too)
- Transpose: Transpose is an Eigen type, so we cannot keep it if Eigen is used. Therefore
I added a .tranpose() to old matrix classes, and modified most of the Transpose() to transpose()
both in vcg and meshlab. In fact, transpose() are free with Eigen, it simply returns a transpose
expression without copies. On the other be carefull: m = m.transpose() won't work as expected,
here me must evaluate to a temporary: m = m.transpose().eval(); However, this operation in very
rarely needed: you transpose at the same sime you set m, or you use m.transpose() directly.
- the last issue is Normalize which both modifies *this and return a ref to it. This behavior
don't make sense anymore when using expression template, e.g., in (a+b).Normalize(), the type
of a+b if not a Point (or whatever Vector types), it an expression of the addition of 2 points,
so we cannot modify the value of *this, since there is no value. Therefore I've already changed
all those .Normalize() of expressions to the Eigen's version .normalized().
- Finally I've changed the Zero to SetZero in the old Point classes too.
2008-10-28 01:59:46 +01:00
|
|
|
|
2013-03-22 17:43:59 +01:00
|
|
|
template <typename T> inline static T Sqr(T a) { return a*a; }
|
make point2 derived Eigen's Matrix, and a set of minimal fixes to make meshlab compile
with both old and new version. The fixes include:
- dot product: vec0 * vec1 => vec0.dot(vec1) (I added .dot() to the old Point classes too)
- Transpose: Transpose is an Eigen type, so we cannot keep it if Eigen is used. Therefore
I added a .tranpose() to old matrix classes, and modified most of the Transpose() to transpose()
both in vcg and meshlab. In fact, transpose() are free with Eigen, it simply returns a transpose
expression without copies. On the other be carefull: m = m.transpose() won't work as expected,
here me must evaluate to a temporary: m = m.transpose().eval(); However, this operation in very
rarely needed: you transpose at the same sime you set m, or you use m.transpose() directly.
- the last issue is Normalize which both modifies *this and return a ref to it. This behavior
don't make sense anymore when using expression template, e.g., in (a+b).Normalize(), the type
of a+b if not a Point (or whatever Vector types), it an expression of the addition of 2 points,
so we cannot modify the value of *this, since there is no value. Therefore I've already changed
all those .Normalize() of expressions to the Eigen's version .normalized().
- Finally I've changed the Zero to SetZero in the old Point classes too.
2008-10-28 01:59:46 +01:00
|
|
|
|
2010-09-22 00:00:39 +02:00
|
|
|
template<class T> inline const T & Min(const T &a, const T &b,const T &c){
|
|
|
|
if (a<b) {
|
|
|
|
if(a<c) return a;
|
|
|
|
else return c;
|
|
|
|
} else {
|
|
|
|
if(b<c) return b;
|
|
|
|
else return c;
|
|
|
|
}
|
2013-03-22 17:43:59 +01:00
|
|
|
}
|
2010-09-22 00:00:39 +02:00
|
|
|
template<class T> inline const T & Max(const T &a, const T &b, const T &c){
|
|
|
|
if (a>b) {
|
|
|
|
if(a>c) return a;
|
|
|
|
else return c; // if c<a then c is smaller than b...
|
|
|
|
} else {
|
|
|
|
if(b>c) return b;
|
|
|
|
else return c;
|
|
|
|
}
|
|
|
|
}
|
2004-05-10 15:00:14 +02:00
|
|
|
|
2004-03-31 12:09:19 +02:00
|
|
|
template<class T> inline void Sort(T &a, T &b){
|
2013-07-26 09:01:21 +02:00
|
|
|
if (a>b) std::swap(a,b);
|
2005-12-01 02:03:37 +01:00
|
|
|
}
|
2004-03-31 12:09:19 +02:00
|
|
|
template<class T> inline void Sort(T &a, T &b, T &c){
|
2013-07-26 09:01:21 +02:00
|
|
|
if (a>b) std::swap(a,b);
|
|
|
|
if (b>c) {std::swap(b,c); if (a>b) std::swap(a,b);}
|
make point2 derived Eigen's Matrix, and a set of minimal fixes to make meshlab compile
with both old and new version. The fixes include:
- dot product: vec0 * vec1 => vec0.dot(vec1) (I added .dot() to the old Point classes too)
- Transpose: Transpose is an Eigen type, so we cannot keep it if Eigen is used. Therefore
I added a .tranpose() to old matrix classes, and modified most of the Transpose() to transpose()
both in vcg and meshlab. In fact, transpose() are free with Eigen, it simply returns a transpose
expression without copies. On the other be carefull: m = m.transpose() won't work as expected,
here me must evaluate to a temporary: m = m.transpose().eval(); However, this operation in very
rarely needed: you transpose at the same sime you set m, or you use m.transpose() directly.
- the last issue is Normalize which both modifies *this and return a ref to it. This behavior
don't make sense anymore when using expression template, e.g., in (a+b).Normalize(), the type
of a+b if not a Point (or whatever Vector types), it an expression of the addition of 2 points,
so we cannot modify the value of *this, since there is no value. Therefore I've already changed
all those .Normalize() of expressions to the Eigen's version .normalized().
- Finally I've changed the Zero to SetZero in the old Point classes too.
2008-10-28 01:59:46 +01:00
|
|
|
}
|
2004-03-08 20:38:29 +01:00
|
|
|
|
2004-02-09 14:32:16 +01:00
|
|
|
/* Some <math.h> files do not define M_PI... */
|
|
|
|
#ifndef M_PI
|
|
|
|
#define M_PI 3.14159265358979323846
|
|
|
|
#endif
|
|
|
|
|
2008-05-28 10:51:32 +02:00
|
|
|
#ifndef SQRT_TWO
|
|
|
|
#define SQRT_TWO 1.4142135623730950488
|
|
|
|
#endif
|
make point2 derived Eigen's Matrix, and a set of minimal fixes to make meshlab compile
with both old and new version. The fixes include:
- dot product: vec0 * vec1 => vec0.dot(vec1) (I added .dot() to the old Point classes too)
- Transpose: Transpose is an Eigen type, so we cannot keep it if Eigen is used. Therefore
I added a .tranpose() to old matrix classes, and modified most of the Transpose() to transpose()
both in vcg and meshlab. In fact, transpose() are free with Eigen, it simply returns a transpose
expression without copies. On the other be carefull: m = m.transpose() won't work as expected,
here me must evaluate to a temporary: m = m.transpose().eval(); However, this operation in very
rarely needed: you transpose at the same sime you set m, or you use m.transpose() directly.
- the last issue is Normalize which both modifies *this and return a ref to it. This behavior
don't make sense anymore when using expression template, e.g., in (a+b).Normalize(), the type
of a+b if not a Point (or whatever Vector types), it an expression of the addition of 2 points,
so we cannot modify the value of *this, since there is no value. Therefore I've already changed
all those .Normalize() of expressions to the Eigen's version .normalized().
- Finally I've changed the Zero to SetZero in the old Point classes too.
2008-10-28 01:59:46 +01:00
|
|
|
|
|
|
|
template <class SCALAR>
|
2004-03-03 23:51:49 +01:00
|
|
|
inline SCALAR Clamp( const SCALAR & val, const SCALAR& minval, const SCALAR& maxval)
|
2004-02-09 14:32:16 +01:00
|
|
|
{
|
|
|
|
if(val < minval) return minval;
|
|
|
|
if(val > maxval) return maxval;
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-03-03 23:51:49 +01:00
|
|
|
inline float ToDeg(const float &a){return a*180.0f/float(M_PI);}
|
|
|
|
inline float ToRad(const float &a){return float(M_PI)*a/180.0f;}
|
|
|
|
inline double ToDeg(const double &a){return a*180.0/M_PI;}
|
|
|
|
inline double ToRad(const double &a){return M_PI*a/180.0;}
|
2004-02-09 14:32:16 +01:00
|
|
|
|
2011-10-05 17:04:40 +02:00
|
|
|
|
2007-07-24 09:09:17 +02:00
|
|
|
#if defined(_MSC_VER) // Microsoft Visual C++
|
2011-10-05 17:04:40 +02:00
|
|
|
template<class T> int IsNAN(T t) { return _isnan(t) || (!_finite(t)); }
|
2007-07-24 09:09:17 +02:00
|
|
|
#elif defined(__GNUC__) // GCC
|
2011-10-05 17:04:40 +02:00
|
|
|
template<class T> int IsNAN(T t) { return isnan(t) || isinf(t); }
|
2007-07-24 09:09:17 +02:00
|
|
|
#else // generic
|
|
|
|
|
|
|
|
template<class T> int IsNAN(T t)
|
|
|
|
{
|
|
|
|
if(std::numeric_limits<T>::has_infinity)
|
|
|
|
return !(t <= std::numeric_limits<T>::infinity());
|
|
|
|
else
|
|
|
|
return t != t;
|
|
|
|
}
|
|
|
|
|
make point2 derived Eigen's Matrix, and a set of minimal fixes to make meshlab compile
with both old and new version. The fixes include:
- dot product: vec0 * vec1 => vec0.dot(vec1) (I added .dot() to the old Point classes too)
- Transpose: Transpose is an Eigen type, so we cannot keep it if Eigen is used. Therefore
I added a .tranpose() to old matrix classes, and modified most of the Transpose() to transpose()
both in vcg and meshlab. In fact, transpose() are free with Eigen, it simply returns a transpose
expression without copies. On the other be carefull: m = m.transpose() won't work as expected,
here me must evaluate to a temporary: m = m.transpose().eval(); However, this operation in very
rarely needed: you transpose at the same sime you set m, or you use m.transpose() directly.
- the last issue is Normalize which both modifies *this and return a ref to it. This behavior
don't make sense anymore when using expression template, e.g., in (a+b).Normalize(), the type
of a+b if not a Point (or whatever Vector types), it an expression of the addition of 2 points,
so we cannot modify the value of *this, since there is no value. Therefore I've already changed
all those .Normalize() of expressions to the Eigen's version .normalized().
- Finally I've changed the Zero to SetZero in the old Point classes too.
2008-10-28 01:59:46 +01:00
|
|
|
#endif
|
2004-03-16 01:23:50 +01:00
|
|
|
} // End math namespace
|
|
|
|
|
|
|
|
/// a type that stands for "void". Useful for Parameter type of a point.
|
|
|
|
class VoidType{ public:
|
2013-03-22 17:43:59 +01:00
|
|
|
VoidType(){};
|
2004-03-16 01:23:50 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
} // End vcg namespace
|
2004-02-09 14:32:16 +01:00
|
|
|
|
|
|
|
|
2004-03-31 12:09:19 +02:00
|
|
|
#endif
|