// $Header: /cvs/gled-1.2/Geom1/Glasses/Amphitheatre.cxx,v 1.3 2005/03/11 17:50:14 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/.
//__________________________________________________________________________
// Amphitheatre
//
//
#include "Amphitheatre.h"
#include "Amphitheatre.c7"
#include <Glasses/ZQueen.h>
#include <Glasses/Sphere.h>
ClassImp(Amphitheatre)
/**************************************************************************/
void Amphitheatre::_init()
{
mNewGuests = 0;
mNumCh = mNumChFree = 0;
mStageSides = 7; mStageRot = 0;
mStageSize = 1; mChairSize = 0.15;
mGuestSize = 0.2;
mGuestScaleFac = 0.01;
mRepX0 = 2*mChairSize;
mRepXm = 0.5*mGuestSize;
mRepXM = 5*mGuestSize;
mGuestStep = 0.08;
mStepSleepMS = 100;
bChairHunt = false;
bRnrStage = true; bRnrChairs = true;
// Stage col white.
mChairCol.rgba(0.6, 0.9, 0.6);
mRnd.SetSeed(0); // !! This NOT distributed.
}
/**************************************************************************/
void Amphitheatre::AdEnlightenment()
{
PARENT_GLASS::AdEnlightenment();
if(mNewGuests == 0) {
ZList* l = new ZList("GuestList", GForm("Newly arrived guests of %s", GetName()));
l->SetElementFID(ZNode::FID());
l->SetMIRActive(false);
mQueen->CheckIn(l);
SetNewGuests(l);
}
}
/**************************************************************************/
void Amphitheatre::CreateChairs(Float_t radius, Float_t xoffset, Float_t z,
Float_t dphi_deg, Int_t nchair)
{
Float_t dphi = dphi_deg * TMath::DegToRad();
Float_t step = dphi / (nchair - 1);
Float_t phi0 = -dphi / 2;
for(int i=0; i<nchair; ++i) {
Float_t p = phi0 + i*step;
TVector3 pos = TVector3(radius*TMath::Cos(p), radius*TMath::Sin(p), z);
pos[0] += xoffset;
mChairs.push_back(Chair(pos));
}
mNumCh += nchair; mNumChFree += nchair;
Stamp(FID());
}
void Amphitheatre::RemoveChairs()
{
mChairs.clear();
mNumCh = mNumChFree = 0;
Stamp(FID());
}
/**************************************************************************/
void Amphitheatre::AddGuest(ZNode* guest)
{
mNewGuests->Add(guest);
guest->WriteLock();
ZNode* gp = guest->GetParent();
if(gp != this) {
if(gp != 0) {
auto_ptr<ZTrans> t( ZNode::BtoA(this, guest) );
if(t.get() != 0) {
Float_t s[3];
t->Unscale3(s[0], s[1], s[2]);
guest->SetTrans(*t);
guest->SetScales(s[0], s[1], s[2]);
}
}
guest->SetParent(this);
Add(guest);
}
guest->WriteUnlock();
}
void Amphitheatre::ClearFailedGuests()
{
lpZGlass_i i, end;
mNewGuests->WriteLock();
mNewGuests->BeginIteration(i, end);
while(i != end) { Remove(*i); ++i; }
mNewGuests->EndIteration();
mNewGuests->ClearList();
mNewGuests->WriteUnlock();
}
void Amphitheatre::ClearAmphitheatre()
{
ClearFailedGuests();
ClearList();
for(lChair_i c=mChairs.begin(); c!=mChairs.end(); ++c) c->fNode = 0;
mNumChFree = mNumCh;
Stamp(FID());
}
/**************************************************************************/
/**************************************************************************/
Amphitheatre::Chair* Amphitheatre::closest_free_chair(TVector3& pos)
{
if(mNumChFree <= 0)
return 0;
Double_t min_r2 = 1e9;
lChair_i min_ch;
for(lChair_i i = mChairs.begin(); i != mChairs.end(); ++i) {
if(i->freep()) {
TVector3 dr(i->fPos - pos);
Double_t r2 = dr.Mag2();
if(r2 < min_r2) {
min_r2 = r2;
min_ch = i;
}
}
}
return &(*min_ch);
}
/**************************************************************************/
void Amphitheatre::chair_hunt()
{
Bool_t changep = false;
typedef list<ZNode*> lpZNode_t;
typedef list<ZNode*>::iterator lpZNode_i;
lpZNode_t nodes;
mNewGuests->CopyByGlass<ZNode*>(nodes);
if(bChairHunt == false || nodes.empty() || mNumChFree <= 0) {
StopHunt();
return;
}
for(lpZNode_i n=nodes.begin(); n!=nodes.end(); ++n) {
ZNode* node = *n;
if(mNumChFree <= 0)
break;
TVector3 x = node->RefTrans().GetPosVec3();
Chair* chair = closest_free_chair(x);
x = chair->fPos - x;
Double_t dx = x.Mag();
if(dx > mGuestStep) {
x *= (mGuestStep/dx);
}
// printf("Got r = %f, %f, %f; %fn", f.x(), f.y(), f.z(), f.Mag());
bool finalp = (dx <= mGuestStep); // Guest has reached the chair.
node->WriteLock();
node->Move3(x.x(), x.y(), x.z());
fix_guest_scale(node, finalp);
// !! Could rotate it along travel axis.
node->WriteUnlock();
if(finalp) {
changep = true;
// !!! Should also rotate it towards the stage.
mNewGuests->WriteLock();
mNewGuests->Remove(node);
mNewGuests->WriteUnlock();
chair->fNode = node;
--mNumChFree;
lpZNode_i to_remove = n--;
nodes.erase(to_remove);
}
}
// Spread the remaining roamers if too close.
const Double_t rxm = mRepX0*mRepXm;
const Double_t rxM = mRepX0*mRepXM;
for(lpZNode_i n=nodes.begin(); n!=nodes.end(); ++n) {
TVector3 f;
ZNode* node = *n;
TVector3 x(node->RefTrans().GetPosVec3());
// loop over rivals
for(lpZNode_i o=nodes.begin(); o!=nodes.end(); ++o) {
if(o == n) continue;
TVector3 y = (*o)->RefTrans().GetPosVec3();
y -= x;
Double_t d = y.Mag();
if(d < rxM) {
if(d < rxm) { y *= rxm/d; d = rxm; }
y *= mRepX0*(1/d - 1/rxm)/d;
f += y;
}
}
// loop over taken chairs
for(lChair_i i=mChairs.begin(); i != mChairs.end(); ++i) {
if(! i->freep()) {
TVector3 y = i->fNode->RefTrans().GetPosVec3();
y -= x;
Double_t d = y.Mag();
if(d < rxM) {
if(d < rxm) { y *= rxm/d; d = rxm; }
y *= mRepX0*(1/d - 1/rxm)/d;
f += y;
}
}
}
Double_t fmag = f.Mag();
if(fmag != 0) {
if(fmag > mGuestStep/2) f *= mGuestStep/2/fmag;
node->WriteLock();
node->Move3(f.x(), f.y(), f.z());
node->WriteUnlock();
}
}
if(changep)
Stamp(FID());
chair_hunt_emit_mir();
}
void Amphitheatre::chair_hunt_emit_mir()
{
GTime at(GTime::I_Now); at += 1000l*mStepSleepMS;
auto_ptr<ZMIR> mir( S_chair_hunt() );
mSaturn->DelayedShootMIR(mir, at);
}
/**************************************************************************/
void Amphitheatre::fix_guest_scale(ZNode* guest, bool finalp)
{
Float_t s[3];
s[0] = guest->GetSx(); s[1] = guest->GetSy(); s[2] = guest->GetSz();
Float_t avgs = (s[0]+s[1]+s[2])/3;
Float_t ds = mGuestSize - avgs;
// printf("%-10s %8f %8fn", guest->GetName(), avgs, ds);
if(TMath::Abs(ds) > 0.05 || finalp) {
if(!finalp) ds *= mGuestScaleFac; // exponential approach
guest->SetSx(s[0]*(1 + ds/s[0]));
guest->SetSy(s[1]*(1 + ds/s[1]));
guest->SetSz(s[2]*(1 + ds/s[2]));
}
}
/**************************************************************************/
void Amphitheatre::StartHunt()
{
if(bChairHunt) return;
bChairHunt = true;
chair_hunt_emit_mir();
Stamp(FID());
}
void Amphitheatre::StopHunt()
{
if(!bChairHunt) return;
bChairHunt = false;
Stamp(FID());
}
/**************************************************************************/
inline
Double_t Amphitheatre::rnd(Double_t k, Double_t n)
{
return k*mRnd.Rndm() + n;
}
void Amphitheatre::MakeRandomGuests(Int_t nguests, Float_t box_size)
{
// This is for testing only; NOT DISTRIBUTED.
Float_t bh = box_size / 2;
for(Int_t i=0; i<nguests; ++i) {
Sphere* s = new Sphere(GForm("Guest %d", int(1000*mRnd.Rndm())));
s->Set3Pos(rnd(box_size, -bh), rnd(box_size, -bh), rnd(box_size, -bh));
s->SetColor(rnd(0.6,0.4), rnd(0.6,0.4), rnd(0.6,0.4));
s->SetLOD(12);
s->SetRadius(0.1);
mQueen->CheckIn(s);
Add(s);
mNewGuests->WriteLock();
mNewGuests->Add(s);
mNewGuests->WriteUnlock();
}
}
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.