<commit_before>#include "TRDModuleImp.h"
#include "TRDData.h"

#include "TMath.h"
#include <TGListTree.h>

#include "Reve/RGTopFrame.h"
#include "Reve/Track.h"

#include "AliLog.h"
#include "AliRun.h"
#include "AliTRDv1.h"
#include "AliTRDgeometry.h"
#include "AliTRDCommonParam.h"
#include "AliTRDpadPlane.h"
#include "AliTRDdigit.h"
#include "AliTRDhit.h"
#include "AliTRDcluster.h"
#include "AliTRDcalibDB.h"
#include "AliTRDdataArrayI.h"
#include "AliTRDmcmTracklet.h"

using namespace Reve;
using namespace Alieve;
using namespace std;

ClassImp(TRDChamber)
ClassImp(TRDNode)

//________________________________________________________
TRDNode::TRDNode(const char *typ, Int_t det) :
  Reve::RenderElement(), TRDModule(typ, det)
{
}

//________________________________________________________
void	TRDNode::Paint(Option_t* option)
{
	List_i iter = fChildren.begin();
	while(iter != fChildren.end()){
		(dynamic_cast<TRDModule*>(*iter))->Paint(option);
		iter++;
	}
}

//________________________________________________________
void	TRDNode::Reset()
{
	List_i iter = fChildren.begin();
	while(iter != fChildren.end()){
		(dynamic_cast<TRDModule*>(*iter))->Reset();
		iter++;
	}
}

//________________________________________________________
void TRDNode::Collapse()
{
	TGListTree *list = gReve->GetListTree();
	TRDNode *node = 0x0;
	List_i iter = fChildren.begin();
	while(iter != fChildren.end()){
		if((node = dynamic_cast<TRDNode*>(*iter))) node->Collapse();
		list->CloseItem(FindListTreeItem(list));
		iter++;
	}
}

//________________________________________________________
void TRDNode::Expand()
{
	TGListTree *list = gReve->GetListTree();
	TRDNode *node = 0x0;
	List_i iter = fChildren.begin();
	while(iter != fChildren.end()){
		if((node = dynamic_cast<TRDNode*>(*iter))) node->Expand();
		list->OpenItem(FindListTreeItem(list));
		iter++;
	}
}

//________________________________________________________
void TRDNode::EnableListElements()
{
	SetRnrSelf(kTRUE);
	TRDNode *node = 0x0;
	TRDChamber *chmb = 0x0;
	List_i iter = fChildren.begin();
	while(iter != fChildren.end()){
		if((node = dynamic_cast<TRDNode*>(*iter))){
			node->SetRnrSelf(kTRUE);
			node->EnableListElements();
		}
		if((chmb = dynamic_cast<TRDChamber*>(*iter))) chmb->SetRnrSelf(kTRUE);
		iter++;
	}
	gReve->Redraw3D();
}

//________________________________________________________
void TRDNode::DisableListElements()
{
	SetRnrSelf(kFALSE);
	TRDNode *node = 0x0;
	TRDChamber *chmb = 0x0;
	List_i iter = fChildren.begin();
	while(iter != fChildren.end()){
		if((node = dynamic_cast<TRDNode*>(*iter))){
			node->SetRnrSelf(kFALSE);
			node->DisableListElements();
		}
		if((chmb = dynamic_cast<TRDChamber*>(*iter))) chmb->SetRnrSelf(kFALSE);
		iter++;
	}
	gReve->Redraw3D();
}

//________________________________________________________
void TRDNode::UpdateLeaves()
{
	TRDModule *module;
	List_i iter = fChildren.begin();
	while(iter != fChildren.end()){
		module = dynamic_cast<TRDModule*>(*iter);
		if(!module) continue;

		module->fRnrHits = fRnrHits;
		module->fRnrDigits = fRnrDigits;
		module->fDigitsLog = fDigitsLog;
		module->fDigitsBox = fDigitsBox;
		module->fDigitsThreshold = fDigitsThreshold;
		module->kDigitsNeedRecompute = kDigitsNeedRecompute;
		module->fRnrRecPoints = fRnrRecPoints;
		module->fRnrTracklets = fRnrTracklets;
		iter++;
	}

	TRDNode *node = 0x0;
	iter = fChildren.begin();
	while(iter != fChildren.end()){
		if((node = dynamic_cast<TRDNode*>(*iter))) node->UpdateLeaves();
		iter++;
	}
}

//________________________________________________________
void TRDNode::UpdateNode()
{
//	Info("UpdateNode()", Form("%s", GetName()));
	TRDNode *node = 0x0;
	List_i iter = fChildren.begin();
	while(iter != fChildren.end()){
		if((node = dynamic_cast<TRDNode*>(*iter))) node->UpdateNode();
		iter++;
	}

	Int_t score[11];
	for(int i=0; i<11; i++) score[i] = 0;
	TRDModule *module;
	iter = fChildren.begin();
	while(iter != fChildren.end()){
		module = dynamic_cast<TRDModule*>(*iter);
		if(!module) continue;
		score[0] += (module->fLoadHits) ? 1 : 0;
		score[1] += (module->fRnrHits) ? 1 : 0;

		score[2] += (module->fLoadDigits) ? 1 : 0;
		score[3] += (module->fRnrDigits) ? 1 : 0;
		score[4] += (module->fDigitsLog) ? 1 : 0;
		score[5] += (module->fDigitsBox) ? 1 : 0;
		score[6] += (module->kDigitsNeedRecompute) ? 1 : 0;

		score[7] += (module->fLoadRecPoints) ? 1 : 0;
		score[8] += (module->fRnrRecPoints) ? 1 : 0;

		score[9] += (module->fLoadTracklets) ? 1 : 0;
		score[10] += (module->fRnrTracklets) ? 1 : 0;
		iter++;
	}

	Int_t size = fChildren.size();
	fLoadHits      = (score[0] > 0) ? kTRUE : kFALSE;
	fRnrHits       = (score[1] == size) ? kTRUE : kFALSE;

	fLoadDigits    = (score[2] > 0) ? kTRUE : kFALSE;
	fRnrDigits     = (score[3] == size) ? kTRUE : kFALSE;
	fDigitsLog     = (score[4] == size) ? kTRUE : kFALSE;
	fDigitsBox     = (score[5] == size) ? kTRUE : kFALSE;
	kDigitsNeedRecompute = (score[6] == size) ? kTRUE : kFALSE;

	fLoadRecPoints = (score[7] > 0) ? kTRUE : kFALSE;
	fRnrRecPoints  = (score[8] == size) ? kTRUE : kFALSE;

	fLoadTracklets = (score[9] > 0) ? kTRUE : kFALSE;
	fRnrTracklets  = (score[10] == size) ? kTRUE : kFALSE;
}

///////////////////////////////////////////////////////////
/////////////        TRDChamber       /////////////////////
///////////////////////////////////////////////////////////

//________________________________________________________
TRDChamber::TRDChamber(Int_t det) :
  Reve::RenderElement(), TRDModule("Chmb", det), rowMax(-1), colMax(-1), timeMax(22), fX0(0.), fPla(-1)
{
  //
  // Constructor
  //

	fDigits    = 0x0;
	fHits      = 0x0;
	fRecPoints = 0x0;
	fTracklets = 0x0;

	AliTRDCommonParam* parCom = AliTRDCommonParam::Instance();
	samplingFrequency = parCom->GetSamplingFrequency();

	fGeo      = 0x0;
	fPadPlane = 0x0;
}

//________________________________________________________
TRDChamber::TRDChamber(const TRDChamber &mod):
  Reve::RenderElement(), TRDModule("Chmb", mod.fDet)
{
  //
  // Copy constructor
  //
	SetMainColor(mod.GetMainColor());

	if(mod.fDigits) {}
	if(mod.fHits) {}
	if(mod.fRecPoints){}
}

//________________________________________________________
TRDChamber& TRDChamber::operator=(const TRDChamber &mod)
{
  //
  // Assignment operator
  //

  if (this != &mod) {
    fDet    = mod.fDet;
		if(mod.fDigits) {}
		if(mod.fHits) {}
		if(mod.fRecPoints){}
  }
  return *this;
}

//________________________________________________________
Int_t	TRDChamber::GetSM() const
{
	if(!fGeo){
		AliWarning("Fail. No TRD geometry defined.");
		return -1;
	}
	return fGeo->GetSector(fDet);
}

//________________________________________________________
Int_t	TRDChamber::GetSTK() const
{
	if(!fGeo){
		AliWarning("Fail. No TRD geometry defined.");
		return -1;
	}
	return fGeo->GetChamber(fDet);
}

//________________________________________________________
void TRDChamber::LoadClusters(TObjArray *clusters)
{
  //
  // Draw clusters
  //

	if(!fGeo){
		AliError(Form("Geometry not set for chamber %d. Please call first TRDChamber::SetGeometry().", fDet));
		return;
	}

	if(!fRecPoints){
		fRecPoints = new TRDClusters(this);
		fRecPoints->SetMarkerSize(1.);
		fRecPoints->SetMarkerStyle(24);
		fRecPoints->SetMarkerColor(6);
		fRecPoints->SetOwnIds(kTRUE);
	} else fRecPoints->Reset();

	Float_t q, z0;
  Double_t cloc[3], cglo[3];

	z0 = fGeo->GetTime0(fPla);
	AliTRDcluster *c=0x0;
	for(int iclus=0; iclus<clusters->GetEntriesFast(); iclus++){
		c = (AliTRDcluster*)clusters->UncheckedAt(iclus);
		cloc[2] = c->GetZ(); //x
		cloc[1] = c->GetY(); //y
		cloc[0] = z0 - c->GetX(); //z
		q = c->GetQ();
		fGeo->RotateBack(fDet,cloc,cglo);
		fRecPoints->SetNextPoint(cglo[0], cglo[1], cglo[2]);
		fRecPoints->SetPointId(c);
	}
	fLoadRecPoints = kTRUE;
}

//________________________________________________________
void TRDChamber::LoadDigits(AliTRDdigitsManager *digits)
{
  //
  // Draw digits
  //
	if(!fGeo){
		AliError(Form("Geometry not set for chamber %d. Please call first TRDChamber::SetGeometry().", fDet));
		return;
	}
//	Info("LoadDigits()", Form("digits =0x%x", digits));

	if(!fDigits) fDigits = new TRDDigits(this);
	else fDigits->Reset();

	fDigits->SetData(digits);
	fLoadDigits = kTRUE;
}

//________________________________________________________
void TRDChamber::AddHit(AliTRDhit *hit)
{
  //
  // Draw hits
  //
//	Info("AddHit()", Form("%s", GetName()));

	if(!fHits){
		fHits = new TRDHits(this);
		fHits->SetMarkerSize(.1);
		fHits->SetMarkerColor(2);
		fHits->SetOwnIds(kTRUE);
	}

	fHits->SetNextPoint(hit->X(), hit->Y(), hit->Z());
	fHits->SetPointId(hit);
	fLoadHits = kTRUE;
}

//________________________________________________________
void TRDChamber::LoadTracklets(TObjArray *tracks)
{
  //
  // Draw tracks
  //
	if(!fGeo){
		Error("LoadTracklets()", Form("Geometry not set for chamber %d. Please call first TRDChamber::SetGeometry().", fDet));
		return;
	}
//	Info("LoadTracklets()", Form("tracks = 0x%x", tracks));

	if(!fTracklets){
		fTracklets = new std::vector<Reve::Track*>;
	} else fTracklets->clear();

	AliTRDmcmTracklet *trk = 0x0;
	Double_t cloc[3], cglo[3];
	for(int itrk=0; itrk<tracks->GetEntries();itrk++){
		trk = (AliTRDmcmTracklet*)tracks->At(itrk);
		trk->MakeTrackletGraph(fGeo,.5);
		fTracklets->push_back(new Reve::Track());
		fTracklets->back()->SetLineColor(4);

		cloc[0] = trk->GetTime0(); // x0
		cloc[1] = trk->GetOffset(); // y0
		cloc[2] = trk->GetRowz(); // z
	  fGeo->RotateBack(fDet,cloc,cglo);
		fTracklets->back()->SetNextPoint(cglo[0], cglo[1], cglo[2]);

		cloc[0] += 3.7; // x1
		cloc[1] += TMath::Tan(trk->GetSlope()*TMath::Pi()/180.) * 3.7; // y1
	  fGeo->RotateBack(fDet,cloc,cglo);
		fTracklets->back()->SetNextPoint(cglo[0], cglo[1], cglo[2]);
	}
	fLoadTracklets = kTRUE;
}

