// $Header: /cvs/gled-1.2/GledCore/Glasses/ZNode.cxx,v 1.12 2005/05/14 11:28:57 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 "ZNode.h"
#include "ZNode.c7"
#include <Stones/ZComet.h>

#include <ctype.h>

typedef list<ZNode*>           lpZNode_t;
typedef list<ZNode*>::iterator lpZNode_i;

ClassImp(ZNode)

namespace {
  // Limit max search depth for 
  int ZNodeTransSearchMaxDepth = 100;
}

 void ZNode::_init()
{
  bUseScale = false;
  bUseOM    = false;
  mOM = 0;
  mSx = mSy = mSz = 1;
  mParent = 0; bKeepParent = true;
  mRnrMod = 0;
  bRnrSelf = bRnrElements = bModSelf = bModElements = true;

  // SetElementFID(ZNode::FID()); // Forces ZNode children only
}

/**************************************************************************/
// ZList virtuals
/**************************************************************************/

// Method SetParent is auto generated.
// Perhaps want manual version that will do list remove. ????
// On the other hand it could also be done here.
// Or require all cals to Add to also remove it from previous list.
// Or provide AdMigration virtual base in ZGlass ... hmmmph

// Locks done in ZList, SetParent

// Yoohoo ... here are some real problems with adding nodes to nodes in lower
// kings. Need TakeParentship method!
// Beta should be relatively permissive ... to allow local collections
// and links to global objects.

 void ZNode::Add(ZGlass* g)
{
  ZNode* n = dynamic_cast<ZNode*>(g);
  if(n==this) return;
  if(n && !n->bKeepParent && n->mParent)
    n->mParent->Remove(g);
  ZList::Add(g);
  if(n && (n->mParent == 0 || (n->mParent !=0 && !n->bKeepParent)))
    n->SetParent(this);
}

 void ZNode::AddBefore(ZGlass* g, ZGlass* before)
{
  ZNode* n = dynamic_cast<ZNode*>(g);
  if(n==this) return;
  if(n && !n->bKeepParent && n->mParent)
    n->mParent->Remove(g);
  ZList::AddBefore(g, before);
  if(n && (n->mParent == 0 || (n->mParent !=0 && !n->bKeepParent)))
    n->SetParent(this);
}

 void ZNode::AddFirst(ZGlass* g)
{
  ZNode* n = dynamic_cast<ZNode*>(g);
  if(n==this) return;
  if(n && !n->bKeepParent && n->mParent)
    n->mParent->Remove(g);
  ZList::AddFirst(g);
  if(n && (n->mParent == 0 || (n->mParent !=0 && !n->bKeepParent)))
    n->SetParent(this);
}

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

 Int_t ZNode::Level()
{
  Int_t l = 0;
  ZNode *p = this;
  while((p = p->GetParent())) ++l;
  return l;
}

