// $Header: /cvs/gled-1.2/GledCore/Stones/ZTrans.cxx,v 1.8 2005/06/06 14:37:05 matevz Exp $

// Copyright (C) 1999-2005, Matevz Tadel. All rights reserved.
// This file is part of GLED, released under GNU General Public License version 2.
// For the licensing terms see $GLEDSYS/LICENSE or http://www.gnu.org/.

#include "ZTrans.h"
#include <Glasses/ZNode.h>

ClassImp(ZTrans)

// Matrix Prototype
static const TMatrixF ZTransMatrixProto(5,5);

/**************************************************************************/

 void ZTrans::_init()
{ 
  mA1 = mA2 = mA3 = 0;
  bAsOK = false;
}

 ZTrans::ZTrans() : TMatrixF(TMatrixFBase::kUnit, ZTransMatrixProto) { _init(); }

 ZTrans::ZTrans(const TMatrixF& m) : TMatrixF(m) { _init(); }

 ZTrans::ZTrans(const ZTrans& z) : TMatrixF(z) { _init(); }

 ZTrans::ZTrans(const ZNode* n) : TMatrixF(n->RefTrans()) { _init(); }

/**************************************************************************/

 void ZTrans::UnitTrans()
{
  UnitMatrix();
  mA1 = mA2 = mA3 = 0;
  bAsOK = true;
}

 Int_t ZTrans::Set3Pos(Float_t x, Float_t y, Float_t z)
{
  ZTrans& M = *this;
  M(1, 4) = x; M(2, 4) = y; M(3, 4) = z;
  return 1;
}

 Int_t ZTrans::Set3Pos(Float_t* x)
{
  ZTrans& M = *this;
  M(1, 4) = x[0]; M(2, 4) = x[1]; M(3, 4) = x[2];
  return 1;
}

 Int_t ZTrans::SetPos(const TVectorF& v)
{
  if(v.GetNoElements() != 5) return 1;
  ZTrans& M = *this;
  for(Int_t i=0;i<5;i++)
    M(i, 4) = v(i);
  return 0;
}

 Int_t ZTrans::SetPos(const ZTrans& t)
{
  if(t.GetNrows() != 5) return 1;
  ZTrans& M = *this;
  for(Int_t i=0;i<5;i++)
    M(i, 4) = t(i,4);
  return 0;
}

 TVectorF* ZTrans::GetBaseV(Int_t b) const
{
  // *CHTD*
  TVectorF* v = new TVectorF(5);
  const ZTrans& M = *this;
  for(Int_t i = 0; i<5; i++)
    (*v)(i) = M(i, b);
  return v;
}

 TVector3 ZTrans::GetBaseVec3(Int_t b) const
{
  const ZTrans& M = *this;
  return TVector3(M(1,b), M(2,b), M(3,b));
}

 void ZTrans::GetBaseVec3(TVector3& v, Int_t b) const
{
  const ZTrans& M = *this;
  v.SetXYZ(M(1,b), M(2,b), M(3,b));
}

/**************************************************************************/

 void ZTrans::SetRot(Int_t i, Int_t j, Float_t f)
{
  // Expects identity matrix
  ZTrans& M = *this;
  M(i,i) = M(j,j) = TMath::Cos(f);
  Float_t s = TMath::Sin(f);
  M(i,j) = -s; M(j,i) = s;
  bAsOK = false;
}

 void ZTrans::SetTrans(const ZTrans& t)
{
  TMatrixF::operator=(t);
  bAsOK = false;
}

 void ZTrans::SetBaseV(Int_t i, Float_t x, Float_t y, Float_t z)
{
  ZTrans& M = *this;
  M(1,i) = x; M(2,i) = y; M(3,i) = z;
  bAsOK = false;
}

 void ZTrans::SetBaseVec3(Int_t i, const TVector3& v)
{
  ZTrans& M = *this;
  M(1,i) = v.x(); M(2,i) = v.y(); M(3,i) = v.z();
  bAsOK = false;
}

