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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkComputeContourSetNormalsFilter.h"

#include "mitkImagePixelReadAccessor.h"

mitk::ComputeContourSetNormalsFilter::ComputeContourSetNormalsFilter()
{
  m_MaxSpacing = 5;
  this->m_UseProgressBar = false;
  this->m_ProgressStepSize = 1;

  mitk::Surface::Pointer output = mitk::Surface::New();
  this->SetNthOutput(0, output.GetPointer());
}

mitk::ComputeContourSetNormalsFilter::~ComputeContourSetNormalsFilter()
{
}

void mitk::ComputeContourSetNormalsFilter::GenerateData()
{
  unsigned int numberOfInputs = this->GetNumberOfIndexedInputs();
  this->CreateOutputsForAllInputs(numberOfInputs);

  //Iterating over each input
  for(unsigned int i = 0; i < numberOfInputs; i++)
  {
    //Getting the inputs polydata and polygons
    Surface* currentSurface = const_cast<Surface*>( this->GetInput(i) );
    vtkPolyData* polyData = currentSurface->GetVtkPolyData();

    vtkSmartPointer<vtkCellArray> existingPolys = polyData->GetPolys();

    vtkSmartPointer<vtkPoints> existingPoints = polyData->GetPoints();

    existingPolys->InitTraversal();

    vtkIdType* cell (NULL);
    vtkIdType cellSize (0);

    //The array that contains all the vertex normals of the current polygon
    vtkSmartPointer<vtkDoubleArray> normals = vtkSmartPointer<vtkDoubleArray>::New();
    normals->SetNumberOfComponents(3);
    normals->SetNumberOfTuples(polyData->GetNumberOfPoints());

    //If the current contour is an inner contour then the direction is -1
    //A contour lies inside another one if the pixel values in the direction of the normal is 1
    m_NegativeNormalCounter = 0;
    m_PositiveNormalCounter = 0;

    //Iterating over each polygon
    for( existingPolys->InitTraversal(); existingPolys->GetNextCell(cellSize, cell);)
    {
      if(cellSize < 3)continue;

      //First we calculate the current polygon's normal
      double polygonNormal[3] = {0.0};

      double p1[3];
      double p2[3];

      double v1[3];
      double v2[3];

      existingPoints->GetPoint(cell[0], p1);
      unsigned int index = cellSize*0.5;
      existingPoints->GetPoint(cell[index], p2);

      v1[0] = p2[0]-p1[0];
      v1[1] = p2[1]-p1[1];
      v1[2] = p2[2]-p1[2];

      for (unsigned int k = 2; k < cellSize; k++)
      {
        index = cellSize*0.25;
        existingPoints->GetPoint(cell[index], p1);
        index = cellSize*0.75;
        existingPoints->GetPoint(cell[index], p2);

        v2[0] = p2[0]-p1[0];
        v2[1] = p2[1]-p1[1];
        v2[2] = p2[2]-p1[2];

        vtkMath::Cross(v1,v2,polygonNormal);
        if (vtkMath::Norm(polygonNormal) != 0)
          break;
      }

      vtkMath::Normalize(polygonNormal);

      //Now we start computing the normal for each vertex

      double vertexNormalTemp[3];
      existingPoints->GetPoint(cell[0], p1);
      existingPoints->GetPoint(cell[1], p2);

      v1[0] = p2[0]-p1[0];
      v1[1] = p2[1]-p1[1];
      v1[2] = p2[2]-p1[2];

      vtkMath::Cross(v1,polygonNormal,vertexNormalTemp);

      vtkMath::Normalize(vertexNormalTemp);

      double vertexNormal[3];

      for (unsigned j = 0; j < cellSize-2; j++)
      {
        existingPoints->GetPoint(cell[j+1], p1);
        existingPoints->GetPoint(cell[j+2], p2);

        v1[0] = p2[0]-p1[0];
        v1[1] = p2[1]-p1[1];
        v1[2] = p2[2]-p1[2];

        vtkMath::Cross(v1,polygonNormal,vertexNormal);

        vtkMath::Normalize(vertexNormal);

        double finalNormal[3];

        finalNormal[0] = (vertexNormal[0] + vertexNormalTemp[0])*0.5;
        finalNormal[1] = (vertexNormal[1] + vertexNormalTemp[1])*0.5;
        finalNormal[2] = (vertexNormal[2] + vertexNormalTemp[2])*0.5;

        //Here we determine the direction of the normal
        if (j == 0 && m_SegmentationBinaryImage)
        {
          Point3D worldCoord;
          worldCoord[0] = p1[0]+finalNormal[0]*m_MaxSpacing;
          worldCoord[1] = p1[1]+finalNormal[1]*m_MaxSpacing;
          worldCoord[2] = p1[2]+finalNormal[2]*m_MaxSpacing;

          double val = 0.0;
          mitk::ImagePixelReadAccessor<unsigned char> readAccess(m_SegmentationBinaryImage);
          val = readAccess.GetPixelByWorldCoordinates(worldCoord);

          if (val == 1.0)
          {
              ++m_PositiveNormalCounter;
          }
          else
          {
              ++m_NegativeNormalCounter;
          }
        }

        vertexNormalTemp[0] = vertexNormal[0];
        vertexNormalTemp[1] = vertexNormal[1];
        vertexNormalTemp[2] = vertexNormal[2];

        vtkIdType id = cell[j+1];
        normals->SetTuple(id,finalNormal);
      }

      existingPoints->GetPoint(cell[0], p1);
      existingPoints->GetPoint(cell[1], p2);

      v1[0] = p2[0]-p1[0];
      v1[1] = p2[1]-p1[1];
      v1[2] = p2[2]-p1[2];

      vtkMath::Cross(v1,polygonNormal,vertexNormal);

      vtkMath::Normalize(vertexNormal);

      vertexNormal[0] = (vertexNormal[0] + vertexNormalTemp[0])*0.5;
      vertexNormal[1] = (vertexNormal[1] + vertexNormalTemp[1])*0.5;
      vertexNormal[2] = (vertexNormal[2] + vertexNormalTemp[2])*0.5;

      vtkIdType id = cell[0];
      normals->SetTuple(id,vertexNormal);
      id = cell[cellSize-1];
      normals->SetTuple(id,vertexNormal);

      int normalDirection(-1);

      if(m_NegativeNormalCounter < m_PositiveNormalCounter)
      {
          normalDirection = 1;
      }

      for(unsigned int n = 0; n < normals->GetNumberOfTuples(); n++)
      {
          double normal[3];
          normals->GetTuple(n,normal);
          normal[0] = normalDirection*normal[0];
          normal[1] = normalDirection*normal[1];
          normal[2] = normalDirection*normal[2];
      }

    }//end for all cells

    Surface::Pointer surface = this->GetOutput(i);
    surface->GetVtkPolyData()->GetCellData()->SetNormals(normals);
  }//end for all inputs

  //Setting progressbar
  if (this->m_UseProgressBar)
    mitk::ProgressBar::GetInstance()->Progress(this->m_ProgressStepSize);
}

mitk::Surface::Pointer mitk::ComputeContourSetNormalsFilter::GetNormalsAsSurface()
{
  //Just for debugging:
  vtkSmartPointer<vtkPolyData> newPolyData = vtkSmartPointer<vtkPolyData>::New();
  vtkSmartPointer<vtkCellArray> newLines = vtkSmartPointer<vtkCellArray>::New();
  vtkSmartPointer<vtkPoints> newPoints = vtkSmartPointer<vtkPoints>::New();
  unsigned int idCounter (0);
  //Debug end

  for (unsigned int i = 0; i < this->GetNumberOfIndexedOutputs(); i++)
  {
    Surface* currentSurface = const_cast<Surface*>( this->GetOutput(i) );
    vtkPolyData* polyData = currentSurface->GetVtkPolyData();

    vtkSmartPointer<vtkDoubleArray> currentCellNormals = vtkDoubleArray::SafeDownCast(polyData->GetCellData()->GetNormals());

    vtkSmartPointer<vtkCellArray> existingPolys = polyData->GetPolys();

    vtkSmartPointer<vtkPoints> existingPoints = polyData->GetPoints();

    existingPolys->InitTraversal();

    vtkIdType* cell (NULL);
    vtkIdType cellSize (0);

    for( existingPolys->InitTraversal(); existingPolys->GetNextCell(cellSize, cell);)
    {
      for ( unsigned int j = 0; j < cellSize; j++ )
      {
        double currentNormal[3];
        currentCellNormals->GetTuple(cell[j], currentNormal);
        vtkSmartPointer<vtkLine> line = vtkSmartPointer<vtkLine>::New();
        line->GetPointIds()->SetNumberOfIds(2);
        double newPoint[3];
        double p0[3];
        existingPoints->GetPoint(cell[j], p0);
        newPoint[0] = p0[0] + currentNormal[0];
        newPoint[1] = p0[1] + currentNormal[1];
        newPoint[2] = p0[2] + currentNormal[2];

        line->GetPointIds()->SetId(0, idCounter);
        newPoints->InsertPoint(idCounter, p0);
        idCounter++;

        line->GetPointIds()->SetId(1, idCounter);
        newPoints->InsertPoint(idCounter, newPoint);
        idCounter++;

        newLines->InsertNextCell(line);
      }//end for all points
    }//end for all cells
  }//end for all outputs

  newPolyData->SetPoints(newPoints);
  newPolyData->SetLines(newLines);
  newPolyData->BuildCells();

  mitk::Surface::Pointer surface = mitk::Surface::New();
  surface->SetVtkPolyData(newPolyData);

  return surface;

}

void mitk::ComputeContourSetNormalsFilter::SetMaxSpacing(double maxSpacing)
{
    m_MaxSpacing = maxSpacing;
}

void mitk::ComputeContourSetNormalsFilter::GenerateOutputInformation()
{
  Superclass::GenerateOutputInformation();
}

void mitk::ComputeContourSetNormalsFilter::Reset()
{
  for (unsigned int i = 0; i < this->GetNumberOfIndexedInputs(); i++)
  {
    this->PopBackInput();
  }
  this->SetNumberOfIndexedInputs(0);
  this->SetNumberOfIndexedOutputs(0);

  mitk::Surface::Pointer output = mitk::Surface::New();
  this->SetNthOutput(0, output.GetPointer());
}

void mitk::ComputeContourSetNormalsFilter::SetUseProgressBar(bool status)
{
  this->m_UseProgressBar = status;
}

void mitk::ComputeContourSetNormalsFilter::SetProgressStepSize(unsigned int stepSize)
{
  this->m_ProgressStepSize = stepSize;
}
<commit_msg>Fixed the crash by replacing the GetPixelByWorldCoordinates method with its internal structure exept the GetPixelByIndex method. This one was changed to GetPixelByIndexSafe.<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkComputeContourSetNormalsFilter.h"

#include "mitkImagePixelReadAccessor.h"

mitk::ComputeContourSetNormalsFilter::ComputeContourSetNormalsFilter()
{
  m_MaxSpacing = 5;
  this->m_UseProgressBar = false;
  this->m_ProgressStepSize = 1;

  mitk::Surface::Pointer output = mitk::Surface::New();
  this->SetNthOutput(0, output.GetPointer());
}

mitk::ComputeContourSetNormalsFilter::~ComputeContourSetNormalsFilter()
{
}

