Commit 5587bbe0 authored by Kenneth Vanhoey's avatar Kenneth Vanhoey

rename localFrame -> Frame ; move from Utils to Geom namespace

parent 5b547772
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps *
* version 0.1 *
* Copyright (C) 2009-2011, IGG Team, LSIIT, University of Strasbourg *
* *
* 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; either version 2.1 of the License, or (at your *
* option) any later version. *
* *
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
* *
* Web site: http://cgogn.u-strasbg.fr/ *
* Contact information: cgogn@unistra.fr *
* *
*******************************************************************************/
#ifndef LOCALFRAME_H_
#define LOCALFRAME_H_
#include <cmath>
namespace CGoGN {
namespace Utils {
/**
* Util for rotation of a 3D point (or vector) around a given line (going through the origin) and of a given angle
* @param axis the rotation axis direction
* @param angle the rotation angle
* @param p the point to rotate
*/
template <typename REAL>
Geom::Vector<3,REAL> rotate (Geom::Vector<3,REAL> axis, REAL angle, Geom::Vector<3,REAL> p) ;
/**
* Util for conversion from spherical to cartesian coordinates.
* The spherical coordinates are in radius-longitude-latitude
* @param sph the spherical coordinates
* @return the cartesian coordinates
*/
template<typename REAL>
Geom::Vector<3,REAL> sphericalTocart (const Geom::Vector<3,REAL>& sph) ;
/**
* Util for conversion from cartesian to spherical coordinates.
* The spherical coordinates are in radius-longitude-latitude
* @param cart the cartesian coordinates
* @return the spherical coordinates
*/
template<typename REAL>
Geom::Vector<3,REAL> cartToSpherical (const Geom::Vector<3,REAL>& cart) ;
/**
* Class for representing a direct right-handed local frame composed of 3 orthonormal vectors T (tangent), B (bitangent) and N (normal).
* This class can compress/decompress a local frame, switching from its explicit representation (3 vectors) to its compressed representation (1 vector composed of the Euler angles).
* Usage :
* VEC3 T,B,N ; // current set of orthonormal vectors composing the direct frame.
* LocalFrame<PFP> lf(T,B,N) ; // Constructor from explicit expression.
* if (lf.isOrthoNormalDirect()) // test if the frame is Orthogonal, Normalized and Direct
* VEC3 compressed = lf.getCompressed() ; // Extract compressed frame
* LocalFrame<PFP> decompressed(compressed) ; // Constructor from implicit (compressed) expression.
*
* All formulae were provided by "Représentation compacte d'un repère local", june 14th, 2011 by K. Vanhoey
*/
template <typename PFP>
class LocalFrame
{
typedef typename PFP::REAL REAL ;
typedef typename Geom::Vector<2,REAL> VEC2 ;
typedef typename Geom::Vector<3,REAL> VEC3 ;
private: // fields
/**
* The three explicit vectors
*/
VEC3 m_T,m_B,m_N ;
public: // methods
/**
* Constructor from explicit data
* @param T the tangent vector
* @param B the bitangent vector
* @param N the normal vector
*/
LocalFrame(const VEC3& T, const VEC3& B, const VEC3& N) ;
/**
* Constructor from implicit (compressed representation)
* @param compressedFrame an implicit (compressed) version of the local frame (can be produced by localFrame.getCompressed())
*/
LocalFrame(const VEC3& compressedFrame) ;
~LocalFrame() {} ;
/**
* Returns a compressed version of the current local frame
* A VEC3 is not sufficient to completely define a local frame (if phiN=0, the decompression is not unique).
*/
VEC3 getCompressed() const ;
/**
* Tests if the frames are identical
* @param lf the frame to compare to the current frame
* @param epsilon the authorized deviation
* @return true if frames are identical (or deviate less than epsilon)
*/
bool equals(const LocalFrame<PFP>& lf, REAL epsilon = 1e-6) const ;
/**
* Equality of frames
* Identical to calling equals with default epsilon
* @return true if frames are identical
*/
bool operator==(const LocalFrame<PFP>& lf) const ;
/**
* Inequality of frames
* Identical to calling !equals with default epsilon
* @return false if frames are identical
*/
bool operator!=(const LocalFrame<PFP>& lf) const ;
/**
* Tests if the frame is direct
* @return true if the frame is direct
*/
bool isDirect(REAL epsilon = 1e-7) const ;
/**
* Tests if the frame is orthogonal
* @return true if the frame is orthogonal
*/
bool isOrthogonal(REAL epsilon = 1e-5) const ;
/**
* Tests if the frame is normalized
* @return true if the frame is normalized
*/
bool isNormalized(REAL epsilon = 1e-5) const ;
/**
* Tests if the frame is direct, normalized and orthogonal
* @return true if the frame is direct, normalized and orthogonal
*/
bool isOrthoNormalDirect(REAL epsilon = 1e-5) const ;
/**
* @return current tangent vector
*/
VEC3& getT() { return m_T ; }
const VEC3& getT() const { return m_T ; }
/**
* @return current bitangent vector
*/
VEC3& getB() { return m_B ; }
const VEC3& getB() const { return m_B ; }
/**
* @return current normal vector
*/
VEC3& getN() { return m_N ; }
const VEC3& getN() const { return m_N ; }
friend std::ostream& operator<< (std::ostream &out, const LocalFrame& lf) {
out << "T : " << lf.m_T << std::endl ;
out << "B : " << lf.m_B << std::endl ;
out << "N : " << lf.m_N ;
return out ;
} ;
private : // private constants
// (T,B,N) can be any orthonormal direct frame
// zeros are not recommended since they can
// easily generate zero vectors after a dot product
// UPDATE : this problem should be handled in compression
// static const REAL Tx = 0.267261 ;
// static const REAL Ty = 0.534522 ;
// static const REAL Tz = 0.801784 ;
// static const REAL Bx = 0.844416 ;
// static const REAL By = -0.530776 ;
// static const REAL Bz = 0.0723785 ;
// static const REAL Nx = 0.464255 ;
// static const REAL Ny = 0.657695 ;
// static const REAL Nz = -0.593215 ;
static const REAL Tx = 0.0766965 ;
static const REAL Ty = 0.383483 ;
static const REAL Tz = 0.920358 ;
static const REAL Bx = -0.760734 ;
static const REAL By = 0.619202 ;
static const REAL Bz = -0.194606 ;
static const REAL Nx = -0.644516 ;
static const REAL Ny = -0.685222 ;
static const REAL Nz = 0.339219 ;
} ;
} // Utils
} // CGoGN
#include "localFrame.hpp"
#endif /* LOCALFRAME_H_ */
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps *
* version 0.1 *
* Copyright (C) 2009-2011, IGG Team, LSIIT, University of Strasbourg *
* *
* 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; either version 2.1 of the License, or (at your *
* option) any later version. *
* *
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
* *
* Web site: http://cgogn.u-strasbg.fr/ *
* Contact information: cgogn@unistra.fr *
* *
*******************************************************************************/
namespace CGoGN {
namespace Utils {
template<typename PFP>
LocalFrame<PFP>::LocalFrame(const VEC3& T, const VEC3& B, const VEC3& N)
{
m_T = T ;
m_B = B ;
m_N = N ;
}
template<typename PFP>
LocalFrame<PFP>::LocalFrame(const VEC3& EulerAngles)
{
const VEC3 T(Tx,Ty,Tz) ;
const VEC3 N(Nx,Ny,Nz) ;
// get known data
const REAL& alpha = EulerAngles[0] ;
const REAL& beta = EulerAngles[1] ;
const REAL& gamma = EulerAngles[2] ;
const VEC3 lineOfNodes = rotate<REAL>(N,alpha,T) ; // rotation around reference normal of vector T
m_N = rotate<REAL>(lineOfNodes,gamma,N) ; // rotation around line of nodes of vector N
m_T = rotate<REAL>(m_N,beta,lineOfNodes) ; // rotation around new normal of vector represented by line of nodes
m_B = m_N ^ m_T ;
}
template<typename PFP>
typename Geom::Vector<3,typename PFP::REAL> LocalFrame<PFP>::getCompressed() const
{
VEC3 EulerAngles ;
const VEC3 T(Tx,Ty,Tz) ;
const VEC3 B(Bx,By,Bz) ;
const VEC3 N(Nx,Ny,Nz) ;
REAL& alpha = EulerAngles[0] ;
REAL& beta = EulerAngles[1] ;
REAL& gamma = EulerAngles[2] ;
VEC3 lineOfNodes = N ^ m_N ;
if (lineOfNodes.norm2() < 1e-5) // if N ~= m_N
{
lineOfNodes = T ; // = reference T
alpha = 0 ;
gamma = 0 ;
}
else
{
lineOfNodes.normalize() ;
// angle between reference T and line of nodes
alpha = (B*lineOfNodes > 0 ? 1 : -1) * std::acos(std::max(std::min(REAL(1.0), T*lineOfNodes ),REAL(-1.0))) ;
// angle between reference normal and normal
gamma = std::acos(std::max(std::min(REAL(1.0), N*m_N ),REAL(-1.0))) ; // gamma is always positive because the direction of vector lineOfNodes=(reference normal)^(normal) (around which a rotation of angle beta is done later on) changes depending on the side on which they lay w.r.t eachother.
}
// angle between line of nodes and T
beta = (m_B*lineOfNodes > 0 ? -1 : 1) * std::acos(std::max(std::min(REAL(1.0), m_T*lineOfNodes ),REAL(-1.0))) ;
return EulerAngles ;
}
template<typename PFP>
bool LocalFrame<PFP>::equals(const Utils::LocalFrame<PFP>& lf, REAL epsilon) const
{
VEC3 dT = m_T - lf.getT() ;
VEC3 dB = m_B - lf.getB() ;
VEC3 dN = m_N - lf.getN() ;
return dT.norm2() < epsilon && dB.norm2() < epsilon && dN.norm2() < epsilon ;
}
template<typename PFP>
bool LocalFrame<PFP>::operator==(const LocalFrame<PFP>& lf) const
{
return this->equals(lf) ;
}
template<typename PFP>
bool LocalFrame<PFP>::operator!=(const LocalFrame<PFP>& lf) const
{
return !(this->equals(lf)) ;
}
template<typename PFP>
bool LocalFrame<PFP>::isDirect(REAL epsilon) const
{
VEC3 new_B = m_N ^ m_T ; // direct
VEC3 diffs = new_B - m_B ; // differences with existing B
REAL diffNorm = diffs.norm2() ; // Norm of this differences vector
return (diffNorm < epsilon) ; // Verify that this difference is very small
}
template<typename PFP>
bool LocalFrame<PFP>::isOrthogonal(REAL epsilon) const
{
return (fabs(m_T * m_B) < epsilon) && (fabs(m_N * m_B) < epsilon) && (fabs(m_T * m_N) < epsilon) ;
}
template<typename PFP>
bool LocalFrame<PFP>::isNormalized(REAL epsilon) const
{
return (1-epsilon < m_N.norm2() && m_N.norm2() < 1+epsilon)
&& (1-epsilon < m_T.norm2() && m_T.norm2() < 1+epsilon)
&& (1-epsilon < m_B.norm2() && m_B.norm2() < 1+epsilon) ;
}
template<typename PFP>
bool LocalFrame<PFP>::isOrthoNormalDirect(REAL epsilon) const
{
return isOrthogonal(epsilon) && isNormalized(epsilon) && isDirect(epsilon) ;
}
template<typename REAL>
Geom::Vector<3,REAL> carthToSpherical (const Geom::Vector<3,REAL>& carth)
{
Geom::Vector<3,REAL> res ;
const REAL& x = carth[0] ;
const REAL& y = carth[1] ;
const REAL& z = carth[2] ;
REAL& rho = res[0] ;
REAL& theta = res[1] ;
REAL& phi = res[2] ;
rho = carth.norm() ;
theta = ((y < 0) ? -1 : 1) * std::acos(x / REAL(sqrt(x*x + y*y)) ) ;
if (isnan(theta))
theta = 0.0 ;
phi = std::asin(z) ;
return res ;
}
template<typename REAL>
Geom::Vector<3,REAL> sphericalToCarth (const Geom::Vector<3,REAL>& sph)
{
Geom::Vector<3,REAL> res ;
const REAL& rho = sph[0] ;
const REAL& theta = sph[1] ;
const REAL& phi = sph[2] ;
REAL& x = res[0] ;
REAL& y = res[1] ;
REAL& z = res[2] ;
x = rho*cos(theta)*cos(phi) ;
y = rho*sin(theta)*cos(phi) ;
z = rho*sin(phi) ;
assert(-1.000001 < x && x < 1.000001) ;
assert(-1.000001 < y && y < 1.000001) ;
assert(-1.000001 < z && z < 1.000001) ;
return res ;
}
template <typename REAL>
Geom::Vector<3,REAL> rotate (Geom::Vector<3,REAL> axis, REAL angle, Geom::Vector<3,REAL> vector)
{
axis.normalize() ;
const REAL& u = axis[0] ;
const REAL& v = axis[1] ;
const REAL& w = axis[2] ;
const REAL& x = vector[0] ;
const REAL& y = vector[1] ;
const REAL& z = vector[2] ;
Geom::Vector<3,REAL> res ;
REAL& xp = res[0] ;
REAL& yp = res[1] ;
REAL& zp = res[2] ;
const REAL tmp1 = u*x+v*y+w*z ;
const REAL cos = std::cos(angle) ;
const REAL sin = std::sin(angle) ;
xp = u*tmp1*(1-cos) + x*cos+(v*z-w*y)*sin ;
yp = v*tmp1*(1-cos) + y*cos-(u*z-w*x)*sin ;
zp = w*tmp1*(1-cos) + z*cos+(u*y-v*x)*sin ;
return res ;
}
} // Utils
} // CGoGN
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment