Commit 0e79b446 authored by Kenneth Vanhoey's avatar Kenneth Vanhoey

localFrame update : compression with only 3 scalars works fine

parent 2545895b
......@@ -31,6 +31,33 @@ 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 carthesian coordinates.
* The spherical coordinates are in radius-longitude-latitude
* @param sph the spherical coordinates
* @return the carthesian coordinates
*/
template<typename REAL>
Geom::Vector<3,REAL> sphericalToCarth (const Geom::Vector<3,REAL>& sph) ;
/**
* Util for conversion from carthesian to spherical coordinates.
* The spherical coordinates are in radius-longitude-latitude
* @param carth the carthesian coordinates
* @return the spherical coordinates
*/
template<typename REAL>
Geom::Vector<3,REAL> carthToSpherical (const Geom::Vector<3,REAL>& carth) ;
/**
* Class for representing a direct 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).
......@@ -39,7 +66,7 @@ namespace Utils {
* 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
* VEC4 compressed = lf.getCompressedSecure() ; // Extract compressed frame
* 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
......@@ -50,7 +77,6 @@ class LocalFrame
typedef typename PFP::REAL REAL ;
typedef typename Geom::Vector<2,REAL> VEC2 ;
typedef typename Geom::Vector<3,REAL> VEC3 ;
typedef typename Geom::Vector<4,REAL> VEC4 ;
private: // fields
/**
......@@ -69,16 +95,10 @@ public: // methods
/**
* Constructor from implicit (compressed representation)
* @param compressedFrame an implicit (compressed) version of the local frame
* @param compressedFrame an implicit (compressed) version of the local frame (can be produced by localFrame.getCompressed())
*/
LocalFrame(const VEC3& compressedFrame) ;
/**
* Constructor from implicit (compressed representation)
* @param secureCompressedFrame an implicit (compressed) version of the local frame
*/
LocalFrame(const VEC4& secureCompressedFrame) ;
~LocalFrame() {} ;
/**
......@@ -87,18 +107,13 @@ public: // methods
*/
VEC3 getCompressed() const ;
/**
* Returns a compressed version of the current local frame (fully defined, no ambiguities)
*/
VEC4 getCompressedSecure() 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-3) const ;
bool equals(const LocalFrame<PFP>& lf, REAL epsilon = 1e-6) const ;
/**
* Equality of frames
......@@ -118,7 +133,7 @@ public: // methods
* Tests if the frame is direct
* @return true if the frame is direct
*/
bool isDirect(REAL epsilon = 1e-5) const ;
bool isDirect(REAL epsilon = 1e-7) const ;
/**
* Tests if the frame is orthogonal
......@@ -163,9 +178,10 @@ public: // methods
return out ;
} ;
private : // methods
VEC2 carthToSpherical(const VEC3& carth) const ;
VEC3 sphericalToCarth(const VEC2& sph) const ;
private : // private constants
const VEC3 T ;
const VEC3 B ;
const VEC3 N ;
} ;
} // Utils
......
......@@ -28,7 +28,10 @@ namespace CGoGN {
namespace Utils {
template<typename PFP>
LocalFrame<PFP>::LocalFrame(const VEC3& T, const VEC3& B, const VEC3& N)
LocalFrame<PFP>::LocalFrame(const VEC3& T, const VEC3& B, const VEC3& N) :
T(1,0,0), // (T,B,N) can be any orthonormal direct frame
B(0,1,0), // but has to be initialized exactly the same
N(0,0,1) // in every constructor !
{
m_T = T ;
m_B = B ;
......@@ -36,44 +39,19 @@ LocalFrame<PFP>::LocalFrame(const VEC3& T, const VEC3& B, const VEC3& N)
}
template<typename PFP>
LocalFrame<PFP>::LocalFrame(const VEC3& compressedFrame)
LocalFrame<PFP>::LocalFrame(const VEC3& compressedFrame) :
T(1,0,0), // (T,B,N) can be any orthonormal direct frame
B(0,1,0), // but has to be initialized exactly the same
N(0,0,1) // in every constructor !{
{
// get known data
const REAL& thetaN = compressedFrame[0] ;
const REAL& phiN = compressedFrame[1] ;
const REAL& thetaT = compressedFrame[2] ;
const REAL& theta1 = compressedFrame[0] ;
const REAL& phi = compressedFrame[1] ;
const REAL& theta2 = compressedFrame[2] ;
// compute phiT
REAL phiT = -std::atan((std::cos(thetaN)*std::cos(thetaT) + std::sin(thetaN)*std::sin(thetaT))*std::cos(phiN) / std::sin(phiN)) ; // if quot==0, atan returns Pi/2
VEC2 Nspher(thetaN,phiN) ;
VEC2 Tspher(thetaT,phiT) ;
// convert to carthesian
m_N = sphericalToCarth(Nspher) ;
m_T = sphericalToCarth(Tspher) ;
// compute B
m_B = m_N ^ m_T ;
}
template<typename PFP>
LocalFrame<PFP>::LocalFrame(const VEC4& compressedFrame)
{
// get known data
const REAL& thetaN = compressedFrame[0] ;
const REAL& phiN = compressedFrame[1] ;
const REAL& thetaT = compressedFrame[2] ;
const REAL& phiT = compressedFrame[3] ;
VEC2 Nspher(thetaN,phiN) ;
VEC2 Tspher(thetaT,phiT) ;
// convert to carthesian
m_N = sphericalToCarth(Nspher) ;
m_T = sphericalToCarth(Tspher) ;
// compute B
const VEC3 Tprime = rotate<REAL>(N,theta1,T) ;
m_N = rotate<REAL>(Tprime,phi,N) ;
m_T = rotate<REAL>(m_N,theta2,Tprime) ;
m_B = m_N ^ m_T ;
}
......@@ -82,41 +60,16 @@ typename Geom::Vector<3,typename PFP::REAL> LocalFrame<PFP>::getCompressed() con
{
VEC3 res ;
REAL& thetaN = res[0] ;
REAL& phiN = res[1] ;
REAL& thetaT = res[2] ;
// convert to spherical coordinates
VEC2 Nspher = carthToSpherical(m_N) ;
VEC2 Tspher = carthToSpherical(m_T) ;
// extract the three scalars
thetaN = Nspher[0] ;
phiN = Nspher[1] ;
thetaT = Tspher[0] ;
return res ;
}
template<typename PFP>
typename Geom::Vector<4,typename PFP::REAL> LocalFrame<PFP>::getCompressedSecure() const
{
VEC4 res ;
REAL& thetaN = res[0] ;
REAL& phiN = res[1] ;
REAL& thetaT = res[2] ;
REAL& phiT = res[3] ;
REAL& theta1 = res[0] ;
REAL& phi = res[1] ;
REAL& theta2 = res[2] ;
// convert to spherical coordinates
VEC2 Nspher = carthToSpherical(m_N) ;
VEC2 Tspher = carthToSpherical(m_T) ;
VEC3 Tprime = N ^ m_N ;
Tprime.normalize() ;
// extract the three scalars
thetaN = Nspher[0] ;
phiN = Nspher[1] ;
thetaT = Tspher[0] ;
phiT = Tspher[1] ;
theta1 = (B*Tprime > 0 ? 1 : -1) * std::acos(std::max(std::min(REAL(1.0), T*Tprime ),REAL(-1.0))) ;
phi = std::acos(std::max(std::min(REAL(1.0), N*m_N ),REAL(-1.0))) ; // phi1 is always positive because the direction of vector Tp=N^N1 (around which a rotation of angle phi is done later on) changes depending on the side on which they lay w.r.t eachother.
theta2 = (m_B*Tprime > 0 ? -1 : 1) * std::acos(std::max(std::min(REAL(1.0), m_T*Tprime ),REAL(-1.0))) ;
return res ;
}
......@@ -162,9 +115,9 @@ bool LocalFrame<PFP>::isOrthogonal(REAL epsilon) const
template<typename PFP>
bool LocalFrame<PFP>::isNormalized(REAL epsilon) const
{
return (1-1e-5 < m_N.norm2() && m_N.norm2() < epsilon)
&& (1-1e-5 < m_T.norm2() && m_T.norm2() < epsilon)
&& (1-1e-5 < m_B.norm2() && m_B.norm2() < epsilon) ;
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>
......@@ -173,42 +126,45 @@ bool LocalFrame<PFP>::isOrthoNormalDirect(REAL epsilon) const
return isOrthogonal(epsilon) && isNormalized(epsilon) && isDirect(epsilon) ;
}
template<typename PFP>
typename Geom::Vector<2,typename PFP::REAL> LocalFrame<PFP>::carthToSpherical (const VEC3& carth) const
template<typename REAL>
Geom::Vector<3,REAL> carthToSpherical (const Geom::Vector<3,REAL>& carth)
{
VEC2 res ;
Geom::Vector<3,REAL> res ;
const REAL& x = carth[0] ;
const REAL& y = carth[1] ;
const REAL& z = carth[2] ;
REAL theta = ((y < 0) ? -1 : 1) * std::acos(x / REAL(sqrt(x*x + y*y)) ) ;
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 ;
REAL phi = std::asin(z) ;
res[0] = theta ;
res[1] = phi ;
phi = std::asin(z) ;
return res ;
}
template<typename PFP>
typename Geom::Vector<3,typename PFP::REAL> LocalFrame<PFP>::sphericalToCarth (const VEC2& sph) const
template<typename REAL>
Geom::Vector<3,REAL> sphericalToCarth (const Geom::Vector<3,REAL>& sph)
{
VEC3 res ;
Geom::Vector<3,REAL> res ;
const REAL& theta = sph[0] ;
const REAL& phi = sph[1] ;
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 = cos(theta)*cos(phi) ;
y = sin(theta)*cos(phi) ;
z = sin(phi) ;
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) ;
......@@ -217,6 +173,35 @@ typename Geom::Vector<3,typename PFP::REAL> LocalFrame<PFP>::sphericalToCarth (c
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