void mitk::ComputeContourSetNormalsFilter::GenerateData()
{
  unsigned int numberOfInputs = this->GetNumberOfIndexedInputs();
  this->CreateOutputsForAllInputs(numberOfInputs);

  //Iterating over each input
  for(unsigned int i = 0; i < numberOfInputs; i++)
  {
    //Getting the inputs polydata and polygons
    Surface* currentSurface = const_cast<Surface*>( this->GetInput(i) );
    vtkPolyData* polyData = currentSurface->GetVtkPolyData();

    vtkSmartPointer<vtkCellArray> existingPolys = polyData->GetPolys();

    vtkSmartPointer<vtkPoints> existingPoints = polyData->GetPoints();

    existingPolys->InitTraversal();

    vtkIdType* cell (NULL);
    vtkIdType cellSize (0);

    //The array that contains all the vertex normals of the current polygon
    vtkSmartPointer<vtkDoubleArray> normals = vtkSmartPointer<vtkDoubleArray>::New();
    normals->SetNumberOfComponents(3);
    normals->SetNumberOfTuples(polyData->GetNumberOfPoints());

    //If the current contour is an inner contour then the direction is -1
    //A contour lies inside another one if the pixel values in the direction of the normal is 1
    m_NegativeNormalCounter = 0;
    m_PositiveNormalCounter = 0;

    //Iterating over each polygon
    for( existingPolys->InitTraversal(); existingPolys->GetNextCell(cellSize, cell);)
    {
      if(cellSize < 3)continue;

      //First we calculate the current polygon's normal
      double polygonNormal[3] = {0.0};

      double p1[3];
      double p2[3];

      double v1[3];
      double v2[3];

      existingPoints->GetPoint(cell[0], p1);
      unsigned int index = cellSize*0.5;
      existingPoints->GetPoint(cell[index], p2);

      v1[0] = p2[0]-p1[0];
      v1[1] = p2[1]-p1[1];
      v1[2] = p2[2]-p1[2];

      for (unsigned int k = 2; k < cellSize; k++)
      {
        index = cellSize*0.25;
        existingPoints->GetPoint(cell[index], p1);
        index = cellSize*0.75;
        existingPoints->GetPoint(cell[index], p2);

        v2[0] = p2[0]-p1[0];
        v2[1] = p2[1]-p1[1];
        v2[2] = p2[2]-p1[2];

        vtkMath::Cross(v1,v2,polygonNormal);
        if (vtkMath::Norm(polygonNormal) != 0)
          break;
      }

      vtkMath::Normalize(polygonNormal);

      //Now we start computing the normal for each vertex

      double vertexNormalTemp[3];
      existingPoints->GetPoint(cell[0], p1);
      existingPoints->GetPoint(cell[1], p2);

      v1[0] = p2[0]-p1[0];
      v1[1] = p2[1]-p1[1];
      v1[2] = p2[2]-p1[2];

      vtkMath::Cross(v1,polygonNormal,vertexNormalTemp);

      vtkMath::Normalize(vertexNormalTemp);

      double vertexNormal[3];

      for (unsigned j = 0; j < cellSize-2; j++)
      {
        existingPoints->GetPoint(cell[j+1], p1);
        existingPoints->GetPoint(cell[j+2], p2);

        v1[0] = p2[0]-p1[0];
        v1[1] = p2[1]-p1[1];
        v1[2] = p2[2]-p1[2];

        vtkMath::Cross(v1,polygonNormal,vertexNormal);

        vtkMath::Normalize(vertexNormal);

        double finalNormal[3];

        finalNormal[0] = (vertexNormal[0] + vertexNormalTemp[0])*0.5;
        finalNormal[1] = (vertexNormal[1] + vertexNormalTemp[1])*0.5;
        finalNormal[2] = (vertexNormal[2] + vertexNormalTemp[2])*0.5;

        //Here we determine the direction of the normal
        if (j == 0 && m_SegmentationBinaryImage)
        {
          Point3D worldCoord;
          worldCoord[0] = p1[0]+finalNormal[0]*m_MaxSpacing;
          worldCoord[1] = p1[1]+finalNormal[1]*m_MaxSpacing;
          worldCoord[2] = p1[2]+finalNormal[2]*m_MaxSpacing;

          double val = 0.0;
          mitk::ImagePixelReadAccessor<unsigned char> readAccess(m_SegmentationBinaryImage);
          mitk::Index3D idx;
          m_SegmentationBinaryImage->GetGeometry()->WorldToIndex(worldCoord, idx);
          val = readAccess.GetPixelByIndexSafe(idx);

          if (val == 1.0)
          {
              ++m_PositiveNormalCounter;
          }
          else
          {
              ++m_NegativeNormalCounter;
          }
        }

        vertexNormalTemp[0] = vertexNormal[0];
        vertexNormalTemp[1] = vertexNormal[1];
        vertexNormalTemp[2] = vertexNormal[2];

        vtkIdType id = cell[j+1];
        normals->SetTuple(id,finalNormal);
      }

      existingPoints->GetPoint(cell[0], p1);
      existingPoints->GetPoint(cell[1], p2);

      v1[0] = p2[0]-p1[0];
      v1[1] = p2[1]-p1[1];
      v1[2] = p2[2]-p1[2];

      vtkMath::Cross(v1,polygonNormal,vertexNormal);

      vtkMath::Normalize(vertexNormal);

      vertexNormal[0] = (vertexNormal[0] + vertexNormalTemp[0])*0.5;
      vertexNormal[1] = (vertexNormal[1] + vertexNormalTemp[1])*0.5;
      vertexNormal[2] = (vertexNormal[2] + vertexNormalTemp[2])*0.5;

      vtkIdType id = cell[0];
      normals->SetTuple(id,vertexNormal);
      id = cell[cellSize-1];
      normals->SetTuple(id,vertexNormal);

      int normalDirection(-1);

      if(m_NegativeNormalCounter < m_PositiveNormalCounter)
      {
          normalDirection = 1;
      }

      for(unsigned int n = 0; n < normals->GetNumberOfTuples(); n++)
      {
          double normal[3];
          normals->GetTuple(n,normal);
          normal[0] = normalDirection*normal[0];
          normal[1] = normalDirection*normal[1];
          normal[2] = normalDirection*normal[2];
      }

    }//end for all cells

    Surface::Pointer surface = this->GetOutput(i);
    surface->GetVtkPolyData()->GetCellData()->SetNormals(normals);
  }//end for all inputs

  //Setting progressbar
  if (this->m_UseProgressBar)
    mitk::ProgressBar::GetInstance()->Progress(this->m_ProgressStepSize);
}

mitk::Surface::Pointer mitk::ComputeContourSetNormalsFilter::GetNormalsAsSurface()
{
  //Just for debugging:
  vtkSmartPointer<vtkPolyData> newPolyData = vtkSmartPointer<vtkPolyData>::New();
  vtkSmartPointer<vtkCellArray> newLines = vtkSmartPointer<vtkCellArray>::New();
  vtkSmartPointer<vtkPoints> newPoints = vtkSmartPointer<vtkPoints>::New();
  unsigned int idCounter (0);
  //Debug end

  for (unsigned int i = 0; i < this->GetNumberOfIndexedOutputs(); i++)
  {
    Surface* currentSurface = const_cast<Surface*>( this->GetOutput(i) );
    vtkPolyData* polyData = currentSurface->GetVtkPolyData();

    vtkSmartPointer<vtkDoubleArray> currentCellNormals = vtkDoubleArray::SafeDownCast(polyData->GetCellData()->GetNormals());

    vtkSmartPointer<vtkCellArray> existingPolys = polyData->GetPolys();

    vtkSmartPointer<vtkPoints> existingPoints = polyData->GetPoints();

    existingPolys->InitTraversal();

    vtkIdType* cell (NULL);
    vtkIdType cellSize (0);

    for( existingPolys->InitTraversal(); existingPolys->GetNextCell(cellSize, cell);)
    {
      for ( unsigned int j = 0; j < cellSize; j++ )
      {
        double currentNormal[3];
        currentCellNormals->GetTuple(cell[j], currentNormal);
        vtkSmartPointer<vtkLine> line = vtkSmartPointer<vtkLine>::New();
        line->GetPointIds()->SetNumberOfIds(2);
        double newPoint[3];
        double p0[3];
        existingPoints->GetPoint(cell[j], p0);
        newPoint[0] = p0[0] + currentNormal[0];
        newPoint[1] = p0[1] + currentNormal[1];
        newPoint[2] = p0[2] + currentNormal[2];

        line->GetPointIds()->SetId(0, idCounter);
        newPoints->InsertPoint(idCounter, p0);
        idCounter++;

        line->GetPointIds()->SetId(1, idCounter);
        newPoints->InsertPoint(idCounter, newPoint);
        idCounter++;

        newLines->InsertNextCell(line);
      }//end for all points
    }//end for all cells
  }//end for all outputs

  newPolyData->SetPoints(newPoints);
  newPolyData->SetLines(newLines);
  newPolyData->BuildCells();

  mitk::Surface::Pointer surface = mitk::Surface::New();
  surface->SetVtkPolyData(newPolyData);

  return surface;

}

void mitk::ComputeContourSetNormalsFilter::SetMaxSpacing(double maxSpacing)
{
    m_MaxSpacing = maxSpacing;
}

void mitk::ComputeContourSetNormalsFilter::GenerateOutputInformation()
{
  Superclass::GenerateOutputInformation();
}

void mitk::ComputeContourSetNormalsFilter::Reset()
{
  for (unsigned int i = 0; i < this->GetNumberOfIndexedInputs(); i++)
  {
    this->PopBackInput();
  }
  this->SetNumberOfIndexedInputs(0);
  this->SetNumberOfIndexedOutputs(0);

  mitk::Surface::Pointer output = mitk::Surface::New();
  this->SetNthOutput(0, output.GetPointer());
}

void mitk::ComputeContourSetNormalsFilter::SetUseProgressBar(bool status)
{
  this->m_UseProgressBar = status;
}

void mitk::ComputeContourSetNormalsFilter::SetProgressStepSize(unsigned int stepSize)
{
  this->m_ProgressStepSize = stepSize;
}
<|endoftext|>


<commit_before>/// \file drawMeanPtRaw.C
/// \brief Macro to draw the Output of AliAnalysisTaskMeanPtRaw
///
/// This macro draws the output of AliAnalysisTaskMeanPtRaw. The first argument is the file, which should be used to plot,
/// the second argument contains additional information, which are put on the plot.
/// This second argument can contain pT cuts in the form lowerPt<pT<higherPt
/// All different information need to be seperated by ; and are then parsed in this macro.
///
/// \author Philipp Luettig <philipp.luettig@cern.ch>, University of Frankfurt, Germany
/// \date May 12th, 2015

#include "TFile.h"
#include "TList.h"
#include "TProfile.h"
#include "TH1.h"
#include "TH2.h"
#include "THnSparse.h"
#include "TCanvas.h"
#include "TStyle.h"
#include "TLatex.h"
#include "TLegend.h"
#include <vector>

Int_t GetMaxBin(std::vector<TProfile> &vec);
Double_t GetMaxPt(std::vector<TProfile> &vec);

void drawMeanPtRaw(const char *fInput = "AnalysisResults.root", const char * cInformation ="")
{
  TFile *f = TFile::Open(fInput,"READ");
  TDirectoryFile *d = (TDirectoryFile*)f->Get("MeanPtRaw");
  TList *l = (TList*)d->Get("MeanPtRaw");
  //l->ls();
  THnSparse *hsMpt = (THnSparse*)l->FindObject("fPtVsMultRaw");
  TH1I *hCutNames = (TH1I*)l->FindObject("fTrackCutName");

  Double_t pTmin = 0.15;
  Double_t pTmax = 10;

  const Int_t colors[] = {kBlue+1, kRed+1, kBlack, kGreen+3, kMagenta+1, kOrange-1,kCyan+2,kYellow+2};

  // parse information given as second argument
  TString sAdditionalInfo(cInformation);
  TObjArray *oAddInfo = sAdditionalInfo.Tokenize(";");

  std::vector<Bool_t> bDrawEntry;
  std::vector<Double_t> dVecPtMin;
  std::vector<Double_t> dVecPtMax;
  Int_t nPtCuts = 0;

  for(Int_t iEntry = 0; iEntry < oAddInfo->GetEntries(); iEntry++)
  {
	bDrawEntry.push_back(kTRUE);
  }

  for(Int_t iEntry = 0; iEntry < oAddInfo->GetEntries(); iEntry++)
  {
	TObjString *osAdd = (TObjString*)oAddInfo->At(iEntry);
	if(osAdd->GetString().Contains("pT"))
	{
	  TObjArray *oPt = osAdd->GetString().Tokenize("<");
	  TObjString *osPtMin = (TObjString*)oPt->At(0);
	  TObjString *osPtMax = (TObjString*)oPt->At(2);

	  dVecPtMin.push_back(atof(osPtMin->GetString().Data()));
	  dVecPtMax.push_back(atof(osPtMax->GetString().Data()));

	  bDrawEntry.at(iEntry) = kFALSE;
	  nPtCuts++;
	}
  }

  std::vector<std::vector<TProfile> > pVecMpt;

  Int_t nCutSettings = hsMpt->GetAxis(2)->GetNbins();

  for(Int_t iCutSetting = 0; iCutSetting < nCutSettings; iCutSetting++) {
	hsMpt->GetAxis(2)->SetRange(iCutSetting+1, iCutSetting+1); // +1 to overcome underflow bin
	std::vector<TProfile> pVecTemp;
	for(Int_t iPtCut = 0; iPtCut < nPtCuts; iPtCut++) {
	  hsMpt->GetAxis(1)->SetRangeUser(dVecPtMin.at(iPtCut), dVecPtMax.at(iPtCut));
	  TProfile pMpt(*(TProfile*)hsMpt->Projection(1,0)->ProfileX());
	  pMpt.SetName(Form("pMpt_%i_%i", iCutSetting, iPtCut));
	  pMpt.SetMarkerStyle(20);
	  pMpt.SetMarkerColor(colors[iPtCut%9]);
	  pVecTemp.push_back(pMpt);
	}
	pVecMpt.push_back(pVecTemp);
  }

  Int_t maxBin = -1;
  Double_t maxPt = -1;
  for(Int_t iCutSetting = 0; iCutSetting < nCutSettings; iCutSetting++) {
	if(GetMaxBin(pVecMpt.at(iCutSetting)) > maxBin)  { maxBin = GetMaxBin(pVecMpt.at(iCutSetting)); }
	if(GetMaxPt(pVecMpt.at(iCutSetting)) > maxPt)  { maxPt = GetMaxPt(pVecMpt.at(iCutSetting)); }
  }

  TH1F hDummy("hDummy",";n_{acc} (raw);#LT #it{p}_{T} #GT (raw) (GeV/c)",3500,-0.5,3499.5);
  hDummy.GetXaxis()->SetRangeUser(0, maxBin);
  hDummy.GetYaxis()->SetRangeUser(0, maxPt);
  hDummy.GetYaxis()->SetTitleOffset(1.2);
  hDummy.SetTitleFont(43);
  hDummy.SetTitleSize(18);

  TLatex lat;
  lat.SetTextFont(43);
  lat.SetTextSize(16);
  lat.SetTextColor(kBlack);

  TLegend leg(0.7, 0.7, 0.9, 0.9);
  leg.SetTextFont(43);
  leg.SetTextSize(15);
  leg.SetTextColor(kBlack);
  leg.SetBorderSize(0);
  leg.SetFillStyle(0);
  for(Int_t iPtCut = 0; iPtCut < nPtCuts; iPtCut++) {
	leg.AddEntry(&pVecMpt.at(0).at(iPtCut), Form("%.2f < #it{p}_{T} < %.2f GeV/c", dVecPtMin.at(iPtCut), dVecPtMax.at(iPtCut)), "P");
  }

  Double_t dYPositionDefault = 0.38;
  Double_t dDeltaYDefault = 0.04;

  gStyle->SetOptStat(0);
  TCanvas c1("c1","c1",nCutSettings*600,600);
  c1.Divide(nCutSettings,1);
  for(Int_t iCutSetting = 0; iCutSetting < nCutSettings; iCutSetting++) {
	c1.cd(iCutSetting+1);
	gPad->SetTopMargin(0.06);
    gPad->SetRightMargin(0.3);

	Double_t dYPosition = dYPositionDefault;
	Double_t dDeltaY = dDeltaYDefault;

	hDummy.SetTitle(hCutNames->GetXaxis()->GetBinLabel(iCutSetting+1));
	hDummy.DrawCopy();

	for(Int_t iPtCut = 0; iPtCut < nPtCuts; iPtCut++) {
	  pVecMpt.at(iCutSetting).at(iPtCut).Draw("same");
	}

	for(Int_t iEntry = 0; iEntry < oAddInfo->GetEntries(); iEntry++)
	{
	  if(bDrawEntry.at(iEntry)) {
		TObjString *osAdd = (TObjString*)oAddInfo->At(iEntry);
// 		lat.DrawLatex(10, dYPosition, Form("%s", osAdd->GetString().Data()));
// 		dYPosition -= dDeltaY;
		lat.DrawLatexNDC(0.72, dYPosition, Form("%s", osAdd->GetString().Data()));
		dYPosition -= dDeltaY;
	  }
	}

	leg.Draw();
  } // end iCutSetting

  c1.SaveAs("meanpt_vs_mult_raw.gif");
}