/**************************************************************************/
// Wrappers for ZTrans
/**************************************************************************/

 Int_t ZNode::MoveLF(int vi, Float_t amount)
{
  if(vi<0 || vi>3) return 0;
  mTrans.MoveLF((Int_t)vi, amount);
  mStampReqTrans = Stamp(FID());
  return 1;
}

 Int_t ZNode::Move3(Float_t x, Float_t y, Float_t z)
{
  mTrans.Move3(x,y,z);
  mStampReqTrans = Stamp(FID());
  return 1;
}

 Int_t ZNode::RotateLF(Int_t i1, Int_t i2, Float_t amount)
{
  if(i1<0 || i1>3 || i2<0 || i2>3) return 0;
  mTrans.RotateLF((Int_t)i1, (Int_t)i2, amount);
  mStampReqTrans = Stamp(FID());
  return 1;
}

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

 Int_t ZNode::Move(ZNode* ref, Int_t vi, Float_t amount)
{
  if(ref==0) return MoveLF(vi, amount);
  if(vi<0 || vi>3) return 0;
  if(ref == this) {
    mTrans.MoveLF((Int_t)vi, amount);
  } else {
    ZTrans* a = BtoA(mParent, ref);
    mTrans.Move(a, (Int_t)vi, amount);
    delete a;
  }
  mStampReqTrans = Stamp(FID());
  return 1;
}

 Int_t ZNode::Rotate(ZNode* ref, Int_t ii1, Int_t ii2, Float_t amount)
{
  if(ref==0) return RotateLF(ii1, ii2, amount);
  if(ii1<0 || ii1>3 || ii2<0 || ii1>3) return 0;
  if(ref == this) {
    // Get segv from m^-1 * m
    mTrans.RotateLF((Int_t)ii1, (Int_t)ii2, amount);
  } else {
    ZTrans* a = BtoA(mParent, ref);
    mTrans.Rotate(a, (Int_t)ii1, (Int_t)ii2, amount);
    delete a;
  }

  mStampReqTrans = Stamp(FID());
  return 1;
}

 Int_t ZNode::SetTrans(const ZTrans& t)
{
  mTrans.SetTrans(t);
  mStampReqTrans = Stamp(FID());
  return 0;
}

 Int_t ZNode::MultBy(ZTrans& t)
{
  mTrans *= t;
  mStampReqTrans = Stamp(FID());
  return 0;
}

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

 Int_t ZNode::Set3Pos(Float_t x, Float_t y, Float_t z)
{
  mTrans.Set3Pos(x,y,z); mStampReqTrans = Stamp(FID()); return 1;
}

 Int_t ZNode::SetRotByAngles(Float_t a1, Float_t a2, Float_t a3)
{
  mTrans.SetRotByAngles(a1,a2,a3);
  mStampReqTrans = Stamp(FID());
  return 1;
}

 Int_t ZNode::SetRotByDegrees(Float_t a1, Float_t a2, Float_t a3)
{
  Float_t f = TMath::Pi()/180;
  SetRotByAngles(f*a1, f*a2, f*a3);
  return 1;
}

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

 void ZNode::SetS(Float_t xx)
{
  WriteLock();
  mSx = mSy = mSz = xx;
  mStampReqTrans = Stamp(FID());
  WriteUnlock();
}

 void ZNode::SetScales(Float_t x, Float_t y, Float_t z)
{
  WriteLock();
  mSx=x; mSy=y; mSz=z;
  mStampReqTrans = Stamp(FID());
  WriteUnlock();
}

 void ZNode::MultS(Float_t s)
{
  WriteLock();
  mSx*=s; mSy*=s; mSz*=s;
  mStampReqTrans = Stamp(FID());
  WriteUnlock();
}

 void ZNode::ApplyScale(ZTrans& t)
{
  if(bUseScale) { t.Scale3(mSx, mSy, mSz); }
  ZNode *p = mParent;
  if(bUseOM && p != 0 && p->bUseOM) {
    const Float_t dom =  mOM - p->mOM;
    if(dom != 0) {
      const Float_t s = TMath::Power(10, dom);
      t.Scale3(s, s, s);
    }
  }
}

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

