<commit_before>#include "TChain.h"
#include "TTree.h"
#include "TList.h"
#include "TH1F.h"
#include "TH2F.h"
#include "TCanvas.h"
#include "TMath.h"
#include "TObjString.h"

#include "AliAnalysisTask.h"
#include "AliAnalysisManager.h"

#include "AliESDEvent.h"
#include "AliESDTZERO.h"
#include "AliESDfriend.h"
#include "AliESDInputHandler.h"
#include "AliESDTZEROfriend.h"
#include "AliT0CalibAnalysisTask.h"
#include "AliESDVZERO.h"
#include "AliMultiplicity.h"
#include "AliESDpid.h"
#include "AliESDtrackCuts.h"
#include "AliCentrality.h"
#include "AliVEvent.h"

ClassImp(AliT0CalibAnalysisTask)

//________________________________________________________________________
AliT0CalibAnalysisTask::AliT0CalibAnalysisTask(const char *name)
  : AliAnalysisTaskSE(name), fESD(0), fOutputList(0),
  fT0OutTree(0x0), fEvent(-99999),   fOrbit(-99999), fBC(-99999),
  fTrackletSPD(-99999), fNcont(-99999),
  fVertex(-99999), fVertexSPD(-99999),
  fMeanAC(-99999), fMeanA(-99999),fMeanC(-99999),
  fMultV0A(-99999), fMultV0C(-99999),fTimeV0A(-99999),fTimeV0C(-99999), fSumampA(-99999), fSumampC(-99999),
  ftimestamp(0), fSep2(0),
  fZDCcut(kFALSE), fT0Trigger(0), fpileup(kFALSE), fTrigger(0x0),
  fT0_amplitude(0x0), fT0_time(0x0),
  fcentralityV0M(0), fcentralityZDC(0), fcentralityTRK(0),
  fESDtracks(0),
  fMultiplicity(-99999),
  fTriggerinput(0x0), fZDCbg(kFALSE),
  fTOFtracks(0), fT0tofTrack(0),
  fESDpid(new AliESDpid()), fPFPbit(0)
{
  // Constructor

  // Define input and output slots here
  // Input slot #0 works with a TChain
  DefineInput(0, TChain::Class());
  // Output slot #0 id reserved by the base class for AOD
  // Output slot #1 writes into a TH1 container
  DefineOutput(1, TList::Class());
}

//________________________________________________________________________
AliT0CalibAnalysisTask::~AliT0CalibAnalysisTask()
{
// Destructor
   if (fT0OutTree) delete fT0OutTree ;
}

//_____________________________________________________________________________
Bool_t AliT0CalibAnalysisTask::UserNotify()
{
//
// Calls the mother class Notify()
//

//  AliDebug(AliLog::kDebug,"<-");
  // AliDebug(AliLog::kDebug,"->");

  return AliAnalysisTaskSE::UserNotify();
}

//________________________________________________________________________
void AliT0CalibAnalysisTask::UserCreateOutputObjects()
{
  // Create histograms
  // Called once
   fOutputList = new TList();
  fOutputList->SetOwner(); // Will delete the histos on cleanup

  fT0OutTree=new TTree("t0tree","None here");
  fT0OutTree->Branch("fNevent", &fEvent);
  fT0OutTree->Branch("fOrbit", &fOrbit);
  fT0OutTree->Branch("fBC", &fBC);
  fT0OutTree->Branch("fNcont", &fNcont, "fNcont/I");
  fT0OutTree->Branch("vertexT0", &fVertex, "fVertex/F");
  fT0OutTree->Branch("vertexSPD", &fVertexSPD, "vertexSPD/F");
  fT0OutTree->Branch("meanAC", &fMeanAC,"meanAC/F");
  fT0OutTree->Branch("meanA", &fMeanA,"meanA/F");
  fT0OutTree->Branch("meanC", &fMeanC,"meanC/F");
  fT0OutTree->Branch("trackletSPD", &fTrackletSPD,"trackletSPD/I");
  fT0OutTree->Branch("TOFtracks", &fTOFtracks);
  fT0OutTree->Branch("ESDtracks", &fESDtracks);
  fT0OutTree->Branch("multV0A", &fMultV0A,"multV0A/F");
  fT0OutTree->Branch("multV0C", &fMultV0C,"multV0C/F");
  fT0OutTree->Branch("timeV0A", &fTimeV0A,"timeV0A/F");
  fT0OutTree->Branch("timeV0C", &fTimeV0C,"timeV0C/F");
  fT0OutTree->Branch("sumampA", &fSumampA);
  fT0OutTree->Branch("sumampC", &fSumampC);
  fT0OutTree->Branch("pileup", &fpileup);
  fT0OutTree->Branch("trigger", &fTrigger);
  fT0OutTree->Branch("triggerinput", &fTriggerinput);
  fT0OutTree->Branch("T0trigger", &fT0Trigger);
  fT0OutTree->Branch("t0tofTrack",  &fT0tofTrack);
  fT0OutTree->Branch("ZDCcut", &fZDCcut);
  fT0OutTree->Branch("ftimestamp", &ftimestamp);
  fT0OutTree->Branch("centralityV0M", &fcentralityV0M);
  fT0OutTree->Branch("centralityZDC", &fcentralityZDC);
  fT0OutTree->Branch("centralityTRK", &fcentralityTRK);
  for ( Int_t i=0; i<24; i++) {
    fT0OutTree->Branch(Form("amp%i", i+1), &famp[i]);
    fT0OutTree->Branch(Form("amp%i_new", i+1), &famp_new[i]);
    fT0OutTree->Branch(Form("time%i", i+1), &ftime[i]);
    fT0OutTree->Branch(Form("fRawTime%i", i+1), &fRawTime[i]);
  }
  for ( Int_t i=0; i<5; i++) {
    fT0OutTree->Branch(Form("fOrA%i", i+1), &fOrA[i]);
    fT0OutTree->Branch(Form("fOrC%i", i+1), &fOrC[i]);
    fT0OutTree->Branch(Form("fTVDC%i", i+1), &fTVDC[i]);
  }
  TString pilename[3] = {"T0pileup", "T0background", "T0satellite"};
  for ( Int_t i=0; i<3; i++)
    fT0OutTree->Branch(pilename[i].Data(), &fT0pileup[i]);
  fT0OutTree->Branch("multEstimator", &fMultiplicity);
  //ZDC background
 fT0OutTree->Branch("zbg", &fZDCbg);
 fESDpid = new AliESDpid();
 //PFP
 fT0OutTree->Branch("bitPFP", &fPFPbit);

  fOutputList->Add(fT0OutTree);

   PostData(1, fOutputList);

}

//________________________________________________________________________
void AliT0CalibAnalysisTask::UserExec(Option_t *)
{
  // Main loop
  // Called for each event
  fVertex= fVertexSPD =  fMeanAC = fMeanA =  fMeanC =  fTrackletSPD = fNcont = -99999;
  fMultV0A=fMultV0C=fTimeV0A=fTimeV0C=fMultiplicity = -99999;

  for (Int_t i=0; i<24; i++)	{
    famp[i] = famp_new[i] = ftime[i] = fRawTime[i] = -9999;
  }
  for ( Int_t i0=0; i0<5; i0++) {
    fTVDC[i0]=-9999;
    fOrC[i0]=-9999;
    fOrA[i0]=-9999;
  }

  Float_t orA , orC, tvdc;
  orA = orC = tvdc = -9999;
  fBC = -9999;
  // Post output data.
  fESD = dynamic_cast<AliESDEvent*>(InputEvent());
  if (!fESD) {
    printf("ERROR: fESD not available\n");
    return;
  }

  if(fESD)
    {
      //    if(fIsSelected)
      {
	fZDCbg = kFALSE;
	/*
	  AliTriggerAnalysis *fTriggerAnalysis;
	  Bool_t	fZDCbgA = fTriggerAnalysis->IsOfflineTriggerFired(fESD, AliTriggerAnalysis::kZNABG);
	  Bool_t	fZDCbgC =  fTriggerAnalysis->IsOfflineTriggerFired(fESD, AliTriggerAnalysis::kZNCBG);
	  fZDCbg = (fZDCbgA);
	  cout<<" ZDC back "<<fZDCbgA<<endl;
	*/
	AliESDVZERO* esdV0 = fESD->GetVZEROData();
	const AliMultiplicity *mult = fESD->GetMultiplicity();
	// printf(" VZERO MULT \n");
	AliESDTZERO* tz= (AliESDTZERO*) fESD->GetESDTZERO();

	const Double32_t *amp, *time, *mean,*amp_new ;
	fVertex= fVertexSPD =  fMeanAC = fMeanA =  fMeanC = fTrackletSPD = fNcont =-99999;
	fMultV0A=fMultV0C=fTimeV0A=fTimeV0C=fMultiplicity = -99999;

	fSumampA=0;
	fSumampC=0;
	fNcont=0;
	TString triggers = fESD->GetFiredTriggerClasses();
	fTrigger.SetString(triggers.Data());
	TString inputtriggers =fESD-> GetHeader()->GetFiredTriggerInputs();
	fTriggerinput.SetString(inputtriggers.Data());
	fEvent=fESD->GetEventNumberInFile();
	fT0Trigger=fESD->GetT0Trig();

	fESDtracks=fESD->GetNumberOfTracks();
	ftimestamp=fESD->GetTimeStamp(); // - 1301217882;
	//	  printf (" timestamp %d \n", ftimestamp);

	fMultiplicity =  AliESDtrackCuts::GetReferenceMultiplicity(fESD);
	//	  cout<<" fMultiplicity "<<fMultiplicity<<endl;
	fOrbit=fESD->GetOrbitNumber();
	fBC=fESD->GetBunchCrossNumber();
	fNcont = fESD->GetPrimaryVertexSPD()->GetNContributors();
	if(fNcont>=0 ) {
	  fVertexSPD = fESD->GetPrimaryVertex()->GetZ();
	}
	fTrackletSPD = mult->GetNumberOfTracklets();
	fMultV0A =  esdV0->GetMTotV0A();
	fMultV0C =  esdV0->GetMTotV0C();
	//TOF hit
	Int_t ntracksMatchedToTOF = 0;
	Int_t ntracks = fESD->GetNumberOfTracks();
	for(Int_t itrk=0;itrk<ntracks;itrk++){
	  AliESDtrack* track = fESD->GetTrack(itrk);
	  if (!track) {
	    Printf("ERROR: Could not receive track %d", itrk);
	    continue;
	  }
	  //no track selection just TOF hit
	  if (track->IsOn(AliESDtrack::kTOFout)) ntracksMatchedToTOF++;
	}

	fTOFtracks = ntracksMatchedToTOF;
	if(fESDpid){ //get T0_TOF
	  fESDpid->SetTOFResponse(fESD,AliESDpid::kTOF_T0);
	  fT0tofTrack =(Float_t) (fESDpid->GetTOFResponse().GetStartTime(10.0)); //Get start time "from all tracks
	  //   printf("@@TOF T0 %f\n",fT0tofTrack);
	}
	fpileup = fESD->IsPileupFromSPD();
	fTimeV0C = esdV0->GetV0CTime();
	fTimeV0A = esdV0->GetV0ATime();
	//T0 info
	mean = fESD->GetT0TOF();
	fVertex=fESD->GetT0zVertex();
	fMeanA = mean[1];
	fMeanC = mean[2];
	if (TMath::Abs(fMeanA)<9999 && TMath::Abs(fMeanC)<9999)
	  fMeanAC = mean[0] ;
	fSumampC = tz->GetMultC();
	fSumampA = tz->GetMultA();
	amp=fESD->GetT0amplitude();
	amp_new = tz->GetT0NewAmplitude();
	time=fESD->GetT0time();
	for (Int_t i=0; i<24; i++){
	  if( time[i]>100 ) {
	    ftime[i] = time[i];
	    if( amp[i]>0.1)  famp[i] = amp[i];
	    if(amp_new)famp_new[i] = amp_new[i];
	  }
	}
	//new raw OrA OrC TVDC all CFD
	for (Int_t ii=0; ii<5; ii++){
	  orA   = tz->GetOrA(ii);
	  orC   = tz->GetOrC(ii);
	  tvdc  = tz->GetTVDC(ii);
	  if(ii==0) {
	    fOrA[ii] = orA;
	    fOrC[ii] = orC;
	    fTVDC[ii] = tvdc;
	  } else {
	    if ( ii>0 && fOrA[ii-1] !=orA)	fOrA[ii] = orA;
	    else fOrA[ii]=-9999;
	    if ( ii>0 && fOrC[ii-1] !=orC)	fOrC[ii] = orC;
	    else fOrC[ii]=-9999;
	  if ( ii>0 && fTVDC[ii-1] != tvdc)	fTVDC[ii] = tvdc;
	  else fTVDC[ii]=-9999;
	  }
	}
	for (Int_t iii=0; iii<24; iii++)
	  fRawTime[iii] =  tz->GetTimeFull(iii,0);

	fT0pileup[0] = tz->GetPileupFlag();
	fT0pileup[1] = tz->GetBackgroundFlag();
	fT0pileup[2] = tz->GetSatellite();

	AliCentrality *centrality = fESD->GetCentrality();
	//The centrality function you can use
	if(centrality) {
	  fcentralityV0M = centrality->GetCentralityPercentile("V0M"); // returns the centrality
	  fcentralityTRK = centrality->GetCentralityPercentile("TRK"); // returns the centrality
	  fcentralityZDC = centrality->GetCentralityPercentile("ZEMvsZDC"); // returns the
	}
	// PFP bit
	fPFPbit = tz->GetT0PileupBits();

      } //selected
    } //ESD

  fT0OutTree->Fill();

  PostData(1, fOutputList);

}

//________________________________________________________________________
void AliT0CalibAnalysisTask::Terminate(Option_t *)
{
  // Draw result to the screen
  // Called once at the end of the query

  /* fOutputList = dynamic_cast<TList*> (GetOutputData(1));
  if (!fOutputList) {
    printf("ERROR: Output list not available\n");
    return;
  }
    */

}
<commit_msg>typo fixed<commit_after>#include "TChain.h"
#include "TTree.h"
#include "TList.h"
#include "TH1F.h"
#include "TH2F.h"
#include "TCanvas.h"
#include "TMath.h"
#include "TObjString.h"

#include "AliAnalysisTask.h"
#include "AliAnalysisManager.h"

#include "AliESDEvent.h"
#include "AliESDTZERO.h"
#include "AliESDfriend.h"
#include "AliESDInputHandler.h"
#include "AliESDTZEROfriend.h"
#include "AliT0CalibAnalysisTask.h"
#include "AliESDVZERO.h"
#include "AliMultiplicity.h"
#include "AliESDpid.h"
#include "AliESDtrackCuts.h"
#include "AliCentrality.h"
#include "AliVEvent.h"