//____________________________________________________
void	TRDChamber::Paint(Option_t* option)
{
/*	Info("Paint()", Form("%s", GetName()));*/
	if(!fRnrSelf) return;
	if(fDigits && fRnrDigits){
		if(kDigitsNeedRecompute){
			fDigits->ComputeRepresentation();
			kDigitsNeedRecompute = kFALSE;
		}
		fDigits->Paint(option);
	}
	if(fRecPoints && fRnrRecPoints) fRecPoints->GetObject()->Paint(option);
	if(fHits && fRnrHits) fHits->GetObject()->Paint(option);
	if(fTracklets && fRnrTracklets){
		for(vector<Reve::Track*>::iterator i=fTracklets->begin(); i != fTracklets->end(); ++i) (*i)->Paint(option);
	}
}

//________________________________________________________
void	TRDChamber::Reset()
{
	if(fHits){
		fHits->Reset();
		fLoadHits = kFALSE;
	}
	if(fDigits){
		fDigits->Reset();
		fLoadDigits = kFALSE;
	}
	if(fRecPoints){
		fRecPoints->Reset();
		fLoadRecPoints = kFALSE;
	}
	if(fTracklets){
		fTracklets->clear();
		fLoadTracklets = kFALSE;
	}
}

//________________________________________________________
void TRDChamber::SetGeometry(AliTRDgeometry *geo)
{
	fGeo = geo;

	fPla = fGeo->GetPlane(fDet);
	fX0 = fGeo->GetTime0(fPla);

	fPadPlane = fGeo->GetPadPlane(fPla,fGeo->GetChamber(fDet));
	rowMax = fPadPlane->GetNrows();
	colMax = fPadPlane->GetNcols();
}

<commit_msg>New treatment of the cluster coordinate (Christoph)<commit_after>#include "TRDModuleImp.h"
#include "TRDData.h"

#include "TMath.h"
#include <TGListTree.h>

#include "Reve/RGTopFrame.h"
#include "Reve/Track.h"

#include "AliLog.h"
#include "AliRun.h"
#include "AliTRDv1.h"
#include "AliTRDgeometry.h"
#include "AliTRDCommonParam.h"
#include "AliTRDpadPlane.h"
#include "AliTRDdigit.h"
#include "AliTRDhit.h"
#include "AliTRDcluster.h"
#include "AliTRDcalibDB.h"
#include "AliTRDdataArrayI.h"
#include "AliTRDmcmTracklet.h"

using namespace Reve;
using namespace Alieve;
using namespace std;

ClassImp(TRDChamber)
ClassImp(TRDNode)

//________________________________________________________
TRDNode::TRDNode(const char *typ, Int_t det) :
  Reve::RenderElement(), TRDModule(typ, det)
{
}

//________________________________________________________
void	TRDNode::Paint(Option_t* option)
{
	List_i iter = fChildren.begin();
	while(iter != fChildren.end()){
		(dynamic_cast<TRDModule*>(*iter))->Paint(option);
		iter++;
	}
}

//________________________________________________________
void	TRDNode::Reset()
{
	List_i iter = fChildren.begin();
	while(iter != fChildren.end()){
		(dynamic_cast<TRDModule*>(*iter))->Reset();
		iter++;
	}
}

//________________________________________________________
void TRDNode::Collapse()
{
	TGListTree *list = gReve->GetListTree();
	TRDNode *node = 0x0;
	List_i iter = fChildren.begin();
	while(iter != fChildren.end()){
		if((node = dynamic_cast<TRDNode*>(*iter))) node->Collapse();
		list->CloseItem(FindListTreeItem(list));
		iter++;
	}
}

//________________________________________________________
void TRDNode::Expand()
{
	TGListTree *list = gReve->GetListTree();
	TRDNode *node = 0x0;
	List_i iter = fChildren.begin();
	while(iter != fChildren.end()){
		if((node = dynamic_cast<TRDNode*>(*iter))) node->Expand();
		list->OpenItem(FindListTreeItem(list));
		iter++;
	}
}

//________________________________________________________
void TRDNode::EnableListElements()
{
	SetRnrSelf(kTRUE);
	TRDNode *node = 0x0;
	TRDChamber *chmb = 0x0;
	List_i iter = fChildren.begin();
	while(iter != fChildren.end()){
		if((node = dynamic_cast<TRDNode*>(*iter))){
			node->SetRnrSelf(kTRUE);
			node->EnableListElements();
		}
		if((chmb = dynamic_cast<TRDChamber*>(*iter))) chmb->SetRnrSelf(kTRUE);
		iter++;
	}
	gReve->Redraw3D();
}

//________________________________________________________
void TRDNode::DisableListElements()
{
	SetRnrSelf(kFALSE);
	TRDNode *node = 0x0;
	TRDChamber *chmb = 0x0;
	List_i iter = fChildren.begin();
	while(iter != fChildren.end()){
		if((node = dynamic_cast<TRDNode*>(*iter))){
			node->SetRnrSelf(kFALSE);
			node->DisableListElements();
		}
		if((chmb = dynamic_cast<TRDChamber*>(*iter))) chmb->SetRnrSelf(kFALSE);
		iter++;
	}
	gReve->Redraw3D();
}

//________________________________________________________
void TRDNode::UpdateLeaves()
{
	TRDModule *module;
	List_i iter = fChildren.begin();
	while(iter != fChildren.end()){
		module = dynamic_cast<TRDModule*>(*iter);
		if(!module) continue;

		module->fRnrHits = fRnrHits;
		module->fRnrDigits = fRnrDigits;
		module->fDigitsLog = fDigitsLog;
		module->fDigitsBox = fDigitsBox;
		module->fDigitsThreshold = fDigitsThreshold;
		module->kDigitsNeedRecompute = kDigitsNeedRecompute;
		module->fRnrRecPoints = fRnrRecPoints;
		module->fRnrTracklets = fRnrTracklets;
		iter++;
	}

	TRDNode *node = 0x0;
	iter = fChildren.begin();
	while(iter != fChildren.end()){
		if((node = dynamic_cast<TRDNode*>(*iter))) node->UpdateLeaves();
		iter++;
	}
}

//________________________________________________________
void TRDNode::UpdateNode()
{
//	Info("UpdateNode()", Form("%s", GetName()));
	TRDNode *node = 0x0;
	List_i iter = fChildren.begin();
	while(iter != fChildren.end()){
		if((node = dynamic_cast<TRDNode*>(*iter))) node->UpdateNode();
		iter++;
	}

	Int_t score[11];
	for(int i=0; i<11; i++) score[i] = 0;
	TRDModule *module;
	iter = fChildren.begin();
	while(iter != fChildren.end()){
		module = dynamic_cast<TRDModule*>(*iter);
		if(!module) continue;
		score[0] += (module->fLoadHits) ? 1 : 0;
		score[1] += (module->fRnrHits) ? 1 : 0;

		score[2] += (module->fLoadDigits) ? 1 : 0;
		score[3] += (module->fRnrDigits) ? 1 : 0;
		score[4] += (module->fDigitsLog) ? 1 : 0;
		score[5] += (module->fDigitsBox) ? 1 : 0;
		score[6] += (module->kDigitsNeedRecompute) ? 1 : 0;

		score[7] += (module->fLoadRecPoints) ? 1 : 0;
		score[8] += (module->fRnrRecPoints) ? 1 : 0;

		score[9] += (module->fLoadTracklets) ? 1 : 0;
		score[10] += (module->fRnrTracklets) ? 1 : 0;
		iter++;
	}

	Int_t size = fChildren.size();
	fLoadHits      = (score[0] > 0) ? kTRUE : kFALSE;
	fRnrHits       = (score[1] == size) ? kTRUE : kFALSE;

	fLoadDigits    = (score[2] > 0) ? kTRUE : kFALSE;
	fRnrDigits     = (score[3] == size) ? kTRUE : kFALSE;
	fDigitsLog     = (score[4] == size) ? kTRUE : kFALSE;
	fDigitsBox     = (score[5] == size) ? kTRUE : kFALSE;
	kDigitsNeedRecompute = (score[6] == size) ? kTRUE : kFALSE;

	fLoadRecPoints = (score[7] > 0) ? kTRUE : kFALSE;
	fRnrRecPoints  = (score[8] == size) ? kTRUE : kFALSE;

	fLoadTracklets = (score[9] > 0) ? kTRUE : kFALSE;
	fRnrTracklets  = (score[10] == size) ? kTRUE : kFALSE;
}

///////////////////////////////////////////////////////////
/////////////        TRDChamber       /////////////////////
///////////////////////////////////////////////////////////

//________________________________________________________
TRDChamber::TRDChamber(Int_t det) :
  Reve::RenderElement(), TRDModule("Chmb", det), rowMax(-1), colMax(-1), timeMax(22), fX0(0.), fPla(-1)
{
  //
  // Constructor
  //

	fDigits    = 0x0;
	fHits      = 0x0;
	fRecPoints = 0x0;
	fTracklets = 0x0;

	AliTRDCommonParam* parCom = AliTRDCommonParam::Instance();
	samplingFrequency = parCom->GetSamplingFrequency();

	fGeo      = 0x0;
	fPadPlane = 0x0;
}

//________________________________________________________
TRDChamber::TRDChamber(const TRDChamber &mod):
  Reve::RenderElement(), TRDModule("Chmb", mod.fDet)
{
  //
  // Copy constructor
  //
	SetMainColor(mod.GetMainColor());

	if(mod.fDigits) {}
	if(mod.fHits) {}
	if(mod.fRecPoints){}
}

//________________________________________________________
TRDChamber& TRDChamber::operator=(const TRDChamber &mod)
{
  //
  // Assignment operator
  //

  if (this != &mod) {
    fDet    = mod.fDet;
		if(mod.fDigits) {}
		if(mod.fHits) {}
		if(mod.fRecPoints){}
  }
  return *this;
}

//________________________________________________________
Int_t	TRDChamber::GetSM() const
{
	if(!fGeo){
		AliWarning("Fail. No TRD geometry defined.");
		return -1;
	}
	return fGeo->GetSector(fDet);
}

//________________________________________________________
Int_t	TRDChamber::GetSTK() const
{
	if(!fGeo){
		AliWarning("Fail. No TRD geometry defined.");
		return -1;
	}
	return fGeo->GetChamber(fDet);
}

//________________________________________________________
void TRDChamber::LoadClusters(TObjArray *clusters)
{
  //
  // Draw clusters
  //

	if(!fGeo){
		AliError(Form("Geometry not set for chamber %d. Please call first TRDChamber::SetGeometry().", fDet));
		return;
	}

	if(!fRecPoints){
		fRecPoints = new TRDClusters(this);
		fRecPoints->SetMarkerSize(1.);
		fRecPoints->SetMarkerStyle(24);
		fRecPoints->SetMarkerColor(6);
		fRecPoints->SetOwnIds(kTRUE);
	} else fRecPoints->Reset();

	Float_t q;
        Double_t cloc[3], cglo[3];

	AliTRDcluster *c=0x0;
	for(int iclus=0; iclus<clusters->GetEntriesFast(); iclus++){
		c = (AliTRDcluster*)clusters->UncheckedAt(iclus);
		cloc[0] = c->GetX();
		cloc[1] = c->GetY();
		cloc[2] = c->GetZ();
		q = c->GetQ();
		fGeo->RotateBack(fDet,cloc,cglo);
		fRecPoints->SetNextPoint(cglo[0], cglo[1], cglo[2]);
		fRecPoints->SetPointId(c);
	}
	fLoadRecPoints = kTRUE;
}