Int_t GetMaxBin(std::vector<TProfile> &vec)
{
  Int_t iMaxBin = -1;
  for(UInt_t iEntry = 0; iEntry < vec.size(); iEntry++) {
	for(Int_t i = 0; i < vec.at(iEntry).GetNbinsX(); i++)
	{
	  if( (vec.at(iEntry).GetBinContent(i)>0) && (vec.at(iEntry).GetBinError(i)>0))
	  {
		iMaxBin = vec.at(iEntry).GetBinCenter(i);
	  }
	}
  }
  return iMaxBin;
}

Double_t GetMaxPt(std::vector<TProfile> &vec)
{
  Double_t dMaxPt = -1;
  for(UInt_t iEntry = 0; iEntry < vec.size(); iEntry++) {
	for(Int_t i = 0; i < vec.at(iEntry).GetNbinsX(); i++)
	{
	  if( ((vec.at(iEntry).GetBinContent(i) + vec.at(iEntry).GetBinError(i)) > dMaxPt) )
	  {
		dMaxPt = (vec.at(iEntry).GetBinContent(i) + vec.at(iEntry).GetBinError(i));
	  }
	}
  }
  return dMaxPt;
}
<commit_msg>update in drawMeanPtRaw to take cut settings correctly into account<commit_after>/// \file drawMeanPtRaw.C
/// \brief Macro to draw the Output of AliAnalysisTaskMeanPtRaw
///
/// This macro draws the output of AliAnalysisTaskMeanPtRaw. The first argument is the file, which should be used to plot,
/// the second argument contains additional information, which are put on the plot.
/// This second argument can contain pT cuts in the form lowerPt<pT<higherPt
/// All different information need to be seperated by ; and are then parsed in this macro.
///
/// \author Philipp Luettig <philipp.luettig@cern.ch>, University of Frankfurt, Germany
/// \date May 12th, 2015

#include "TFile.h"
#include "TList.h"
#include "TProfile.h"
#include "TH1.h"
#include "TH2.h"
#include "THnSparse.h"
#include "TCanvas.h"
#include "TStyle.h"
#include "TLatex.h"
#include "TLegend.h"
#include <vector>

Int_t GetMaxBin(std::vector<TProfile> &vec);
Double_t GetMaxPt(std::vector<TProfile> &vec);

void drawMeanPtRaw(const char *fInput = "AnalysisResults.root", const char * cInformation ="")
{
  TFile *f = TFile::Open(fInput,"READ");
  TDirectoryFile *d = (TDirectoryFile*)f->Get("MeanPtRaw");
  TList *l = (TList*)d->Get("MeanPtRaw");
  //l->ls();
  THnSparse *hsMpt = (THnSparse*)l->FindObject("fPtVsMultRaw");
  TH1I *hCutNames = (TH1I*)l->FindObject("fTrackCutName");

  Double_t pTmin = 0.15;
  Double_t pTmax = 10;

  const Int_t colors[] = {kBlue+1, kRed+1, kBlack, kGreen+3, kMagenta+1, kOrange-1,kCyan+2,kYellow+2};

  // parse information given as second argument
  TString sAdditionalInfo(cInformation);
  TObjArray *oAddInfo = sAdditionalInfo.Tokenize(";");

  TObjString *osPlot = 0x0;
  std::vector<Bool_t> bDrawEntry;
  std::vector<Double_t> dVecPtMin;
  std::vector<Double_t> dVecPtMax;
  Int_t nPtCuts = 0;

  for(Int_t iEntry = 0; iEntry < oAddInfo->GetEntries(); iEntry++)
  {
	bDrawEntry.push_back(kTRUE);
  }

  for(Int_t iEntry = 0; iEntry < oAddInfo->GetEntries(); iEntry++)
  {
	TObjString *osAdd = (TObjString*)oAddInfo->At(iEntry);
	if(osAdd->GetString().Contains("pT"))
	{
	  TObjArray *oPt = osAdd->GetString().Tokenize("<");
	  TObjString *osPtMin = (TObjString*)oPt->At(0);
	  TObjString *osPtMax = (TObjString*)oPt->At(2);

	  dVecPtMin.push_back(atof(osPtMin->GetString().Data()));
	  dVecPtMax.push_back(atof(osPtMax->GetString().Data()));

	  bDrawEntry.at(iEntry) = kFALSE;
	  nPtCuts++;
	}
	if(osAdd->GetString().Contains("plot"))
	{
	  TObjArray *oPlot = osAdd->GetString().Tokenize("=");
          osPlot = (TObjString*)oPlot->At(1);
	  bDrawEntry.at(iEntry) = kFALSE;
	  //Printf("%s" ,osPlot->GetString().Data());
	}
  }

  std::vector<std::vector<TProfile> > pVecMpt;

  Int_t nCutSettings = hsMpt->GetAxis(2)->GetNbins();

  for(Int_t iCutSetting = 0; iCutSetting < nCutSettings; iCutSetting++) {
	hsMpt->GetAxis(2)->SetRange(iCutSetting+1, iCutSetting+1); // +1 to overcome underflow bin
	std::vector<TProfile> pVecTemp;
	for(Int_t iPtCut = 0; iPtCut < nPtCuts; iPtCut++) {
	  hsMpt->GetAxis(1)->SetRangeUser(dVecPtMin.at(iPtCut), dVecPtMax.at(iPtCut));
	  TProfile pMpt(*(TProfile*)hsMpt->Projection(1,0)->ProfileX());
	  pMpt.SetName(Form("pMpt_%i_%i", iCutSetting, iPtCut));
	  pMpt.SetMarkerStyle(20);
	  pMpt.SetMarkerColor(colors[iPtCut%9]);
	  pVecTemp.push_back(pMpt);
	}
	pVecMpt.push_back(pVecTemp);
  }

  Int_t maxBin = 160;
  Double_t maxPt = 6;
  for(Int_t iCutSetting = 0; iCutSetting < nCutSettings; iCutSetting++) {
	if(GetMaxBin(pVecMpt.at(iCutSetting)) > maxBin)  { maxBin = GetMaxBin(pVecMpt.at(iCutSetting)); }
	if(GetMaxPt(pVecMpt.at(iCutSetting)) > maxPt)  { maxPt = GetMaxPt(pVecMpt.at(iCutSetting)); }
  }

  TH1F hDummy("hDummy",";n_{acc} (raw);#LT #it{p}_{T} #GT (raw) (GeV/c)",3500,-0.5,3499.5);
  hDummy.GetXaxis()->SetRangeUser(0, maxBin);
  hDummy.GetYaxis()->SetRangeUser(0, maxPt);
  hDummy.GetYaxis()->SetTitleOffset(1.2);
  hDummy.SetTitleFont(43);
  hDummy.SetTitleSize(18);

  TLatex lat;
  lat.SetTextFont(43);
  lat.SetTextSize(16);
  lat.SetTextColor(kBlack);

  TLegend leg(0.7, 0.7, 0.9, 0.9);
  leg.SetTextFont(43);
  leg.SetTextSize(15);
  leg.SetTextColor(kBlack);
  leg.SetBorderSize(0);
  leg.SetFillStyle(0);
  for(Int_t iPtCut = 0; iPtCut < nPtCuts; iPtCut++) {
	leg.AddEntry(&pVecMpt.at(0).at(iPtCut), Form("%.2f < #it{p}_{T} < %.2f GeV/c", dVecPtMin.at(iPtCut), dVecPtMax.at(iPtCut)), "P");
  }

  Double_t dYPositionDefault = 0.38;
  Double_t dDeltaYDefault = 0.04;

  gStyle->SetOptStat(0);
  TCanvas c1("c1","c1",nCutSettings*600,600);
  c1.Divide(nCutSettings,1);
  for(Int_t iCutSetting = 0; iCutSetting < nCutSettings; iCutSetting++) {
	c1.cd(iCutSetting+1);
	gPad->SetTopMargin(0.06);
    gPad->SetRightMargin(0.3);

	Double_t dYPosition = dYPositionDefault;
	Double_t dDeltaY = dDeltaYDefault;

	hDummy.SetTitle(hCutNames->GetXaxis()->GetBinLabel(iCutSetting+1));
	hDummy.DrawCopy();

	for(Int_t iPtCut = 0; iPtCut < nPtCuts; iPtCut++) {
	  pVecMpt.at(iCutSetting).at(iPtCut).Draw("same");
	}

	for(Int_t iEntry = 0; iEntry < oAddInfo->GetEntries(); iEntry++)
	{
	  if(bDrawEntry.at(iEntry)) {
		TObjString *osAdd = (TObjString*)oAddInfo->At(iEntry);
// 		lat.DrawLatex(10, dYPosition, Form("%s", osAdd->GetString().Data()));
// 		dYPosition -= dDeltaY;
		lat.DrawLatexNDC(0.72, dYPosition, Form("%s", osAdd->GetString().Data()));
		dYPosition -= dDeltaY;
	  }
	}

	leg.Draw();
  } // end iCutSetting

  c1.SaveAs(Form("meanpt_vs_mult_raw_%s.gif", osPlot->GetString().Data()));
}

Int_t GetMaxBin(std::vector<TProfile> &vec)
{
  Int_t iMaxBin = -1;
  for(UInt_t iEntry = 0; iEntry < vec.size(); iEntry++) {
	for(Int_t i = 0; i < vec.at(iEntry).GetNbinsX(); i++)
	{
	  if( (vec.at(iEntry).GetBinContent(i)>0) && (vec.at(iEntry).GetBinError(i)>0))
	  {
		iMaxBin = vec.at(iEntry).GetBinCenter(i);
	  }
	}
  }
  return iMaxBin;
}

Double_t GetMaxPt(std::vector<TProfile> &vec)
{
  Double_t dMaxPt = -1;
  for(UInt_t iEntry = 0; iEntry < vec.size(); iEntry++) {
	for(Int_t i = 0; i < vec.at(iEntry).GetNbinsX(); i++)
	{
	  if( ((vec.at(iEntry).GetBinContent(i) + vec.at(iEntry).GetBinError(i)) > dMaxPt) )
	  {
		dMaxPt = (vec.at(iEntry).GetBinContent(i) + vec.at(iEntry).GetBinError(i));
	  }
	}
  }
  return dMaxPt;
}
<|endoftext|>


<commit_before>/**
 * @file
 *
 * Distributed under the Boost Software License, Version 1.0.
 * See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt
 */

#include "meka/action/build.hpp"

#include "meka/package.hpp"

#include <boost/filesystem.hpp>
#include <boost/regex.hpp>
#include <boost/algorithm/string/join.hpp>

#include <unordered_map>
#include <fstream>

namespace meka {

  void build(meka::package const& package) {
    std::system("ninja -f build/build.ninja");
  }

}
<commit_msg>Use NINJA environment variable in the build action as well.<commit_after>/**
 * @file
 *
 * Distributed under the Boost Software License, Version 1.0.
 * See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt
 */

#include "meka/action/build.hpp"

#include "meka/package.hpp"

#include <boost/filesystem.hpp>
#include <boost/regex.hpp>
#include <boost/algorithm/string/join.hpp>

#include <unordered_map>
#include <fstream>

namespace meka {

  void build(meka::package const& package) {
    std::system("${NINJA:-ninja} -f build/build.ninja");
  }

}
<|endoftext|>


<commit_before>/**
 * AtomCache.cc
 *
 * Persistant Atom storage, backed by memcachedb
 *
 * Atoms are saved to, and restored from one, or more, memcachdb
 * servers.
 *
 * HISTORY:
 * Copyright (c) 2008 Linas Vepstas <linas@linas.org>
 */