ClassImp(AliT0CalibAnalysisTask)

//________________________________________________________________________
AliT0CalibAnalysisTask::AliT0CalibAnalysisTask(const char *name)
  : AliAnalysisTaskSE(name), fESD(0), fOutputList(0),
  fT0OutTree(0x0), fEvent(-99999),   fOrbit(-99999), fBC(-99999),
  fTrackletSPD(-99999), fNcont(-99999),
  fVertex(-99999), fVertexSPD(-99999),
  fMeanAC(-99999), fMeanA(-99999),fMeanC(-99999),
  fMultV0A(-99999), fMultV0C(-99999),fTimeV0A(-99999),fTimeV0C(-99999), fSumampA(-99999), fSumampC(-99999),
  ftimestamp(0), fSep2(0),
  fZDCcut(kFALSE), fT0Trigger(0), fpileup(kFALSE), fTrigger(0x0),
  fT0_amplitude(0x0), fT0_time(0x0),
  fcentralityV0M(0), fcentralityZDC(0), fcentralityTRK(0),
  fESDtracks(0),
  fMultiplicity(-99999),
  fTriggerinput(0x0), fZDCbg(kFALSE),
  fTOFtracks(0), fT0tofTrack(0),
  fESDpid(new AliESDpid()), fPFPbit(0)
{
  // Constructor

  // Define input and output slots here
  // Input slot #0 works with a TChain
  DefineInput(0, TChain::Class());
  // Output slot #0 id reserved by the base class for AOD
  // Output slot #1 writes into a TH1 container
  DefineOutput(1, TList::Class());
}

//________________________________________________________________________
AliT0CalibAnalysisTask::~AliT0CalibAnalysisTask()
{
// Destructor
   if (fT0OutTree) delete fT0OutTree ;
}

//_____________________________________________________________________________
Bool_t AliT0CalibAnalysisTask::UserNotify()
{
//
// Calls the mother class Notify()
//

//  AliDebug(AliLog::kDebug,"<-");
  // AliDebug(AliLog::kDebug,"->");

  return AliAnalysisTaskSE::UserNotify();
}

//________________________________________________________________________
void AliT0CalibAnalysisTask::UserCreateOutputObjects()
{
  // Create histograms
  // Called once
   fOutputList = new TList();
  fOutputList->SetOwner(); // Will delete the histos on cleanup

  fT0OutTree=new TTree("t0tree","None here");
  fT0OutTree->Branch("fNevent", &fEvent);
  fT0OutTree->Branch("fOrbit", &fOrbit);
  fT0OutTree->Branch("fBC", &fBC);
  fT0OutTree->Branch("fNcont", &fNcont, "fNcont/I");
  fT0OutTree->Branch("vertexT0", &fVertex, "fVertex/F");
  fT0OutTree->Branch("vertexSPD", &fVertexSPD, "vertexSPD/F");
  fT0OutTree->Branch("meanAC", &fMeanAC,"meanAC/F");
  fT0OutTree->Branch("meanA", &fMeanA,"meanA/F");
  fT0OutTree->Branch("meanC", &fMeanC,"meanC/F");
  fT0OutTree->Branch("trackletSPD", &fTrackletSPD,"trackletSPD/I");
  fT0OutTree->Branch("TOFtracks", &fTOFtracks);
  fT0OutTree->Branch("ESDtracks", &fESDtracks);
  fT0OutTree->Branch("multV0A", &fMultV0A,"multV0A/F");
  fT0OutTree->Branch("multV0C", &fMultV0C,"multV0C/F");
  fT0OutTree->Branch("timeV0A", &fTimeV0A,"timeV0A/F");
  fT0OutTree->Branch("timeV0C", &fTimeV0C,"timeV0C/F");
  fT0OutTree->Branch("sumampA", &fSumampA);
  fT0OutTree->Branch("sumampC", &fSumampC);
  fT0OutTree->Branch("pileup", &fpileup);
  fT0OutTree->Branch("trigger", &fTrigger);
  fT0OutTree->Branch("triggerinput", &fTriggerinput);
  fT0OutTree->Branch("T0trigger", &fT0Trigger);
  fT0OutTree->Branch("t0tofTrack",  &fT0tofTrack);
  fT0OutTree->Branch("ZDCcut", &fZDCcut);
  fT0OutTree->Branch("ftimestamp", &ftimestamp);
  fT0OutTree->Branch("centralityV0M", &fcentralityV0M);
  fT0OutTree->Branch("centralityZDC", &fcentralityZDC);
  fT0OutTree->Branch("centralityTRK", &fcentralityTRK);
  for ( Int_t i=0; i<24; i++) {
    fT0OutTree->Branch(Form("amp%i", i+1), &famp[i]);
    fT0OutTree->Branch(Form("amp%i_new", i+1), &famp_new[i]);
    fT0OutTree->Branch(Form("time%i", i+1), &ftime[i]);
    fT0OutTree->Branch(Form("fRawTime%i", i+1), &fRawTime[i]);
  }
  for ( Int_t i=0; i<5; i++) {
    fT0OutTree->Branch(Form("fOrA%i", i+1), &fOrA[i]);
    fT0OutTree->Branch(Form("fOrC%i", i+1), &fOrC[i]);
    fT0OutTree->Branch(Form("fTVDC%i", i+1), &fTVDC[i]);
  }
  TString pilename[3] = {"T0pileup", "T0background", "T0satellite"};
  for ( Int_t i=0; i<3; i++)
    fT0OutTree->Branch(pilename[i].Data(), &fT0pileup[i]);
  fT0OutTree->Branch("multEstimator", &fMultiplicity);
  //ZDC background
 fT0OutTree->Branch("zbg", &fZDCbg);
 fESDpid = new AliESDpid();
 //PFP
 fT0OutTree->Branch("bitPFP", &fPFPbit);

  fOutputList->Add(fT0OutTree);

   PostData(1, fOutputList);

}

//________________________________________________________________________
void AliT0CalibAnalysisTask::UserExec(Option_t *)
{
  // Main loop
  // Called for each event
  fVertex= fVertexSPD =  fMeanAC = fMeanA =  fMeanC =  fTrackletSPD = fNcont = -99999;
  fMultV0A=fMultV0C=fTimeV0A=fTimeV0C=fMultiplicity = -99999;

  for (Int_t i=0; i<24; i++)	{
    famp[i] = famp_new[i] = ftime[i] = fRawTime[i] = -9999;
  }
  for ( Int_t i0=0; i0<5; i0++) {
    fTVDC[i0]=-9999;
    fOrC[i0]=-9999;
    fOrA[i0]=-9999;
  }

  Float_t orA , orC, tvdc;
  orA = orC = tvdc = -9999;
  fBC = -9999;
  // Post output data.
  fESD = dynamic_cast<AliESDEvent*>(InputEvent());
  if (!fESD) {
    printf("ERROR: fESD not available\n");
    return;
  }

  if(fESD)
    {
      //    if(fIsSelected)
      {
	fZDCbg = kFALSE;
	/*
	  AliTriggerAnalysis *fTriggerAnalysis;
	  Bool_t	fZDCbgA = fTriggerAnalysis->IsOfflineTriggerFired(fESD, AliTriggerAnalysis::kZNABG);
	  Bool_t	fZDCbgC =  fTriggerAnalysis->IsOfflineTriggerFired(fESD, AliTriggerAnalysis::kZNCBG);
	  fZDCbg = (fZDCbgA);
	  cout<<" ZDC back "<<fZDCbgA<<endl;
	*/
	AliESDVZERO* esdV0 = fESD->GetVZEROData();
	const AliMultiplicity *mult = fESD->GetMultiplicity();
	// printf(" VZERO MULT \n");
	AliESDTZERO* tz= (AliESDTZERO*) fESD->GetESDTZERO();

	const Double32_t *amp, *time, *mean,*amp_new ;
	fVertex= fVertexSPD =  fMeanAC = fMeanA =  fMeanC = fTrackletSPD = fNcont =-99999;
	fMultV0A=fMultV0C=fTimeV0A=fTimeV0C=fMultiplicity = -99999;

	fSumampA=0;
	fSumampC=0;
	fNcont=0;
	TString triggers = fESD->GetFiredTriggerClasses();
	fTrigger.SetString(triggers.Data());
	TString inputtriggers =fESD-> GetHeader()->GetFiredTriggerInputs();
	fTriggerinput.SetString(inputtriggers.Data());
	fEvent=fESD->GetEventNumberInFile();
	fT0Trigger=fESD->GetT0Trig();

	fESDtracks=fESD->GetNumberOfTracks();
	ftimestamp=fESD->GetTimeStamp(); // - 1301217882;
	//	  printf (" timestamp %d \n", ftimestamp);

	fMultiplicity =  AliESDtrackCuts::GetReferenceMultiplicity(fESD);
	//	  cout<<" fMultiplicity "<<fMultiplicity<<endl;
	fOrbit=fESD->GetOrbitNumber();
	fBC=fESD->GetBunchCrossNumber();
	fNcont = fESD->GetPrimaryVertexSPD()->GetNContributors();
	if(fNcont>=0 ) {
	  fVertexSPD = fESD->GetPrimaryVertex()->GetZ();
	}
	fTrackletSPD = mult->GetNumberOfTracklets();
	fMultV0A =  esdV0->GetMTotV0A();
	fMultV0C =  esdV0->GetMTotV0C();
	//TOF hit
	Int_t ntracksMatchedToTOF = 0;
	Int_t ntracks = fESD->GetNumberOfTracks();
	for(Int_t itrk=0;itrk<ntracks;itrk++){
	  AliESDtrack* track = fESD->GetTrack(itrk);
	  if (!track) {
	    Printf("ERROR: Could not receive track %d", itrk);
	    continue;
	  }
	  //no track selection just TOF hit
	  if (track->IsOn(AliESDtrack::kTOFout)) ntracksMatchedToTOF++;
	}

	fTOFtracks = ntracksMatchedToTOF;
	if(fESDpid){ //get T0_TOF
	  fESDpid->SetTOFResponse(fESD,AliESDpid::kTOF_T0);
	  fT0tofTrack =(Float_t) (fESDpid->GetTOFResponse().GetStartTime(10.0)); //Get start time "from all tracks
	  //   printf("@@TOF T0 %f\n",fT0tofTrack);
	}
	fpileup = fESD->IsPileupFromSPD();
	fTimeV0C = esdV0->GetV0CTime();
	fTimeV0A = esdV0->GetV0ATime();
	//T0 info
	mean = fESD->GetT0TOF();
	fVertex=fESD->GetT0zVertex();
	fMeanA = mean[1];
	fMeanC = mean[2];
	if (TMath::Abs(fMeanA)<9999 && TMath::Abs(fMeanC)<9999)
	  fMeanAC = mean[0] ;
	fSumampC = tz->GetMultC();
	fSumampA = tz->GetMultA();
	amp=fESD->GetT0amplitude();
	amp_new = tz->GetT0NewAmplitude();
	time=fESD->GetT0time();
	for (Int_t i=0; i<24; i++){
	  if( time[i]>!=0 ) {
	    ftime[i] = time[i];
	    if( amp[i]>0.1)  famp[i] = amp[i];
	    if(amp_new[i]>0) famp_new[i] = amp_new[i];
	  }
	}
	//new raw OrA OrC TVDC all CFD
	for (Int_t ii=0; ii<5; ii++){
	  orA   = tz->GetOrA(ii);
	  orC   = tz->GetOrC(ii);
	  tvdc  = tz->GetTVDC(ii);
	  if(ii==0) {
	    fOrA[ii] = orA;
	    fOrC[ii] = orC;
	    fTVDC[ii] = tvdc;
	  } else {
	    if ( ii>0 && fOrA[ii-1] !=orA)	fOrA[ii] = orA;
	    else fOrA[ii]=-9999;
	    if ( ii>0 && fOrC[ii-1] !=orC)	fOrC[ii] = orC;
	    else fOrC[ii]=-9999;
	  if ( ii>0 && fTVDC[ii-1] != tvdc)	fTVDC[ii] = tvdc;
	  else fTVDC[ii]=-9999;
	  }
	}
	for (Int_t iii=0; iii<24; iii++)
	  fRawTime[iii] =  tz->GetTimeFull(iii,0);

	fT0pileup[0] = tz->GetPileupFlag();
	fT0pileup[1] = tz->GetBackgroundFlag();
	fT0pileup[2] = tz->GetSatellite();

	AliCentrality *centrality = fESD->GetCentrality();
	//The centrality function you can use
	if(centrality) {
	  fcentralityV0M = centrality->GetCentralityPercentile("V0M"); // returns the centrality
	  fcentralityTRK = centrality->GetCentralityPercentile("TRK"); // returns the centrality
	  fcentralityZDC = centrality->GetCentralityPercentile("ZEMvsZDC"); // returns the
	}
	// PFP bit
	fPFPbit = tz->GetT0PileupBits();

      } //selected
    } //ESD

  fT0OutTree->Fill();

  PostData(1, fOutputList);

}

//________________________________________________________________________
void AliT0CalibAnalysisTask::Terminate(Option_t *)
{
  // Draw result to the screen
  // Called once at the end of the query

  /* fOutputList = dynamic_cast<TList*> (GetOutputData(1));
  if (!fOutputList) {
    printf("ERROR: Output list not available\n");
    return;
  }
    */

}
<|endoftext|>


<commit_before>#include <iostream>
#include <functional>

template<int depth>
struct Repeat
{
	template <typename F>
	static void Do(F f)
	{
		f();
		Repeat<depth-1>::Do(f);
	}
};

template<>
struct Repeat <0>
{
	template <typename F>
	static void Do(F f)
	{
		return;
	}
};

int main(int argc, char* argv[])
{
	Repeat<5>::Do([]{std::cout << "Hello" << std::endl; });
}

<commit_msg>Templated iteration using iteration count<commit_after>#include <iostream>
#include <functional>

template<int depth>
struct Repeat
{
	template <typename F>
	static void Do(F f)
	{
		f();
		Repeat<depth-1>::Do(f);
	}

	template <typename F>
	static void DoWithN(F f)
	{
		f(depth);
		Repeat<depth-1>::DoWithN(f);
	}
};

template<>
struct Repeat <0>
{
	template <typename F>
	static void Do(F f)
	{
		return;
	}

	template <typename F>
	static void DoWithN(F f)
	{
		return;
	}
};

int main(int argc, char* argv[])
{
	Repeat<5>::Do([]{std::cout << "Hello" << std::endl; });
	Repeat<5>::DoWithN([](int N){std::cout << "Goodbye " << N << std::endl; });
}

<|endoftext|>


<commit_before>//
// StructLayer.cpp
//
// Copyright (c) 2001 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "Frame.h"
#include "StructLayer.h"
#include "ScaledView.h"
#include "BuildingDlg.h"