//________________________________________________________
void TRDChamber::LoadDigits(AliTRDdigitsManager *digits)
{
  //
  // Draw digits
  //
	if(!fGeo){
		AliError(Form("Geometry not set for chamber %d. Please call first TRDChamber::SetGeometry().", fDet));
		return;
	}
//	Info("LoadDigits()", Form("digits =0x%x", digits));

	if(!fDigits) fDigits = new TRDDigits(this);
	else fDigits->Reset();

	fDigits->SetData(digits);
	fLoadDigits = kTRUE;
}

//________________________________________________________
void TRDChamber::AddHit(AliTRDhit *hit)
{
  //
  // Draw hits
  //
//	Info("AddHit()", Form("%s", GetName()));

	if(!fHits){
		fHits = new TRDHits(this);
		fHits->SetMarkerSize(.1);
		fHits->SetMarkerColor(2);
		fHits->SetOwnIds(kTRUE);
	}

	fHits->SetNextPoint(hit->X(), hit->Y(), hit->Z());
	fHits->SetPointId(hit);
	fLoadHits = kTRUE;
}

//________________________________________________________
void TRDChamber::LoadTracklets(TObjArray *tracks)
{
  //
  // Draw tracks
  //
	if(!fGeo){
		Error("LoadTracklets()", Form("Geometry not set for chamber %d. Please call first TRDChamber::SetGeometry().", fDet));
		return;
	}
//	Info("LoadTracklets()", Form("tracks = 0x%x", tracks));

	if(!fTracklets){
		fTracklets = new std::vector<Reve::Track*>;
	} else fTracklets->clear();

	AliTRDmcmTracklet *trk = 0x0;
	Double_t cloc[3], cglo[3];
	for(int itrk=0; itrk<tracks->GetEntries();itrk++){
		trk = (AliTRDmcmTracklet*)tracks->At(itrk);
		trk->MakeTrackletGraph(fGeo,.5);
		fTracklets->push_back(new Reve::Track());
		fTracklets->back()->SetLineColor(4);

		cloc[0] = trk->GetTime0(); // x0
		cloc[1] = trk->GetOffset(); // y0
		cloc[2] = trk->GetRowz(); // z
	  fGeo->RotateBack(fDet,cloc,cglo);
		fTracklets->back()->SetNextPoint(cglo[0], cglo[1], cglo[2]);

		cloc[0] += 3.7; // x1
		cloc[1] += TMath::Tan(trk->GetSlope()*TMath::Pi()/180.) * 3.7; // y1
	  fGeo->RotateBack(fDet,cloc,cglo);
		fTracklets->back()->SetNextPoint(cglo[0], cglo[1], cglo[2]);
	}
	fLoadTracklets = kTRUE;
}

//____________________________________________________
void	TRDChamber::Paint(Option_t* option)
{
/*	Info("Paint()", Form("%s", GetName()));*/
	if(!fRnrSelf) return;
	if(fDigits && fRnrDigits){
		if(kDigitsNeedRecompute){
			fDigits->ComputeRepresentation();
			kDigitsNeedRecompute = kFALSE;
		}
		fDigits->Paint(option);
	}
	if(fRecPoints && fRnrRecPoints) fRecPoints->GetObject()->Paint(option);
	if(fHits && fRnrHits) fHits->GetObject()->Paint(option);
	if(fTracklets && fRnrTracklets){
		for(vector<Reve::Track*>::iterator i=fTracklets->begin(); i != fTracklets->end(); ++i) (*i)->Paint(option);
	}
}

//________________________________________________________
void	TRDChamber::Reset()
{
	if(fHits){
		fHits->Reset();
		fLoadHits = kFALSE;
	}
	if(fDigits){
		fDigits->Reset();
		fLoadDigits = kFALSE;
	}
	if(fRecPoints){
		fRecPoints->Reset();
		fLoadRecPoints = kFALSE;
	}
	if(fTracklets){
		fTracklets->clear();
		fLoadTracklets = kFALSE;
	}
}

//________________________________________________________
void TRDChamber::SetGeometry(AliTRDgeometry *geo)
{
	fGeo = geo;

	fPla = fGeo->GetPlane(fDet);
	fX0 = fGeo->GetTime0(fPla);

	fPadPlane = fGeo->GetPadPlane(fPla,fGeo->GetChamber(fDet));
	rowMax = fPadPlane->GetNrows();
	colMax = fPadPlane->GetNcols();
}

<|endoftext|>


<commit_before>#ifndef __CINT__
#include <TEveManager.h>
#include <TEvePointSet.h>
#include <EveBase/AliEveEventManager.h>

#include "AliRunLoader.h"
#include "AliCluster.h"
#include "AliTracker.h"
#include "AliReconstruction.h"
#include "AliESDEvent.h"
#include "AliESDtrack.h"
#include "AliESDfriend.h"
#endif

void clusters()
{
  AliEveEventManager::AssertGeometry();

  AliRunLoader *rl        = AliEveEventManager::AssertRunLoader();
  AliESDEvent  *esd       = AliEveEventManager::AssertESD();
  AliESDfriend *esdfriend = AliEveEventManager::AssertESDfriend();
  AliMagF      *magfield  = AliEveEventManager::AssertMagField();

  AliTracker::SetFieldMap(magfield, kFALSE);

  const char* detNames[] = { "ITS", "TPC", "TRD", "TOF", "HMPID" };
  const Int_t detIds[]   = {   0,     1,     2,     3,     5   };
  const Int_t detN       = sizeof(detNames)/sizeof(char*);

  AliReconstruction* reco = new AliReconstruction;
  reco->ImportRunLoader(rl);
  {
    TString alldets;
    for (Int_t i = 0; i < detN; ++i) {
      alldets += detNames[i];
      alldets += " ";
    }
    reco->CreateTrackers(alldets);
  }

  TObjArray* clarr = new TObjArray();

  // Load clusters, fill them into clarr.

  for (Int_t i = 0; i < detN; ++i)
  {
    Int_t det = detIds[i];
    rl->LoadRecPoints(detNames[i]);

    TTree *cTree = rl->GetTreeR(detNames[i], false);
    if (cTree == 0)
      continue;

    AliTracker* tracker = reco->GetTracker(det);
    tracker->LoadClusters(cTree);
    tracker->FillClusterArray(clarr);
  }

  // Loop over tracks and friends, tag used clusters.

  for (Int_t n = 0; n < esd->GetNumberOfTracks(); ++n)
  {
    AliESDtrack* at = esd->GetTrack(n);

    Int_t idx[200];
    for (Int_t i = 0; i < detN; ++i)
    {
      Int_t det = detIds[i];
      AliTracker* tracker = reco->GetTracker(det);
      Int_t nclusters = at->GetClusters(det, idx);
      Int_t p=0;
      for (Int_t c = 0; c < nclusters; )
      {
        Int_t index = idx[p++];
        if (index < 0) continue;
        c++;
        AliCluster* cluster = tracker->GetCluster(index);
        if (cluster) cluster->IncreaseClusterUsage();
        //else printf("Zero cluster pointer for detector: %s\n",detNames[i]);
      }
    }
  }

  for (Int_t i = 0; i < detN; ++i)
    rl->UnloadRecPoints(detNames[i]);

  // Fill visualization structs

  TEveElementList* list = new TEveElementList("Clusters");
  gEve->AddElement(list);

  TEvePointSet* shared = new TEvePointSet("Shared Clusters");
  shared->SetMainColor(2);
  shared->SetMarkerSize(0.4);
  shared->SetMarkerStyle(2);
  list->AddElement(shared);

  TEvePointSet* used = new TEvePointSet("Single-used Clusters");
  used->SetMainColor(3);
  used->SetMarkerSize(0.4);
  used->SetMarkerStyle(2);
  list->AddElement(used);

  TEvePointSet* nonused = new TEvePointSet("Not-used Clusters");
  nonused->SetMainColor(4);
  nonused->SetMarkerSize(0.4);
  nonused->SetMarkerStyle(2);
  list->AddElement(nonused);

  // Loop over all clusters, fill appropriate container based
  // on shared/used information.

  Int_t ncl = clarr->GetEntriesFast();
  for (Int_t i = 0; i < ncl; ++i)
  {
    AliCluster   *cluster = (AliCluster*) clarr->UncheckedAt(i);
    TEvePointSet *dest    = 0;
    if (cluster->IsClusterShared())
      dest = shared;
    else if (cluster->IsClusterUsed())
      dest = used;
    else
      dest = nonused;

    Float_t g[3]; //global coordinates
    cluster->GetGlobalXYZ(g);
    dest->SetNextPoint(g[0], g[1], g[2]);
    dest->SetPointId(cluster);
  }

  delete clarr;

  // ??? What to do with trackers ???
  // I'd propose: have global reconstruction that owns them.
  // AliEveEventManager::AssertAliReconstruction();
  // do we have bit-field for detectors, like
  // enum AliDetectors_e {
  //    kITS = BIT(0),
  //    kTPC = BIT(1),
  //    ...
  //    kCentralTracking = kITS | kTPC | kTRD | kTOF,
  //    ...
  //  };

  gEve->Redraw3D();
}
<commit_msg>With Cvetan: two hacks to make it work again: a) set gGeoManager to 0 before instantiating AliReconstruction and restore    it afterwards; b) set dummy low-flux reco-params for ITS as they are required at tracker    construction time.<commit_after>#ifndef __CINT__
#include <TEveManager.h>
#include <TEvePointSet.h>
#include <EveBase/AliEveEventManager.h>

#include "AliRunLoader.h"
#include "AliCluster.h"
#include "AliTracker.h"
#include "AliReconstruction.h"
#include "AliESDEvent.h"
#include "AliESDtrack.h"
#include "AliESDfriend.h"
#endif