#ifdef HAVE_LIBMEMCACHED

#include <string>

#include <memcached.h>

#include "Atom.h"
#include "AtomCache.h"
#include "AtomTable.h"
#include "ClassServer.h"
#include "Node.h"
#include "Link.h"
#include "TLB.h"

using namespace opencog;

AtomCache::AtomCache(const std::string server, int portno)
{
	memcached_return rc;
	mc = memcached_create(NULL);

	memcached_server_st *servers;
	const char *servername = server.c_str();
	servers = memcached_server_list_append(NULL, (char *) servername, portno, &rc);

	connect_status = memcached_server_push(mc, servers);

	memcached_server_list_free(servers);
}

AtomCache::~AtomCache()
{
	memcached_free(mc);
}

#define CHECK_RC(rc) \
	if(MEMCACHED_SUCCESS != rc) \
	{ \
		fprintf(stderr, "Error: memcachedb: %s\n", memcached_strerror(mc, rc)); \
		return; \
	}

void AtomCache::storeAtom(Atom *atom)
{
	memcached_return rc;

	Handle h = TLB::getHandle(atom);

	// Set up the basic root of the key
#define KBSIZE 50
	char keybuff[KBSIZE];
	int rootlen = snprintf(keybuff, KBSIZE, "%lu/", h);
	char *p = &keybuff[rootlen];

	// The buffer for values.
#define VBSIZE 1050
	char valbuff[VBSIZE];

	// Get the atom type.
	Type t = atom->getType();
	strcpy(p, "type");
	int vlen = snprintf(valbuff, VBSIZE, "%d", t);

	rc = memcached_set (mc, keybuff, rootlen+4, valbuff, vlen, 0, 0);
	CHECK_RC(rc);

	// If a node, store the name
	Node *n = dynamic_cast<Node *>(atom);
	if (n)
	{
		strcpy(p, "name");
		const char *name = n->getName().c_str();
		vlen = n->getName().size();
		rc = memcached_set (mc, keybuff, rootlen+4, name, vlen, 0, 0);
		CHECK_RC(rc);
	}
	else
	{
		// Store the outgoing set
		Link *l = dynamic_cast<Link *>(atom);
		int arity = l->getArity();
		vlen = snprintf(valbuff, VBSIZE, "(%d", arity);

		std::vector<Handle> out = l->getOutgoingSet();
		for (int i=0; i<arity; i++)
		{
			vlen += snprintf(valbuff+vlen, VBSIZE-vlen, ", %lu", out[i]);
		}

		vlen += snprintf(valbuff+vlen, VBSIZE-vlen, ")");
		strcpy(p, "edges");
		rc = memcached_set (mc, keybuff, rootlen+5, valbuff, vlen, 0, 0);
		CHECK_RC(rc);
	}
}

#define NCHECK_RC(rc, val) \
	if(MEMCACHED_SUCCESS != rc) \
	{ \
		fprintf(stderr, "Error: memcachedb: %s\n", memcached_strerror(mc, rc)); \
		if (val) free(val); \
		return atom; \
	}

Atom * AtomCache::getAtom(Handle h)
{
	memcached_return rc;
	char keybuff[KBSIZE];
	int rootlen = snprintf(keybuff, KBSIZE, "%lu/", h);
	char *p = &keybuff[rootlen];

	// Does the atom exist already ?
	Atom *atom = TLB::getAtom(h);

// for sniff test only
atom = NULL;
	if (NULL == atom)
	{
		// Get the atom type.
		strcpy(p, "type");
		size_t vlen;
		uint32_t flags;
		char *val = memcached_get(mc, keybuff, rootlen+4, &vlen, &flags, &rc);
		NCHECK_RC(rc, val);
		int atype = atoi(val);
		free(val);

		if (ClassServer::isAssignableFrom(NODE, atype))
		{
			// Get the atom name
			strcpy(p, "name");
			val = memcached_get(mc, keybuff, rootlen+4, &vlen, &flags, &rc);
			NCHECK_RC(rc, val);
			atom = new Node(atype, val);
			free(val);
		}
		else
		{
			// Get the outvec.
			strcpy(p, "edges");
			val = memcached_get(mc, keybuff, rootlen+5, &vlen, &flags, &rc);
			NCHECK_RC(rc, val);

			int arity = atoi(val+1);
			std::vector<Handle> outvec;
			outvec.resize(arity);

			char *comma = strchr(val+2, ',');
			for (int i=0; i<arity; i++)
			{
				Handle ho = (Handle) strtoul(comma+1, &comma, 10);
				outvec.at(i) = ho;
			}
			atom = new Link(atype, outvec);
		}
	}
	return atom;
}

void AtomCache::load(AtomTable &at)
{
}

void AtomCache::store(const AtomTable &at)
{
}

#endif /* HAVE_LIBMEMCACHED */

<commit_msg>add truth value storage<commit_after>/**
 * AtomCache.cc
 *
 * Persistant Atom storage, backed by memcachedb
 *
 * Atoms are saved to, and restored from one, or more, memcachdb
 * servers.
 *
 * HISTORY:
 * Copyright (c) 2008 Linas Vepstas <linas@linas.org>
 */

#ifdef HAVE_LIBMEMCACHED

#include <string>

#include <memcached.h>

#include "Atom.h"
#include "AtomCache.h"
#include "AtomTable.h"
#include "ClassServer.h"
#include "Node.h"
#include "Link.h"
#include "SimpleTruthValue.h"
#include "TLB.h"
#include "TruthValue.h"

using namespace opencog;

AtomCache::AtomCache(const std::string server, int portno)
{
	memcached_return rc;
	mc = memcached_create(NULL);

	memcached_server_st *servers;
	const char *servername = server.c_str();
	servers = memcached_server_list_append(NULL, (char *) servername, portno, &rc);

	connect_status = memcached_server_push(mc, servers);

	memcached_server_list_free(servers);
}

AtomCache::~AtomCache()
{
	memcached_free(mc);
}

/* ================================================================== */

#define CHECK_RC(rc) \
	if(MEMCACHED_SUCCESS != rc) \
	{ \
		fprintf(stderr, "Error: memcachedb: %s\n", memcached_strerror(mc, rc)); \
		return; \
	}

void AtomCache::storeAtom(Atom *atom)
{
	memcached_return rc;

	Handle h = TLB::getHandle(atom);

	// Set up the basic root of the key
#define KBSIZE 50
	char keybuff[KBSIZE];
	int rootlen = snprintf(keybuff, KBSIZE, "%lu/", h);
	char *p = &keybuff[rootlen];

	// The buffer for values.
#define VBSIZE 1050
	char valbuff[VBSIZE];

	// Get the atom type.
	Type t = atom->getType();
	strcpy(p, "type");
	int vlen = snprintf(valbuff, VBSIZE, "%d", t);

	rc = memcached_set (mc, keybuff, rootlen+4, valbuff, vlen, 0, 0);
	CHECK_RC(rc);

	// If a node, store the name
	Node *n = dynamic_cast<Node *>(atom);
	if (n)
	{
		strcpy(p, "name");
		const char *name = n->getName().c_str();
		vlen = n->getName().size();
		rc = memcached_set (mc, keybuff, rootlen+4, name, vlen, 0, 0);
		CHECK_RC(rc);
	}
	else
	{
		// Store the outgoing set
		Link *l = dynamic_cast<Link *>(atom);
		int arity = l->getArity();
		vlen = snprintf(valbuff, VBSIZE, "(%d", arity);

		std::vector<Handle> out = l->getOutgoingSet();
		for (int i=0; i<arity; i++)
		{
			vlen += snprintf(valbuff+vlen, VBSIZE-vlen, ", %lu", out[i]);
		}

		vlen += snprintf(valbuff+vlen, VBSIZE-vlen, ")");
		strcpy(p, "edges");
		rc = memcached_set (mc, keybuff, rootlen+5, valbuff, vlen, 0, 0);
		CHECK_RC(rc);
	}

	// Store the truth value
	const TruthValue &tv = atom->getTruthValue();
	const SimpleTruthValue *stv = dynamic_cast<const SimpleTruthValue *>(&tv);
	if (NULL == stv)
	{
		fprintf(stderr, "Error: non-simple truth values are not handled\n");
		return;
	}

	vlen = snprintf(valbuff, VBSIZE, "(%20.16g, %20.16g)", tv.getMean(), tv.getCount());
	strcpy(p, "stv");
	rc = memcached_set (mc, keybuff, rootlen+3, valbuff, vlen, 0, 0);
	CHECK_RC(rc);
}

/* ================================================================== */

#define NCHECK_RC(rc, val) \
	if(MEMCACHED_SUCCESS != rc) \
	{ \
		fprintf(stderr, "Error: memcachedb: %s\n", memcached_strerror(mc, rc)); \
		if (val) free(val); \
		return atom; \
	}

Atom * AtomCache::getAtom(Handle h)
{
	memcached_return rc;
	char keybuff[KBSIZE];
	int rootlen = snprintf(keybuff, KBSIZE, "%lu/", h);
	char *p = &keybuff[rootlen];

	// Does the atom exist already ?
	Atom *atom = TLB::getAtom(h);

// for sniff test only
atom = NULL;
	if (NULL == atom)
	{
		// Get the atom type.
		strcpy(p, "type");
		size_t vlen;
		uint32_t flags;
		char *val = memcached_get(mc, keybuff, rootlen+4, &vlen, &flags, &rc);
		NCHECK_RC(rc, val);
		int atype = atoi(val);
		free(val);

		if (ClassServer::isAssignableFrom(NODE, atype))
		{
			// Get the atom name
			strcpy(p, "name");
			val = memcached_get(mc, keybuff, rootlen+4, &vlen, &flags, &rc);
			NCHECK_RC(rc, val);
			atom = new Node(atype, val);
			free(val);
		}
		else
		{
			// Get the outvec.
			strcpy(p, "edges");
			val = memcached_get(mc, keybuff, rootlen+5, &vlen, &flags, &rc);
			NCHECK_RC(rc, val);

			int arity = atoi(val+1);
			std::vector<Handle> outvec;
			outvec.resize(arity);

			char *comma = strchr(val+2, ',');
			for (int i=0; i<arity; i++)
			{
				Handle ho = (Handle) strtoul(comma+1, &comma, 10);
				outvec.at(i) = ho;
			}
			atom = new Link(atype, outvec);
		}
	}
	return atom;
}

/* ================================================================== */

void AtomCache::load(AtomTable &at)
{
}

void AtomCache::store(const AtomTable &at)
{
}

#endif /* HAVE_LIBMEMCACHED */

/* ======================= END OF FILE ============================== */
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <map>

#include "anim_generated.h"
#include "anim_table_generated.h"
#include "motive/anim_table.h"
#include "motive/io/flatbuffers.h"

using motive::Range;

namespace motive {

// Wrap the source data for an AnimTable.
// Allows AnimTables to be loaded from many different data sources.
class TableDescriberInterface {
 public:
  virtual int NumObjects() const = 0;
  virtual int NumAnims(int object) const = 0;
  virtual const char* SourceFileName(int object, int anim_idx) const = 0;
  virtual const RigAnimFb* SourceRigAnimFb(int object, int anim_idx) const = 0;
};

static int AnimListLen(const AnimListFb* list) {
  if (list == nullptr) return 0;

  // Handle `anims` interface (with union).
  if (list->anims() != nullptr) return static_cast<int>(list->anims()->size());

  // Handle `anim_files` interface.
  if (list->anim_files() != nullptr)
    return static_cast<int>(list->anim_files()->size());

  return 0;
}

static const char* AnimListFileName(const AnimListFb* list, int anim_idx) {
  if (list == nullptr) return nullptr;

  // Handle `anims` interface (with union).
  if (list->anims() != nullptr) {
    const AnimSource* source = list->anims()->Get(anim_idx);
    if (source->u_type() != AnimSourceUnion_AnimSourceFileName) return nullptr;
    return reinterpret_cast<const AnimSourceFileName*>(source->u())
        ->file_name()
        ->c_str();
  }

  // Handle `anim_files` interface.
  if (list->anim_files() != nullptr)
    return list->anim_files()->Get(anim_idx)->c_str();

  return nullptr;
}

static const RigAnimFb* AnimListRigAnimFb(const AnimListFb* list,
                                          int anim_idx) {
  if (list == nullptr) return nullptr;

  // Handle `anims` interface (with union).
  if (list->anims() != nullptr) {
    const AnimSource* source = list->anims()->Get(anim_idx);
    if (source->u_type() != AnimSourceUnion_AnimSourceEmbedded) return nullptr;
    return reinterpret_cast<const AnimSourceEmbedded*>(source->u())->embedded();
  }

  return nullptr;
}

class AnimTableFbDescriber : public TableDescriberInterface {
 public:
  explicit AnimTableFbDescriber(const AnimTableFb& table_fb)
      : table_fb_(&table_fb) {}
  virtual int NumObjects() const {
    return table_fb_->lists() == nullptr
               ? 0
               : static_cast<int>(table_fb_->lists()->size());
  }
  virtual int NumAnims(int object) const { return AnimListLen(List(object)); }
  virtual const char* SourceFileName(int object, int anim_idx) const {
    return AnimListFileName(List(object), anim_idx);
  }
  virtual const RigAnimFb* SourceRigAnimFb(int object, int anim_idx) const {
    return AnimListRigAnimFb(List(object), anim_idx);
  }