#ifndef _MSC_VER	// for non-MSVC
#include <string.h>
#define stricmp strcasecmp
#endif

wxPen orangePen;
wxPen yellowPen;
static bool g_bInitializedPens = false;

//////////////////////////////////////////////////////////////////////////

vtStructureLayer::vtStructureLayer() : vtLayer(LT_STRUCTURE)
{
	m_strFilename = "Untitled.xml";

	if (!g_bInitializedPens)
	{
		g_bInitializedPens = true;
		orangePen.SetColour(255,128,0);
		yellowPen.SetColour(255,255,0);
	}
}

bool vtStructureLayer::GetExtent(DRECT &rect)
{
	if (IsEmpty())
		return false;

	GetExtents(rect);

	// expand by 10 meters
	rect.left -= 10.0f;
	rect.right += 10.0f;
	rect.bottom -= 10.0f;
	rect.top += 10.0f;

	return true;
}

#define BLENGTH 5

void vtStructureLayer::DrawLayer(wxDC* pDC, vtScaledView *pView)
{
	int structs = GetSize();
	if (!structs)
		return;

	pDC->SetPen(orangePen);
	pDC->SetBrush(*wxTRANSPARENT_BRUSH);
	bool bSel = false;

	m_size = pView->sdx(20);
	if (m_size > 5) m_size = 5;
	if (m_size < 1) m_size = 1;

	for (int i = 0; i < structs; i++)
	{
		// draw each building
		vtStructure *str = GetAt(i);
		vtBuilding *bld = str->GetBuilding();
		if (bld)
		{
			if (str->IsSelected())
			{
				if (!bSel)
				{
					pDC->SetPen(yellowPen);
					bSel = true;
				}
			}
			else
			{
				if (bSel)
				{
					pDC->SetPen(orangePen);
					bSel = false;
				}
			}
			DrawBuilding(pDC, pView, bld);
		}
		else
		{
			vtFence *fen = str->GetFence();
			if (fen)
			{
				// TODO
			}
		}
	}
}

#define MAX_SIDES	100
static wxPoint array[MAX_SIDES];

void vtStructureLayer::DrawBuilding(wxDC* pDC, vtScaledView *pView, vtBuilding *bld)
{
	DPoint2 corner[4];
	float fWidth, fDepth, fRotation;
	int j;

	wxPoint origin;
	pView->screen(bld->GetLocation(), origin);

	pDC->DrawLine(origin.x-m_size, origin.y, origin.x+m_size+1, origin.y);
	pDC->DrawLine(origin.x, origin.y-m_size, origin.x, origin.y+m_size+1);

	if (bld->GetShape() == SHAPE_POLY)
	{
		DLine2 &dl = bld->GetFootprint();
		int size = dl.GetSize();
		for (j = 0; j < size && j < MAX_SIDES-1; j++)
			pView->screen(dl.GetAt(j), array[j]);
		pView->screen(dl.GetAt(0), array[j++]);

		pDC->DrawLines(j, array);
	}
	if (bld->GetShape() == SHAPE_CIRCLE)
	{
		int size = pView->sdx(bld->GetRadius());
		pDC->DrawEllipse(origin.x-size, origin.y-size,
			size<<1, size<<1);
	}
	if (bld->GetShape() == SHAPE_RECTANGLE)
	{
		bld->GetRectangle(fWidth, fDepth);
		bld->GetRotation(fRotation);
		if (fRotation == -1.0f) fRotation = 0.0f;
		DPoint2 pt(fWidth / 2.0, fDepth / 2.0);
		corner[0].Set(-pt.x, pt.y);
		corner[1].Set(pt.x, pt.y);
		corner[2].Set(pt.x, -pt.y);
		corner[3].Set(-pt.x, -pt.y);
		corner[0].Rotate(fRotation);
		corner[1].Rotate(fRotation);
		corner[2].Rotate(fRotation);
		corner[3].Rotate(fRotation);
		array[0] = origin + pView->screen_delta(corner[0]);
		array[1] = origin + pView->screen_delta(corner[1]);
		array[2] = origin + pView->screen_delta(corner[2]);
		array[3] = origin + pView->screen_delta(corner[3]);
		array[4] = array[0];
		pDC->DrawLines(5, array);
	}
}

bool vtStructureLayer::OnSave()
{
	return WriteXML(m_strFilename);
}

bool vtStructureLayer::OnLoad()
{
	return ReadXML(m_strFilename);
}

void vtStructureLayer::GetProjection(vtProjection &proj)
{
	proj = m_proj;
}

bool vtStructureLayer::ConvertProjection(vtProjection &proj)
{
	if (proj == m_proj)
		return true;

	// Create conversion object
	vtProjection Source;
	GetProjection(Source);
	OCT *trans = OGRCreateCoordinateTransformation(&Source, &proj);
	if (!trans)
		return false;		// inconvertible projections

	DPoint2 loc;
	int i;
	int count = GetSize();
	for (i = 0; i < count; i++)
	{
		vtStructure *str = GetAt(i);
		vtBuilding *bld = str->GetBuilding();
		if (bld)
		{
			loc = bld->GetLocation();
			trans->Transform(1, &loc.x, &loc.y);
			bld->SetLocation(loc);
		}
		vtFence *fen = str->GetFence();
		if (fen)
		{
			// TODO
		}
	}

	delete trans;
	return false;
}

bool vtStructureLayer::AppendDataFrom(vtLayer *pL)
{
	// safety check
	if (pL->GetType() != LT_STRUCTURE)
		return false;

	vtStructureLayer *pFrom = (vtStructureLayer *)pL;

	int count = pFrom->GetSize();
	for (int i = 0; i < count; i++)
	{
		vtStructure *str = pFrom->GetAt(i);
		Append(str);
	}
	return true;
}

void vtStructureLayer::Offset(const DPoint2 &p)
{
	int npoints = GetSize();
	if (!npoints)
		return;

	DPoint2 temp;
	for (int i = 0; i < npoints; i++)
	{
		vtStructure *str = GetAt(i);
		vtBuilding *bld = str->GetBuilding();
		if (bld)
			bld->Offset(p);
		vtFence *fen = str->GetFence();
		if (fen)
		{
			// TODO
		}
	}
}

//
// Locate the closest building that is no more than epsilon units in either
// dimension away from point.
//
// Return NULL if there is no building.
//
vtStructure *vtStructureLayer::FindBuilding(DPoint2 &point, double epsilon)
{
	int count = GetSize();
	DPoint2 loc, diff;
	double dist2, closest = 1.0E10f, eps2 = epsilon * epsilon;

	vtStructure *best_bld = NULL;

	for (int i = 0; i < count; i++)
	{
		vtStructure *str = GetAt(i);
		vtBuilding *bld = str->GetBuilding();
		if (!bld)
			continue;
		loc = bld->GetLocation();
		diff = loc - point;
		dist2 = diff.x*diff.x + diff.y*diff.y;
		if (dist2 < eps2)
		{
			if (dist2 < closest)
			{
				closest = dist2;
				best_bld = str;
			}
		}
	}
	return best_bld;
}

bool vtStructureLayer::EditBuildingProperties()
{
	int count = 0;
	vtBuilding *bld_selected;

	int size = GetSize();
	for (int i = 0; i < size; i++)
	{
		vtStructure *str = GetAt(i);
		vtBuilding *bld = str->GetBuilding();
		if (bld && str->IsSelected())
		{
			count++;
			bld_selected = bld;
		}
	}
	if (count != 1)
		return false;

	// for now, assume they will change something (pessimistic)
	SetModified(true);

	BuildingDlg dlg(NULL, -1, "Building Properties", wxDefaultPosition);
		dlg.Setup(bld_selected);
	return (dlg.ShowModal() == wxID_OK);
}

void vtStructureLayer::InvertSelection()
{
	int i, size = GetSize();
	for (i = 0; i < size; i++)
	{
		vtStructure *str = GetAt(i);
		str->Select(!str->IsSelected());
	}
}

//
// Helper: find the index of a field in a DBF file, given the name of the field.
// Returns -1 if not found.
//
int FindDBField(DBFHandle db, const char *field_name)
{
	int count = DBFGetFieldCount(db);
	for (int i = 0; i < count; i++)
	{
		int pnWidth, pnDecimals;
		char pszFieldName[80];
		DBFFieldType fieldtype = DBFGetFieldInfo(db, i,
			pszFieldName, &pnWidth, &pnDecimals );
		if (!stricmp(field_name, pszFieldName))
			return i;
	}
	return -1;
}

void vtStructureLayer::AddElementsFromSHP(const char *filename, vtProjection &proj)
{
	//Open the SHP File & Get Info from SHP:
	SHPHandle hSHP = SHPOpen(filename, "rb");
	if (hSHP == NULL)
		return;

	//  Get number of polys (m_iNumPolys) and type of data (nShapeType)
	int		nElem;
	int		nShapeType;
    double	adfMinBound[4], adfMaxBound[4];
	SHPGetInfo(hSHP, &nElem, &nShapeType, adfMinBound, adfMaxBound);

	//  Check Shape Type, Building outlines should be Poly data
	if (nShapeType == SHPT_POINT)
		AddElementsFromSHPPoints(hSHP, nElem);
	else if (nShapeType == SHPT_POLYGON)
		AddElementsFromSHPPolygons(filename, hSHP, nElem);

	m_proj = proj;	// Set projection

	SHPClose(hSHP);
}

void vtStructureLayer::AddElementsFromSHPPoints(SHPHandle hSHP, int nElem)
{
	// Initialize arrays
	SetMaxSize(nElem);

	// Read Points from SHP
	int i;
	SHPObject *psShape;
	for (i = 0; i < nElem; i++)
	{
		// Get the i-th Point in the SHP file
		psShape = SHPReadObject(hSHP, i);

		vtBuilding *new_bld = new vtBuilding();
		new_bld->SetShape(SHAPE_RECTANGLE);
		new_bld->SetLocation(DPoint2(psShape->padfX[0], psShape->padfY[0]));
		new_bld->SetStories(1);
		AddBuilding(new_bld);

		SHPDestroyObject(psShape);
	}
}

void vtStructureLayer::AddElementsFromSHPPolygons(const char *filename,
												 SHPHandle hSHP, int nElem)
{
	// Open DBF File & Get DBF Info:
	DBFHandle db = DBFOpen(filename, "rb");
	if (db == NULL)
		return;

	// Check for field with number of stories
	int stories_field = FindDBField(db, "Stories");

	// Initialize arrays
	SetMaxSize(nElem);

	// Read Polys from SHP
	int i;
	SHPObject *psShape;
	for (i = 0; i < nElem; i++)
	{
		// Get the i-th Poly in the SHP file
		psShape = SHPReadObject(hSHP, i);

		// Store each SHP Poly as Building Footprint

		// The SHP appears to repeat the first point as the last, so ignore
		// the last point.
		int num_points = psShape->nVertices-1;

		vtBuilding *new_bld = new vtBuilding();
		new_bld->SetShape(SHAPE_POLY);

		DLine2 foot;
		foot.SetSize(num_points);

		int j, k;
		for (j = 0; j < num_points; j++)
		{
			// The SHP polygons appear to be clockwise - but the vtBuilding
			//  convention is counter-clockwise, so reverse the order.
			k = num_points-1-j;

			foot.SetAt(j, DPoint2(psShape->padfX[k], psShape->padfY[k]));
		}
		new_bld->SetFootprint(foot);
		new_bld->SetCenterFromPoly();

		int num_stories = 1;
		if (stories_field != -1)
		{
			// attempt to get number of stories from the DBF
			num_stories = DBFReadIntegerAttribute(db, i, stories_field);
			if (num_stories < 1)
				num_stories = 1;
		}
		new_bld->SetStories(num_stories);

		AddBuilding(new_bld);

		SHPDestroyObject(psShape);
	}
	DBFClose(db);
}

<commit_msg>fixed setting of Projection<commit_after>//
// StructLayer.cpp
//
// Copyright (c) 2001 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "Frame.h"
#include "StructLayer.h"
#include "ScaledView.h"
#include "BuildingDlg.h"

#ifndef _MSC_VER	// for non-MSVC
#include <string.h>
#define stricmp strcasecmp
#endif

wxPen orangePen;
wxPen yellowPen;
static bool g_bInitializedPens = false;

//////////////////////////////////////////////////////////////////////////

vtStructureLayer::vtStructureLayer() : vtLayer(LT_STRUCTURE)
{
	m_strFilename = "Untitled.xml";

	if (!g_bInitializedPens)
	{
		g_bInitializedPens = true;
		orangePen.SetColour(255,128,0);
		yellowPen.SetColour(255,255,0);
	}
}

bool vtStructureLayer::GetExtent(DRECT &rect)
{
	if (IsEmpty())
		return false;

	GetExtents(rect);

	// expand by 10 meters
	rect.left -= 10.0f;
	rect.right += 10.0f;
	rect.bottom -= 10.0f;
	rect.top += 10.0f;

	return true;
}

#define BLENGTH 5

void vtStructureLayer::DrawLayer(wxDC* pDC, vtScaledView *pView)
{
	int structs = GetSize();
	if (!structs)
		return;

	pDC->SetPen(orangePen);
	pDC->SetBrush(*wxTRANSPARENT_BRUSH);
	bool bSel = false;

	m_size = pView->sdx(20);
	if (m_size > 5) m_size = 5;
	if (m_size < 1) m_size = 1;

	for (int i = 0; i < structs; i++)
	{
		// draw each building
		vtStructure *str = GetAt(i);
		vtBuilding *bld = str->GetBuilding();
		if (bld)
		{
			if (str->IsSelected())
			{
				if (!bSel)
				{
					pDC->SetPen(yellowPen);
					bSel = true;
				}
			}
			else
			{
				if (bSel)
				{
					pDC->SetPen(orangePen);
					bSel = false;
				}
			}
			DrawBuilding(pDC, pView, bld);
		}
		else
		{
			vtFence *fen = str->GetFence();
			if (fen)
			{
				// TODO
			}
		}
	}
}

#define MAX_SIDES	100
static wxPoint array[MAX_SIDES];