void clusters()
{
  AliEveEventManager::AssertGeometry();

  AliRunLoader *rl        = AliEveEventManager::AssertRunLoader();
  AliESDEvent  *esd       = AliEveEventManager::AssertESD();
  AliESDfriend *esdfriend = AliEveEventManager::AssertESDfriend();
  AliMagF      *magfield  = AliEveEventManager::AssertMagField();

  AliTracker::SetFieldMap(magfield, kFALSE);

  const char* detNames[] = { "ITS", "TPC", "TRD", "TOF", "HMPID" };
  const Int_t detIds[]   = {   0,     1,     2,     3,     5   };
  const Int_t detN       = sizeof(detNames)/sizeof(char*);

  // Hack - AliReconstruction does wonders with gGeoManager.
  TGeoManager* xxx = gGeoManager; gGeoManager = 0;
  AliReconstruction* reco = new AliReconstruction;
  gGeoManager = xxx;

  // Hack for ITS - it requires RecoParams outside event-loop!
  reco.SetRecoParam("ITS", AliITSRecoParam::GetLowFluxParam());

  reco->ImportRunLoader(rl);
  {
    TString alldets;
    for (Int_t i = 0; i < detN; ++i) {
      alldets += detNames[i];
      alldets += " ";
    }
    reco->CreateTrackers(alldets);
  }

  TObjArray* clarr = new TObjArray();

  // Load clusters, fill them into clarr.

  for (Int_t i = 0; i < detN; ++i)
  {
    Int_t det = detIds[i];
    rl->LoadRecPoints(detNames[i]);

    TTree *cTree = rl->GetTreeR(detNames[i], false);
    if (cTree == 0)
      continue;

    AliTracker* tracker = reco->GetTracker(det);
    tracker->LoadClusters(cTree);
    tracker->FillClusterArray(clarr);
  }

  // Loop over tracks and friends, tag used clusters.

  for (Int_t n = 0; n < esd->GetNumberOfTracks(); ++n)
  {
    AliESDtrack* at = esd->GetTrack(n);

    Int_t idx[200];
    for (Int_t i = 0; i < detN; ++i)
    {
      Int_t det = detIds[i];
      AliTracker* tracker = reco->GetTracker(det);
      Int_t nclusters = at->GetClusters(det, idx);
      Int_t p=0;
      for (Int_t c = 0; c < nclusters; )
      {
        Int_t index = idx[p++];
        if (index < 0) continue;
        c++;
        AliCluster* cluster = tracker->GetCluster(index);
        if (cluster) cluster->IncreaseClusterUsage();
        //else printf("Zero cluster pointer for detector: %s\n",detNames[i]);
      }
    }
  }

  for (Int_t i = 0; i < detN; ++i)
    rl->UnloadRecPoints(detNames[i]);

  // Fill visualization structs

  TEveElementList* list = new TEveElementList("Clusters");
  gEve->AddElement(list);

  TEvePointSet* shared = new TEvePointSet("Shared Clusters");
  shared->SetMainColor(2);
  shared->SetMarkerSize(0.4);
  shared->SetMarkerStyle(2);
  list->AddElement(shared);

  TEvePointSet* used = new TEvePointSet("Single-used Clusters");
  used->SetMainColor(3);
  used->SetMarkerSize(0.4);
  used->SetMarkerStyle(2);
  list->AddElement(used);

  TEvePointSet* nonused = new TEvePointSet("Not-used Clusters");
  nonused->SetMainColor(4);
  nonused->SetMarkerSize(0.4);
  nonused->SetMarkerStyle(2);
  list->AddElement(nonused);

  // Loop over all clusters, fill appropriate container based
  // on shared/used information.

  Int_t ncl = clarr->GetEntriesFast();
  for (Int_t i = 0; i < ncl; ++i)
  {
    AliCluster   *cluster = (AliCluster*) clarr->UncheckedAt(i);
    TEvePointSet *dest    = 0;
    if (cluster->IsClusterShared())
      dest = shared;
    else if (cluster->IsClusterUsed())
      dest = used;
    else
      dest = nonused;

    Float_t g[3]; //global coordinates
    cluster->GetGlobalXYZ(g);
    dest->SetNextPoint(g[0], g[1], g[2]);
    dest->SetPointId(cluster);
  }

  delete clarr;

  // ??? What to do with trackers ???
  // I'd propose: have global reconstruction that owns them.
  // AliEveEventManager::AssertAliReconstruction();
  // do we have bit-field for detectors, like
  // enum AliDetectors_e {
  //    kITS = BIT(0),
  //    kTPC = BIT(1),
  //    ...
  //    kCentralTracking = kITS | kTPC | kTRD | kTOF,
  //    ...
  //  };

  gEve->Redraw3D();
}
<|endoftext|>


<commit_before>/******************************************************************************\
* UsersGuide.hpp                                                               *
* Additional Doxygen documentation for Diluculum: user's guide.                *
*                                                                              *
*                                                                              *
* Copyright (C) 2005-2007 by Leandro Motta Barros.                             *
*                                                                              *
* Permission is hereby granted, free of charge, to any person obtaining a copy *
* of this software and associated documentation files (the "Software"), to     *
* deal in the Software without restriction, including without limitation the   *
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or  *
* sell copies of the Software, and to permit persons to whom the Software is   *
* furnished to do so, subject to the following conditions:                     *
*                                                                              *
* The above copyright notice and this permission notice shall be included in   *
* all copies or substantial portions of the Software.                          *
*                                                                              *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR   *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,     *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER       *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      *
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS *
* IN THE SOFTWARE.                                                             *
\******************************************************************************/

/** @page pag-UsersGuide Diluculum's Quick User's Guide

\section Introduction

Diluculum is a library that intends to make the coexistence of C++ and Lua more
harmonious. In this regard, it offers essentially three capabilities:

- A nice way to access data stored in a Lua interpreter. This is provided by the
  \c Diluculum::LuaState class, which encapsulates a <tt>lua_State*</tt>.

- A not so bad way to write functions in C++ and make them available to
  Lua. This is done with the use of macros like \c DILUCULUM_WRAP_FUNCTION().

- A limited and just barely usable way to register C++ classes and objects in a
  Lua state. This is done with a set of macros, like \c DILUCULUM_BEGIN_CLASS()
  and \c DILUCULUM_REGISTER_OBJECT().

The next sections discuss each of these three items in more detail. One more
note: Diluculum has unit tests for all its features, at the \c Tests directory
in the source distribution. These tests also serve as good examples on how to
use the library.

\section sec-AcessingLuaState Accessing Data In a Lua State

The class \c Diluculum::LuaState encapsulates a <tt>lua_State*</tt>, that is a
Lua interpreter. Lua is frequently used as a configuration language, and for
this purpose, a \c Diluculum::LuaState works pretty well. Suppose we have a Lua
file named \c config.lua which will be used as the configuration file for some
application:

\verbatim
-- A configuration file

FavoriteColor = "blue"

FavoritePiApproximation = 22/7

UserInfo = {
   Name = "Fulano de Tal",
   Age = 33,
   LikesLargeIcons = true,
}

WindowSize = { 456, 234 }

function EmphasizeFunc(s)
   return "<EMPH>"..s.."</EMPH>"
end

\endverbatim

In order to access the information in this file from C++, the first step is to
create a \c Diluculum::LuaState, and execute the file, as shown below.

\code
#include <Diluculum/LuaState.hpp>

// ...

Diluculum::LuaState ls;
ls.doFile ("config.lua");
\endcode

Then, you are ready to used the subscript operator of \c Diluculum::LuaState to
access the variables living in it.

\code
const std::string favColor = ls["FavoriteColor"].value().asString();
const double favPiApprox = ls["FavoritePiApproximation"].value().asNumber();

const std::string userName = ls["UserInfo"]["Name"].value().asString();
const int userAge = static_cast<int>(ls["UserInfo"]["Age"].value().asNumber());
const bool userLikesLargeIcons = ls["UserInfo"]["LikesLargeIcons"].value().asBoolean();

const int winWidth = static_cast<int>(ls["WindowSize"][1].value().asNumber());
const int winHeight = static_cast<int>(ls["WindowSize"][2].value().asNumber());
\endcode

These calls to \c value(), \c asNumber(), \c asString() and so on are a little
cumbersome, but not \e that bad. Anyway, if you are just testing for equality
(or inequality), you can omit them:

\code
if (ls["UserInfo"]["LikesLargeIcons"] == true)
{
   // ...
}

if (ls["FavoriteColor"] != "blue")
{
   std::cout << "You have bad taste for colors!\n";
}
\endcode

You may also have noticed that a function was defined in \c config.lua. It can
be called from C++ with relative ease. The only thing to notice is that Lua
functions can return an arbitrary number of values, so the return in C++ will
be a \c Diluculum::LuaValueList. The code snippet below shows how to call that
function.

\code
Diluculum::LuaValueList ret = ls["EmphasizeFunc"]("String to be emphasized");
std::cout << ret[0].asString() << '\n';
\endcode

Notice that no call to \c value() is necessary here, because function calls will
aready return values (<tt>Diluculum::LuaValue</tt>s) instead of variables
(<tt>Diluculum::LuaVariable</tt>s).

The subscript operator also provides write access to the Lua state, so you can
change or add new variables. Perhaps this doesn't make much sense if you are
using Lua just as a simple configuration language, as shown up to this point,
but the feature is useful nevertheless. The example below shows how to do this.

\code
ls["newNumber"] = -123.456;
ls["newString"] = "Ahhhh!";
ls["FavoritePiApproximation"] = 3.14159265;
\endcode

\section sec-WrappingFunctions Wrapping C++ Functions

First of all, if you happen to have a <tt>lua_CFunction</tt> (the functions used
with the Lua API), you can just assign them to a \c Diluculum::LuaState, as done
in the previous section, and as shown below.

\code
int aLuaCFunction (lua_State* ls)
{
   // ...
}

// ...

// Create a Lua state and register the function there
Diluculum::LuaState ls;
ls["Func"] = aLuaCFunction;

// Call the function from Lua
ls.doString ("Func (1, 2, 3, 'four')");
\endcode

It turns out that writing a <tt>lua_CFunction</tt> involves manipulating a raw
<tt>lua_State*</tt>, which may not be what you want. So, Diluculum can
automatically create a <tt>lua_CFunction</tt> from a function that takes and
returns a \c Diluculum::LuaValueList. Then, this function can be registered in a
\c Diluculum::LuaState as above. The code snippet below demonstrates this.

\code
#include <Diluculum/LuaWrappers.hpp>

// [...]

// In Lua, this will take one number parameter and return three numbers, which
// are equal the parameter, two times the parameter, and three times the
// parameter. Not very useful, uh?
Diluculum::LuaValueList MyFunction (const Diluculum::LuaValueList& params)
{
   if (params.size() != 1 || params[0].type() != LUA_TNUMBER)
      throw Diluculum::LuaError ("Bad parameters!");

   Diluculum::LuaValueList ret;

   ret.push_back (params[0].asNumber());
   ret.push_back (params[0].asNumber() * 2);
   ret.push_back (params[0].asNumber() * 3);

   return ret;
}

// Create a 'lua_CFunction'
DILUCULUM_WRAP_FUNCTION (MyFunction);

// ...

// Create a Lua state and register the function.
Diluculum::LuaState ls;
ls["MyFunction"] = DILUCULUM_WRAPPER_FUNCTION (MyFunction);

// Now, 'MyFunction' can be called from Lua
ls.doString ("a, b, c = MyFunction (4.5)");
\endcode

Perhaps the only important thingh to notice in the example above is that
throwing a \c Diluculum::LuaError is the proper way to report an error from the
wrapped function. For those that know the Lua C API, this exception will be
handled and "translated" to a call to \c lua_error().

And that's it. Not exactly a proper and "generic" wrapper like
toLua,
toLua++ or
Luabind,
but may be useful for someone (it is for me!)

\section sec-WrappingClasses Wrapping C++ Classes and Objects

Finally, Diluculum has limited support for wrapping C++ classes and objects to
Lua and registering them in a Lua state. I call it "limited" because it
doesn't support real object orientation (most notably, it lacks inheritance). It
is also somewhat cumbersome to use. But, again, it may be useful for someone
other than me.

Diluculum cannot handle any class. Just as it expected functions with a specific
signature (see the previous section), classes must follow some rules in order to
be usable with Diluculum. First, it must have a constructor that takes a
\c Diluculum::LuaValueList as parameter. Second, all methods that will be
exported must take a \c Diluculum::LuaValueList as parameter and also return a
\c Diluculum::LuaValueList. The class below is an example of a "valid" class.

\code
// A class that stores one value. Duh.
class ValueBox
{
   public:
      // The constructor taking a 'Diluculum::LuaValueList' parameter.
      ValueBox (const Diluculum::LuaValueList& params)
      {
         if (params.size() > 0)
            value_ = params[0];
      }

      // Stores the value passed as parameter in the box, and returns the value
      // previously stored there.
      Diluculum::LuaValueList swap (const Diluculum::LuaValueList& params)
      {
         if (params.size() != 1)
            throw Diluculum::LuaError ("Exactly one parameter was expected.");

         Diluculum::LuaValueList ret;
         ret.push_back (value_);
         value_ = params[0];
         return ret;
      }

   private:
      Diluculum::LuaValue value_;
};
\endcode

As was the case with free functions, throwing a \c Diluculum::LuaError is the
way to report errors from methods. The class is exported to Lua by issuing a
sequence of macro calls that will create some data structures representing the
class. (For the Lua-inclined readers: more specifically, it will create a global
\c Diluculum::LuaValueMap representing the class; it will be used as the
metatable for the objects in Lua.) These macro calls are shown below.

\code
DILUCULUM_BEGIN_CLASS (ValueBox);
   DILUCULUM_CLASS_METHOD (ValueBox, swap);
DILUCULUM_END_CLASS (ValueBox);
\endcode

I'm showing just a single call of \c DILUCULUM_CLASS_METHOD() here because the
class being exported has just one method. It is OK to add as many methods as
desired. Now we are ready to register this class in a Lua state, so that it can
actually be used. This requires one more macro call. After this final macro
call, objects of this class can be instantiated from Lua. The code snippet below
shows how to do this.

\code
Diluculum::LuaState ls;
DILUCULUM_REGISTER_CLASS (ls["ValueBox"], ValueBox);

ls.doString ("box = ValueBox.new(3)");
ls.doString ("print (box:swap('foo'))"); // prints '3'
ls.doString ("print (box:swap(789.987))"); // prints 'foo'

\endcode

\subsection sec-MemoryManagement Memory Management

When an object instantiated in Lua is garbage collected, the object's destructor
will be properly called, so that its resources are properly freed (assuming that
the programmer in the C++ side wrote a proper destructor, of course). It is also
possible to explicitly call the object's destructor in order to free its
resources before the object is garbage collected. See below.

\code
Diluculum::LuaState ls;
DILUCULUM_REGISTER_CLASS (ls["ValueBox"], ValueBox);

ls.doString ("box = ValueBox.new()");

// ...use 'box'...

ls.doString ("box:delete()");
\endcode

And this is a good moment to discuss a very important case in which calling the
destructor explicitly in Lua is a good idea. The problem is that Lua doesn't
know how much memory an object occupies. For every object instantiated using
Diluculum's facilities, Lua is only aware of a little of memory (a pointer and
some additional flags). If the object itself allocates more memory (as any
decent object is supposed to do), Lua will not know this, and the garbage
collector will not detect the "right" amount of memory allocated from within
Lua. So, if you instantiate a big object, you better free it manually from Lua
as soon as you don't need it anymore. Likewise, if you allocate many objects (in
a loop, perhaps), you better delete each of them manually.

\subsection sec-RegisteringObjects Registering Objects

Sometimes one may have an object constructed in the C++ side, and want to make
it available to a Lua state. In other words, one may want to create an object in
C++ and call its methods from Lua. This can be done with Diluculum, using yet
another macro, as shown below.

\code
Diluculum::LuaState ls;

Diluculum::LuaValueList params;
ValueBox vb (params);

DILUCULUM_REGISTER_OBJECT (ls["box"], ValueBox, vb);

ls.doString ("box:swap (123)");

std::cout << vb.swap("abc") << '\n'; // prints '123'.
\endcode

Notice that when \c box is garbage collected in Lua, the C++ object will \e not
be destroyed. In this case, cleaning the object is responsibility of the
programmer on the C++ side.

\subsection sec-DynamicModules Dynamically Loadable Modules

Since release 0.4, Diluculum has some facilities for creating dynamically
loadable Lua modules. These are those modules compiled to a dynamic-link
library, and which are automatically loaded when the Lua programmer says
something like

\code
require "MyModule"
\endcode

Actually, Diluculum doesn't do much in this regard, and using its facilities is
\em not so much simpler than using the Lua API itself. Anyway, this is a user's
guide, so it is supposed to explain how this thing works. So, here we go.
Basically, all we can do is to create a module and add functions and classes to
it. Here is an example, that shows how to create a module containing a single
function and a single class that were defined previously in this guide.

\code
DILUCULUM_BEGIN_MODULE (MyFineModule);
   DILUCULUM_MODULE_ADD_CLASS (ValueBox, "ValueBox");
   DILUCULUM_MODULE_ADD_FUNCTION (DILUCULUM_WRAPPER_FUNCTION(MyFunction), "MyFunction");
DILUCULUM_END_MODULE();
\endcode

So, if this is compiled to a properly named dynamic library (see
Lua's Reference Manual to know what
constitutes a proper module name), the Lua programmer can say something like:

\code
require "MyFineModule"

local v = MyFineModule.ValueBox.new(4321)
v.swap ("Weeeeee!")

local x, y, z = MyFineModule.MyFunction (4.567)
\endcode

*/
<commit_msg>Fixed typo in the User's Guide: replaced "aready" with "already".<commit_after>/******************************************************************************\
* UsersGuide.hpp                                                               *
* Additional Doxygen documentation for Diluculum: user's guide.                *
*                                                                              *
*                                                                              *
* Copyright (C) 2005-2007 by Leandro Motta Barros.                             *
*                                                                              *
* Permission is hereby granted, free of charge, to any person obtaining a copy *
* of this software and associated documentation files (the "Software"), to     *
* deal in the Software without restriction, including without limitation the   *
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or  *
* sell copies of the Software, and to permit persons to whom the Software is   *
* furnished to do so, subject to the following conditions:                     *
*                                                                              *
* The above copyright notice and this permission notice shall be included in   *
* all copies or substantial portions of the Software.                          *
*                                                                              *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR   *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,     *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER       *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      *
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS *
* IN THE SOFTWARE.                                                             *
\******************************************************************************/

