Commit 99a37a51 by Kenneth Vanhoey

### new naming convention for frames : XYZ instead of TBN

parent 5587bbe0
 /******************************************************************************* * 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 namespace CGoGN { namespace Geom { /** * 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 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 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 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 X,Y,Z ; // current set of orthonormal vectors composing the direct frame. * Frame lf(X,Y,Z) ; // Constructor from explicit expression. * if (lf.isOrthoNormalDirect()) // test if the frame is Orthogonal, Normalized and Direct * VEC3 compressed = lf.getCompressed() ; // Extract compressed frame * Frame decompressed(compressed) ; // Constructor from implicit (compressed) expression. */ template class Frame { 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_X,m_Y,m_Z ; public: // methods /** * Constructor from explicit data * @param X the tangent vector * @param Y the bitangent vector * @param Z the normal vector */ Frame(const VEC3& X, const VEC3& Y, const VEC3& Z) ; /** * Constructor from implicit (compressed representation) * @param compressedFrame an implicit (compressed) version of the local frame (can be produced by localFrame.getCompressed()) */ Frame(const VEC3& eulerAngles) ; ~Frame() {} ; /** * 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 Frame& 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 Frame& lf) const ; /** * Inequality of frames * Identical to calling !equals with default epsilon * @return false if frames are identical */ bool operator!=(const Frame& 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& getX() { return m_X ; } const VEC3& getX() const { return m_X ; } /** * @return current bitangent vector */ VEC3& getY() { return m_Y ; } const VEC3& getY() const { return m_Y ; } /** * @return current normal vector */ VEC3& getZ() { return m_Z ; } const VEC3& getZ() const { return m_Z ; } friend std::ostream& operator<< (std::ostream &out, const Frame& lf) { out << "X : " << lf.m_X << std::endl ; out << "Y : " << lf.m_Y << std::endl ; out << "Z : " << lf.m_Z ; return out ; } ; private : // private constants // The reference frame (X,Y,Z) 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 Xx = 0.267261 ; // static const REAL Xy = 0.534522 ; // static const REAL Xz = 0.801784 ; // static const REAL Yx = 0.844416 ; // static const REAL Yy = -0.530776 ; // static const REAL Yz = 0.0723785 ; // static const REAL Zx = 0.464255 ; // static const REAL Zy = 0.657695 ; // static const REAL Zz = -0.593215 ; static const REAL Xx = 0.0766965 ; static const REAL Xy = 0.383483 ; static const REAL Xz = 0.920358 ; static const REAL Yx = -0.760734 ; static const REAL Yy = 0.619202 ; static const REAL Yz = -0.194606 ; static const REAL Zx = -0.644516 ; static const REAL Zy = -0.685222 ; static const REAL Zz = 0.339219 ; } ; } // Geom } // CGoGN #include "frame.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 Geom { template Frame::Frame(const VEC3& X, const VEC3& Y, const VEC3& Z) { m_X = X ; m_Y = Y ; m_Z = Z ; } template Frame::Frame(const VEC3& EulerAngles) { const VEC3 X(Xx,Xy,Xz) ; const VEC3 Z(Zx,Zy,Zz) ; // get known data const REAL& alpha = EulerAngles[0] ; const REAL& beta = EulerAngles[1] ; const REAL& gamma = EulerAngles[2] ; const VEC3 lineOfNodes = rotate(Z,alpha,X) ; // rotation around reference normal of vector T m_Z = rotate(lineOfNodes,gamma,Z) ; // rotation around line of nodes of vector N m_X = rotate(m_Z,beta,lineOfNodes) ; // rotation around new normal of vector represented by line of nodes m_Y = m_Z ^ m_X ; } template typename Geom::Vector<3,typename PFP::REAL> Frame::getCompressed() const { VEC3 EulerAngles ; const VEC3 X(Xx,Xy,Xz) ; const VEC3 Y(Yx,Yy,Yz) ; const VEC3 Z(Zx,Zy,Zz) ; REAL& alpha = EulerAngles[0] ; REAL& beta = EulerAngles[1] ; REAL& gamma = EulerAngles[2] ; VEC3 lineOfNodes = Z ^ m_Z ; if (lineOfNodes.norm2() < 1e-5) // if Z ~= m_Z { lineOfNodes = X ; // = reference T alpha = 0 ; gamma = 0 ; } else { lineOfNodes.normalize() ; // angle between reference T and line of nodes alpha = (Y*lineOfNodes > 0 ? 1 : -1) * std::acos(std::max(std::min(REAL(1.0), X*lineOfNodes ),REAL(-1.0))) ; // angle between reference normal and normal gamma = std::acos(std::max(std::min(REAL(1.0), Z*m_Z ),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_Y*lineOfNodes > 0 ? -1 : 1) * std::acos(std::max(std::min(REAL(1.0), m_X*lineOfNodes ),REAL(-1.0))) ; return EulerAngles ; } template bool Frame::equals(const Geom::Frame& lf, REAL epsilon) const { VEC3 dX = m_X - lf.getX() ; VEC3 dY = m_Y - lf.getY() ; VEC3 dZ = m_Z - lf.getZ() ; return dX.norm2() < epsilon && dY.norm2() < epsilon && dZ.norm2() < epsilon ; } template bool Frame::operator==(const Frame& lf) const { return this->equals(lf) ; } template bool Frame::operator!=(const Frame& lf) const { return !(this->equals(lf)) ; } template bool Frame::isDirect(REAL epsilon) const { VEC3 new_Y = m_Z ^ m_X ; // direct VEC3 diffs = new_Y - m_Y ; // differences with existing B REAL diffNorm = diffs.norm2() ; // Norm of this differences vector return (diffNorm < epsilon) ; // Verify that this difference is very small } template bool Frame::isOrthogonal(REAL epsilon) const { return (fabs(m_X * m_Y) < epsilon) && (fabs(m_Z * m_Y) < epsilon) && (fabs(m_X * m_Z) < epsilon) ; } template bool Frame::isNormalized(REAL epsilon) const { return (1-epsilon < m_Z.norm2() && m_Z.norm2() < 1+epsilon) && (1-epsilon < m_X.norm2() && m_X.norm2() < 1+epsilon) && (1-epsilon < m_Y.norm2() && m_Y.norm2() < 1+epsilon) ; } template bool Frame::isOrthoNormalDirect(REAL epsilon) const { return isOrthogonal(epsilon) && isNormalized(epsilon) && isDirect(epsilon) ; } template 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 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 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 ; } } // Geom } // 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