void vtStructureLayer::DrawBuilding(wxDC* pDC, vtScaledView *pView, vtBuilding *bld)
{
	DPoint2 corner[4];
	float fWidth, fDepth, fRotation;
	int j;

	wxPoint origin;
	pView->screen(bld->GetLocation(), origin);

	pDC->DrawLine(origin.x-m_size, origin.y, origin.x+m_size+1, origin.y);
	pDC->DrawLine(origin.x, origin.y-m_size, origin.x, origin.y+m_size+1);

	if (bld->GetShape() == SHAPE_POLY)
	{
		DLine2 &dl = bld->GetFootprint();
		int size = dl.GetSize();
		for (j = 0; j < size && j < MAX_SIDES-1; j++)
			pView->screen(dl.GetAt(j), array[j]);
		pView->screen(dl.GetAt(0), array[j++]);

		pDC->DrawLines(j, array);
	}
	if (bld->GetShape() == SHAPE_CIRCLE)
	{
		int size = pView->sdx(bld->GetRadius());
		pDC->DrawEllipse(origin.x-size, origin.y-size,
			size<<1, size<<1);
	}
	if (bld->GetShape() == SHAPE_RECTANGLE)
	{
		bld->GetRectangle(fWidth, fDepth);
		bld->GetRotation(fRotation);
		if (fRotation == -1.0f) fRotation = 0.0f;
		DPoint2 pt(fWidth / 2.0, fDepth / 2.0);
		corner[0].Set(-pt.x, pt.y);
		corner[1].Set(pt.x, pt.y);
		corner[2].Set(pt.x, -pt.y);
		corner[3].Set(-pt.x, -pt.y);
		corner[0].Rotate(fRotation);
		corner[1].Rotate(fRotation);
		corner[2].Rotate(fRotation);
		corner[3].Rotate(fRotation);
		array[0] = origin + pView->screen_delta(corner[0]);
		array[1] = origin + pView->screen_delta(corner[1]);
		array[2] = origin + pView->screen_delta(corner[2]);
		array[3] = origin + pView->screen_delta(corner[3]);
		array[4] = array[0];
		pDC->DrawLines(5, array);
	}
}

bool vtStructureLayer::OnSave()
{
	return WriteXML(m_strFilename);
}

bool vtStructureLayer::OnLoad()
{
	return ReadXML(m_strFilename);
}

void vtStructureLayer::GetProjection(vtProjection &proj)
{
	proj = m_proj;
}

bool vtStructureLayer::ConvertProjection(vtProjection &proj)
{
	if (proj == m_proj)
		return true;

	// Create conversion object
	vtProjection Source;
	GetProjection(Source);
	OCT *trans = OGRCreateCoordinateTransformation(&Source, &proj);
	if (!trans)
		return false;		// inconvertible projections

	DPoint2 loc;
	int i;
	int count = GetSize();
	for (i = 0; i < count; i++)
	{
		vtStructure *str = GetAt(i);
		vtBuilding *bld = str->GetBuilding();
		if (bld)
		{
			loc = bld->GetLocation();
			trans->Transform(1, &loc.x, &loc.y);
			bld->SetLocation(loc);
		}
		vtFence *fen = str->GetFence();
		if (fen)
		{
			// TODO
		}
	}

	// set the projection
	m_proj = proj;

	delete trans;
	return true;
}

bool vtStructureLayer::AppendDataFrom(vtLayer *pL)
{
	// safety check
	if (pL->GetType() != LT_STRUCTURE)
		return false;

	vtStructureLayer *pFrom = (vtStructureLayer *)pL;

	int count = pFrom->GetSize();
	for (int i = 0; i < count; i++)
	{
		vtStructure *str = pFrom->GetAt(i);
		Append(str);
	}
	return true;
}

void vtStructureLayer::Offset(const DPoint2 &p)
{
	int npoints = GetSize();
	if (!npoints)
		return;

	DPoint2 temp;
	for (int i = 0; i < npoints; i++)
	{
		vtStructure *str = GetAt(i);
		vtBuilding *bld = str->GetBuilding();
		if (bld)
			bld->Offset(p);
		vtFence *fen = str->GetFence();
		if (fen)
		{
			// TODO
		}
	}
}

//
// Locate the closest building that is no more than epsilon units in either
// dimension away from point.
//
// Return NULL if there is no building.
//
vtStructure *vtStructureLayer::FindBuilding(DPoint2 &point, double epsilon)
{
	int count = GetSize();
	DPoint2 loc, diff;
	double dist2, closest = 1.0E10f, eps2 = epsilon * epsilon;

	vtStructure *best_bld = NULL;

	for (int i = 0; i < count; i++)
	{
		vtStructure *str = GetAt(i);
		vtBuilding *bld = str->GetBuilding();
		if (!bld)
			continue;
		loc = bld->GetLocation();
		diff = loc - point;
		dist2 = diff.x*diff.x + diff.y*diff.y;
		if (dist2 < eps2)
		{
			if (dist2 < closest)
			{
				closest = dist2;
				best_bld = str;
			}
		}
	}
	return best_bld;
}

bool vtStructureLayer::EditBuildingProperties()
{
	int count = 0;
	vtBuilding *bld_selected;

	int size = GetSize();
	for (int i = 0; i < size; i++)
	{
		vtStructure *str = GetAt(i);
		vtBuilding *bld = str->GetBuilding();
		if (bld && str->IsSelected())
		{
			count++;
			bld_selected = bld;
		}
	}
	if (count != 1)
		return false;

	// for now, assume they will change something (pessimistic)
	SetModified(true);

	BuildingDlg dlg(NULL, -1, "Building Properties", wxDefaultPosition);
		dlg.Setup(bld_selected);
	return (dlg.ShowModal() == wxID_OK);
}

void vtStructureLayer::InvertSelection()
{
	int i, size = GetSize();
	for (i = 0; i < size; i++)
	{
		vtStructure *str = GetAt(i);
		str->Select(!str->IsSelected());
	}
}

//
// Helper: find the index of a field in a DBF file, given the name of the field.
// Returns -1 if not found.
//
int FindDBField(DBFHandle db, const char *field_name)
{
	int count = DBFGetFieldCount(db);
	for (int i = 0; i < count; i++)
	{
		int pnWidth, pnDecimals;
		char pszFieldName[80];
		DBFFieldType fieldtype = DBFGetFieldInfo(db, i,
			pszFieldName, &pnWidth, &pnDecimals );
		if (!stricmp(field_name, pszFieldName))
			return i;
	}
	return -1;
}

void vtStructureLayer::AddElementsFromSHP(const char *filename, vtProjection &proj)
{
	//Open the SHP File & Get Info from SHP:
	SHPHandle hSHP = SHPOpen(filename, "rb");
	if (hSHP == NULL)
		return;

	//  Get number of polys (m_iNumPolys) and type of data (nShapeType)
	int		nElem;
	int		nShapeType;
    double	adfMinBound[4], adfMaxBound[4];
	SHPGetInfo(hSHP, &nElem, &nShapeType, adfMinBound, adfMaxBound);

	//  Check Shape Type, Building outlines should be Poly data
	if (nShapeType == SHPT_POINT)
		AddElementsFromSHPPoints(hSHP, nElem);
	else if (nShapeType == SHPT_POLYGON)
		AddElementsFromSHPPolygons(filename, hSHP, nElem);

	m_proj = proj;	// Set projection

	SHPClose(hSHP);
}

void vtStructureLayer::AddElementsFromSHPPoints(SHPHandle hSHP, int nElem)
{
	// Initialize arrays
	SetMaxSize(nElem);

	// Read Points from SHP
	int i;
	SHPObject *psShape;
	for (i = 0; i < nElem; i++)
	{
		// Get the i-th Point in the SHP file
		psShape = SHPReadObject(hSHP, i);

		vtBuilding *new_bld = new vtBuilding();
		new_bld->SetShape(SHAPE_RECTANGLE);
		new_bld->SetLocation(DPoint2(psShape->padfX[0], psShape->padfY[0]));
		new_bld->SetStories(1);
		AddBuilding(new_bld);

		SHPDestroyObject(psShape);
	}
}

void vtStructureLayer::AddElementsFromSHPPolygons(const char *filename,
												 SHPHandle hSHP, int nElem)
{
	// Open DBF File & Get DBF Info:
	DBFHandle db = DBFOpen(filename, "rb");
	if (db == NULL)
		return;

	// Check for field with number of stories
	int stories_field = FindDBField(db, "Stories");

	// Initialize arrays
	SetMaxSize(nElem);

	// Read Polys from SHP
	int i;
	SHPObject *psShape;
	for (i = 0; i < nElem; i++)
	{
		// Get the i-th Poly in the SHP file
		psShape = SHPReadObject(hSHP, i);

		// Store each SHP Poly as Building Footprint

		// The SHP appears to repeat the first point as the last, so ignore
		// the last point.
		int num_points = psShape->nVertices-1;

		vtBuilding *new_bld = new vtBuilding();
		new_bld->SetShape(SHAPE_POLY);

		DLine2 foot;
		foot.SetSize(num_points);

		int j, k;
		for (j = 0; j < num_points; j++)
		{
			// The SHP polygons appear to be clockwise - but the vtBuilding
			//  convention is counter-clockwise, so reverse the order.
			k = num_points-1-j;

			foot.SetAt(j, DPoint2(psShape->padfX[k], psShape->padfY[k]));
		}
		new_bld->SetFootprint(foot);
		new_bld->SetCenterFromPoly();

		int num_stories = 1;
		if (stories_field != -1)
		{
			// attempt to get number of stories from the DBF
			num_stories = DBFReadIntegerAttribute(db, i, stories_field);
			if (num_stories < 1)
				num_stories = 1;
		}
		new_bld->SetStories(num_stories);

		AddBuilding(new_bld);

		SHPDestroyObject(psShape);
	}
	DBFClose(db);
}

<|endoftext|>


<commit_before>#include <ContentForgeTool.h>
#include <Render/ShaderMetaCommon.h>
#include <Utils.h>
#include <ParamsUtils.h>
#include <Subprocess.h>
#include <CLI11.hpp>

namespace fs = std::filesystem;

// Set working directory to $(TargetDir)
// Example args:
// -s src/sky --path Data ../../../content --ibl -b -t

class CSkyboxTool : public CContentForgeTool
{
protected:

	Data::CSchemeSet _SceneSchemes;

	std::map<std::string, std::string> _EffectsByType;
	std::map<std::string, std::string> _EffectParamAliases;

	std::string _ResourceRoot;
	std::string _SchemeFile;
	std::string _SettingsFile;
	bool        _CalcIBL = false;
	bool        _OutputBin = false;
	bool        _OutputHRD = false; // For debug purposes, saves scene hierarchies in a human-readable format

public:

	CSkyboxTool(const std::string& Name, const std::string& Desc, CVersion Version)
		: CContentForgeTool(Name, Desc, Version)
		, _ResourceRoot("Data:")
	{
		// Set default before parsing command line
		_SchemeFile = "../schemes/scene.dss";
		_SettingsFile = "../schemes/settings.hrd";
	}

	virtual bool SupportsMultithreading() const override
	{
		// FIXME: must handle duplicate targets (for example 2 metafiles writing the same resulting file, like depth_atest_ps)
		// FIXME: CStrID
		return false;
	}

	virtual int Init() override
	{
		if (_ResourceRoot.empty())
			if (_LogVerbosity >= EVerbosity::Warnings)
				std::cout << "Resource root is empty, external references may not be resolved from the game!";

		if (!_OutputHRD) _OutputBin = true;

		if (_OutputBin)
		{
			if (!ParamsUtils::LoadSchemes(_SchemeFile.c_str(), _SceneSchemes))
			{
				std::cout << "Couldn't load scene binary serialization scheme from " << _SchemeFile;
				return 2;
			}
		}

		{
			Data::CParams EffectSettings;
			if (!ParamsUtils::LoadParamsFromHRD(_SettingsFile.c_str(), EffectSettings))
			{
				std::cout << "Couldn't load effect settings from " << _SettingsFile;
				return 3;
			}

			const Data::CParams* pMap;
			if (ParamsUtils::TryGetParam(pMap, EffectSettings, "Effects"))
			{
				for (const auto& Pair : *pMap)
					_EffectsByType.emplace(Pair.first.ToString(), Pair.second.GetValue<std::string>());
			}
			if (ParamsUtils::TryGetParam(pMap, EffectSettings, "Params"))
			{
				for (const auto& Pair : *pMap)
					_EffectParamAliases.emplace(Pair.first.ToString(), Pair.second.GetValue<std::string>());
			}
		}

		return 0;
	}

	virtual void ProcessCommandLine(CLI::App& CLIApp) override
	{
		//???use --project-file instead of --res-root + --settings?
		CContentForgeTool::ProcessCommandLine(CLIApp);
		CLIApp.add_option("--res-root", _ResourceRoot, "Resource root prefix for referencing external subresources by path");
		CLIApp.add_option("--scheme,--schema", _SchemeFile, "Scene binary serialization scheme file path");
		CLIApp.add_option("--settings", _SettingsFile, "Settings file path");
		CLIApp.add_flag("-t,--txt", _OutputHRD, "Output scenes in a human-readable format, suitable for debugging only");
		CLIApp.add_flag("-b,--bin", _OutputBin, "Output scenes in a binary format, suitable for loading into the engine");
		CLIApp.add_flag("--ibl", _CalcIBL, "Calculate image-based lighting resources (IEM, PMREM)");
	}

	fs::path GetPath(const Data::CParams& TaskParams, const char* pPathID)
	{
		fs::path Result;

		std::string PathValue;
		if (ParamsUtils::TryGetParam(PathValue, TaskParams, pPathID))
			Result = PathValue;
		else if (ParamsUtils::TryGetParam(PathValue, TaskParams, "Output"))
			Result = PathValue;
		else return Result;

		if (!_RootDir.empty() && Result.is_relative())
			Result = fs::path(_RootDir) / Result;

		return Result;
	}

	const std::string& GetEffectParamID(const std::string& Alias)
	{
		auto It = _EffectParamAliases.find(Alias);
		return (It == _EffectParamAliases.cend()) ? Alias : It->second;
	}