/** @page pag-UsersGuide Diluculum's Quick User's Guide

\section Introduction

Diluculum is a library that intends to make the coexistence of C++ and Lua more
harmonious. In this regard, it offers essentially three capabilities:

- A nice way to access data stored in a Lua interpreter. This is provided by the
  \c Diluculum::LuaState class, which encapsulates a <tt>lua_State*</tt>.

- A not so bad way to write functions in C++ and make them available to
  Lua. This is done with the use of macros like \c DILUCULUM_WRAP_FUNCTION().

- A limited and just barely usable way to register C++ classes and objects in a
  Lua state. This is done with a set of macros, like \c DILUCULUM_BEGIN_CLASS()
  and \c DILUCULUM_REGISTER_OBJECT().

The next sections discuss each of these three items in more detail. One more
note: Diluculum has unit tests for all its features, at the \c Tests directory
in the source distribution. These tests also serve as good examples on how to
use the library.

\section sec-AcessingLuaState Accessing Data In a Lua State

The class \c Diluculum::LuaState encapsulates a <tt>lua_State*</tt>, that is a
Lua interpreter. Lua is frequently used as a configuration language, and for
this purpose, a \c Diluculum::LuaState works pretty well. Suppose we have a Lua
file named \c config.lua which will be used as the configuration file for some
application:

\verbatim
-- A configuration file

FavoriteColor = "blue"

FavoritePiApproximation = 22/7

UserInfo = {
   Name = "Fulano de Tal",
   Age = 33,
   LikesLargeIcons = true,
}

WindowSize = { 456, 234 }

function EmphasizeFunc(s)
   return "<EMPH>"..s.."</EMPH>"
end

\endverbatim

In order to access the information in this file from C++, the first step is to
create a \c Diluculum::LuaState, and execute the file, as shown below.

\code
#include <Diluculum/LuaState.hpp>

// ...

Diluculum::LuaState ls;
ls.doFile ("config.lua");
\endcode

Then, you are ready to used the subscript operator of \c Diluculum::LuaState to
access the variables living in it.

\code
const std::string favColor = ls["FavoriteColor"].value().asString();
const double favPiApprox = ls["FavoritePiApproximation"].value().asNumber();

const std::string userName = ls["UserInfo"]["Name"].value().asString();
const int userAge = static_cast<int>(ls["UserInfo"]["Age"].value().asNumber());
const bool userLikesLargeIcons = ls["UserInfo"]["LikesLargeIcons"].value().asBoolean();

const int winWidth = static_cast<int>(ls["WindowSize"][1].value().asNumber());
const int winHeight = static_cast<int>(ls["WindowSize"][2].value().asNumber());
\endcode

These calls to \c value(), \c asNumber(), \c asString() and so on are a little
cumbersome, but not \e that bad. Anyway, if you are just testing for equality
(or inequality), you can omit them:

\code
if (ls["UserInfo"]["LikesLargeIcons"] == true)
{
   // ...
}

if (ls["FavoriteColor"] != "blue")
{
   std::cout << "You have bad taste for colors!\n";
}
\endcode

You may also have noticed that a function was defined in \c config.lua. It can
be called from C++ with relative ease. The only thing to notice is that Lua
functions can return an arbitrary number of values, so the return in C++ will
be a \c Diluculum::LuaValueList. The code snippet below shows how to call that
function.

\code
Diluculum::LuaValueList ret = ls["EmphasizeFunc"]("String to be emphasized");
std::cout << ret[0].asString() << '\n';
\endcode

Notice that no call to \c value() is necessary here, because function calls will
already return values (<tt>Diluculum::LuaValue</tt>s) instead of variables
(<tt>Diluculum::LuaVariable</tt>s).

The subscript operator also provides write access to the Lua state, so you can
change or add new variables. Perhaps this doesn't make much sense if you are
using Lua just as a simple configuration language, as shown up to this point,
but the feature is useful nevertheless. The example below shows how to do this.

\code
ls["newNumber"] = -123.456;
ls["newString"] = "Ahhhh!";
ls["FavoritePiApproximation"] = 3.14159265;
\endcode

\section sec-WrappingFunctions Wrapping C++ Functions

First of all, if you happen to have a <tt>lua_CFunction</tt> (the functions used
with the Lua API), you can just assign them to a \c Diluculum::LuaState, as done
in the previous section, and as shown below.

\code
int aLuaCFunction (lua_State* ls)
{
   // ...
}

// ...

// Create a Lua state and register the function there
Diluculum::LuaState ls;
ls["Func"] = aLuaCFunction;

// Call the function from Lua
ls.doString ("Func (1, 2, 3, 'four')");
\endcode

It turns out that writing a <tt>lua_CFunction</tt> involves manipulating a raw
<tt>lua_State*</tt>, which may not be what you want. So, Diluculum can
automatically create a <tt>lua_CFunction</tt> from a function that takes and
returns a \c Diluculum::LuaValueList. Then, this function can be registered in a
\c Diluculum::LuaState as above. The code snippet below demonstrates this.

\code
#include <Diluculum/LuaWrappers.hpp>

// [...]

// In Lua, this will take one number parameter and return three numbers, which
// are equal the parameter, two times the parameter, and three times the
// parameter. Not very useful, uh?
Diluculum::LuaValueList MyFunction (const Diluculum::LuaValueList& params)
{
   if (params.size() != 1 || params[0].type() != LUA_TNUMBER)
      throw Diluculum::LuaError ("Bad parameters!");

   Diluculum::LuaValueList ret;

   ret.push_back (params[0].asNumber());
   ret.push_back (params[0].asNumber() * 2);
   ret.push_back (params[0].asNumber() * 3);

   return ret;
}

// Create a 'lua_CFunction'
DILUCULUM_WRAP_FUNCTION (MyFunction);

// ...

// Create a Lua state and register the function.
Diluculum::LuaState ls;
ls["MyFunction"] = DILUCULUM_WRAPPER_FUNCTION (MyFunction);

// Now, 'MyFunction' can be called from Lua
ls.doString ("a, b, c = MyFunction (4.5)");
\endcode

Perhaps the only important thingh to notice in the example above is that
throwing a \c Diluculum::LuaError is the proper way to report an error from the
wrapped function. For those that know the Lua C API, this exception will be
handled and "translated" to a call to \c lua_error().

And that's it. Not exactly a proper and "generic" wrapper like
toLua,
toLua++ or
Luabind,
but may be useful for someone (it is for me!)

\section sec-WrappingClasses Wrapping C++ Classes and Objects

Finally, Diluculum has limited support for wrapping C++ classes and objects to
Lua and registering them in a Lua state. I call it "limited" because it
doesn't support real object orientation (most notably, it lacks inheritance). It
is also somewhat cumbersome to use. But, again, it may be useful for someone
other than me.

Diluculum cannot handle any class. Just as it expected functions with a specific
signature (see the previous section), classes must follow some rules in order to
be usable with Diluculum. First, it must have a constructor that takes a
\c Diluculum::LuaValueList as parameter. Second, all methods that will be
exported must take a \c Diluculum::LuaValueList as parameter and also return a
\c Diluculum::LuaValueList. The class below is an example of a "valid" class.

\code
// A class that stores one value. Duh.
class ValueBox
{
   public:
      // The constructor taking a 'Diluculum::LuaValueList' parameter.
      ValueBox (const Diluculum::LuaValueList& params)
      {
         if (params.size() > 0)
            value_ = params[0];
      }

      // Stores the value passed as parameter in the box, and returns the value
      // previously stored there.
      Diluculum::LuaValueList swap (const Diluculum::LuaValueList& params)
      {
         if (params.size() != 1)
            throw Diluculum::LuaError ("Exactly one parameter was expected.");

         Diluculum::LuaValueList ret;
         ret.push_back (value_);
         value_ = params[0];
         return ret;
      }

   private:
      Diluculum::LuaValue value_;
};
\endcode

As was the case with free functions, throwing a \c Diluculum::LuaError is the
way to report errors from methods. The class is exported to Lua by issuing a
sequence of macro calls that will create some data structures representing the
class. (For the Lua-inclined readers: more specifically, it will create a global
\c Diluculum::LuaValueMap representing the class; it will be used as the
metatable for the objects in Lua.) These macro calls are shown below.

\code
DILUCULUM_BEGIN_CLASS (ValueBox);
   DILUCULUM_CLASS_METHOD (ValueBox, swap);
DILUCULUM_END_CLASS (ValueBox);
\endcode

I'm showing just a single call of \c DILUCULUM_CLASS_METHOD() here because the
class being exported has just one method. It is OK to add as many methods as
desired. Now we are ready to register this class in a Lua state, so that it can
actually be used. This requires one more macro call. After this final macro
call, objects of this class can be instantiated from Lua. The code snippet below
shows how to do this.

\code
Diluculum::LuaState ls;
DILUCULUM_REGISTER_CLASS (ls["ValueBox"], ValueBox);

ls.doString ("box = ValueBox.new(3)");
ls.doString ("print (box:swap('foo'))"); // prints '3'
ls.doString ("print (box:swap(789.987))"); // prints 'foo'

\endcode

\subsection sec-MemoryManagement Memory Management

When an object instantiated in Lua is garbage collected, the object's destructor
will be properly called, so that its resources are properly freed (assuming that
the programmer in the C++ side wrote a proper destructor, of course). It is also
possible to explicitly call the object's destructor in order to free its
resources before the object is garbage collected. See below.

\code
Diluculum::LuaState ls;
DILUCULUM_REGISTER_CLASS (ls["ValueBox"], ValueBox);

ls.doString ("box = ValueBox.new()");

// ...use 'box'...

ls.doString ("box:delete()");
\endcode

And this is a good moment to discuss a very important case in which calling the
destructor explicitly in Lua is a good idea. The problem is that Lua doesn't
know how much memory an object occupies. For every object instantiated using
Diluculum's facilities, Lua is only aware of a little of memory (a pointer and
some additional flags). If the object itself allocates more memory (as any
decent object is supposed to do), Lua will not know this, and the garbage
collector will not detect the "right" amount of memory allocated from within
Lua. So, if you instantiate a big object, you better free it manually from Lua
as soon as you don't need it anymore. Likewise, if you allocate many objects (in
a loop, perhaps), you better delete each of them manually.

\subsection sec-RegisteringObjects Registering Objects

Sometimes one may have an object constructed in the C++ side, and want to make
it available to a Lua state. In other words, one may want to create an object in
C++ and call its methods from Lua. This can be done with Diluculum, using yet
another macro, as shown below.

\code
Diluculum::LuaState ls;

Diluculum::LuaValueList params;
ValueBox vb (params);

DILUCULUM_REGISTER_OBJECT (ls["box"], ValueBox, vb);

ls.doString ("box:swap (123)");

std::cout << vb.swap("abc") << '\n'; // prints '123'.
\endcode

Notice that when \c box is garbage collected in Lua, the C++ object will \e not
be destroyed. In this case, cleaning the object is responsibility of the
programmer on the C++ side.

\subsection sec-DynamicModules Dynamically Loadable Modules

Since release 0.4, Diluculum has some facilities for creating dynamically
loadable Lua modules. These are those modules compiled to a dynamic-link
library, and which are automatically loaded when the Lua programmer says
something like

\code
require "MyModule"
\endcode

Actually, Diluculum doesn't do much in this regard, and using its facilities is
\em not so much simpler than using the Lua API itself. Anyway, this is a user's
guide, so it is supposed to explain how this thing works. So, here we go.
Basically, all we can do is to create a module and add functions and classes to
it. Here is an example, that shows how to create a module containing a single
function and a single class that were defined previously in this guide.

\code
DILUCULUM_BEGIN_MODULE (MyFineModule);
   DILUCULUM_MODULE_ADD_CLASS (ValueBox, "ValueBox");
   DILUCULUM_MODULE_ADD_FUNCTION (DILUCULUM_WRAPPER_FUNCTION(MyFunction), "MyFunction");
DILUCULUM_END_MODULE();
\endcode

So, if this is compiled to a properly named dynamic library (see
Lua's Reference Manual to know what
constitutes a proper module name), the Lua programmer can say something like:

\code
require "MyFineModule"

local v = MyFineModule.ValueBox.new(4321)
v.swap ("Weeeeee!")

local x, y, z = MyFineModule.MyFunction (4.567)
\endcode

*/
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkGlyph2D.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkGlyph2D.h"