// Methods for changing properties of daugters.

 void ZNode::RnrOnForDaughters()
{
  lpZNode_t dts; CopyByGlass<ZNode*>(dts);
  for(lpZNode_i i=dts.begin(); i!=dts.end(); ++i) {
    GLensReadHolder _rlck(*i);
    (*i)->SetRnrSelf(true);
  }
}

 void ZNode::RnrOffForDaughters()
{ 
  lpZNode_t dts; CopyByGlass<ZNode*>(dts);
  for(lpZNode_i i=dts.begin(); i!=dts.end(); ++i) {
    GLensReadHolder _rlck(*i);
    (*i)->SetRnrSelf(false);
  }
}

 void ZNode::SetOMofDaughters(Float_t om, Bool_t enforce_to_all)
{
  // If enforce_to_all also changes OM of children w/ parent != this.
  
  lpZNode_t dts; CopyByGlass<ZNode*>(dts);
  for(lpZNode_i i=dts.begin(); i!=dts.end(); ++i) {
    ZNode* d = *i;
    GLensReadHolder _rlck(d);
    if(enforce_to_all || d->mParent == this) {
      d->SetOM(om);
    }
  }
}

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

 ZTrans* ZNode::ToMFR(int depth)
{
  if(depth > ZNodeTransSearchMaxDepth) {
    ISerr("ZNode::ToMFR max search depth exceeded.");
    return 0;
  }

  ZNode *p = mParent;
  ZTrans* x;
  if(p == 0) {
    ReadLock();
    x = new ZTrans(mTrans);
    if(bUseScale) { x->Scale3(mSx, mSy, mSz); }
    ReadUnlock();
  } else {
    x = p->ToMFR(++depth);
    if(x == 0) return 0;
    ReadLock();
    *x *= mTrans;
    if(bUseScale) { x->Scale3(mSx, mSy, mSz); }
    if(bUseOM && p->bUseOM) {
      Float_t dom =  mOM - p->mOM;
      if(dom != 0) {
	Float_t s = TMath::Power(10, dom);
	x->Scale3(s, s, s);
      }
    }
    ReadUnlock();
  }
  return x;
}

 ZTrans* ZNode::ToNode(ZNode* top, int depth)
{
  if(depth > ZNodeTransSearchMaxDepth)  {
    ISerr("ZNode::ToNode max search depth exceeded.");
    return 0;
  }

  ZNode *p = mParent;
  if(p == 0) return 0;

  ZTrans* x;
  if(p == top) {
    GLensReadHolder rd_lck(this);
    x = new ZTrans(mTrans);
  } else {
    x = p->ToNode(top, ++depth);
    if(x) {
      GLensReadHolder rd_lck(this);
      *x *= mTrans;
    } else {
      return 0;
    }
  }

  if(bUseScale) { x->Scale3(mSx, mSy, mSz); }
  if(bUseOM && p->bUseOM) {
    Float_t dom =  mOM - p->mOM;
    if(dom != 0) {
      Float_t s = TMath::Power(10, dom);
      x->Scale3(s, s, s);
    }
  }

  return x;
}

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

 ZTrans* ZNode::BtoA(ZNode* a, ZNode* b, ZNode* top)
{
  if(top == 0) {
    top = FindCommonParent(a,b);
    if(top == 0) return 0;
  }
  ZTrans* at = a->ToNode(top); if(at == 0) { return 0; }
  at->Invert();
  ZTrans* bt = b->ToNode(top); if(bt == 0) { delete at; return 0; }
  *at *= *bt;
  delete bt;
  return at;
}

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

 void ZNode::FillParentList(list<ZNode*>& plist)
{
  ZNode* p = mParent;
  if(p) {
    plist.push_back(p);
    p->FillParentList(plist);
  }
}

 ZNode* ZNode::FindCommonParent(ZNode* a, ZNode* b)
{
  if(a == 0 || b == 0) return 0;
  if(a == b) return a;

  // !! This far from optimal, methinks.

  lpZNode_t l[2];
  l[0].push_back(a); a->FillParentList(l[0]);
  l[1].push_back(b); b->FillParentList(l[1]);
  int x = 0, y = 1;
  do {    
    lpZNode_i i = find(l[y].begin(), l[y].end(), l[x].front());
    if(i != l[y].end()) return l[x].front();
    l[x].pop_front();
    y = x; x = 1 - x;
  } while(!l[0].empty() && !l[1].empty());
  return 0;
}

/**************************************************************************/
/*** Stupid junk ***/
/**************************************************************************/

 void ZNode::Spit() const
{
  cout << GetName() << endl << mTrans;
}

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

ostream& operator<<(ostream& s, const ZNode& n) {
  const ZTrans& t = n.RefTrans();
  for(Int_t i=0; i<=3; i++) {
    s << t(i,4u) << "t|t";
    for(Int_t j=0; j<=3; j++)
      s << t(i,j) << ((j==3) ? "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.