	virtual bool ProcessTask(CContentForgeTask& Task) override
	{
		// TODO: check whether the metafile can be processed by this tool

		const std::string TaskName = Task.TaskID.ToString();

		std::string SkyboxFileName = Task.SrcFilePath.filename().generic_string();
		ToLower(SkyboxFileName);

		// Generate material

		std::string MaterialID;

		const auto TexturePath = GetPath(Task.Params, "TextureOutput");

		auto EffectIt = _EffectsByType.find("MetallicRoughnessSkybox");
		if (EffectIt == _EffectsByType.cend() || EffectIt->second.empty())
		{
			Task.Log.LogError("Material type MetallicRoughnessTerrain has no mapped DEM effect file in effect settings");
			return false;
		}

		CMaterialParams MtlParamTable;
		auto Path = ResolvePathAliases(EffectIt->second).generic_string();
		Task.Log.LogDebug("Opening effect " + Path);
		if (!GetEffectMaterialParams(MtlParamTable, Path, Task.Log))
		{
			Task.Log.LogError("Error reading material param table for effect " + Path);
			return false;
		}

		Data::CParams MtlParams;

		const auto& SkyboxTextureID = GetEffectParamID("SkyboxTexture");
		if (MtlParamTable.HasResource(SkyboxTextureID))
		{
			auto DestPath = TexturePath / SkyboxFileName;
			fs::create_directories(DestPath.parent_path());
			std::error_code ec;
			if (!fs::copy_file(Task.SrcFilePath, DestPath, fs::copy_options::overwrite_existing, ec))
			{
				Task.Log.LogError("Error copying texture from " + Task.SrcFilePath.generic_string() + " to " + DestPath.generic_string() + ": " + ec.message());
				return false;
			}

			MtlParams.emplace_back(CStrID(SkyboxTextureID), _ResourceRoot + fs::relative(DestPath, _RootDir).generic_string());
		}
		else
		{
			Task.Log.LogError("No SkyboxTexture (" + SkyboxTextureID + ") parameter found in a material");
			return false;
		}

		{
			auto DestPath = GetPath(Task.Params, "MaterialOutput") / (TaskName + ".mtl");

			fs::create_directories(DestPath.parent_path());

			std::ofstream File(DestPath, std::ios_base::binary | std::ios_base::trunc);

			if (!SaveMaterial(File, EffectIt->second, MtlParamTable, MtlParams, Task.Log)) return false;

			MaterialID = _ResourceRoot + fs::relative(DestPath, _RootDir).generic_string();
		}

		// Calculate IBL resources

		std::string IEMID, PMREMID;

		if (_CalcIBL)
		{
			// See https://seblagarde.wordpress.com/2012/06/10/amd-cubemapgen-for-physically-based-rendering/

			// Calculate IEM

			auto IEMPath = TexturePath / (fs::path(SkyboxFileName).filename().replace_extension().string() + "_iem.dds");
			const int IEMDimensionSize = ParamsUtils::GetParam(Task.Params, "IEMDimensionSize", 128);
			const std::string IEMFormat = ParamsUtils::GetParam(Task.Params, "IEMFormat", std::string("A8R8G8B8"));

			const std::string IEMCmdLine = "cubemapgen/mcmg.exe -IrradianceCubemap -importCubeDDS:\"" + Task.SrcFilePath.string() +
				"\" -exportCubeDDS -exportFilename:\"" + IEMPath.string() + "\" -exportSize:" + std::to_string(IEMDimensionSize) +
				" -exportPixelFormat:" + IEMFormat + " -consoleErrorOutput -exit";
			if (RunSubprocess(IEMCmdLine, &Task.Log) == 0)
			{
				IEMID = _ResourceRoot + fs::relative(IEMPath, _RootDir).generic_string();
			}
			else
			{
				Task.Log.LogError("Error generating irradiance environment map (IEM)");
				return false;
			}

			// Calculate PMREM (Mipmap mode)

			auto PMREMPath = TexturePath / (fs::path(SkyboxFileName).filename().replace_extension().string() + "_pmrem.dds");
			const int PMREMDimensionSize = ParamsUtils::GetParam(Task.Params, "PMREMDimensionSize", 256);
			const std::string PMREMFormat = ParamsUtils::GetParam(Task.Params, "PMREMFormat", std::string("A8R8G8B8"));
			const int PMREMMipCount = ParamsUtils::GetParam(Task.Params, "PMREMMipCount", 7);
			const float PMREMGlossScale = ParamsUtils::GetParam(Task.Params, "PMREMGlossScale", 10.f);
			const float PMREMGlossBias = ParamsUtils::GetParam(Task.Params, "PMREMGlossBias", 1.f);

			const std::string PMREMCmdLine = "cubemapgen/mcmg.exe -filterTech:CosinePower -CosinePowerMipmapChainMode:Mipmap"
				" -NumMipmap:" + std::to_string(PMREMMipCount) +
				" -GlossScale:" + std::to_string(PMREMGlossScale) +
				" -GlossBias:" + std::to_string(PMREMGlossBias) +
				" -importCubeDDS:\"" + Task.SrcFilePath.string() + "\""
				" -LightingModel:PhongBRDF -ExcludeBase -solidAngleWeighting -edgeFixupTech:Warp -importDegamma:1.0 -exportGamma:1.0 "
				" -exportCubeDDS -exportFilename:\"" + PMREMPath.string() + "\" -exportSize:" + std::to_string(PMREMDimensionSize) +
				" -exportPixelFormat:A8R8G8B8 -exportMipChain -consoleErrorOutput -exit";
			if (RunSubprocess(PMREMCmdLine, &Task.Log) == 0)
			{
				PMREMID = _ResourceRoot + fs::relative(PMREMPath, _RootDir).generic_string();
			}
			else
			{
				Task.Log.LogError("Error generating prefiltered mipmaped radiance environment map (PMREM)");
				return false;
			}
		}

		// Write scene file

		Data::CParams Result;

		Data::CDataArray Attributes;

		{
			Data::CParams Attribute;
			Attribute.emplace_back(CStrID("Class"), 'SKBA'); // Frame::CSkyboxAttribute
			Attribute.emplace_back(CStrID("Material"), MaterialID);
			Attributes.push_back(std::move(Attribute));
		}

		if (_CalcIBL)
		{
			Data::CParams Attribute;
			Attribute.emplace_back(CStrID("Class"), 'NAAL'); // Frame::CAmbientLightAttribute
			Attribute.emplace_back(CStrID("IrradianceMap"), IEMID);
			Attribute.emplace_back(CStrID("RadianceEnvMap"), PMREMID);
			Attributes.push_back(std::move(Attribute));
		}

		Result.emplace_back(CStrID("Attrs"), std::move(Attributes));

		const fs::path OutPath = GetPath(Task.Params, "Output");

		if (_OutputHRD)
		{
			const auto DestPath = OutPath / (TaskName + ".hrd");
			if (!ParamsUtils::SaveParamsToHRD(DestPath.string().c_str(), Result))
			{
				Task.Log.LogError("Error serializing " + TaskName + " to text");
				return false;
			}
		}

		if (_OutputBin)
		{
			const auto DestPath = OutPath / (Task.TaskID.ToString() + ".scn");
			if (!ParamsUtils::SaveParamsByScheme(DestPath.string().c_str(), Result, CStrID("SceneNode"), _SceneSchemes))
			{
				Task.Log.LogError("Error serializing " + TaskName + " to binary");
				return false;
			}
		}

		return true;
	}
};

int main(int argc, const char** argv)
{
	CSkyboxTool Tool("cf-skybox", "Cubemap to DeusExMachina skybox asset converter", { 0, 1, 0 });
	return Tool.Execute(argc, argv);
}
<commit_msg>cf-skybox less aggressive recalculation of IBL resources. Version 1.0.0.<commit_after>#include <ContentForgeTool.h>
#include <Render/ShaderMetaCommon.h>
#include <Utils.h>
#include <ParamsUtils.h>
#include <Subprocess.h>
#include <CLI11.hpp>

namespace fs = std::filesystem;

// Set working directory to $(TargetDir)
// Example args:
// -s src/sky --path Data ../../../content --ibl -b -t

class CSkyboxTool : public CContentForgeTool
{
protected:

	Data::CSchemeSet _SceneSchemes;

	std::map<std::string, std::string> _EffectsByType;
	std::map<std::string, std::string> _EffectParamAliases;

	std::string _ResourceRoot;
	std::string _SchemeFile;
	std::string _SettingsFile;
	bool        _IBL = false;
	bool        _RecalcIBL = false;
	bool        _OutputBin = false;
	bool        _OutputHRD = false; // For debug purposes, saves scene hierarchies in a human-readable format

public:

	CSkyboxTool(const std::string& Name, const std::string& Desc, CVersion Version)
		: CContentForgeTool(Name, Desc, Version)
		, _ResourceRoot("Data:")
	{
		// Set default before parsing command line
		_SchemeFile = "../schemes/scene.dss";
		_SettingsFile = "../schemes/settings.hrd";
	}

	virtual bool SupportsMultithreading() const override
	{
		// FIXME: must handle duplicate targets (for example 2 metafiles writing the same resulting file, like depth_atest_ps)
		// FIXME: CStrID
		return false;
	}

	virtual int Init() override
	{
		if (_ResourceRoot.empty())
			if (_LogVerbosity >= EVerbosity::Warnings)
				std::cout << "Resource root is empty, external references may not be resolved from the game!";

		if (!_OutputHRD) _OutputBin = true;

		if (_OutputBin)
		{
			if (!ParamsUtils::LoadSchemes(_SchemeFile.c_str(), _SceneSchemes))
			{
				std::cout << "Couldn't load scene binary serialization scheme from " << _SchemeFile;
				return 2;
			}
		}

		{
			Data::CParams EffectSettings;
			if (!ParamsUtils::LoadParamsFromHRD(_SettingsFile.c_str(), EffectSettings))
			{
				std::cout << "Couldn't load effect settings from " << _SettingsFile;
				return 3;
			}

			const Data::CParams* pMap;
			if (ParamsUtils::TryGetParam(pMap, EffectSettings, "Effects"))
			{
				for (const auto& Pair : *pMap)
					_EffectsByType.emplace(Pair.first.ToString(), Pair.second.GetValue<std::string>());
			}
			if (ParamsUtils::TryGetParam(pMap, EffectSettings, "Params"))
			{
				for (const auto& Pair : *pMap)
					_EffectParamAliases.emplace(Pair.first.ToString(), Pair.second.GetValue<std::string>());
			}
		}

		return 0;
	}

	virtual void ProcessCommandLine(CLI::App& CLIApp) override
	{
		//???use --project-file instead of --res-root + --settings?
		CContentForgeTool::ProcessCommandLine(CLIApp);
		CLIApp.add_option("--res-root", _ResourceRoot, "Resource root prefix for referencing external subresources by path");
		CLIApp.add_option("--scheme,--schema", _SchemeFile, "Scene binary serialization scheme file path");
		CLIApp.add_option("--settings", _SettingsFile, "Settings file path");
		CLIApp.add_flag("-t,--txt", _OutputHRD, "Output scenes in a human-readable format, suitable for debugging only");
		CLIApp.add_flag("-b,--bin", _OutputBin, "Output scenes in a binary format, suitable for loading into the engine");
		CLIApp.add_flag("--ibl", _IBL, "Add image-based lighting resources (IEM, PMREM) to the asset");
		CLIApp.add_flag("-r", _RecalcIBL, "Recalculate image-based lighting resources (IEM, PMREM) even if they exist");
	}

	fs::path GetPath(const Data::CParams& TaskParams, const char* pPathID)
	{
		fs::path Result;

		std::string PathValue;
		if (ParamsUtils::TryGetParam(PathValue, TaskParams, pPathID))
			Result = PathValue;
		else if (ParamsUtils::TryGetParam(PathValue, TaskParams, "Output"))
			Result = PathValue;
		else return Result;

		if (!_RootDir.empty() && Result.is_relative())
			Result = fs::path(_RootDir) / Result;

		return Result;
	}

	const std::string& GetEffectParamID(const std::string& Alias)
	{
		auto It = _EffectParamAliases.find(Alias);
		return (It == _EffectParamAliases.cend()) ? Alias : It->second;
	}

	virtual bool ProcessTask(CContentForgeTask& Task) override
	{
		// TODO: check whether the metafile can be processed by this tool

		const std::string TaskName = Task.TaskID.ToString();

		std::string SkyboxFileName = Task.SrcFilePath.filename().generic_string();
		ToLower(SkyboxFileName);

		// Generate material

		std::string MaterialID;

		const auto TexturePath = GetPath(Task.Params, "TextureOutput");

		auto EffectIt = _EffectsByType.find("MetallicRoughnessSkybox");
		if (EffectIt == _EffectsByType.cend() || EffectIt->second.empty())
		{
			Task.Log.LogError("Material type MetallicRoughnessTerrain has no mapped DEM effect file in effect settings");
			return false;
		}

		CMaterialParams MtlParamTable;
		auto Path = ResolvePathAliases(EffectIt->second).generic_string();
		Task.Log.LogDebug("Opening effect " + Path);
		if (!GetEffectMaterialParams(MtlParamTable, Path, Task.Log))
		{
			Task.Log.LogError("Error reading material param table for effect " + Path);
			return false;
		}

		Data::CParams MtlParams;

		const auto& SkyboxTextureID = GetEffectParamID("SkyboxTexture");
		if (MtlParamTable.HasResource(SkyboxTextureID))
		{
			auto DestPath = TexturePath / SkyboxFileName;
			fs::create_directories(DestPath.parent_path());
			std::error_code ec;
			if (!fs::copy_file(Task.SrcFilePath, DestPath, fs::copy_options::overwrite_existing, ec))
			{
				Task.Log.LogError("Error copying texture from " + Task.SrcFilePath.generic_string() + " to " + DestPath.generic_string() + ": " + ec.message());
				return false;
			}

			MtlParams.emplace_back(CStrID(SkyboxTextureID), _ResourceRoot + fs::relative(DestPath, _RootDir).generic_string());
		}
		else
		{
			Task.Log.LogError("No SkyboxTexture (" + SkyboxTextureID + ") parameter found in a material");
			return false;
		}

		{
			auto DestPath = GetPath(Task.Params, "MaterialOutput") / (TaskName + ".mtl");

			fs::create_directories(DestPath.parent_path());

			std::ofstream File(DestPath, std::ios_base::binary | std::ios_base::trunc);

			if (!SaveMaterial(File, EffectIt->second, MtlParamTable, MtlParams, Task.Log)) return false;

			MaterialID = _ResourceRoot + fs::relative(DestPath, _RootDir).generic_string();
		}

		// Calculate IBL resources

		std::string IEMID, PMREMID;

		if (_IBL)
		{
			// See https://seblagarde.wordpress.com/2012/06/10/amd-cubemapgen-for-physically-based-rendering/

			// Calculate IEM

			auto IEMPath = TexturePath / (fs::path(SkyboxFileName).filename().replace_extension().string() + "_iem.dds");
			IEMID = _ResourceRoot + fs::relative(IEMPath, _RootDir).generic_string();
			if (_RecalcIBL || !fs::exists(IEMPath))
			{
				const int IEMDimensionSize = ParamsUtils::GetParam(Task.Params, "IEMDimensionSize", 128);
				const std::string IEMFormat = ParamsUtils::GetParam(Task.Params, "IEMFormat", std::string("A8R8G8B8"));

				const std::string IEMCmdLine = "cubemapgen/mcmg.exe -IrradianceCubemap -importCubeDDS:\"" + Task.SrcFilePath.string() +
					"\" -exportCubeDDS -exportFilename:\"" + IEMPath.string() + "\" -exportSize:" + std::to_string(IEMDimensionSize) +
					" -exportPixelFormat:" + IEMFormat + " -consoleErrorOutput -exit";
				if (RunSubprocess(IEMCmdLine, &Task.Log) != 0)
				{
					Task.Log.LogError("Error generating irradiance environment map (IEM)");
					return false;
				}
			}

			// Calculate PMREM (Mipmap mode)

			auto PMREMPath = TexturePath / (fs::path(SkyboxFileName).filename().replace_extension().string() + "_pmrem.dds");
			PMREMID = _ResourceRoot + fs::relative(PMREMPath, _RootDir).generic_string();
			if (_RecalcIBL || !fs::exists(PMREMPath))
			{
				const int PMREMDimensionSize = ParamsUtils::GetParam(Task.Params, "PMREMDimensionSize", 256);
				const std::string PMREMFormat = ParamsUtils::GetParam(Task.Params, "PMREMFormat", std::string("A8R8G8B8"));
				const int PMREMMipCount = ParamsUtils::GetParam(Task.Params, "PMREMMipCount", 7);
				const float PMREMGlossScale = ParamsUtils::GetParam(Task.Params, "PMREMGlossScale", 10.f);
				const float PMREMGlossBias = ParamsUtils::GetParam(Task.Params, "PMREMGlossBias", 1.f);

				const std::string PMREMCmdLine = "cubemapgen/mcmg.exe -filterTech:CosinePower -CosinePowerMipmapChainMode:Mipmap"
					" -NumMipmap:" + std::to_string(PMREMMipCount) +
					" -GlossScale:" + std::to_string(PMREMGlossScale) +
					" -GlossBias:" + std::to_string(PMREMGlossBias) +
					" -importCubeDDS:\"" + Task.SrcFilePath.string() + "\""
					" -LightingModel:PhongBRDF -ExcludeBase -solidAngleWeighting -edgeFixupTech:Warp -importDegamma:1.0 -exportGamma:1.0 "
					" -exportCubeDDS -exportFilename:\"" + PMREMPath.string() + "\" -exportSize:" + std::to_string(PMREMDimensionSize) +
					" -exportPixelFormat:A8R8G8B8 -exportMipChain -consoleErrorOutput -exit";
				if (RunSubprocess(PMREMCmdLine, &Task.Log) != 0)
				{
					Task.Log.LogError("Error generating prefiltered mipmaped radiance environment map (PMREM)");
					return false;
				}
			}
		}

		// Write scene file

		Data::CParams Result;

		Data::CDataArray Attributes;

		{
			Data::CParams Attribute;
			Attribute.emplace_back(CStrID("Class"), 'SKBA'); // Frame::CSkyboxAttribute
			Attribute.emplace_back(CStrID("Material"), MaterialID);
			Attributes.push_back(std::move(Attribute));
		}

		if (_IBL)
		{
			Data::CParams Attribute;
			Attribute.emplace_back(CStrID("Class"), 'NAAL'); // Frame::CAmbientLightAttribute
			Attribute.emplace_back(CStrID("IrradianceMap"), IEMID);
			Attribute.emplace_back(CStrID("RadianceEnvMap"), PMREMID);
			Attributes.push_back(std::move(Attribute));
		}

		Result.emplace_back(CStrID("Attrs"), std::move(Attributes));

		const fs::path OutPath = GetPath(Task.Params, "Output");

		if (_OutputHRD)
		{
			const auto DestPath = OutPath / (TaskName + ".hrd");
			if (!ParamsUtils::SaveParamsToHRD(DestPath.string().c_str(), Result))
			{
				Task.Log.LogError("Error serializing " + TaskName + " to text");
				return false;
			}
		}

		if (_OutputBin)
		{
			const auto DestPath = OutPath / (Task.TaskID.ToString() + ".scn");
			if (!ParamsUtils::SaveParamsByScheme(DestPath.string().c_str(), Result, CStrID("SceneNode"), _SceneSchemes))
			{
				Task.Log.LogError("Error serializing " + TaskName + " to binary");
				return false;
			}
		}

		return true;
	}
};