/**************************************************************************/
// Basic Transformations
/**************************************************************************/

 Int_t ZTrans::MoveLF(Int_t ai, Float_t amount)
{
  ZTrans& M = *this;
  for(Int_t i=0; i<=3; i++)
    M(i,4) += amount*M(i, ai);
  bAsOK = false;
  return 1;
}

 Int_t ZTrans::Move3(Float_t x, Float_t y, Float_t z)
{
  ZTrans& M = *this;
  M(1,4) += x; M(2,4) += y; M(3,4) += z;
  bAsOK = false;
  return 1;
}

 Int_t ZTrans::RotateLF(Int_t i1, Int_t i2, Float_t amount)
{
  if(i1==i2) return 0;
  ZTrans a;
  a(i1,i1) = a(i2,i2) = TMath::Cos(amount);
  Float_t s = TMath::Sin(amount);
  a(i1,i2) = -s; a(i2,i1) = s;
  *this *= a;
  bAsOK = false;
  return 1;
}

/**************************************************************************/

 Int_t ZTrans::Move(ZTrans* a, Int_t ai, Float_t amount)
{
  ZTrans& M = *this;
  for(Int_t i=0; i<=3; i++)
    M(i,4) += amount * (*a)(i, ai);
  return 1;
}

 Int_t ZTrans::Rotate(ZTrans* a, Int_t i1, Int_t i2, Float_t amount)
{
  // a is shitted
  if(i1==i2) return 0;
  ZTrans ai(*a); ai.Invert();
  ZTrans R; R.SetRot(i1, i2, amount); 
  *a *= R;
  *a *= ai;
  *a *= *this;
  *this = *a;
  bAsOK = false;
  return 1;
}

namespace {
  inline void clamp_angle(Float_t& a) {
    while(a < -2*TMath::Pi()) a += 2*TMath::Pi();
    while(a >  2*TMath::Pi()) a -= 2*TMath::Pi();
  }
}

 Int_t ZTrans::SetRotByAngles(Float_t a1, Float_t a2, Float_t a3)
{
  // Sets Rotation part as given by angles:
  // a1 around z, -a2 around y, a3 around x
  clamp_angle(a1); clamp_angle(a2); clamp_angle(a3);

  Float_t A, B, C, D, E, F;
  A = cos(a3); B = sin(a3);
  C = cos(a2); D = sin(a2); // should be -sin(a2) for positive direction
  E = cos(a1); F = sin(a1);
  Float_t AD = A*D, BD = B*D;

  ZTrans& M = *this;
  M(1,1) = C*E; M(1,2) = -BD*E -A*F;  M(1,3) = -AD*E + B*F;
  M(2,1) = C*F; M(2,2) = -BD*F + A*E; M(2,3) = -AD*F - B*E;
  M(3,1) = D;   M(3,2) = B*C;         M(3,3) = A*C;

  mA1 = a1; mA2 = a2; mA3 = a3;
  bAsOK = true;
  return 1;
}


 void ZTrans::Get3Rot(Float_t* x) const
{
  const ZTrans& M = *this;
  if(!bAsOK) {
    Float_t d = M(3,1);
    if(d>1) d=1; else if(d<-1) d=-1; // Fix numerical errors
    mA2 = TMath::ASin(d);
    Float_t C = TMath::Cos(mA2);
    if(TMath::Abs(C) > 8.7e-6) {
      mA1 = TMath::ATan2(M(2,1), M(1,1));      
      mA3 = TMath::ATan2(M(3,2), M(3,3));
    } else {
      mA1 = TMath::ATan2(M(2,1), M(2,2));
      mA3 = 0;
    }
    bAsOK = true;
  }
  x[0] = mA1; x[1] = mA2; x[2] = mA3;
}