 protected:
  const AnimListFb* List(int object) const {
    return table_fb_->lists() == nullptr ? nullptr
                                         : table_fb_->lists()->Get(object);
  }

  const AnimTableFb* table_fb_;
};

class AnimListFbDescriber : public TableDescriberInterface {
 public:
  explicit AnimListFbDescriber(const AnimListFb& list_fb)
      : list_fb_(&list_fb) {}
  virtual int NumObjects() const { return AnimListLen(list_fb_) == 0 ? 0 : 1; }
  virtual int NumAnims(int /*object*/) const { return AnimListLen(list_fb_); }
  virtual const char* SourceFileName(int /*object*/, int anim_idx) const {
    return AnimListFileName(list_fb_, anim_idx);
  }
  virtual const RigAnimFb* SourceRigAnimFb(int /*object*/, int anim_idx) const {
    return AnimListRigAnimFb(list_fb_, anim_idx);
  }

 protected:
  const AnimListFb* list_fb_;
};

class TableFileNamesDescriber : public TableDescriberInterface {
 public:
  explicit TableFileNamesDescriber(const AnimTable::TableFileNames& table_names)
      : table_names_(&table_names) {}
  virtual int NumObjects() const { return table_names_->size(); }
  virtual int NumAnims(int object) const {
    return (*table_names_)[object].size();
  }
  virtual const char* SourceFileName(int object, int anim_idx) const {
    return (*table_names_)[object][anim_idx].c_str();
  }
  virtual const RigAnimFb* SourceRigAnimFb(int /*object*/,
                                           int /*anim_idx*/) const {
    return nullptr;
  }

 protected:
  const AnimTable::TableFileNames* table_names_;
};

class ListFileNamesDescriber : public TableDescriberInterface {
 public:
  explicit ListFileNamesDescriber(const AnimTable::ListFileNames& list_names)
      : list_names_(&list_names) {}
  virtual int NumObjects() const { return list_names_->size() == 0 ? 0 : 1; }
  virtual int NumAnims(int /*object*/) const { return list_names_->size(); }
  virtual const char* SourceFileName(int /*object*/, int anim_idx) const {
    return (*list_names_)[anim_idx].c_str();
  }
  virtual const RigAnimFb* SourceRigAnimFb(int /*object*/,
                                           int /*anim_idx*/) const {
    return nullptr;
  }

 protected:
  const AnimTable::ListFileNames* list_names_;
};

bool AnimTable::InitFromFlatBuffers(const AnimTableFb& table_fb,
                                    LoadFn* load_fn) {
  AnimTableFbDescriber describer(table_fb);
  return Load(&describer, load_fn);
}

bool AnimTable::InitFromFlatBuffers(const AnimListFb& list_fb,
                                    LoadFn* load_fn) {
  AnimListFbDescriber describer(list_fb);
  return Load(&describer, load_fn);
}

bool AnimTable::InitFromAnimFileNames(const TableFileNames& table_names,
                                      LoadFn* load_fn) {
  TableFileNamesDescriber describer(table_names);
  return Load(&describer, load_fn);
}

bool AnimTable::InitFromAnimFileNames(const ListFileNames& list_names,
                                      LoadFn* load_fn) {
  ListFileNamesDescriber describer(list_names);
  return Load(&describer, load_fn);
}

bool AnimTable::Load(TableDescriberInterface* describer, LoadFn* load_fn) {
  std::string scratch_buf;
  bool success = true;

  // An AnimTable is a list-of-lists. The outside list is indexed by object.
  // Loop through each object (e.g. character type).
  const int num_objects = describer->NumObjects();
  indices_.resize(num_objects);
  defining_anims_.resize(num_objects);
  for (int object = 0; object < num_objects; ++object) {
    const int num_anims = describer->NumAnims(object);
    indices_[object].resize(num_anims);

    // The inside list is animations for the given object.
    // Loop through all animations, loading animations or referencing animations
    // that have already been loaded.
    AnimList& list = indices_[object];
    for (int anim_idx = 0; anim_idx < num_anims; ++anim_idx) {
      // Initialize this anim_idx to point to no data.
      list[anim_idx] = kInvalidAnimIndex;

      const RigAnimFb* anim_fb = describer->SourceRigAnimFb(object, anim_idx);
      const char* anim_name = anim_fb != nullptr
                                  ? anim_fb->name()->c_str()
                                  : describer->SourceFileName(object, anim_idx);

      // Case 1: source data is empty.
      if (anim_name == nullptr || anim_name[0] == '\0') continue;

      // Case 2: source data has already been processed.
      auto existing = name_map_.find(anim_name);
      if (existing != name_map_.end()) {
        list[anim_idx] = existing->second;
        continue;
      }

      // Case 3: load source data.
      if (anim_fb == nullptr) {
        const char* anim_buf = load_fn(anim_name, &scratch_buf);
        anim_fb = anim_buf == nullptr ? nullptr : GetRigAnimFb(anim_buf);

        // Error loading file. Keep loading but return false.
        if (anim_fb == nullptr) {
          success = false;
          continue;
        }
      }

      // Create RigAnim from FlatBuffer.
      const AnimIndex new_idx = static_cast<AnimIndex>(anims_.size());
      anims_.resize(new_idx + 1);
      RigAnimFromFlatBuffers(*anim_fb, &anims_[new_idx]);

      // Insert index into name map so that we only load this anim once.
      name_map_.insert(NameToIndex(anim_name, new_idx));
      list[anim_idx] = new_idx;
    }
  }

  // Now that all animations have been loaded, calculate defining animation,
  // which is the union of all the animations on an object.
  CalculateDefiningAnims();
  return success;
}

static const RigAnim* FindCompleteRig(const RigAnim** anims, size_t num_anims) {
  // We assume that that animation with the most bones has all the bones.
  // Not necessarily true, since all animations could animate a subset of the
  // rig. We should really do a deeper union of the bone hierarchy.
  assert(num_anims > 0);
  BoneIndex max_bone_index = 0;
  for (size_t i = 1; i < num_anims; ++i) {
    if (anims[i]->NumBones() > anims[max_bone_index]->NumBones()) {
      max_bone_index = static_cast<BoneIndex>(i);
    }
  }
  return anims[max_bone_index];
}

static const MatrixOperationInit* FindOpInit(const MatrixOpArray::OpVector& ops,
                                             MatrixOperationType op) {
  for (size_t i = 0; i < ops.size(); ++i) {
    if (ops[i].type == op) return &ops[i];
  }
  return nullptr;
}

static void CreateDefiningAnim(const RigAnim** anims, size_t num_anims,
                               RigAnim* defining_anim) {
  // Get the bone hierarchy that covers all the hierarchies in `anims`.
  const RigAnim* complete_rig = FindCompleteRig(anims, num_anims);
  const BoneIndex num_bones = complete_rig->NumBones();
  const BoneIndex* parents = complete_rig->bone_parents();
  defining_anim->Init("defining_anim", num_bones, true);

  // For each bone, consider adding each operation in the canonical operations.
  for (BoneIndex j = 0; j < num_bones; ++j) {
    // Start initializing this bone.
    MatrixAnim& matrix_anim =
        defining_anim->InitMatrixAnim(j, parents[j], complete_rig->BoneName(j));
    MatrixOpArray& ops = matrix_anim.ops();

    // Create a sorted map from operation id to the range of values that it
    // takes.
    struct OpRange {
      MatrixOperationType op;
      Range range;
    };
    std::map<int, OpRange> id_to_range;

    for (size_t i = 0; i < num_anims; ++i) {
      if (j >= anims[i]->NumBones()) continue;
      const MatrixOpArray::OpVector& opv = anims[i]->Anim(j).ops().ops();
      for (auto op_it = opv.begin(); op_it != opv.end(); ++op_it) {
        const MatrixOperationInit& op_init = *op_it;
        auto& range_it = id_to_range[op_init.id];

        // Bone `j` with matrix op id `op_init.id` has two animations with
        // mismatched operations. Things will go strangely when a kTranslateX
        // is blended with a kScaleZ, for example.
        assert(range_it.op == kInvalidMatrixOperation ||
               range_it.op == op_init.type);

        range_it.op = op_init.type;
        Range& range = range_it.range;
        if (op_init.init == nullptr) {
          range = range.Include(op_init.initial_value);
        } else {
          range = Range::Full();
        }
      }
    }

    // Count the number of ranges that need init parameters.
    int num_ops_with_init = 0;
    for (auto it = id_to_range.begin(); it != id_to_range.end(); ++it) {
      if (it->second.range.Length() > 0.0f) num_ops_with_init++;
    }
    MatrixAnim::Spline* splines = matrix_anim.Construct(num_ops_with_init);

    // Create the array of matrix operations.
    int num_ops_inited = 0;
    for (auto it = id_to_range.begin(); it != id_to_range.end(); ++it) {
      // If this operation exists, add it to the `defining_anim`.
      const MatrixOpId id = it->first;
      const MatrixOperationType op = it->second.op;
      const Range& range = it->second.range;
      if (range.Length() == 0.0f) {
        // If there is only one value for an operation, add it as a const.
        const float const_value = range.start();
        ops.AddOp(id, op, const_value);
      } else {
        // Otherwise, add it as an animated parameter.
        // The range is modular for rotate operations, but not for scale or
        // translate operations.
        const Range& op_range = RangeOfOp(op);
        splines[num_ops_inited].init = SplineInit(op_range);
        ops.AddOp(id, op, splines[num_ops_inited].init);
        num_ops_inited++;
      }
    }
  }
}

size_t AnimTable::MaxAnimIndex() const {
  size_t max_anim_idx = 0;
  for (size_t i = 0; i < indices_.size(); ++i) {
    max_anim_idx = std::max(max_anim_idx, indices_[i].size());
  }
  return max_anim_idx;
}

size_t AnimTable::GatherObjectAnims(int object, const RigAnim** anims) const {
  const AnimList& list = indices_[object];
  size_t num_anims = 0;
  for (size_t j = 0; j < list.size(); ++j) {
    if (list[j] == kInvalidAnimIndex) continue;
    anims[num_anims++] = &anims_[list[j]];
  }
  return num_anims;
}

void AnimTable::CalculateDefiningAnims() {
  std::vector<const RigAnim*> anims(MaxAnimIndex());
  for (int object = 0; object < NumObjects(); ++object) {
    const size_t num_anims = GatherObjectAnims(object, &anims[0]);
    if (num_anims == 0) continue;

    CreateDefiningAnim(&anims[0], num_anims, &defining_anims_[object]);
  }
}

}  // namespace motive
<commit_msg>Add virtual destructor to TableDescriberInterface.<commit_after>// Copyright 2015 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <map>

#include "anim_generated.h"
#include "anim_table_generated.h"
#include "motive/anim_table.h"
#include "motive/io/flatbuffers.h"

using motive::Range;

namespace motive {

// Wrap the source data for an AnimTable.
// Allows AnimTables to be loaded from many different data sources.
class TableDescriberInterface {
 public:
  virtual ~TableDescriberInterface() {}
  virtual int NumObjects() const = 0;
  virtual int NumAnims(int object) const = 0;
  virtual const char* SourceFileName(int object, int anim_idx) const = 0;
  virtual const RigAnimFb* SourceRigAnimFb(int object, int anim_idx) const = 0;
};

static int AnimListLen(const AnimListFb* list) {
  if (list == nullptr) return 0;

  // Handle `anims` interface (with union).
  if (list->anims() != nullptr) return static_cast<int>(list->anims()->size());

  // Handle `anim_files` interface.
  if (list->anim_files() != nullptr)
    return static_cast<int>(list->anim_files()->size());

  return 0;
}

static const char* AnimListFileName(const AnimListFb* list, int anim_idx) {
  if (list == nullptr) return nullptr;

  // Handle `anims` interface (with union).
  if (list->anims() != nullptr) {
    const AnimSource* source = list->anims()->Get(anim_idx);
    if (source->u_type() != AnimSourceUnion_AnimSourceFileName) return nullptr;
    return reinterpret_cast<const AnimSourceFileName*>(source->u())
        ->file_name()
        ->c_str();
  }

  // Handle `anim_files` interface.
  if (list->anim_files() != nullptr)
    return list->anim_files()->Get(anim_idx)->c_str();

  return nullptr;
}

static const RigAnimFb* AnimListRigAnimFb(const AnimListFb* list,
                                          int anim_idx) {
  if (list == nullptr) return nullptr;

  // Handle `anims` interface (with union).
  if (list->anims() != nullptr) {
    const AnimSource* source = list->anims()->Get(anim_idx);
    if (source->u_type() != AnimSourceUnion_AnimSourceEmbedded) return nullptr;
    return reinterpret_cast<const AnimSourceEmbedded*>(source->u())->embedded();
  }

  return nullptr;
}

class AnimTableFbDescriber : public TableDescriberInterface {
 public:
  explicit AnimTableFbDescriber(const AnimTableFb& table_fb)
      : table_fb_(&table_fb) {}
  virtual int NumObjects() const {
    return table_fb_->lists() == nullptr
               ? 0
               : static_cast<int>(table_fb_->lists()->size());
  }
  virtual int NumAnims(int object) const { return AnimListLen(List(object)); }
  virtual const char* SourceFileName(int object, int anim_idx) const {
    return AnimListFileName(List(object), anim_idx);
  }
  virtual const RigAnimFb* SourceRigAnimFb(int object, int anim_idx) const {
    return AnimListRigAnimFb(List(object), anim_idx);
  }