int main(int argc, const char** argv)
{
	CSkyboxTool Tool("cf-skybox", "Cubemap to DeusExMachina skybox asset converter", { 1, 0, 0 });
	return Tool.Execute(argc, argv);
}
<|endoftext|>


<commit_before>/**************************************************************************************************************
* Copyright (C) *   2017, peterwinzell
*
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.*
*
*
***************************************************************************************************************/
#include <QThread>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDateTime>
#include "subscribehandler.h"
#include "subscriptions.h"

const int SubscribeHandler::m_defaultIntervalMs = 1000;

SubscribeHandler::SubscribeHandler(QObject* parent,VISSRequest* vissrequest,QWebSocket *client):
    RequestHandler(parent,vissrequest,client),m_dosubscription(true)
{
}

void SubscribeHandler::processRequest()
{
    connect(p_client, &QWebSocket::disconnected, this, &SubscribeHandler::socketDisconnected);

    //Add to subscriptions and store subscriptions ID
    Subscriptions* subscriptions = Subscriptions::getInstance();
    m_subId = subscriptions -> addSubcription(this);

    qDebug() << " processing get handler requests";

    //Setup filter params
    initializeFilter();

    //Send subscription response
    //Format response on JSON format
    QString successMessage = getSubscriptionSuccessJson();

    //Send message to client
    p_client->sendTextMessage(successMessage);

    while (m_dosubscription)
    {
        //Get latest value of subscribed signal
        QString value = getSignalValue(p_vissrequest->getSignalPath());

//        qDebug() << "Unfiltered value: " << value;

        if (isFilterPass(value))
        {
            //Format response on JSON format
            QString message = getSubscriptionNotificationJson(value);

            qDebug() << "Sending message:" << message;

            //Send message to client
            p_client->sendTextMessage(message);
        }

        //Sleep for the period defined by filter
        QThread::currentThread()->msleep(m_filter.intervalMs);
    }

    qDebug() << " subscription cancelled ";
}

void SubscribeHandler::socketDisconnected()
{
    m_dosubscription = false;
}

void SubscribeHandler::unsubscribe()
{
    m_dosubscription = false;
}

QWebSocket* SubscribeHandler::getSocketClient()
{
    return p_client;
}

QString SubscribeHandler::getSubscriptionNotificationJson(QString signalValue)
{
    QJsonObject jsonObject;
    jsonObject.insert("action", "subscribing");
    jsonObject.insert("subscriptionId", m_subId);
    jsonObject.insert("value", signalValue);
    jsonObject.insert("timestamp", QString::number(QDateTime::currentDateTime().toTime_t() ));

    QJsonDocument jsonDoc(jsonObject);
    return jsonDoc.toJson();
}

QString SubscribeHandler::getSubscriptionSuccessJson()
{
    QJsonObject jsonObject;
    jsonObject.insert("action", "subscribe");
    jsonObject.insert("requestId", p_vissrequest->getRequestId());
    jsonObject.insert("subscriptionId", m_subId);
    jsonObject.insert("timestamp", QString::number(QDateTime::currentDateTime().toTime_t() ));

    QJsonDocument jsonDoc(jsonObject);
    return jsonDoc.toJson();
}

bool SubscribeHandler::isFilterPass(QString valueString)
{
    int value = valueString.toInt();
    int diff = abs(value - m_lastValue);
    m_lastValue = value;
/*
    qDebug() << " isFilterPass(): value = " << value << " isFilterPass(): diff = " << diff;;

    qDebug() << " isFilterPass(): m_filter.rangeMin = " << m_filter.rangeMin
             << " isFilterPass(): m_filter.rangeMax = " << m_filter.rangeMax
             << " isFilterPass(): m_filter.minChange = " << m_filter.minChange;
*/
    //Check whether value is within range and from last value is big enough
    return ((value >= m_filter.rangeMin) &&
            (value <= m_filter.rangeMax) &&
            (diff >= m_filter.minChange));
}

void SubscribeHandler::initializeFilter()
{
    qDebug() << "initializeFilter(): Enter";
    qDebug() << "std::numeric_limits<int>::max() = " << std::numeric_limits<int>::max();
    qDebug() << "m_defaultIntervalMs = " << m_defaultIntervalMs;

    m_filter.intervalMs = m_defaultIntervalMs;

    qDebug() << "m_filter.intervalMs = " << m_filter.intervalMs;

    m_filter.rangeMin = 0;
    m_filter.rangeMax = std::numeric_limits<int>::max();
    m_filter.minChange = 0;

    //Parse filter from request
    QJsonObject jsonObject = p_vissrequest->getJsonObject();

    qDebug() << "jsonObject = " << jsonObject;
    qDebug() << "jsonObject[filters] = " << jsonObject["filters"];
    qDebug() << "jsonObject[filters].isUndefined() = " << jsonObject["filters"].isUndefined();

    //First, check that filter is included in the request
    if(!jsonObject["filters"].isUndefined())
    {
        qDebug() << "initializeFilter(): filters found";

        //Filter can be one or more tags, where supported tags are:
        //
        // "interval" , for example:
        //          "filters": { "interval": 100 }
        //
        // "range" , for example:
        //          "filters": { "range": { "above": 100, "below": 200 } }
        //          "filters": { "range": { "below": 100 } }
        //
        // "minChange" , for example:
        //          "filters": { "minChange": 100 }
        //          "filters": { "range": { "below": 200 }, "minChange": 20}

        QJsonObject filterList = jsonObject["filters"].toObject();

        // Handle interval
        if(!filterList["interval"].isUndefined())
        {
            m_filter.intervalMs = filterList["interval"].toInt();

            qDebug() << "initializeFilter(): interval = " << m_filter.intervalMs;
        }

        // Handle range
        if(!filterList["range"].isUndefined())
        {
            qDebug() << "initializeFilter(): range found";

            // Range can consist of "above", "below" or both
            QJsonObject range = filterList["range"].toObject();

            if(!range["above"].isUndefined())
            {
                m_filter.rangeMin = range["above"].toInt();

                qDebug() << "initializeFilter(): above = " << m_filter.rangeMin;
            }
            if(!range["below"].isUndefined())
            {
                m_filter.rangeMax = range["below"].toInt();

                qDebug() << "initializeFilter(): below = " << m_filter.rangeMax;
            }
        }

        // Handle minchange
        if(!filterList["minChange"].isUndefined())
        {
            m_filter.minChange = filterList["minChange"].toInt();

            qDebug() << "initializeFilter(): minChange = " << m_filter.minChange;
        }

        /*
        QJsonObject::const_iterator it;
        for (it = filterList.constBegin(); it != filterList.constEnd(); it++)
        {
          QString filter = it;
        }
         */

    }
}

QString SubscribeHandler::getSignalValue(QString path)
{
    //Dummy function, just return a random number 0 - 320
    (void)path;
    return QString::number(qrand() % 320);
}

<commit_msg>Filter implemented.<commit_after>/**************************************************************************************************************
* Copyright (C) *   2017, peterwinzell
*
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.*
*
*
***************************************************************************************************************/
#include <QThread>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDateTime>
#include "subscribehandler.h"
#include "subscriptions.h"

const int SubscribeHandler::m_defaultIntervalMs = 1000;

SubscribeHandler::SubscribeHandler(QObject* parent,VISSRequest* vissrequest,QWebSocket *client):
    RequestHandler(parent,vissrequest,client),m_dosubscription(true)
{
}

void SubscribeHandler::processRequest()
{
    connect(p_client, &QWebSocket::disconnected, this, &SubscribeHandler::socketDisconnected);

    //Add to subscriptions and store subscriptions ID
    Subscriptions* subscriptions = Subscriptions::getInstance();
    m_subId = subscriptions -> addSubcription(this);

    qDebug() << " processing get handler requests";

    //Setup filter params
    initializeFilter();

    //Send subscription response
    //Format response on JSON format
    QString successMessage = getSubscriptionSuccessJson();

    //Send message to client
    p_client->sendTextMessage(successMessage);

    while (m_dosubscription)
    {
        //Get latest value of subscribed signal
        QString value = getSignalValue(p_vissrequest->getSignalPath());

        if (isFilterPass(value))
        {
            m_lastValue = value.toInt();

            //Format response on JSON format
            QString message = getSubscriptionNotificationJson(value);

            qDebug() << "Sending message:" << message;

            //Send message to client
            p_client->sendTextMessage(message);
        }

        //Sleep for the period defined by filter
        QThread::currentThread()->msleep(m_filter.intervalMs);
    }

    qDebug() << " subscription cancelled ";
}

void SubscribeHandler::socketDisconnected()
{
    m_dosubscription = false;
}

void SubscribeHandler::unsubscribe()
{
    m_dosubscription = false;
}

QWebSocket* SubscribeHandler::getSocketClient()
{
    return p_client;
}

QString SubscribeHandler::getSubscriptionNotificationJson(QString signalValue)
{
    QJsonObject jsonObject;
    jsonObject.insert("action", "subscribing");
    jsonObject.insert("subscriptionId", m_subId);
    jsonObject.insert("value", signalValue);
    jsonObject.insert("timestamp", QString::number(QDateTime::currentDateTime().toTime_t() ));

    QJsonDocument jsonDoc(jsonObject);
    return jsonDoc.toJson();
}

QString SubscribeHandler::getSubscriptionSuccessJson()
{
    QJsonObject jsonObject;
    jsonObject.insert("action", "subscribe");
    jsonObject.insert("requestId", p_vissrequest->getRequestId());
    jsonObject.insert("subscriptionId", m_subId);
    jsonObject.insert("timestamp", QString::number(QDateTime::currentDateTime().toTime_t() ));

    QJsonDocument jsonDoc(jsonObject);
    return jsonDoc.toJson();
}

bool SubscribeHandler::isFilterPass(QString valueString)
{
    int value = valueString.toInt();
    int diff = abs(value - m_lastValue);

    //Check whether value is within range and from last value is big enough
    return ((value >= m_filter.rangeMin) &&
            (value <= m_filter.rangeMax) &&
            (diff >= m_filter.minChange));
}

void SubscribeHandler::initializeFilter()
{
    qDebug() << "initializeFilter(): Enter";

    m_filter.intervalMs = m_defaultIntervalMs;
    m_filter.rangeMin = 0;
    m_filter.rangeMax = std::numeric_limits<int>::max();
    m_filter.minChange = 0;
    m_lastValue = 0;

    //Parse filter from request
    QJsonObject jsonObject = p_vissrequest->getJsonObject();

    //First, check that filter is included in the request
    if(!jsonObject["filters"].isNull())
    {
        qDebug() << "initializeFilter(): filters found";

        //Filter can be one or more tags, where supported tags are:
        //
        // "interval" , for example:
        //          "filters": { "interval": 100 }
        //
        // "range" , for example:
        //          "filters": { "range": { "above": 100, "below": 200 } }
        //          "filters": { "range": { "below": 100 } }
        //
        // "minChange" , for example:
        //          "filters": { "minChange": 100 }
        //          "filters": { "range": { "below": 200 }, "minChange": 20}

        QJsonObject filterList = jsonObject["filters"].toObject();

        // Handle interval
        if(!filterList["interval"].isNull())
        {
            m_filter.intervalMs = filterList["interval"].toString().toInt();

            qDebug() << "initializeFilter(): interval = " << m_filter.intervalMs;
        }

        // Handle range
        if(!filterList["range"].isNull())
        {
            qDebug() << "initializeFilter(): range found";

            // Range can consist of "above", "below" or both
            QJsonObject range = filterList["range"].toObject();

            if(!range["above"].isNull())
            {
                m_filter.rangeMin = range["above"].toString().toInt();

                qDebug() << "initializeFilter(): above = " << m_filter.rangeMin;
            }
            if(!range["below"].isNull())
            {
                m_filter.rangeMax = range["below"].toString().toInt();

                qDebug() << "initializeFilter(): below = " << m_filter.rangeMax;
            }
        }

        // Handle minchange
        if(!filterList["minChange"].isNull())
        {
            m_filter.minChange = filterList["minChange"].toString().toInt();

            qDebug() << "initializeFilter(): minChange = " << m_filter.minChange;
        }
    }
}