#include "vtkCell.h"
#include "vtkDoubleArray.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkTransform.h"
#include "vtkUnsignedCharArray.h"

vtkStandardNewMacro(vtkGlyph2D);

int vtkGlyph2D::RequestData(
  vtkInformation *vtkNotUsed(request),
  vtkInformationVector **inputVector,
  vtkInformationVector *outputVector)
{
  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
  vtkInformation *outInfo = outputVector->GetInformationObject(0);

  vtkPointData *pd;
  vtkDataArray *inScalars;
  vtkDataArray *inVectors;
  unsigned char* inGhostLevels = 0;
  vtkDataArray *inNormals, *sourceNormals = NULL;
  vtkIdType numPts, numSourcePts, numSourceCells, inPtId, i;
  int index;
  vtkPoints *sourcePts = NULL;
  vtkPoints *newPts;
  vtkDataArray *newScalars=NULL;
  vtkDataArray *newVectors=NULL;
  vtkDataArray *newNormals=NULL;
  double x[3], v[3], s = 0.0, vMag = 0.0, value, theta;
  vtkTransform *trans = vtkTransform::New();
  vtkCell *cell;
  vtkIdList *cellPts;
  int npts;
  vtkIdList *pts;
  vtkIdType ptIncr, cellId;
  int haveVectors, haveNormals;
  double scalex,scaley, den;
  vtkPolyData *output = vtkPolyData::SafeDownCast(
    outInfo->Get(vtkDataObject::DATA_OBJECT()));
  vtkPointData *outputPD = output->GetPointData();
  vtkDataSet *input = vtkDataSet::SafeDownCast(
    inInfo->Get(vtkDataObject::DATA_OBJECT()));
  int numberOfSources = this->GetNumberOfInputConnections(1);
  vtkPolyData *source = 0;

  vtkDebugMacro(<<"Generating 2D glyphs");

  pts = vtkIdList::New();
  pts->Allocate(VTK_CELL_SIZE);

  pd = input->GetPointData();

  inScalars = this->GetInputArrayToProcess(0,inputVector);
  inVectors = this->GetInputArrayToProcess(1,inputVector);
  inNormals = this->GetInputArrayToProcess(2,inputVector);

  vtkDataArray* temp = 0;
  if (pd)
    {
    temp = pd->GetArray("vtkGhostLevels");
    }
  if ( (!temp) || (temp->GetDataType() != VTK_UNSIGNED_CHAR)
    || (temp->GetNumberOfComponents() != 1))
    {
    vtkDebugMacro("No appropriate ghost levels field available.");
    }
  else
    {
    inGhostLevels =static_cast<vtkUnsignedCharArray *>(temp)->GetPointer(0);
    }

  numPts = input->GetNumberOfPoints();
  if (numPts < 1)
    {
    vtkDebugMacro(<<"No points to glyph!");
    pts->Delete();
    trans->Delete();
    return 1;
    }

  // Check input for consistency
  //
  if ( (den = this->Range[1] - this->Range[0]) == 0.0 )
    {
    den = 1.0;
    }
  if ( this->VectorMode != VTK_VECTOR_ROTATION_OFF &&
       ((this->VectorMode == VTK_USE_VECTOR && inVectors != NULL) ||
        (this->VectorMode == VTK_USE_NORMAL && inNormals != NULL)) )
    {
    haveVectors = 1;
    }
  else
    {
    haveVectors = 0;
    }

  if ( (this->IndexMode == VTK_INDEXING_BY_SCALAR && !inScalars) ||
       (this->IndexMode == VTK_INDEXING_BY_VECTOR &&
       ((!inVectors && this->VectorMode == VTK_USE_VECTOR) ||
        (!inNormals && this->VectorMode == VTK_USE_NORMAL))) )
    {
    if ( this->GetSource(0, inputVector[1]) == NULL )
      {
      vtkErrorMacro(<<"Indexing on but don't have data to index with");
      pts->Delete();
      trans->Delete();
      return 1;
      }
    else
      {
      vtkWarningMacro(<<"Turning indexing off: no data to index with");
      this->IndexMode = VTK_INDEXING_OFF;
      }
    }

  // Allocate storage for output PolyData
  //
  outputPD->CopyVectorsOff();
  outputPD->CopyNormalsOff();
  if ( this->IndexMode != VTK_INDEXING_OFF )
    {
    pd = NULL;
    //numSourcePts = numSourceCells = 0;
    haveNormals = 1;
    for (numSourcePts=numSourceCells=i=0; i < numberOfSources; i++)
      {
      source = this->GetSource(i, inputVector[1]);
      if ( source != NULL )
        {
        numSourcePts += source->GetNumberOfPoints();
        numSourceCells += source->GetNumberOfCells();
        sourceNormals = source->GetPointData()->GetNormals();
        if ( !sourceNormals )
          {
          haveNormals = 0;
          }
        }
      }
    }
  else
    {
    source = this->GetSource(0, inputVector[1]);
    sourcePts = source->GetPoints();
    numSourcePts = sourcePts->GetNumberOfPoints();
    numSourceCells = source->GetNumberOfCells();

    sourceNormals = source->GetPointData()->GetNormals();
    if ( sourceNormals )
      {
      haveNormals = 1;
      }
    else
      {
      haveNormals = 0;
      }

    // Prepare to copy output.
    pd = source->GetPointData();
    outputPD->CopyAllocate(pd,numPts*numSourcePts);
    }

  newPts = vtkPoints::New();
  newPts->Allocate(numPts*numSourcePts);
  if ( this->ColorMode == VTK_COLOR_BY_SCALAR && inScalars )
    {
    newScalars = inScalars->NewInstance();
    newScalars->SetNumberOfComponents(inScalars->GetNumberOfComponents());
    newScalars->Allocate(inScalars->GetNumberOfComponents()*numPts*numSourcePts);
    }
  else if ( (this->ColorMode == VTK_COLOR_BY_SCALE) && inScalars)
    {
    newScalars = vtkDoubleArray::New();
    newScalars->Allocate(numPts*numSourcePts);
    newScalars->SetName("GlyphScale");
    }
  else if ( (this->ColorMode == VTK_COLOR_BY_VECTOR) && haveVectors)
    {
    newScalars = vtkDoubleArray::New();
    newScalars->Allocate(numPts*numSourcePts);
    newScalars->SetName("VectorMagnitude");
    }
  if ( haveVectors )
    {
    newVectors = vtkDoubleArray::New();
    newVectors->SetNumberOfComponents(3);
    newVectors->Allocate(3*numPts*numSourcePts);
    newVectors->SetName("GlyphVector");
    }
  if ( haveNormals )
    {
    newNormals = vtkDoubleArray::New();
    newNormals->SetNumberOfComponents(3);
    newNormals->Allocate(3*numPts*numSourcePts);
    newNormals->SetName("Normals");
    }

  // Setting up for calls to PolyData::InsertNextCell()
  if (this->IndexMode != VTK_INDEXING_OFF )
    {
    output->Allocate(3*numPts*numSourceCells,numPts*numSourceCells);
    }
  else
    {
    output->Allocate(this->GetSource(0, inputVector[1]),
                     3*numPts*numSourceCells, numPts*numSourceCells);
    }

  // Traverse all Input points, transforming Source points and copying
  // point attributes.
  //
  ptIncr=0;
  for (inPtId=0; inPtId < numPts; inPtId++)
    {
    scalex = scaley = 1.0;
    if ( ! (inPtId % 10000) )
      {
      this->UpdateProgress(static_cast<double>(inPtId)/numPts);
      if (this->GetAbortExecute())
        {
        break;
        }
      }

    // Get the scalar and vector data
    if ( inScalars )
      {
      s = inScalars->GetComponent(inPtId, 0);
      if ( this->ScaleMode == VTK_SCALE_BY_SCALAR ||
                this->ScaleMode == VTK_DATA_SCALING_OFF )
        {
        scalex = scaley = s;
        }
      }

    if ( haveVectors )
      {
      if ( this->VectorMode == VTK_USE_NORMAL )
        {
        inNormals->GetTuple(inPtId, v);
        }
      else
        {
        inVectors->GetTuple(inPtId, v);
        }
      vMag = vtkMath::Norm(v);
      if ( this->ScaleMode == VTK_SCALE_BY_VECTORCOMPONENTS )
        {
        scalex = v[0];
        scaley = v[1];
        }
      else if ( this->ScaleMode == VTK_SCALE_BY_VECTOR )
        {
        scalex = scaley = vMag;
        }
      }

    // Clamp data scale if enabled
    if ( this->Clamping )
      {
      scalex = (scalex < this->Range[0] ? this->Range[0] :
                (scalex > this->Range[1] ? this->Range[1] : scalex));
      scalex = (scalex - this->Range[0]) / den;
      scaley = (scaley < this->Range[0] ? this->Range[0] :
                (scaley > this->Range[1] ? this->Range[1] : scaley));
      scaley = (scaley - this->Range[0]) / den;
      }

    // Compute index into table of glyphs
    if ( this->IndexMode == VTK_INDEXING_OFF )
      {
      index = 0;
      }
    else
      {
      if ( this->IndexMode == VTK_INDEXING_BY_SCALAR )
        {
        value = s;
        }
      else
        {
        value = vMag;
        }

      index = static_cast<int>((value-this->Range[0])*numberOfSources/den);
      index = (index < 0 ? 0 :
              (index >= numberOfSources ? (numberOfSources-1) : index));

      source = this->GetSource(index, inputVector[1]);
      if ( source != NULL )
        {
        sourcePts = source->GetPoints();
        sourceNormals = source->GetPointData()->GetNormals();
        numSourcePts = sourcePts->GetNumberOfPoints();
        numSourceCells = source->GetNumberOfCells();
        }
      }

    // Make sure we're not indexing into empty glyph
    if ( this->GetSource(index, inputVector[1]) == NULL )
      {
      continue;
      }

    // Check ghost points.
    if (inGhostLevels && inGhostLevels[inPtId] > 0)
      {
      continue;
      }

    // Now begin copying/transforming glyph
    trans->Identity();

    // Copy all topology (transformation independent)
    for (cellId=0; cellId < numSourceCells; cellId++)
      {
      cell = this->GetSource(index, inputVector[1])->GetCell(cellId);
      cellPts = cell->GetPointIds();
      npts = cellPts->GetNumberOfIds();
      for (pts->Reset(), i=0; i < npts; i++)
        {
        pts->InsertId(i,cellPts->GetId(i) + ptIncr);
        }
      output->InsertNextCell(cell->GetCellType(),pts);
      }

    // translate Source to Input point
    input->GetPoint(inPtId, x);
    trans->Translate(x[0], x[1], 0.0);

    if ( haveVectors )
      {
      // Copy Input vector
      for (i=0; i < numSourcePts; i++)
        {
        newVectors->InsertTuple(i+ptIncr, v);
        }
      if (this->Orient && (vMag > 0.0))
        {
        theta = vtkMath::DegreesFromRadians( atan2( v[1], v[0] ) );
        trans->RotateWXYZ( theta, 0.0, 0.0, 1.0 );
        }
      }

    // determine scale factor from scalars if appropriate
    if ( inScalars )
      {
      // Copy scalar value
      if (this->ColorMode == VTK_COLOR_BY_SCALE)
        {
        for (i=0; i < numSourcePts; i++)
          {
          newScalars->InsertTuple(i+ptIncr, &scalex);
          }
        }
      else if (this->ColorMode == VTK_COLOR_BY_SCALAR)
        {
        for (i=0; i < numSourcePts; i++)
          {
          outputPD->CopyTuple(inScalars, newScalars, inPtId, ptIncr+i);
          }
        }
      }
    if (haveVectors && this->ColorMode == VTK_COLOR_BY_VECTOR)
      {
      for (i=0; i < numSourcePts; i++)
        {
        newScalars->InsertTuple(i+ptIncr, &vMag);
        }
      }

    // scale data if appropriate
    if ( this->Scaling )
      {
      if ( this->ScaleMode == VTK_DATA_SCALING_OFF )
        {
        scalex = scaley = this->ScaleFactor;
        }
      else
        {
        scalex *= this->ScaleFactor;
        scaley *= this->ScaleFactor;
        }

      if ( scalex == 0.0 )
        {
        scalex = 1.0e-10;
        }
      if ( scaley == 0.0 )
        {
        scaley = 1.0e-10;
        }
      trans->Scale(scalex,scaley,1.0);
      }

    // multiply points and normals by resulting matrix
    trans->TransformPoints(sourcePts,newPts);

    if ( haveNormals )
      {
      trans->TransformNormals(sourceNormals,newNormals);
      }

    // Copy point data from source (if possible)
    if ( pd )
      {
      for (i=0; i < numSourcePts; i++)
        {
        outputPD->CopyData(pd,i,ptIncr+i);
        }
      }
    ptIncr += numSourcePts;
    }

  // Update ourselves and release memory
  //
  output->SetPoints(newPts);
  newPts->Delete();

  if (newScalars)
    {
    outputPD->AddArray(newScalars);
    outputPD->SetActiveScalars(newScalars->GetName());
    newScalars->Delete();
    }

  if (newVectors)
    {
    outputPD->SetVectors(newVectors);
    newVectors->Delete();
    }

  if (newNormals)
    {
    outputPD->SetNormals(newNormals);
    newNormals->Delete();
    }

  output->Squeeze();
  trans->Delete();
  pts->Delete();

  return 1;
}

