/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (C) 2001-2010 by Computer Graphics Group, RWTH Aachen *
* www.openflipper.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenFlipper. *
* *
* OpenFlipper 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, either version 3 of *
* the License, or (at your option) any later version with the *
* following exceptions: *
* *
* If other files instantiate templates or use macros *
* or inline functions from this file, or you compile this file and *
* link it with other files to produce an executable, this file does *
* not by itself cause the resulting executable to be covered by the *
* GNU Lesser General Public License. This exception does not however *
* invalidate any other reasons why the executable file might be *
* covered by the GNU Lesser General Public License. *
* *
* OpenFlipper 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 LesserGeneral Public *
* License along with OpenFlipper. If not, *
* see . *
* *
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision$ *
* $Author$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS PlaneT
//
//=============================================================================
#ifndef ACG_PLANE_HH
#define ACG_PLANE_HH
//== INCLUDES =================================================================
#include "../../Math/VectorT.hh"
#include "../../Math/Matrix4x4T.hh"
//== NAMESPACES ===============================================================
namespace ACG {
namespace Geometry {
//== CLASS DEFINITION =========================================================
/** \class PlaneT PlaneT.hh
This class stores a plane in normal form and provides useful
algorithms for left/right test, itersection, and so on.
**/
template
class PlaneT
{
public:
/// typedefs
typedef VectorT Vec3;
typedef VectorT Vec4;
typedef Matrix4x4T Mat4x4;
/// constructor: coefficients
PlaneT( Scalar _a=0, Scalar _b=0, Scalar _c=0, Scalar _d=0 )
: coeffs_(_a, _b, _c, _d)
{ HNF(); }
/// constructor: origin and normal
PlaneT( const Vec3& _o, const Vec3& _n )
: coeffs_(_n[0], _n[1], _n[2], -(_n|_o))
{ HNF(); }
/// constructor: 3 points
PlaneT( const Vec3& _v0, const Vec3& _v1, const Vec3& _v2 )
{
Vec3 n = (_v1-_v0) % (_v2-_v0);
coeffs_ = Vec4(n[0], n[1], n[2], -(n|_v0));
HNF();
}
/// normal vector
Vec3 normal() const { return Vec3(coeffs_[0], coeffs_[1], coeffs_[2]); }
/// coeffitients
const Vec4& coeffs() const { return coeffs_; }
/// signed distance point-plane
Scalar distance( const Vec3& _v ) const
{
return ( _v[0]*coeffs_[0] +
_v[1]*coeffs_[1] +
_v[2]*coeffs_[2] +
coeffs_[3] );
}
/// predicate: above plane
bool operator() ( const Vec3& _v ) const { return distance(_v) > 0; }
// INTERSECTION
enum IntersectionTarget { Line, LineSegment, Ray };
// intersect with (infinite) line
bool intersect_line( const Vec3& _v0, const Vec3& _v1,
Vec3& _v, Scalar& _t ) const
{ return intersect(_v0, _v1, _v, _t, Line); }
// intersect with ray
bool intersect_ray( const Vec3& _v0, const Vec3& _v1,
Vec3& _v, Scalar& _t ) const
{ return intersect(_v0, _v1, _v, _t, Ray); }
// intersect with line segment
bool intersect_linesegment( const Vec3& _v0, const Vec3& _v1,
Vec3& _v, Scalar& _t ) const
{ return intersect(_v0, _v1, _v, _t, LineSegment); }
/** \brief General intersection function.
*
* General intersection between a line/ray and the plane.
*
* @param _v0 start vector of the ray
* @param _v1 end vector of the ray
* @param _v returned intersection point
* @param _t returned relative distance from the interection to _v0 compared to _v1
* @param _target type of intersection to test
* @return true if an intersection was found
*/
bool intersect( const Vec3& _v0,
const Vec3& _v1,
Vec3& _v,
Scalar& _t,
IntersectionTarget _target ) const
{
#define SGN(d) ((d>0.0) ? 1 : -1)
Scalar d0(distance(_v0)), d1(distance(_v1));
Scalar a0(fabs(d0)), a1(fabs(d1));
// endpoint on plane
if (a0 < FLT_MIN) { _v = _v0; _t = 0.0; return true; }
if (a1 < FLT_MIN) { _v = _v1; _t = 1.0; return true; }
// triv accept
if (SGN(d0) != SGN(d1))
{
_t = (a0/(a0+a1));
_v = _v0*(1.0-_t) + _v1*_t;
return true;
}
// depends on target
else
{
if (_target == LineSegment) return false;
if (fabs(d0-d1) < FLT_MIN) return false; // line parallel to plane
else _t = d0/(d0-d1);
if (_target == Ray && _t < 0.0) return false;
_v = _v0*(1.0-_t) + _v1*_t;
return true;
}
#undef SGN
}
/// affine transformation of the plane
bool affine_transformation( const Mat4x4& _M )
{
Mat4x4 M(_M);
if (!M.invert()) return false;
M.transpone();
affineTransformation_precomp(M);
return true;
}
/// affine transformation of the plane (M^{-T} precomputed)
void affine_transformation_precomp( const Mat4x4& _M_inverseTransposed )
{
coeffs_ = _M_inverseTransposed*coeffs_;
HNF();
}
private:
void HNF() {
Scalar n = normal().norm();
if (n != 0.0) coeffs_ /= n;
}
Vec4 coeffs_;
};
typedef PlaneT Planef;
typedef PlaneT Planed;
//=============================================================================
} // namespace Geometry
} // namespace ACG
//=============================================================================
#endif // ACG_PLANE_HH defined
//=============================================================================