QString SubscribeHandler::getSignalValue(QString path)
{
    //Dummy function, just return a random number 0 - 320
    (void)path;
    return QString::number(qrand() % 320);
}

<|endoftext|>


<commit_before>/* +---------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)               |
   |                          http://www.mrpt.org/                             |
   |                                                                           |
   | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file        |
   | See: http://www.mrpt.org/Authors - All rights reserved.                   |
   | Released under BSD License. See details in http://www.mrpt.org/License    |
   +---------------------------------------------------------------------------+ */

#include "base-precomp.h"  // Precompiled headers

#include <mrpt/utils/CObject.h>

#include <map>
#include <cstdarg>
#include <mutex>
#include <atomic>

#include "internal_class_registry.h"

using namespace mrpt;
using namespace mrpt::utils;
using namespace mrpt::synch;
using namespace mrpt::system;
using namespace std;

/*---------------------------------------------------------------
					STATIC GLOBAL VARIABLES
 ---------------------------------------------------------------*/
volatile bool mrpt::utils::pending_class_registers_modified = false;

// Creation on first call pattern:
CAtomicCounter	& mrpt::utils::pending_class_registers_count()
{
	static CAtomicCounter cnt(0);
	return cnt;
}

// Creation on first call pattern:
CThreadSafeQueue<TRegisterFunction>	 &mrpt::utils::pending_class_registers()
{
	pending_class_registers_modified = true;
	static CThreadSafeQueue<TRegisterFunction> lst;
	return lst;
}

namespace mrpt
{
	namespace utils
	{
		typedef std::map<std::string,const TRuntimeClassId*> TClassnameToRuntimeId;

		/** A singleton with the central registry for CSerializable run-time classes: users do not use this class in any direct way.
	      * \note Class is thread-safe.
		  */
		class BASE_IMPEXP CClassRegistry
		{
		public:
			/**  The unique access point point to the singleton instance.
			  */
			static CClassRegistry& Instance()
			{
				static CClassRegistry obj;
				return obj;
			}

			void Add( const std::string &className, const TRuntimeClassId &id )
			{
				m_being_modified=true;
				{
					std::unique_lock<std::mutex> lk(m_cs);

					// Sanity check: don't allow registering twice the same class name!
					const auto it = registeredClasses.find(className);
					if (it != registeredClasses.cend()) {
						if (it->second != &id) {
							THROW_EXCEPTION_FMT("[MRPT class registry] Error: trying to register twice className=`%s` with different `TRuntimeClassId`!", className.c_str());
						}
					}
					registeredClasses[className] = &id;
				}
				m_being_modified=false;
			}

			const TRuntimeClassId *Get(const std::string &className)
			{
				// Optimization to avoid the costly lock() in virtually all situations:
				bool has_to_unlock = false;
				if (m_being_modified)
				{
					m_cs.lock();
					has_to_unlock = true;
				}
				const TRuntimeClassId *ret = registeredClasses[className];
				if (has_to_unlock) m_cs.unlock();
				return ret;
			}

			std::vector<const TRuntimeClassId*> getListOfAllRegisteredClasses()
			{
				std::unique_lock<std::mutex> lk(m_cs);

				std::vector<const TRuntimeClassId*> ret;
				for (TClassnameToRuntimeId::iterator it=registeredClasses.begin();it!=registeredClasses.end();++it)
					ret.push_back( it->second );
				return ret;
			}

		private:
			// PRIVATE constructor
			CClassRegistry() : m_being_modified(false)
			{
			}
			// PRIVATE destructor
			~CClassRegistry() { }

			// This must be static since we can be called from C startup
			// functions and it cannot be assured that classesKeeper will be
			// initialized before other classes that call it...
			TClassnameToRuntimeId			registeredClasses;
			std::mutex        m_cs;
			std::atomic<bool> m_being_modified;

		};

	}	// End of namespace
}	// End of namespace

/** Register all pending classes - to be called just before de-serializing an object, for example.
*/
void mrpt::utils::registerAllPendingClasses()
{
	if (!pending_class_registers_modified) return; // Quick return

	while( pending_class_registers_count()!=0 )
	{
		TRegisterFunction *ptrToPtr = pending_class_registers().get();
		--pending_class_registers_count();

		// Call it:
		if((*ptrToPtr)!=NULL)
		{
			(*(*ptrToPtr)) ();
			delete ptrToPtr;
		}
	}
	pending_class_registers_modified = false;
}

/*---------------------------------------------------------------
					RegisterClass
 ---------------------------------------------------------------*/
void utils::registerClass(const TRuntimeClassId* pNewClass)
{
	// Register it:
	CClassRegistry::Instance().Add( std::string( pNewClass->className ), *pNewClass);

	// Automatically register all classes when the first one is registered.
	registerAllPendingClasses();
}

/** For internal use within mrpt sources, and only in exceptional cases (CMultiMetricMaps, CImage,...)
  */
void utils::registerClassCustomName(const char*customName, const TRuntimeClassId* pNewClass)
{
	// Register it:
	CClassRegistry::Instance().Add( customName, *pNewClass);

	// Automatically register all classes when the first one is registered.
	registerAllPendingClasses();
}

/*---------------------------------------------------------------
					getAllRegisteredClasses
 ---------------------------------------------------------------*/
std::vector<const TRuntimeClassId*> utils::getAllRegisteredClasses()
{
	return CClassRegistry::Instance().getListOfAllRegisteredClasses();
}

std::vector<const TRuntimeClassId*> utils::getAllRegisteredClassesChildrenOf(const TRuntimeClassId* parent_id)
{
	std::vector<const TRuntimeClassId*> res;
	const auto lst = mrpt::utils::getAllRegisteredClasses();
	for (const auto &c : lst) {
		if (c->derivedFrom(parent_id) && c!=parent_id) {
			res.push_back(c);
		}
	}
	return res;
}

/*---------------------------------------------------------------
					findRegisteredClass
 ---------------------------------------------------------------*/
const TRuntimeClassId *mrpt::utils::findRegisteredClass(const std::string &className)
{
	return CClassRegistry::Instance().Get( className );
}

<commit_msg>error to warning<commit_after>/* +---------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)               |
   |                          http://www.mrpt.org/                             |
   |                                                                           |
   | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file        |
   | See: http://www.mrpt.org/Authors - All rights reserved.                   |
   | Released under BSD License. See details in http://www.mrpt.org/License    |
   +---------------------------------------------------------------------------+ */

#include "base-precomp.h"  // Precompiled headers

#include <mrpt/utils/CObject.h>

#include <map>
#include <cstdarg>
#include <mutex>
#include <atomic>
#include <iostream>

#include "internal_class_registry.h"

using namespace mrpt;
using namespace mrpt::utils;
using namespace mrpt::synch;
using namespace mrpt::system;
using namespace std;

/*---------------------------------------------------------------
					STATIC GLOBAL VARIABLES
 ---------------------------------------------------------------*/
volatile bool mrpt::utils::pending_class_registers_modified = false;

// Creation on first call pattern:
CAtomicCounter	& mrpt::utils::pending_class_registers_count()
{
	static CAtomicCounter cnt(0);
	return cnt;
}

// Creation on first call pattern:
CThreadSafeQueue<TRegisterFunction>	 &mrpt::utils::pending_class_registers()
{
	pending_class_registers_modified = true;
	static CThreadSafeQueue<TRegisterFunction> lst;
	return lst;
}

namespace mrpt
{
	namespace utils
	{
		typedef std::map<std::string,const TRuntimeClassId*> TClassnameToRuntimeId;

		/** A singleton with the central registry for CSerializable run-time classes: users do not use this class in any direct way.
	      * \note Class is thread-safe.
		  */
		class BASE_IMPEXP CClassRegistry
		{
		public:
			/**  The unique access point point to the singleton instance.
			  */
			static CClassRegistry& Instance()
			{
				static CClassRegistry obj;
				return obj;
			}

			void Add( const std::string &className, const TRuntimeClassId &id )
			{
				m_being_modified=true;
				{
					std::unique_lock<std::mutex> lk(m_cs);

					// Sanity check: don't allow registering twice the same class name!
					const auto it = registeredClasses.find(className);
					if (it != registeredClasses.cend()) {
						if (it->second != &id) {
							std::cerr << mrpt::format("[MRPT class registry] Warning: overwriting already registered className=`%s` with different `TRuntimeClassId`!\n", className.c_str());
						}
					}
					registeredClasses[className] = &id;
				}
				m_being_modified=false;
			}

			const TRuntimeClassId *Get(const std::string &className)
			{
				// Optimization to avoid the costly lock() in virtually all situations:
				bool has_to_unlock = false;
				if (m_being_modified)
				{
					m_cs.lock();
					has_to_unlock = true;
				}
				const TRuntimeClassId *ret = registeredClasses[className];
				if (has_to_unlock) m_cs.unlock();
				return ret;
			}

			std::vector<const TRuntimeClassId*> getListOfAllRegisteredClasses()
			{
				std::unique_lock<std::mutex> lk(m_cs);

				std::vector<const TRuntimeClassId*> ret;
				for (TClassnameToRuntimeId::iterator it=registeredClasses.begin();it!=registeredClasses.end();++it)
					ret.push_back( it->second );
				return ret;
			}

		private:
			// PRIVATE constructor
			CClassRegistry() : m_being_modified(false)
			{
			}
			// PRIVATE destructor
			~CClassRegistry() { }

			// This must be static since we can be called from C startup
			// functions and it cannot be assured that classesKeeper will be
			// initialized before other classes that call it...
			TClassnameToRuntimeId			registeredClasses;
			std::mutex        m_cs;
			std::atomic<bool> m_being_modified;

		};

	}	// End of namespace
}	// End of namespace

/** Register all pending classes - to be called just before de-serializing an object, for example.
*/
void mrpt::utils::registerAllPendingClasses()
{
	if (!pending_class_registers_modified) return; // Quick return

	while( pending_class_registers_count()!=0 )
	{
		TRegisterFunction *ptrToPtr = pending_class_registers().get();
		--pending_class_registers_count();

		// Call it:
		if((*ptrToPtr)!=NULL)
		{
			(*(*ptrToPtr)) ();
			delete ptrToPtr;
		}
	}
	pending_class_registers_modified = false;
}

/*---------------------------------------------------------------
					RegisterClass
 ---------------------------------------------------------------*/
void utils::registerClass(const TRuntimeClassId* pNewClass)
{
	// Register it:
	CClassRegistry::Instance().Add( std::string( pNewClass->className ), *pNewClass);

	// Automatically register all classes when the first one is registered.
	registerAllPendingClasses();
}

/** For internal use within mrpt sources, and only in exceptional cases (CMultiMetricMaps, CImage,...)
  */
void utils::registerClassCustomName(const char*customName, const TRuntimeClassId* pNewClass)
{
	// Register it:
	CClassRegistry::Instance().Add( customName, *pNewClass);

	// Automatically register all classes when the first one is registered.
	registerAllPendingClasses();
}

/*---------------------------------------------------------------
					getAllRegisteredClasses
 ---------------------------------------------------------------*/
std::vector<const TRuntimeClassId*> utils::getAllRegisteredClasses()
{
	return CClassRegistry::Instance().getListOfAllRegisteredClasses();
}

std::vector<const TRuntimeClassId*> utils::getAllRegisteredClassesChildrenOf(const TRuntimeClassId* parent_id)
{
	std::vector<const TRuntimeClassId*> res;
	const auto lst = mrpt::utils::getAllRegisteredClasses();
	for (const auto &c : lst) {
		if (c->derivedFrom(parent_id) && c!=parent_id) {
			res.push_back(c);
		}
	}
	return res;
}

/*---------------------------------------------------------------
					findRegisteredClass
 ---------------------------------------------------------------*/
const TRuntimeClassId *mrpt::utils::findRegisteredClass(const std::string &className)
{
	return CClassRegistry::Instance().Get( className );
}
<|endoftext|>


<commit_before>#include <stack>
#include <string>
#include <string.h>

using namespace std;

bool IsOp(const char ch)
{
	return ch == '+' || ch == '-' || ch == '*' || ch == '/';
}
bool IsOp(const string &str)
{
	return str == "+" || str == "-" || str == "*" || str == "/";
}
bool IsEqualOrGreat(char ch1, char ch2)
{
	if(ch1 == '+' || ch1 == '-')
	{
		if(ch2 == '+' || ch2 == '-')
		{
			return true;
		}
		return false;
	}
	return true;
}