void vtkGlyph2D::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}
<commit_msg>Error if attribute arrays are incorrectly sized in vtkGlyph2D.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkGlyph2D.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkGlyph2D.h"

#include "vtkCell.h"
#include "vtkDoubleArray.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkTransform.h"
#include "vtkUnsignedCharArray.h"

vtkStandardNewMacro(vtkGlyph2D);

int vtkGlyph2D::RequestData(
  vtkInformation *vtkNotUsed(request),
  vtkInformationVector **inputVector,
  vtkInformationVector *outputVector)
{
  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
  vtkInformation *outInfo = outputVector->GetInformationObject(0);

  vtkPointData *pd;
  vtkDataArray *inScalars;
  vtkDataArray *inVectors;
  unsigned char* inGhostLevels = 0;
  vtkDataArray *inNormals, *sourceNormals = NULL;
  vtkIdType numPts, numSourcePts, numSourceCells, inPtId, i;
  int index;
  vtkPoints *sourcePts = NULL;
  vtkPoints *newPts;
  vtkDataArray *newScalars=NULL;
  vtkDataArray *newVectors=NULL;
  vtkDataArray *newNormals=NULL;
  double x[3], v[3], s = 0.0, vMag = 0.0, value, theta;
  vtkTransform *trans = vtkTransform::New();
  vtkCell *cell;
  vtkIdList *cellPts;
  int npts;
  vtkIdList *pts;
  vtkIdType ptIncr, cellId;
  int haveVectors, haveNormals;
  double scalex,scaley, den;
  vtkPolyData *output = vtkPolyData::SafeDownCast(
    outInfo->Get(vtkDataObject::DATA_OBJECT()));
  vtkPointData *outputPD = output->GetPointData();
  vtkDataSet *input = vtkDataSet::SafeDownCast(
    inInfo->Get(vtkDataObject::DATA_OBJECT()));
  int numberOfSources = this->GetNumberOfInputConnections(1);
  vtkPolyData *source = 0;

  vtkDebugMacro(<<"Generating 2D glyphs");

  pts = vtkIdList::New();
  pts->Allocate(VTK_CELL_SIZE);

  pd = input->GetPointData();

  inScalars = this->GetInputArrayToProcess(0,inputVector);
  inVectors = this->GetInputArrayToProcess(1,inputVector);
  inNormals = this->GetInputArrayToProcess(2,inputVector);

  vtkDataArray* temp = 0;
  if (pd)
    {
    temp = pd->GetArray("vtkGhostLevels");
    }
  if ( (!temp) || (temp->GetDataType() != VTK_UNSIGNED_CHAR)
    || (temp->GetNumberOfComponents() != 1))
    {
    vtkDebugMacro("No appropriate ghost levels field available.");
    }
  else
    {
    inGhostLevels =static_cast<vtkUnsignedCharArray *>(temp)->GetPointer(0);
    }

  numPts = input->GetNumberOfPoints();
  if (numPts < 1)
    {
    vtkDebugMacro(<<"No points to glyph!");
    pts->Delete();
    trans->Delete();
    return 1;
    }

  // Check input for consistency
  //
  if ( (den = this->Range[1] - this->Range[0]) == 0.0 )
    {
    den = 1.0;
    }
  if ( this->VectorMode != VTK_VECTOR_ROTATION_OFF &&
       ((this->VectorMode == VTK_USE_VECTOR && inVectors != NULL) ||
        (this->VectorMode == VTK_USE_NORMAL && inNormals != NULL)) )
    {
    haveVectors = 1;
    }
  else
    {
    haveVectors = 0;
    }

  if (inNormals && numPts != inNormals->GetNumberOfTuples())
    {
    vtkErrorMacro(<< "Number of points (" << numPts << ") does not match "
                  << "number of normals (" << inNormals->GetNumberOfTuples()
                  << ").");
    pts->Delete();
    trans->Delete();
    return 1;
    }

  if (inVectors && numPts != inVectors->GetNumberOfTuples())
    {
    vtkErrorMacro(<< "Number of points (" << numPts << ") does not match "
                  << "number of vectors (" << inVectors->GetNumberOfTuples()
                  << ").");
    pts->Delete();
    trans->Delete();
    return 1;
    }

  if (inScalars && numPts != inScalars->GetNumberOfTuples())
    {
    vtkErrorMacro(<< "Number of points (" << numPts << ") does not match "
                  << "number of scalars (" << inScalars->GetNumberOfTuples()
                  << ").");
    pts->Delete();
    trans->Delete();
    return 1;
    }

  if ( (this->IndexMode == VTK_INDEXING_BY_SCALAR && !inScalars) ||
       (this->IndexMode == VTK_INDEXING_BY_VECTOR &&
       ((!inVectors && this->VectorMode == VTK_USE_VECTOR) ||
        (!inNormals && this->VectorMode == VTK_USE_NORMAL))) )
    {
    if ( this->GetSource(0, inputVector[1]) == NULL )
      {
      vtkErrorMacro(<<"Indexing on but don't have data to index with");
      pts->Delete();
      trans->Delete();
      return 1;
      }
    else
      {
      vtkWarningMacro(<<"Turning indexing off: no data to index with");
      this->IndexMode = VTK_INDEXING_OFF;
      }
    }

  // Allocate storage for output PolyData
  //
  outputPD->CopyVectorsOff();
  outputPD->CopyNormalsOff();
  if ( this->IndexMode != VTK_INDEXING_OFF )
    {
    pd = NULL;
    //numSourcePts = numSourceCells = 0;
    haveNormals = 1;
    for (numSourcePts=numSourceCells=i=0; i < numberOfSources; i++)
      {
      source = this->GetSource(i, inputVector[1]);
      if ( source != NULL )
        {
        numSourcePts += source->GetNumberOfPoints();
        numSourceCells += source->GetNumberOfCells();
        sourceNormals = source->GetPointData()->GetNormals();
        if ( !sourceNormals )
          {
          haveNormals = 0;
          }
        }
      }
    }
  else
    {
    source = this->GetSource(0, inputVector[1]);
    sourcePts = source->GetPoints();
    numSourcePts = sourcePts->GetNumberOfPoints();
    numSourceCells = source->GetNumberOfCells();

    sourceNormals = source->GetPointData()->GetNormals();
    if ( sourceNormals )
      {
      haveNormals = 1;
      }
    else
      {
      haveNormals = 0;
      }

    // Prepare to copy output.
    pd = source->GetPointData();
    outputPD->CopyAllocate(pd,numPts*numSourcePts);
    }

  newPts = vtkPoints::New();
  newPts->Allocate(numPts*numSourcePts);
  if ( this->ColorMode == VTK_COLOR_BY_SCALAR && inScalars )
    {
    newScalars = inScalars->NewInstance();
    newScalars->SetNumberOfComponents(inScalars->GetNumberOfComponents());
    newScalars->Allocate(inScalars->GetNumberOfComponents()*numPts*numSourcePts);
    }
  else if ( (this->ColorMode == VTK_COLOR_BY_SCALE) && inScalars)
    {
    newScalars = vtkDoubleArray::New();
    newScalars->Allocate(numPts*numSourcePts);
    newScalars->SetName("GlyphScale");
    }
  else if ( (this->ColorMode == VTK_COLOR_BY_VECTOR) && haveVectors)
    {
    newScalars = vtkDoubleArray::New();
    newScalars->Allocate(numPts*numSourcePts);
    newScalars->SetName("VectorMagnitude");
    }
  if ( haveVectors )
    {
    newVectors = vtkDoubleArray::New();
    newVectors->SetNumberOfComponents(3);
    newVectors->Allocate(3*numPts*numSourcePts);
    newVectors->SetName("GlyphVector");
    }
  if ( haveNormals )
    {
    newNormals = vtkDoubleArray::New();
    newNormals->SetNumberOfComponents(3);
    newNormals->Allocate(3*numPts*numSourcePts);
    newNormals->SetName("Normals");
    }

  // Setting up for calls to PolyData::InsertNextCell()
  if (this->IndexMode != VTK_INDEXING_OFF )
    {
    output->Allocate(3*numPts*numSourceCells,numPts*numSourceCells);
    }
  else
    {
    output->Allocate(this->GetSource(0, inputVector[1]),
                     3*numPts*numSourceCells, numPts*numSourceCells);
    }

  // Traverse all Input points, transforming Source points and copying
  // point attributes.
  //
  ptIncr=0;
  for (inPtId=0; inPtId < numPts; inPtId++)
    {
    scalex = scaley = 1.0;
    if ( ! (inPtId % 10000) )
      {
      this->UpdateProgress(static_cast<double>(inPtId)/numPts);
      if (this->GetAbortExecute())
        {
        break;
        }
      }

    // Get the scalar and vector data
    if ( inScalars )
      {
      s = inScalars->GetComponent(inPtId, 0);
      if ( this->ScaleMode == VTK_SCALE_BY_SCALAR ||
                this->ScaleMode == VTK_DATA_SCALING_OFF )
        {
        scalex = scaley = s;
        }
      }

    if ( haveVectors )
      {
      if ( this->VectorMode == VTK_USE_NORMAL )
        {
        inNormals->GetTuple(inPtId, v);
        }
      else
        {
        inVectors->GetTuple(inPtId, v);
        }
      vMag = vtkMath::Norm(v);
      if ( this->ScaleMode == VTK_SCALE_BY_VECTORCOMPONENTS )
        {
        scalex = v[0];
        scaley = v[1];
        }
      else if ( this->ScaleMode == VTK_SCALE_BY_VECTOR )
        {
        scalex = scaley = vMag;
        }
      }

    // Clamp data scale if enabled
    if ( this->Clamping )
      {
      scalex = (scalex < this->Range[0] ? this->Range[0] :
                (scalex > this->Range[1] ? this->Range[1] : scalex));
      scalex = (scalex - this->Range[0]) / den;
      scaley = (scaley < this->Range[0] ? this->Range[0] :
                (scaley > this->Range[1] ? this->Range[1] : scaley));
      scaley = (scaley - this->Range[0]) / den;
      }

    // Compute index into table of glyphs
    if ( this->IndexMode == VTK_INDEXING_OFF )
      {
      index = 0;
      }
    else
      {
      if ( this->IndexMode == VTK_INDEXING_BY_SCALAR )
        {
        value = s;
        }
      else
        {
        value = vMag;
        }

      index = static_cast<int>((value-this->Range[0])*numberOfSources/den);
      index = (index < 0 ? 0 :
              (index >= numberOfSources ? (numberOfSources-1) : index));

      source = this->GetSource(index, inputVector[1]);
      if ( source != NULL )
        {
        sourcePts = source->GetPoints();
        sourceNormals = source->GetPointData()->GetNormals();
        numSourcePts = sourcePts->GetNumberOfPoints();
        numSourceCells = source->GetNumberOfCells();
        }
      }

    // Make sure we're not indexing into empty glyph
    if ( this->GetSource(index, inputVector[1]) == NULL )
      {
      continue;
      }

    // Check ghost points.
    if (inGhostLevels && inGhostLevels[inPtId] > 0)
      {
      continue;
      }

    // Now begin copying/transforming glyph
    trans->Identity();

    // Copy all topology (transformation independent)
    for (cellId=0; cellId < numSourceCells; cellId++)
      {
      cell = this->GetSource(index, inputVector[1])->GetCell(cellId);
      cellPts = cell->GetPointIds();
      npts = cellPts->GetNumberOfIds();
      for (pts->Reset(), i=0; i < npts; i++)
        {
        pts->InsertId(i,cellPts->GetId(i) + ptIncr);
        }
      output->InsertNextCell(cell->GetCellType(),pts);
      }

    // translate Source to Input point
    input->GetPoint(inPtId, x);
    trans->Translate(x[0], x[1], 0.0);

    if ( haveVectors )
      {
      // Copy Input vector
      for (i=0; i < numSourcePts; i++)
        {
        newVectors->InsertTuple(i+ptIncr, v);
        }
      if (this->Orient && (vMag > 0.0))
        {
        theta = vtkMath::DegreesFromRadians( atan2( v[1], v[0] ) );
        trans->RotateWXYZ( theta, 0.0, 0.0, 1.0 );
        }
      }

    // determine scale factor from scalars if appropriate
    if ( inScalars )
      {
      // Copy scalar value
      if (this->ColorMode == VTK_COLOR_BY_SCALE)
        {
        for (i=0; i < numSourcePts; i++)
          {
          newScalars->InsertTuple(i+ptIncr, &scalex);
          }
        }
      else if (this->ColorMode == VTK_COLOR_BY_SCALAR)
        {
        for (i=0; i < numSourcePts; i++)
          {
          outputPD->CopyTuple(inScalars, newScalars, inPtId, ptIncr+i);
          }
        }
      }
    if (haveVectors && this->ColorMode == VTK_COLOR_BY_VECTOR)
      {
      for (i=0; i < numSourcePts; i++)
        {
        newScalars->InsertTuple(i+ptIncr, &vMag);
        }
      }

    // scale data if appropriate
    if ( this->Scaling )
      {
      if ( this->ScaleMode == VTK_DATA_SCALING_OFF )
        {
        scalex = scaley = this->ScaleFactor;
        }
      else
        {
        scalex *= this->ScaleFactor;
        scaley *= this->ScaleFactor;
        }

      if ( scalex == 0.0 )
        {
        scalex = 1.0e-10;
        }
      if ( scaley == 0.0 )
        {
        scaley = 1.0e-10;
        }
      trans->Scale(scalex,scaley,1.0);
      }

    // multiply points and normals by resulting matrix
    trans->TransformPoints(sourcePts,newPts);

    if ( haveNormals )
      {
      trans->TransformNormals(sourceNormals,newNormals);
      }

    // Copy point data from source (if possible)
    if ( pd )
      {
      for (i=0; i < numSourcePts; i++)
        {
        outputPD->CopyData(pd,i,ptIncr+i);
        }
      }
    ptIncr += numSourcePts;
    }

  // Update ourselves and release memory
  //
  output->SetPoints(newPts);
  newPts->Delete();

  if (newScalars)
    {
    outputPD->AddArray(newScalars);
    outputPD->SetActiveScalars(newScalars->GetName());
    newScalars->Delete();
    }

  if (newVectors)
    {
    outputPD->SetVectors(newVectors);
    newVectors->Delete();
    }

  if (newNormals)
    {
    outputPD->SetNormals(newNormals);
    newNormals->Delete();
    }

  output->Squeeze();
  trans->Delete();
  pts->Delete();

  return 1;
}