/**************************************************************************/

 void ZTrans::Scale3(Float_t sx, Float_t sy, Float_t sz)
{
  Double_t s[4] = {0, sx, sy, sz};
  ZTrans& M = *this;
  for(int i=1;i<=3;++i)
    for(int j=1;j<=3;++j)
      M(j,i) *= s[i];
}

 void ZTrans::GetScale3(Float_t& sx, Float_t& sy, Float_t& sz)
{
  ZTrans& M = *this;
  Double_t s[4] = {0,0,0,0};
  for(int i=1;i<=3;++i) {
    for(int j=1;j<=3;++j)
      s[i] += M(j, i) * M(j, i);
    s[i] = TMath::Sqrt(s[i]);
  }
  sx = s[1]; sy = s[2]; sz = s[3];
}

 void ZTrans::Unscale3(Float_t& sx, Float_t& sy, Float_t& sz)
{
  ZTrans& M = *this;
  Double_t s[4] = {0,0,0,0};
  for(int i=1;i<=3;++i) {
    for(int j=1;j<=3;++j)
      s[i] += M(j, i) * M(j, i);
    s[i] = TMath::Sqrt(s[i]);
  }
  for(int i=1;i<=3;++i)
    for(int j=1;j<=3;++j)
      M(j,i) /= s[i];
  sx = s[1]; sy = s[2]; sz = s[3];
}


 Float_t ZTrans::Unscale3()
{
  Float_t sx, sy, sz;
  Unscale3(sx, sy, sz);
  return (sx + sy + sz)/3;
}

/**************************************************************************/
// 3 Vec manipulation ... perhaps should have uniform funcs ... well ...
/**************************************************************************/

 TVectorF& ZTrans::Mult3Vec(TVectorF& v) const
{
  // Multiplies v in-place w/ spatial part of mM ... takes Scale to be 1
  const ZTrans& M = *this;
  Float_t buf[4];
  for(Int_t i=0; i<=2; i++) buf[i]=v(i);
  buf[3] = 1; // Scale

  for(Int_t i=0; i<=2; i++) {
    v(i) = 0;
    for(Int_t j=0; j<=3; j++)
      v(i) += M(i+1, j+1)*buf[j];
  }
  return v;
}

 TVectorF& ZTrans::Rot3Vec(TVectorF& v) const
{
  // Multiplies v in-place w/ rotational-spatial part of mM ... Scale not used
  const ZTrans& M = *this;
  Float_t buf[3];
  for(Int_t i=0; i<=2; i++) buf[i]=v(i);

  for(Int_t i=0; i<=2; i++) {
    v(i) = 0;
    for(Int_t j=0; j<=2; j++)
      v(i) += M(i+1, j+1)*buf[j];
  }
  return v;
}

/**************************************************************************/

 Float_t ZTrans::norm3_column(Int_t col)
{
  ZTrans& M = *this;
  Double_t l = 0;
  for(Int_t i=1; i<=3; ++i) l += M(i,col)*M(i,col);
  l = TMath::Sqrt(l);
  for(Int_t i=1; i<=3; ++i) M(i,col) /= l;
  return l;
}

 Float_t ZTrans::orto3_column(Int_t col, Int_t ref)
{
  ZTrans& M = *this;
  Double_t dp = 0;
  for(Int_t i=1; i<=3; ++i) dp       += M(i,col)*M(i,ref);
  for(Int_t i=1; i<=3; ++i) M(i,col) -= M(i,ref)*dp;
  return dp;
}

 void ZTrans::OrtoNorm3()
{
  norm3_column(1);
  orto3_column(2,1); norm3_column(2);
  orto3_column(3,1); orto3_column(3,2); norm3_column(3);
}

/**************************************************************************/

#include <iomanip>

ostream& operator<<(ostream& s, const ZTrans& t) {
  s.setf(ios::fixed, ios::floatfield); s.precision(3);
  for(Int_t i=0; i<5; i++)
    for(Int_t j=0; j<5; j++)
      s << t(i,j) << ((j==4) ? "\n" : "\t");
  return s;
}


ROOT page - Home page - Class index - Class Hierarchy - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.