void CalculatePrefix(stack<string> &prefix)
{
	stack<int> cal;
	while(prefix.empty() == false)
	{
		string str = prefix.top();
		prefix.pop();
		if(IsOp(str) == false)
		{
			cal.push(atoi(str.data()));
		}
		else
		{
			int lhs = cal.top();
			cal.pop();
			int rhs = cal.top();
			cal.pop();
			switch(*str.data())
			{
			case '+':
				lhs += rhs;
				break;
			case '-':
				lhs -= rhs;
				break;
			case '*':
				lhs *= rhs;
				break;
			case '/':
				lhs /= rhs;
			}
			cal.push(lhs);
		}
	}
	printf("\nResult is: %d\n", cal.top());
}
void InfixToPrefix(const char *infix)
{
	stack<char> op;
	stack<string> prefix;
	int input_size = static_cast<int>(strlen(infix));
	for(int index = input_size - 1; index >= 0; )
	{
		if(isdigit(infix[index]))
		{
			int begin_index = index - 1;
			for(; begin_index >= 0 && isdigit(infix[begin_index]); --begin_index);
			if(begin_index < 0)
			{
				prefix.push(string(infix, index + 1));
				break;
			}
			else if(begin_index == 0)
			{
				if(infix[0] != '-')
				{
					prefix.push(string(infix + 1, index));
					index = 0;
				}
				else
				{
					prefix.push(string(infix, index + 1));
					break;
				}
			}
			else
			{
				if(IsOp(infix[begin_index - 1]) && infix[begin_index] == '-')
				{
					prefix.push(string(infix + begin_index, index - begin_index + 1));
					index = begin_index - 1;
				}
				else
				{
					prefix.push(string(infix + begin_index + 1, index - begin_index));
					index = begin_index;
				}
			}
		}
		else if(IsOp(infix[index]))
		{
			if(op.empty() == true || op.top() == ')' || IsEqualOrGreat(infix[index], op.top()))
			{
				op.push(infix[index]);
				--index;
			}
			else
			{
				prefix.push(string(&op.top(), 1));
				op.pop();
				continue;
			}
		}
		else
		{
			if(infix[index] == ')')
			{
				op.push(infix[index]);
			}
			else
			{
				while(op.top() != ')')
				{
					prefix.push(string(&op.top(), 1));
					op.pop();
				}
				op.pop();
			}
			--index;
		}
	}
	while(op.empty() == false)
	{
		prefix.push(string(&op.top(), 1));
		op.pop();
	}
	stack<string> temp;
	printf("Prefix is: ");
	while(prefix.empty() == false)
	{
		temp.push(prefix.top());
		printf("%s,", prefix.top().data());
		prefix.pop();
	}
	CalculatePrefix(temp);
}

int main()
{
	const int kInputSize = 1024;
	char infix[kInputSize];
	while(scanf("%s", infix) == 1)
	{
		InfixToPrefix(infix);
	}
}
/*
-23+((4+56)*78)+-5+6*-78+123
**********************************
Prefix is: +,+,+,+,-23,*,+,4,56,78,-5,*,6,-78,123,
Result is: 4307
*/
<commit_msg>feat: impl GetValueOfInfix<commit_after>#include <stack>
#include <string>
#include <string.h>

using namespace std;

bool IsOp(const char ch)
{
	return ch == '+' || ch == '-' || ch == '*' || ch == '/';
}
bool IsOp(const string &str)
{
	return str == "+" || str == "-" || str == "*" || str == "/";
}
bool IsEqualOrGreat(char ch1, char ch2)
{
	if(ch1 == '+' || ch1 == '-')
	{
		if(ch2 == '+' || ch2 == '-')
		{
			return true;
		}
		return false;
	}
	return true;
}
void CalculatePrefix(stack<string> &prefix)
{
	stack<int> cal;
	while(prefix.empty() == false)
	{
		string str = prefix.top();
		prefix.pop();
		if(IsOp(str) == false)
		{
			cal.push(atoi(str.data()));
		}
		else
		{
			int lhs = cal.top();
			cal.pop();
			int rhs = cal.top();
			cal.pop();
			switch(*str.data())
			{
			case '+':
				lhs += rhs;
				break;
			case '-':
				lhs -= rhs;
				break;
			case '*':
				lhs *= rhs;
				break;
			case '/':
				lhs /= rhs;
			}
			cal.push(lhs);
		}
	}
	printf("\nResult is: %d\n", cal.top());
}
void InfixToPrefix(const char *infix)
{
	stack<char> op;
	stack<string> prefix;
	int input_size = static_cast<int>(strlen(infix));
	for(int index = input_size - 1; index >= 0; )
	{
		if(isdigit(infix[index]))
		{
			int begin_index = index - 1;
			for(; begin_index >= 0 && isdigit(infix[begin_index]); --begin_index);
			if(begin_index < 0)
			{
				prefix.push(string(infix, index + 1));
				break;
			}
			else if(begin_index == 0)
			{
				if(infix[0] != '-')
				{
					prefix.push(string(infix + 1, index));
					index = 0;
				}
				else
				{
					prefix.push(string(infix, index + 1));
					break;
				}
			}
			else
			{
				if(IsOp(infix[begin_index - 1]) && infix[begin_index] == '-')
				{
					prefix.push(string(infix + begin_index, index - begin_index + 1));
					index = begin_index - 1;
				}
				else
				{
					prefix.push(string(infix + begin_index + 1, index - begin_index));
					index = begin_index;
				}
			}
		}
		else if(IsOp(infix[index]))
		{
			if(op.empty() == true || op.top() == ')' || IsEqualOrGreat(infix[index], op.top()))
			{
				op.push(infix[index]);
				--index;
			}
			else
			{
				prefix.push(string(&op.top(), 1));
				op.pop();
				continue;
			}
		}
		else
		{
			if(infix[index] == ')')
			{
				op.push(infix[index]);
			}
			else
			{
				while(op.top() != ')')
				{
					prefix.push(string(&op.top(), 1));
					op.pop();
				}
				op.pop();
			}
			--index;
		}
	}
	while(op.empty() == false)
	{
		prefix.push(string(&op.top(), 1));
		op.pop();
	}
	stack<string> temp;
	printf("Prefix is: ");
	while(prefix.empty() == false)
	{
		temp.push(prefix.top());
		printf("%s,", prefix.top().data());
		prefix.pop();
	}
	CalculatePrefix(temp);
}
/*

int main()
{
	const int kInputSize = 1024;
	char infix[kInputSize];
	while(scanf("%s", infix) == 1)
	{
		InfixToPrefix(infix);
	}
}
(-23)+(4+56)*78+(-5)+6*(-78)+123#
**********************************
Prefix is: +,+,+,+,-23,*,+,4,56,78,-5,*,6,-78,123,
Result is: 4307
*/

/*   数据结构分析与学习专栏
*   Copyright (c) 2015, 山东大学 计算机科学与技术专业 学生
*   All rights reserved.
*   作    者：   高祥
*   完成日期：  2015 年 4 月 5 日
*   版 本 号：011

*任务：使用栈实现表达式求值

*算法思想：判断运算符的优先级并执行相应的操作

*功能：
1.对负数、浮点数均有效
2.可进行多括号的复杂运算

*主要函数：
*   1.void InitNumberStack(Number &NumberStack);//初始化数字栈
*   2.void InitOperatorStack(Operator &OperatorStack);//初始化运算符栈
*   3.void NumberPush(Number &NumberStack,double number);//压入数字栈
*   4.void NumberPop(Number &NumberStack);//弹出数字栈
*   5.void OperatorPush(Operator &OperatorStack,char op);//压入运算符栈
*   6.void OperatorPop(Operator &OperatorStack);//弹出运算符栈
*   7.char GetTopOperator(Operator &OperatorStack);//得到运算符栈栈顶元素
*   8.double GetTopNumber(Number &NumberStack);//得到数字栈栈顶元素
*   9.double ToNumber(string s);//字符串转换成数字函数
*   10.char Precede(char stacktop,char willpush);//判断运算符的优先级
*   11.double calculate(double a,double b,char op);//计算
*   12.int IsDigit(char ch);//判断字符是否为数字

*运行示例：
请输入运算表达式（表达时应当合法且不含空格且负数必须使用括号括起来且以‘#’结尾，仅输入‘#’表示退出）：
1+2-3+4-5#
运算结果为：-1
请输入运算表达式（表达时应当合法且不含空格且负数必须使用括号括起来且以‘#’结尾，仅输入‘#’表示退出）：
1.23+3.45-6.78+9.01#
运算结果为：6.91
请输入运算表达式（表达时应当合法且不含空格且负数必须使用括号括起来且以‘#’结尾，仅输入‘#’表示退出）：
1+2*3+4/5-6#
运算结果为：1.8
请输入运算表达式（表达时应当合法且不含空格且负数必须使用括号括起来且以‘#’结尾，仅输入‘#’表示退出）：
1+((-3)*3+7.2*5/9)/((-4)*6+25-7/2)+23.9#
运算结果为：26.9
请输入运算表达式（表达时应当合法且不含空格且负数必须使用括号括起来且以‘#’结尾，仅输入‘#’表示退出）：
#

*/
#include<iostream>
#include<cstdlib>
using namespace std;

#define MAXSIZE 100

typedef struct
{
	double *top;
	double *base;
} Number; //数字栈类型

typedef struct
{
	char *top;
	char *base;
} Operator;//运算符栈类型

void InitNumberStack(Number &NumberStack);//初始化数字栈
void InitOperatorStack(Operator &OperatorStack);//初始化运算符栈
void NumberPush(Number &NumberStack,double number);//压入数字栈
void  NumberPop(Number &NumberStack);//弹出数字栈
void OperatorPush(Operator &OperatorStack,char op);//压入运算符栈
void OperatorPop(Operator &OperatorStack);//弹出运算符栈
char GetTopOperator(Operator &OperatorStack);//得到运算符栈栈顶元素
double GetTopNumber(Number &NumberStack);//得到数字栈栈顶元素
double ToNumber(string s);//字符串转换成数字函数
char Precede(char stacktop,char willpush);//判断运算符的优先级
double calculate(double a,double b,char op);//计算
int IsDigit(char ch);//判断字符是否为数字

int main()
{
	string str;
	cout<<"请输入运算表达式（表达时应当合法且不含空格且负数必须使用括号括起来且以‘#’结尾，仅输入‘#’表示退出）：\n";

	while(getline(cin,str)&&str!="#")
	{
		Operator OperatorStack;
		Number NumberStack;

		InitNumberStack(NumberStack);//初始化两个栈
		InitOperatorStack(OperatorStack);

		OperatorPush(OperatorStack,'#');//运算符栈中预存一个‘#’便于判断运算符的优先级

		for(int i=0; i<static_cast<int>(str.size()); i++)//遍历表达式
		{
			if(IsDigit(str[i]))//若当前字符为数字，将该数字全部截取出来
			{
				int j=i;//数字字符串的起点索引

				while(i<str.size()&&(IsDigit(str[i])||str[i]=='.'))
					//当不越界且字符为数字或小数点时，数字字符串未结束
				{
					i++;
				}
				//利用转换函数将截取的数字字符串转换为数字并压入数字栈中
				NumberPush(NumberStack,ToNumber(str.substr(j,i-j)));
				i--;//索引减1
			}
			else if(str[i]=='('&&str[i+1]=='-')//若遇到负数
			{
				int j=i;

				i++;//细节
				while(i<str.size()&&(IsDigit(str[i])||str[i]=='.'||str[i]=='-'||str[i]==')'))
					//注意连同负数的左右括号一同截取，防止对后续的判断造成影响
				{
					i++;
				}
				NumberPush(NumberStack,ToNumber(str.substr(j,i-j)));
				i--;
			}
			else//不是数字
			{
				switch(Precede(GetTopOperator(OperatorStack),str[i]))
					//Precede函数判断运算符栈栈顶运算符和将要压入的运算符的优先级，以此来决定操作
				{
				case '<'://栈顶运算符优先级低
					OperatorPush(OperatorStack,str[i]);//压入优先级高的运算符
					break;
				case '='://优先级相同：表明括号内运算完成
					OperatorPop(OperatorStack);//弹出栈顶的括号
					break;
				case '>'://栈顶运算符优先级高：执行栈顶运算符代表的运算
					char op=GetTopOperator(OperatorStack);//得到栈顶运算符
					OperatorPop(OperatorStack);//删除运算符栈栈顶运算符

					double b=GetTopNumber(NumberStack);//得到第二个运算数字，注意是后进先出
					NumberPop(NumberStack);//删除数字栈栈顶数字
					double a=GetTopNumber(NumberStack);//得到第一个运算数字
					NumberPop(NumberStack);//删除数字栈栈顶数字
					NumberPush(NumberStack,calculate(a,b,op));//执行运算并将结果压入数字栈

					i--;//推迟压入运算符栈中，避免运算符栈内出现能运算但未运算的运算符
					break;
				}
			}
		}

		cout<<"运算结果为："<<GetTopNumber(NumberStack)<<endl;
		cout<<"请输入运算表达式（表达时应当合法且不含空格且负数必须使用括号括起来且以‘#’结尾，仅输入‘#’表示退出）：\n";
	}
	return 0;
}

double ToNumber(string s)//字符串转换成数字函数
{
	string s1;//去掉括号的部分
	if(s[0]=='(')
	{
		s1=s.substr(2,s.size()-3);
	}
	else
	{
		s1=s;
	}

	double num=0.0;//返回值
	int i;
	for(i=0; i<s1.size(); i++)
	{
		if(s1[i]=='.')//整数部分转换完成
		{
			break;
		}
		num=num*10+s1[i]-'0';
	}

	//转换小数部分
	double j=0.1;
	for(i=i+1; i<s1.size(); i++)
	{
		num=num+(s1[i]-'0')*j;
		j=j*0.1;
	}

	if(s1==s)//非负数
	{
		return num;
	}
	return -1*num;//负数添负号再返回
}

char Precede(char stacktop,char willpush)//判断运算符的优先级
{
	switch(stacktop)
	{
	case '#':
		if(willpush=='#')
		{
			return '=';
		}
		return '<';

	case '+':
	case '-':
		if(willpush=='+'||willpush=='-'||willpush==')'||willpush=='#')
		{
			return '>';
		}
		return '<';

	case '*':
	case '/':
		if(willpush=='(')
		{
			return '<';
		}
		return '>';

	case '(':
		if(willpush==')')
		{
			return '=';
		}
		return '<';

	case ')':
		return '>';
	}
}

double calculate(double a,double b,char op)//计算
{
	switch(op)
	{
	case '+':
		return a+b;
	case '-':
		return a-b;
	case '*':
		return a*b;
	case '/':
		return a/b;
	}
}

void InitNumberStack(Number &NumberStack)//初始化数字栈
{
	NumberStack.base=(double*)malloc(MAXSIZE*sizeof(double));
	NumberStack.top=NumberStack.base;
}

void InitOperatorStack(Operator &OperatorStack)//初始化运算符栈
{
	OperatorStack.base=(char*)malloc(MAXSIZE*sizeof(char));
	OperatorStack.top=OperatorStack.base;
}

void NumberPush(Number &NumberStack,double number)//压入数字栈
{
	*NumberStack.top=number;
	NumberStack.top++;
}

void  NumberPop(Number &NumberStack)//弹出数字栈
{
	NumberStack.top--;
}

void OperatorPush(Operator &OperatorStack,char op)//压入运算符栈
{
	*OperatorStack.top=op;
	OperatorStack.top++;
}

void OperatorPop(Operator &OperatorStack)//弹出运算符栈
{
	OperatorStack.top--;
}

char GetTopOperator(Operator &OperatorStack)//得到运算符栈栈顶元素
{
	return *(OperatorStack.top-1);
}

double GetTopNumber(Number &NumberStack)//得到数字栈栈顶元素
{
	return *(NumberStack.top-1);
}

int IsDigit(char ch)//判断字符是否为数字
{
	if(ch>='0'&&ch<='9')
	{
		return 1;
	}
	return 0;
}
<|endoftext|>