void vtkGlyph2D::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}
<|endoftext|>


<commit_before>
#include "stdafx.h"
#include "character.h"

using namespace graphic;

cCharacter::cCharacter() :
	m_weapon(NULL)
,	m_weaponNode(NULL)
{

}

cCharacter::~cCharacter()
{
	SAFE_DELETE(m_weapon);
}

void cCharacter::LoadWeapon(const string &fileName)
{
	if (!m_weapon)
		m_weapon = new cModel();

	if (!m_weapon->Create(fileName))
		return;

	RET(!m_bone);

	m_weaponNode = m_bone->FindBone("dummy_weapon");
	RET(!m_weaponNode);
}

bool cCharacter::Move(const float elapseTime)
{
	cModel::Move(elapseTime);

	if (m_weapon && m_weaponNode)
	{
		Matrix44 mat = m_weaponNode->GetAccTM();
		m_weapon->SetTM(mat * m_matTM);
		m_weapon->Move(elapseTime);
	}
	return true;
}

void cCharacter::Render()
{
	cModel::Render();

	if (m_weapon)
		m_weapon->Render();
}
<commit_msg>update weapon disp<commit_after>
#include "stdafx.h"
#include "character.h"

using namespace graphic;

cCharacter::cCharacter() :
	m_weapon(NULL)
,	m_weaponNode(NULL)
{

}

cCharacter::~cCharacter()
{
	SAFE_DELETE(m_weapon);
}

void cCharacter::LoadWeapon(const string &fileName)
{
	RET(!m_bone);
	m_weaponNode = m_bone->FindBone("dummy_weapon");
	RET(!m_weaponNode);

	if (!m_weapon)
		m_weapon = new cModel();

	if (!m_weapon->Create(fileName))
		return;
}

bool cCharacter::Move(const float elapseTime)
{
	cModel::Move(elapseTime);

	if (m_weapon && m_weaponNode)
	{
		Matrix44 mat = m_weaponNode->GetAccTM();
		m_weapon->SetTM(mat * m_matTM);
		m_weapon->Move(elapseTime);
	}
	return true;
}

void cCharacter::Render()
{
	cModel::Render();

	if (m_weapon)
		m_weapon->Render();
}
<|endoftext|>