 protected:
  const AnimListFb* List(int object) const {
    return table_fb_->lists() == nullptr ? nullptr
                                         : table_fb_->lists()->Get(object);
  }

  const AnimTableFb* table_fb_;
};

class AnimListFbDescriber : public TableDescriberInterface {
 public:
  explicit AnimListFbDescriber(const AnimListFb& list_fb)
      : list_fb_(&list_fb) {}
  virtual int NumObjects() const { return AnimListLen(list_fb_) == 0 ? 0 : 1; }
  virtual int NumAnims(int /*object*/) const { return AnimListLen(list_fb_); }
  virtual const char* SourceFileName(int /*object*/, int anim_idx) const {
    return AnimListFileName(list_fb_, anim_idx);
  }
  virtual const RigAnimFb* SourceRigAnimFb(int /*object*/, int anim_idx) const {
    return AnimListRigAnimFb(list_fb_, anim_idx);
  }

 protected:
  const AnimListFb* list_fb_;
};

class TableFileNamesDescriber : public TableDescriberInterface {
 public:
  explicit TableFileNamesDescriber(const AnimTable::TableFileNames& table_names)
      : table_names_(&table_names) {}
  virtual int NumObjects() const { return table_names_->size(); }
  virtual int NumAnims(int object) const {
    return (*table_names_)[object].size();
  }
  virtual const char* SourceFileName(int object, int anim_idx) const {
    return (*table_names_)[object][anim_idx].c_str();
  }
  virtual const RigAnimFb* SourceRigAnimFb(int /*object*/,
                                           int /*anim_idx*/) const {
    return nullptr;
  }

 protected:
  const AnimTable::TableFileNames* table_names_;
};

class ListFileNamesDescriber : public TableDescriberInterface {
 public:
  explicit ListFileNamesDescriber(const AnimTable::ListFileNames& list_names)
      : list_names_(&list_names) {}
  virtual int NumObjects() const { return list_names_->size() == 0 ? 0 : 1; }
  virtual int NumAnims(int /*object*/) const { return list_names_->size(); }
  virtual const char* SourceFileName(int /*object*/, int anim_idx) const {
    return (*list_names_)[anim_idx].c_str();
  }
  virtual const RigAnimFb* SourceRigAnimFb(int /*object*/,
                                           int /*anim_idx*/) const {
    return nullptr;
  }

 protected:
  const AnimTable::ListFileNames* list_names_;
};

bool AnimTable::InitFromFlatBuffers(const AnimTableFb& table_fb,
                                    LoadFn* load_fn) {
  AnimTableFbDescriber describer(table_fb);
  return Load(&describer, load_fn);
}

bool AnimTable::InitFromFlatBuffers(const AnimListFb& list_fb,
                                    LoadFn* load_fn) {
  AnimListFbDescriber describer(list_fb);
  return Load(&describer, load_fn);
}

bool AnimTable::InitFromAnimFileNames(const TableFileNames& table_names,
                                      LoadFn* load_fn) {
  TableFileNamesDescriber describer(table_names);
  return Load(&describer, load_fn);
}

bool AnimTable::InitFromAnimFileNames(const ListFileNames& list_names,
                                      LoadFn* load_fn) {
  ListFileNamesDescriber describer(list_names);
  return Load(&describer, load_fn);
}

bool AnimTable::Load(TableDescriberInterface* describer, LoadFn* load_fn) {
  std::string scratch_buf;
  bool success = true;

  // An AnimTable is a list-of-lists. The outside list is indexed by object.
  // Loop through each object (e.g. character type).
  const int num_objects = describer->NumObjects();
  indices_.resize(num_objects);
  defining_anims_.resize(num_objects);
  for (int object = 0; object < num_objects; ++object) {
    const int num_anims = describer->NumAnims(object);
    indices_[object].resize(num_anims);

    // The inside list is animations for the given object.
    // Loop through all animations, loading animations or referencing animations
    // that have already been loaded.
    AnimList& list = indices_[object];
    for (int anim_idx = 0; anim_idx < num_anims; ++anim_idx) {
      // Initialize this anim_idx to point to no data.
      list[anim_idx] = kInvalidAnimIndex;

      const RigAnimFb* anim_fb = describer->SourceRigAnimFb(object, anim_idx);
      const char* anim_name = anim_fb != nullptr
                                  ? anim_fb->name()->c_str()
                                  : describer->SourceFileName(object, anim_idx);

      // Case 1: source data is empty.
      if (anim_name == nullptr || anim_name[0] == '\0') continue;

      // Case 2: source data has already been processed.
      auto existing = name_map_.find(anim_name);
      if (existing != name_map_.end()) {
        list[anim_idx] = existing->second;
        continue;
      }

      // Case 3: load source data.
      if (anim_fb == nullptr) {
        const char* anim_buf = load_fn(anim_name, &scratch_buf);
        anim_fb = anim_buf == nullptr ? nullptr : GetRigAnimFb(anim_buf);

        // Error loading file. Keep loading but return false.
        if (anim_fb == nullptr) {
          success = false;
          continue;
        }
      }

      // Create RigAnim from FlatBuffer.
      const AnimIndex new_idx = static_cast<AnimIndex>(anims_.size());
      anims_.resize(new_idx + 1);
      RigAnimFromFlatBuffers(*anim_fb, &anims_[new_idx]);

      // Insert index into name map so that we only load this anim once.
      name_map_.insert(NameToIndex(anim_name, new_idx));
      list[anim_idx] = new_idx;
    }
  }

  // Now that all animations have been loaded, calculate defining animation,
  // which is the union of all the animations on an object.
  CalculateDefiningAnims();
  return success;
}

static const RigAnim* FindCompleteRig(const RigAnim** anims, size_t num_anims) {
  // We assume that that animation with the most bones has all the bones.
  // Not necessarily true, since all animations could animate a subset of the
  // rig. We should really do a deeper union of the bone hierarchy.
  assert(num_anims > 0);
  BoneIndex max_bone_index = 0;
  for (size_t i = 1; i < num_anims; ++i) {
    if (anims[i]->NumBones() > anims[max_bone_index]->NumBones()) {
      max_bone_index = static_cast<BoneIndex>(i);
    }
  }
  return anims[max_bone_index];
}

static const MatrixOperationInit* FindOpInit(const MatrixOpArray::OpVector& ops,
                                             MatrixOperationType op) {
  for (size_t i = 0; i < ops.size(); ++i) {
    if (ops[i].type == op) return &ops[i];
  }
  return nullptr;
}

static void CreateDefiningAnim(const RigAnim** anims, size_t num_anims,
                               RigAnim* defining_anim) {
  // Get the bone hierarchy that covers all the hierarchies in `anims`.
  const RigAnim* complete_rig = FindCompleteRig(anims, num_anims);
  const BoneIndex num_bones = complete_rig->NumBones();
  const BoneIndex* parents = complete_rig->bone_parents();
  defining_anim->Init("defining_anim", num_bones, true);

  // For each bone, consider adding each operation in the canonical operations.
  for (BoneIndex j = 0; j < num_bones; ++j) {
    // Start initializing this bone.
    MatrixAnim& matrix_anim =
        defining_anim->InitMatrixAnim(j, parents[j], complete_rig->BoneName(j));
    MatrixOpArray& ops = matrix_anim.ops();

    // Create a sorted map from operation id to the range of values that it
    // takes.
    struct OpRange {
      MatrixOperationType op;
      Range range;
    };
    std::map<int, OpRange> id_to_range;

    for (size_t i = 0; i < num_anims; ++i) {
      if (j >= anims[i]->NumBones()) continue;
      const MatrixOpArray::OpVector& opv = anims[i]->Anim(j).ops().ops();
      for (auto op_it = opv.begin(); op_it != opv.end(); ++op_it) {
        const MatrixOperationInit& op_init = *op_it;
        auto& range_it = id_to_range[op_init.id];

        // Bone `j` with matrix op id `op_init.id` has two animations with
        // mismatched operations. Things will go strangely when a kTranslateX
        // is blended with a kScaleZ, for example.
        assert(range_it.op == kInvalidMatrixOperation ||
               range_it.op == op_init.type);

        range_it.op = op_init.type;
        Range& range = range_it.range;
        if (op_init.init == nullptr) {
          range = range.Include(op_init.initial_value);
        } else {
          range = Range::Full();
        }
      }
    }

    // Count the number of ranges that need init parameters.
    int num_ops_with_init = 0;
    for (auto it = id_to_range.begin(); it != id_to_range.end(); ++it) {
      if (it->second.range.Length() > 0.0f) num_ops_with_init++;
    }
    MatrixAnim::Spline* splines = matrix_anim.Construct(num_ops_with_init);

    // Create the array of matrix operations.
    int num_ops_inited = 0;
    for (auto it = id_to_range.begin(); it != id_to_range.end(); ++it) {
      // If this operation exists, add it to the `defining_anim`.
      const MatrixOpId id = it->first;
      const MatrixOperationType op = it->second.op;
      const Range& range = it->second.range;
      if (range.Length() == 0.0f) {
        // If there is only one value for an operation, add it as a const.
        const float const_value = range.start();
        ops.AddOp(id, op, const_value);
      } else {
        // Otherwise, add it as an animated parameter.
        // The range is modular for rotate operations, but not for scale or
        // translate operations.
        const Range& op_range = RangeOfOp(op);
        splines[num_ops_inited].init = SplineInit(op_range);
        ops.AddOp(id, op, splines[num_ops_inited].init);
        num_ops_inited++;
      }
    }
  }
}

size_t AnimTable::MaxAnimIndex() const {
  size_t max_anim_idx = 0;
  for (size_t i = 0; i < indices_.size(); ++i) {
    max_anim_idx = std::max(max_anim_idx, indices_[i].size());
  }
  return max_anim_idx;
}

size_t AnimTable::GatherObjectAnims(int object, const RigAnim** anims) const {
  const AnimList& list = indices_[object];
  size_t num_anims = 0;
  for (size_t j = 0; j < list.size(); ++j) {
    if (list[j] == kInvalidAnimIndex) continue;
    anims[num_anims++] = &anims_[list[j]];
  }
  return num_anims;
}

void AnimTable::CalculateDefiningAnims() {
  std::vector<const RigAnim*> anims(MaxAnimIndex());
  for (int object = 0; object < NumObjects(); ++object) {
    const size_t num_anims = GatherObjectAnims(object, &anims[0]);
    if (num_anims == 0) continue;

    CreateDefiningAnim(&anims[0], num_anims, &defining_anims_[object]);
  }
}

}  // namespace motive
<|endoftext|>


<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2012 Scientific Computing and Imaging Institute,
   University of Utah.

   License for the specific language governing rights and limitations under
   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

#include <QtGui>
#include <iostream>
#include <Interface/Application/ModuleLogWindow.h>
#include <Interface/Application/SCIRunMainWindow.h>
#include <Interface/Application/DialogErrorControl.h>

using namespace SCIRun::Gui;
using namespace SCIRun::Dataflow::Networks;

ModuleLogWindow::ModuleLogWindow(const QString& moduleName, boost::shared_ptr<SCIRun::Gui::DialogErrorControl> dialogErrorControl, QWidget* parent) : QDialog(parent), moduleName_(moduleName),
		dialogErrorControl_(dialogErrorControl)
{
	setupUi(this);
	setModal(false);
	setWindowTitle("Log for " + moduleName);
  setVisible(false);
  buttonBox->button(QDialogButtonBox::Discard)->setText("Foo!");
  connect(buttonBox->button(QDialogButtonBox::Discard), SIGNAL(clicked()), logTextEdit_, SLOT(clear()));
}

void ModuleLogWindow::appendMessage(const QString& message, const QColor& color /* = Qt::black */)
{
  logTextEdit_->insertHtml(QString("
" + message + "

");
}

void ModuleLogWindow::popupMessageBox(const QString& message)
{
  dialogErrorControl_->increaseCounter();
  if (dialogErrorControl_->showDialog())
  {
    QMessageBox* msgBox = new QMessageBox(parentWidget());
    msgBox->setIcon(QMessageBox::Critical);
    msgBox->setAttribute(Qt::WA_DeleteOnClose);
    msgBox->setStandardButtons(QMessageBox::Ok);
    auto showButton = msgBox->addButton("Show Module", QMessageBox::ApplyRole);
    connect(showButton, SIGNAL(clicked()), this, SIGNAL(requestModuleVisible()));
    msgBox->setWindowTitle(windowTitle());
    msgBox->setText("Error in " + moduleName_ + "\n" + message);
    msgBox->setModal(false);
    msgBox->show();
  }
}

ModuleLogger::ModuleLogger(ModuleLogWindow* window)
{
  connect(this, SIGNAL(logSignal(const QString&, const QColor&)), window, SLOT(appendMessage(const QString&, const QColor&)));
  connect(this, SIGNAL(alert(const QColor&)), window, SIGNAL(messageReceived(const QColor&)));
  connect(this, SIGNAL(popup(const QString&)), window, SLOT(popupMessageBox(const QString&)));
}

void ModuleLogger::error(const std::string& msg) const
{
  const QColor red = Qt::red;
  auto qmsg = QString::fromStdString(msg);
  logSignal("ERROR: " + qmsg + "", red);
  alert(red);
  popup(qmsg);
}

void ModuleLogger::warning(const std::string& msg) const
{
  const QColor yellow = Qt::yellow;
  logSignal("WARNING: " + QString::fromStdString(msg), yellow);
  alert(yellow);
}

void ModuleLogger::remark(const std::string& msg) const
{
  const QColor blue = Qt::blue;
  logSignal("REMARK: " + QString::fromStdString(msg), blue);
  alert(blue);
}

void ModuleLogger::status(const std::string& msg) const
{
  logSignal(QString::fromStdString(msg), Qt::black);
}
<commit_msg>Fix platform-dependent log text clear button<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2012 Scientific Computing and Imaging Institute,
   University of Utah.

   License for the specific language governing rights and limitations under
   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

#include <QtGui>
#include <iostream>
#include <Interface/Application/ModuleLogWindow.h>
#include <Interface/Application/SCIRunMainWindow.h>
#include <Interface/Application/DialogErrorControl.h>

using namespace SCIRun::Gui;
using namespace SCIRun::Dataflow::Networks;

ModuleLogWindow::ModuleLogWindow(const QString& moduleName, boost::shared_ptr<SCIRun::Gui::DialogErrorControl> dialogErrorControl, QWidget* parent) : QDialog(parent), moduleName_(moduleName),
		dialogErrorControl_(dialogErrorControl)
{
	setupUi(this);
	setModal(false);
	setWindowTitle("Log for " + moduleName);
  setVisible(false);
  buttonBox->button(QDialogButtonBox::Discard)->setText("Clear");
  connect(buttonBox->button(QDialogButtonBox::Discard), SIGNAL(clicked()), logTextEdit_, SLOT(clear()));
}

void ModuleLogWindow::appendMessage(const QString& message, const QColor& color /* = Qt::black */)
{
  logTextEdit_->insertHtml(QString("
" + message + "

");
}

void ModuleLogWindow::popupMessageBox(const QString& message)
{
  dialogErrorControl_->increaseCounter();
  if (dialogErrorControl_->showDialog())
  {
    QMessageBox* msgBox = new QMessageBox(parentWidget());
    msgBox->setIcon(QMessageBox::Critical);
    msgBox->setAttribute(Qt::WA_DeleteOnClose);
    msgBox->setStandardButtons(QMessageBox::Ok);
    auto showButton = msgBox->addButton("Show Module", QMessageBox::ApplyRole);
    connect(showButton, SIGNAL(clicked()), this, SIGNAL(requestModuleVisible()));
    msgBox->setWindowTitle(windowTitle());
    msgBox->setText("Error in " + moduleName_ + "\n" + message);
    msgBox->setModal(false);
    msgBox->show();
  }
}

ModuleLogger::ModuleLogger(ModuleLogWindow* window)
{
  connect(this, SIGNAL(logSignal(const QString&, const QColor&)), window, SLOT(appendMessage(const QString&, const QColor&)));
  connect(this, SIGNAL(alert(const QColor&)), window, SIGNAL(messageReceived(const QColor&)));
  connect(this, SIGNAL(popup(const QString&)), window, SLOT(popupMessageBox(const QString&)));
}

void ModuleLogger::error(const std::string& msg) const
{
  const QColor red = Qt::red;
  auto qmsg = QString::fromStdString(msg);
  logSignal("ERROR: " + qmsg + "", red);
  alert(red);
  popup(qmsg);
}

void ModuleLogger::warning(const std::string& msg) const
{
  const QColor yellow = Qt::yellow;
  logSignal("WARNING: " + QString::fromStdString(msg), yellow);
  alert(yellow);
}

void ModuleLogger::remark(const std::string& msg) const
{
  const QColor blue = Qt::blue;
  logSignal("REMARK: " + QString::fromStdString(msg), blue);
  alert(blue);
}

void ModuleLogger::status(const std::string& msg) const
{
  logSignal(QString::fromStdString(msg), Qt::black);
}
<|endoftext|>


<commit_before>#pragma once
// TODO: ditch this
#include <gfx/opengl/lib.hpp>
#include <gfx/pipeline.hpp>
#include <gfx/factory.hpp>

#include <stlw/burrito.hpp>
#include <stlw/type_ctors.hpp>

namespace gfx
{

namespace impl
{

template<typename P>
auto
make_shape_factories(P &pipelines)
{
  auto &d2 = pipelines.d2;
  auto &d3 = pipelines.d3;

  gfx::pipeline_factory pf;
  return gfx::make_shape_factories(
    pf.make_pipeline(d2.color),
    pf.make_pipeline(d2.texture_wall),
    pf.make_pipeline(d2.texture_container),
    pf.make_pipeline(d2.wireframe),

    pf.make_pipeline(d3.color),
    pf.make_pipeline(d3.texture),
    pf.make_pipeline(d3.skybox),
    pf.make_pipeline(d3.wireframe));
}

} // ns impl

template <typename L>
struct render_args {
  L &logger;
  camera const& camera;
  glm::mat4 const& projection;
};

template<typename L>
auto make_render_args(L &l, camera const& c, glm::mat4 const& projection)
{
  return render_args<L>{l, c, projection};
}

using namespace stlw;

template<typename B>
class gfx_lib
{
  friend struct factory;
  NO_COPY(gfx_lib);
public:
  B lib;
private:
  gfx_lib(B &&l)
      : lib(MOVE(l))
  {
  }

  template <typename Args, typename Ctx, typename Burrito>
  void draw_burrito(Args const& args, Ctx &ctx, Burrito const& burrito)
  {
    this->lib.draw(args, ctx, stlw::make_burrito(burrito));
  }

  template <typename Args, typename Ctx, typename Burrito>
  void draw_burrito(Args const& args, Ctx &ctx, Burrito &&burrito)
  {
    this->lib.draw(args, ctx, stlw::make_burrito(MOVE(burrito)));
  }

public:
  MOVE_DEFAULT(gfx_lib);

  void begin()
  {
    this->lib.begin();
  }

  // TODO: poc
  auto
  make_shape_factories() const
  {
    return impl::make_shape_factories(this->lib.opengl_pipelines);
  }

  template<typename Args, typename Ctx, template<class, std::size_t> typename C, typename T, std::size_t N>
  void
  draw(Args const& args, Ctx &ctx, C<T, N> const& arr)
  {
    auto x = stlw::tuple_from_array(arr);
    this->draw_burrito(args, ctx, MOVE(x));
  }

  // The last parameter type here ensures that the value passed is similar to a stl container.
  template<typename Args, typename Ctx, typename C, typename IGNORE= typename C::value_type>
  void
  draw(Args const& args, Ctx &ctx, C &&c)
  {
    this->draw_burrito(args, ctx, MOVE(c));
  }

  template<typename Args, typename Ctx, typename ...T>
  void
  draw(Args const& args, Ctx &ctx, std::tuple<T...> &&t)
  {
    this->draw_burrito(args, ctx, MOVE(t));
  }

  template<typename Args, typename Ctx, typename ...T>
  void
  draw(Args const& args, Ctx &ctx, T &&... t)
  {
    this->draw_burrito(args, ctx, std::make_tuple(std::forward<T>(t)...));
  }

  void end()
  {
    this->lib.end();
  }
};

struct factory {
  factory() = delete;
  ~factory() = delete;

  template <typename L, typename LIB>
  static stlw::result<gfx_lib<LIB>, std::string> make(L &logger, LIB &&gfx)
  {
    return gfx_lib<LIB>{MOVE(gfx)};
  }
};

} // ns gfx
<commit_msg>ctx ->pipeline<commit_after>#pragma once
// TODO: ditch this
#include <gfx/opengl/lib.hpp>
#include <gfx/pipeline.hpp>
#include <gfx/factory.hpp>

#include <stlw/burrito.hpp>
#include <stlw/type_ctors.hpp>

namespace gfx
{

namespace impl
{

template<typename P>
auto
make_shape_factories(P &pipelines)
{
  auto &d2 = pipelines.d2;
  auto &d3 = pipelines.d3;

  gfx::pipeline_factory pf;
  return gfx::make_shape_factories(
    pf.make_pipeline(d2.color),
    pf.make_pipeline(d2.texture_wall),
    pf.make_pipeline(d2.texture_container),
    pf.make_pipeline(d2.wireframe),

    pf.make_pipeline(d3.color),
    pf.make_pipeline(d3.texture),
    pf.make_pipeline(d3.skybox),
    pf.make_pipeline(d3.wireframe));
}

} // ns impl

template <typename L>
struct render_args {
  L &logger;
  camera const& camera;
  glm::mat4 const& projection;
};

template<typename L>
auto make_render_args(L &l, camera const& c, glm::mat4 const& projection)
{
  return render_args<L>{l, c, projection};
}

using namespace stlw;

template<typename B>
class gfx_lib
{
  friend struct factory;
  NO_COPY(gfx_lib);
public:
  B lib;
private:
  gfx_lib(B &&l)
      : lib(MOVE(l))
  {
  }

  template <typename Args, typename P, typename Burrito>
  void draw_burrito(Args const& args, P &pipeline, Burrito const& burrito)
  {
    this->lib.draw(args, pipeline, stlw::make_burrito(burrito));
  }

  template <typename Args, typename P, typename Burrito>
  void draw_burrito(Args const& args, P &pipeline, Burrito &&burrito)
  {
    this->lib.draw(args, pipeline, stlw::make_burrito(MOVE(burrito)));
  }

public:
  MOVE_DEFAULT(gfx_lib);

  void begin()
  {
    this->lib.begin();
  }

  // TODO: poc
  auto
  make_shape_factories() const
  {
    return impl::make_shape_factories(this->lib.opengl_pipelines);
  }

  template<typename Args, typename P, template<class, std::size_t> typename Container,
    typename T, std::size_t N>
  void
  draw(Args const& args, P &pipeline, Container<T, N> const& arr)
  {
    auto x = stlw::tuple_from_array(arr);
    this->draw_burrito(args, pipeline, MOVE(x));
  }

  // The last parameter type here ensures that the value passed is similar to a stl container.
  template<typename Args, typename P, typename Container, typename IGNORE= typename Container::value_type>
  void
  draw(Args const& args, P &pipeline, Container &&c)
  {
    this->draw_burrito(args, pipeline, MOVE(c));
  }

  template<typename Args, typename P, typename ...T>
  void
  draw(Args const& args, P &pipeline, std::tuple<T...> &&t)
  {
    this->draw_burrito(args, pipeline, MOVE(t));
  }

  template<typename Args, typename P, typename ...T>
  void
  draw(Args const& args, P &pipeline, T &&... t)
  {
    this->draw_burrito(args, pipeline, std::make_tuple(std::forward<T>(t)...));
  }

  void end()
  {
    this->lib.end();
  }
};

struct factory {
  factory() = delete;
  ~factory() = delete;

  template <typename L, typename LIB>
  static stlw::result<gfx_lib<LIB>, std::string> make(L &logger, LIB &&gfx)
  {
    return gfx_lib<LIB>{MOVE(gfx)};
  }
};

} // ns gfx
<|endoftext|>


<commit_before>#pragma once

#include <unordered_map>
#include <memory>
#include <type_traits>
#include <tuple>

#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc++98-compat"
#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
#pragma clang diagnostic ignored "-Wweak-vtables"
#endif  // CLANG

namespace kgr {

template<typename... Types>
struct Dependency {
	using DependenciesTypes = std::tuple<Types...>;
};

using NoDependencies = Dependency<>;

struct Single {
	using ParentTypes = std::tuple<>;
};

template<typename T>
struct Service;

template<typename... Types>
struct Overrides : Single {
	using ParentTypes = std::tuple<Types...>;
};

namespace detail {

enum class enabler {};

template <bool B, typename T>
using enable_if_t = typename std::enable_if<B, T>::type;

template<int ...>
struct seq { };

template<int N, int ...S>
struct seq_gen : seq_gen<N-1, N-1, S...> { };

template<int ...S>
struct seq_gen<0, S...> {
	using type = seq<S...>;
};

struct Holder {
	virtual ~Holder() = default;
};

template<typename T>
struct InstanceHolder final : Holder {
	explicit InstanceHolder(std::shared_ptr<T> instance) : _instance{std::move(instance)} {}

	std::shared_ptr<T> getInstance() const {
		return _instance;
	}

private:
	std::shared_ptr<T> _instance;
};

template<typename T, typename... Args>
struct CallbackHolder final : Holder {
	using callback_t = std::function<std::shared_ptr<T>(Args...)>;

	explicit CallbackHolder(callback_t callback) : _callback{std::move(callback)} {}

	std::shared_ptr<T> operator ()(Args... args) {
		return _callback(args...);
	}
private:
	callback_t _callback;
};

template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
    return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}

template <typename T> void type_id() {}
using type_id_fn = void(*)();

} // namespace detail

struct Container : std::enable_shared_from_this<Container> {
private:
	template<typename Condition, typename T = detail::enabler> using enable_if = detail::enable_if_t<Condition::value, T>;
	template<typename Condition, typename T = detail::enabler> using disable_if = detail::enable_if_t<!Condition::value, T>;
	template<typename T> using is_service_single = std::is_base_of<Single, Service<T>>;
	template<typename T> using is_abstract = std::is_abstract<T>;
	template<typename T> using is_base_of_container = std::is_base_of<Container, T>;
	template<typename T> using is_container = std::is_same<T, Container>;
	template<typename T> using dependency_types = typename Service<T>::DependenciesTypes;
	template<typename T> using parent_types = typename Service<T>::ParentTypes;
	template <typename Tuple> using tuple_seq = typename detail::seq_gen<std::tuple_size<Tuple>::value>::type;
	template<int S, typename T> using parent_element = typename std::tuple_element<S, parent_types<T>>::type;
	template<int S, typename Tuple> using tuple_element = typename std::tuple_element<S, Tuple>::type;
	using holder_ptr = std::unique_ptr<detail::Holder>;
	using holder_cont = std::unordered_map<detail::type_id_fn, holder_ptr>;
	constexpr static detail::enabler null = {};

public:
	Container() = default;
	Container(const Container &) = default;
	Container(Container &&) = default;
	Container& operator =(const Container &) = default;
	Container& operator =(Container &&) = default;
	virtual ~Container() = default;

	template<typename T>
	void instance(std::shared_ptr<T> service) {
		static_assert(is_service_single<T>::value, "instance only accept Single Service instance.");

		call_save_instance(std::move(service), tuple_seq<parent_types<T>>{});
	}

	template<typename T>
	void instance() {
		static_assert(is_service_single<T>::value, "instance only accept Single Service instance.");

		instance(make_service<T>());
	}

	template<typename T, disable_if<is_abstract<T>> = null, disable_if<is_base_of_container<T>> = null>
	std::shared_ptr<T> service() {
		return get_service<T>();
	}

	template<typename T, enable_if<is_container<T>> = null>
	std::shared_ptr<T> service() {
		return shared_from_this();
	}

	template<typename T, disable_if<is_container<T>> = null, enable_if<is_base_of_container<T>> = null>
	std::shared_ptr<T> service() {
		return std::dynamic_pointer_cast<T>(shared_from_this());
	}

	template<typename T, enable_if<is_abstract<T>> = null>
	std::shared_ptr<T> service() {
		auto it = _services.find(&detail::template type_id<T>);

		if (it != _services.end()) {
			auto holder = static_cast<detail::InstanceHolder<T>*>(it->second.get());

			if (holder) {
				return holder->getInstance();
			}
		}
		return {};
	}

	template<typename T, typename U>
	void callback(U callback) {
		static_assert(!is_service_single<T>::value, "instance does not accept Single Service.");

		save_callback<T, dependency_types<T>>(tuple_seq<dependency_types<T>>{}, callback);
	}

	virtual void init(){}

private:
	template<typename T, enable_if<is_service_single<T>> = null>
	std::shared_ptr<T> get_service() {
		auto it = _services.find(&detail::template type_id<T>);

		if (it == _services.end()) {
			auto service = make_service<T>();
			instance(service);

			return service;
		} else {
			auto holder = static_cast<detail::InstanceHolder<T>*>(it->second.get());

			if (holder) {
				return holder->getInstance();
			}
		}
		return {};
	}

	template<typename T, disable_if<is_service_single<T>> = null>
	std::shared_ptr<T> get_service() {
		return make_service<T>();
	}

	template<typename T, int ...S>
	void call_save_instance(std::shared_ptr<T> service, detail::seq<S...>) {
		save_instance<T, parent_element<S, T>...>(std::move(service));
	}

	template<typename Tuple, int ...S>
	std::tuple<std::shared_ptr<tuple_element<S, Tuple>>...> dependency(detail::seq<S...>) {
		return std::make_tuple(service<tuple_element<S, Tuple>>()...);
	}

	template<typename T, typename Tuple, int ...S>
	std::shared_ptr<T> callback_make_service(detail::seq<S...>, Tuple dependencies) const {
		auto it = _callbacks.find(&detail::template type_id<T>);

		if (it != _callbacks.end()) {
			auto holder = static_cast<detail::CallbackHolder<T, tuple_element<S, Tuple>...>*>(it->second.get());
			if (holder) {
				return (*holder)(std::get<S>(dependencies)...);
			}
		}
		return {};
	}

	template<typename T, typename Tuple, int ...S>
	std::shared_ptr<T> make_service(detail::seq<S...> seq, Tuple dependencies) const {
		auto service = callback_make_service<T, Tuple>(seq, dependencies);

		if (service) {
			return service;
		}

		return std::make_shared<T>(std::get<S>(dependencies)...);
	}

	template <typename T>
	std::shared_ptr<T> make_service() {
		auto seq = tuple_seq<dependency_types<T>>{};
		return make_service<T>(seq, dependency<dependency_types<T>>(seq));
	}

	template<typename T, typename ...Others>
	detail::enable_if_t<(sizeof...(Others) > 0), void> save_instance(std::shared_ptr<T> service) {
		save_instance<T>(service);
		save_instance<Others...>(std::move(service));
	}

	template<typename T>
	void save_instance (std::shared_ptr<T> service) {
		_services[&detail::template type_id<T>] = detail::make_unique<detail::InstanceHolder<T>>(std::move(service));
	}

	template<typename T, typename Tuple, int ...S, typename U>
	void save_callback (detail::seq<S...>, U callback) {
		_callbacks[&detail::template type_id<T>] = detail::make_unique<detail::CallbackHolder<T, std::shared_ptr<tuple_element<S, Tuple>>...>>(callback);
	}

	holder_cont _callbacks;
	holder_cont _services;
};

template<typename T = Container, typename ...Args>
std::shared_ptr<T> make_container(Args&& ...args) {
	static_assert(std::is_base_of<Container, T>::value, "make_container only accept container types.");

	auto container = std::make_shared<T>(std::forward<Args>(args)...);
	container->init();

	return container;
}

}  // namespace kgr

#if defined(__clang__)
#pragma clang diagnostic pop
#endif  // CLANG
<commit_msg>no need for virtual destructor of vtable aanymore<commit_after>#pragma once

#include <unordered_map>
#include <memory>
#include <type_traits>
#include <tuple>

#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc++98-compat"
#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
#endif  // CLANG

namespace kgr {

template<typename... Types>
struct Dependency {
	using DependenciesTypes = std::tuple<Types...>;
};

using NoDependencies = Dependency<>;

struct Single {
	using ParentTypes = std::tuple<>;
};

template<typename T>
struct Service;

template<typename... Types>
struct Overrides : Single {
	using ParentTypes = std::tuple<Types...>;
};

namespace detail {

enum class enabler {};

template <bool B, typename T>
using enable_if_t = typename std::enable_if<B, T>::type;

template<int ...>
struct seq { };

template<int N, int ...S>
struct seq_gen : seq_gen<N-1, N-1, S...> { };

template<int ...S>
struct seq_gen<0, S...> {
	using type = seq<S...>;
};

struct Holder {};

template<typename T>
struct InstanceHolder final : Holder {
	explicit InstanceHolder(std::shared_ptr<T> instance) : _instance{std::move(instance)} {}

	std::shared_ptr<T> getInstance() const {
		return _instance;
	}

private:
	std::shared_ptr<T> _instance;
};

template<typename T, typename... Args>
struct CallbackHolder final : Holder {
	using callback_t = std::function<std::shared_ptr<T>(Args...)>;

	explicit CallbackHolder(callback_t callback) : _callback{std::move(callback)} {}

	std::shared_ptr<T> operator ()(Args... args) {
		return _callback(args...);
	}
private:
	callback_t _callback;
};

template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
    return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}

template <typename T> void type_id() {}
using type_id_fn = void(*)();

} // namespace detail

struct Container : std::enable_shared_from_this<Container> {
private:
	template<typename Condition, typename T = detail::enabler> using enable_if = detail::enable_if_t<Condition::value, T>;
	template<typename Condition, typename T = detail::enabler> using disable_if = detail::enable_if_t<!Condition::value, T>;
	template<typename T> using is_service_single = std::is_base_of<Single, Service<T>>;
	template<typename T> using is_abstract = std::is_abstract<T>;
	template<typename T> using is_base_of_container = std::is_base_of<Container, T>;
	template<typename T> using is_container = std::is_same<T, Container>;
	template<typename T> using dependency_types = typename Service<T>::DependenciesTypes;
	template<typename T> using parent_types = typename Service<T>::ParentTypes;
	template <typename Tuple> using tuple_seq = typename detail::seq_gen<std::tuple_size<Tuple>::value>::type;
	template<int S, typename T> using parent_element = typename std::tuple_element<S, parent_types<T>>::type;
	template<int S, typename Tuple> using tuple_element = typename std::tuple_element<S, Tuple>::type;
	using holder_ptr = std::unique_ptr<detail::Holder>;
	using holder_cont = std::unordered_map<detail::type_id_fn, holder_ptr>;
	constexpr static detail::enabler null = {};

public:
	Container() = default;
	Container(const Container &) = default;
	Container(Container &&) = default;
	Container& operator =(const Container &) = default;
	Container& operator =(Container &&) = default;
	virtual ~Container() = default;

	template<typename T>
	void instance(std::shared_ptr<T> service) {
		static_assert(is_service_single<T>::value, "instance only accept Single Service instance.");

		call_save_instance(std::move(service), tuple_seq<parent_types<T>>{});
	}

	template<typename T>
	void instance() {
		static_assert(is_service_single<T>::value, "instance only accept Single Service instance.");

		instance(make_service<T>());
	}

	template<typename T, disable_if<is_abstract<T>> = null, disable_if<is_base_of_container<T>> = null>
	std::shared_ptr<T> service() {
		return get_service<T>();
	}

	template<typename T, enable_if<is_container<T>> = null>
	std::shared_ptr<T> service() {
		return shared_from_this();
	}

	template<typename T, disable_if<is_container<T>> = null, enable_if<is_base_of_container<T>> = null>
	std::shared_ptr<T> service() {
		return std::dynamic_pointer_cast<T>(shared_from_this());
	}

	template<typename T, enable_if<is_abstract<T>> = null>
	std::shared_ptr<T> service() {
		auto it = _services.find(&detail::template type_id<T>);

		if (it != _services.end()) {
			auto holder = static_cast<detail::InstanceHolder<T>*>(it->second.get());

			if (holder) {
				return holder->getInstance();
			}
		}
		return {};
	}

	template<typename T, typename U>
	void callback(U callback) {
		static_assert(!is_service_single<T>::value, "instance does not accept Single Service.");

		save_callback<T, dependency_types<T>>(tuple_seq<dependency_types<T>>{}, callback);
	}

	virtual void init(){}

private:
	template<typename T, enable_if<is_service_single<T>> = null>
	std::shared_ptr<T> get_service() {
		auto it = _services.find(&detail::template type_id<T>);

		if (it == _services.end()) {
			auto service = make_service<T>();
			instance(service);

			return service;
		} else {
			auto holder = static_cast<detail::InstanceHolder<T>*>(it->second.get());

			if (holder) {
				return holder->getInstance();
			}
		}
		return {};
	}

	template<typename T, disable_if<is_service_single<T>> = null>
	std::shared_ptr<T> get_service() {
		return make_service<T>();
	}

	template<typename T, int ...S>
	void call_save_instance(std::shared_ptr<T> service, detail::seq<S...>) {
		save_instance<T, parent_element<S, T>...>(std::move(service));
	}

	template<typename Tuple, int ...S>
	std::tuple<std::shared_ptr<tuple_element<S, Tuple>>...> dependency(detail::seq<S...>) {
		return std::make_tuple(service<tuple_element<S, Tuple>>()...);
	}

	template<typename T, typename Tuple, int ...S>
	std::shared_ptr<T> callback_make_service(detail::seq<S...>, Tuple dependencies) const {
		auto it = _callbacks.find(&detail::template type_id<T>);

		if (it != _callbacks.end()) {
			auto holder = static_cast<detail::CallbackHolder<T, tuple_element<S, Tuple>...>*>(it->second.get());
			if (holder) {
				return (*holder)(std::get<S>(dependencies)...);
			}
		}
		return {};
	}

	template<typename T, typename Tuple, int ...S>
	std::shared_ptr<T> make_service(detail::seq<S...> seq, Tuple dependencies) const {
		auto service = callback_make_service<T, Tuple>(seq, dependencies);

		if (service) {
			return service;
		}

		return std::make_shared<T>(std::get<S>(dependencies)...);
	}

	template <typename T>
	std::shared_ptr<T> make_service() {
		auto seq = tuple_seq<dependency_types<T>>{};
		return make_service<T>(seq, dependency<dependency_types<T>>(seq));
	}

	template<typename T, typename ...Others>
	detail::enable_if_t<(sizeof...(Others) > 0), void> save_instance(std::shared_ptr<T> service) {
		save_instance<T>(service);
		save_instance<Others...>(std::move(service));
	}

	template<typename T>
	void save_instance (std::shared_ptr<T> service) {
		_services[&detail::template type_id<T>] = detail::make_unique<detail::InstanceHolder<T>>(std::move(service));
	}

	template<typename T, typename Tuple, int ...S, typename U>
	void save_callback (detail::seq<S...>, U callback) {
		_callbacks[&detail::template type_id<T>] = detail::make_unique<detail::CallbackHolder<T, std::shared_ptr<tuple_element<S, Tuple>>...>>(callback);
	}

	holder_cont _callbacks;
	holder_cont _services;
};

template<typename T = Container, typename ...Args>
std::shared_ptr<T> make_container(Args&& ...args) {
	static_assert(std::is_base_of<Container, T>::value, "make_container only accept container types.");

	auto container = std::make_shared<T>(std::forward<Args>(args)...);
	container->init();

	return container;
}

}  // namespace kgr

#if defined(__clang__)
#pragma clang diagnostic pop
#endif  // CLANG
<|endoftext|>