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

  Program:   Visualization Toolkit
  Module:    vtkImageAnisotropicDiffusion2D.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$
  Thanks:    Thanks to C. Charles Law who developed this class.

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include <math.h>
#include "vtkImageAnisotropicDiffusion2D.h"

//----------------------------------------------------------------------------
// Description:
// Construct an instance of vtkImageAnisotropicDiffusion2D fitler.
vtkImageAnisotropicDiffusion2D::vtkImageAnisotropicDiffusion2D()
{
  this->HandleBoundaries = 1;
  this->SetNumberOfIterations(4);
  this->DiffusionThreshold = 5.0;
  this->DiffusionFactor = 1;
  this->EdgesOn();
  this->CornersOn();
  this->GradientMagnitudeThresholdOff();
}

//----------------------------------------------------------------------------
void
vtkImageAnisotropicDiffusion2D::PrintSelf(ostream& os, vtkIndent indent)
{
  this->vtkImageSpatialFilter::PrintSelf(os, indent);
  os << indent << "NumberOfIterations: " << this->NumberOfIterations << "\n";
  os << indent << "DiffusionThreshold: " << this->DiffusionThreshold << "\n";
  os << indent << "DiffusionFactor: " << this->DiffusionFactor << "\n";

  if (this->Edges)
    {
    os << indent << "Edges: On\n";
    }
  else
    {
    os << indent << "Edges: Off\n";
    }

  if (this->Corners)
    {
    os << indent << "Corners: On\n";
    }
  else
    {
    os << indent << "Corners: Off\n";
    }

  if (this->GradientMagnitudeThreshold)
    {
    os << indent << "GradientMagnitudeThreshold: On\n";
    }
  else
    {
    os << indent << "GradientMagnitudeThreshold: Off\n";
    }
}

//----------------------------------------------------------------------------
// Description:
// This method sets the number of inputs which also affects the
// input neighborhood needed to compute one output pixel.
void vtkImageAnisotropicDiffusion2D::SetNumberOfIterations(int num)
{
  int temp;

  vtkDebugMacro(<< "SetNumberOfIterations: " << num);
  if (this->NumberOfIterations == num) return;

  this->Modified();
  temp = num*2 + 1;
  this->KernelSize[0] = temp;
  this->KernelSize[1] = temp;
  this->KernelMiddle[0] = num;
  this->KernelMiddle[1] = num;

  this->NumberOfIterations = num;
}

//----------------------------------------------------------------------------
// Description:
// This method contains a switch statement that calls the correct
// templated function for the input data type.  The input and output datas
// must have the same data type.
void vtkImageAnisotropicDiffusion2D::ThreadedExecute(vtkImageData *inData,
						     vtkImageData *outData,
						     int outExt[6], int id)
{
  int inExt[6];
  float *ar;
  int idx;
  vtkImageData *temp;

  this->ComputeRequiredInputUpdateExtent(inExt,outExt);

  vtkDebugMacro(<< "Execute: inData = " << inData
  << ", outData = " << outData);

  // this filter expects that input is the same type as output.
  if (inData->GetScalarType() != outData->GetScalarType())
    {
    vtkErrorMacro(<< "Execute: input ScalarType, " << inData->GetScalarType()
                  << ", must match out ScalarType " << outData->GetScalarType());
    return;
    }

  ar = inData->GetSpacing();

  // make the temporary regions to iterate over.
  vtkImageData *in = vtkImageData::New();
  in->SetExtent(inExt);
  in->SetNumberOfScalarComponents(inData->GetNumberOfScalarComponents());
  in->SetScalarType(VTK_FLOAT);
  in->CopyAndCastFrom(inData,inExt);

  vtkImageData *out = vtkImageData::New();
  out->SetExtent(inExt);
  out->SetNumberOfScalarComponents(inData->GetNumberOfScalarComponents());
  out->SetScalarType(VTK_FLOAT);

  // Loop performing the diffusion
  // Note: region extent could get smaller as the diffusion progresses
  // (but never get smaller than output region).
  for (idx = this->NumberOfIterations - 1; idx >= 0; --idx)
    {
    if (!id) this->UpdateProgress((float)(this->NumberOfIterations - idx)
				  /this->NumberOfIterations);
    this->Iterate(in, out, ar[0], ar[1], outExt, idx);
    temp = in;
    in = out;
    out = temp;
    }

  // copy results into output.
  outData->CopyAndCastFrom(in,outExt);
  in->Delete();
  out->Delete();
}

//----------------------------------------------------------------------------
// Description:
// This method performs one pass of the diffusion filter.
// The inData and outData are assumed to have data type float,
// and have the same extent.
void vtkImageAnisotropicDiffusion2D::Iterate(vtkImageData *inData,
					     vtkImageData *outData,
					     float ar0, float ar1,
					     int *coreExtent, int count)
{
  int idx0, idx1, idx2;
  int inInc0, inInc1, inInc2;
  int outInc0, outInc1, outInc2;
  int inMin0, inMax0, inMin1, inMax1, inMin2, inMax2;
  int min0, max0, min1, max1, min2, max2;
  float *inPtr0, *inPtr1, *inPtr2;
  float *outPtr0, *outPtr1, *outPtr2;
  float th0, th1, th01;
  float df0, df1, df01;
  float temp, sum;
  int idxC, maxC;

  maxC = inData->GetNumberOfScalarComponents();
  inData->GetExtent(inMin0, inMax0, inMin1, inMax1, inMin2, inMax2);
  inData->GetIncrements(inInc0, inInc1, inInc2);
  outData->GetIncrements(outInc0, outInc1, outInc2);

  // Avoid warnings.
  th0 = th1 = th01 = df0 = df1 = df01 = 0.0;

  // Compute direction specific diffusion thresholds and factors.
  sum = 0.0;
  if (this->Edges)
    {
    th0 = ar0 * this->DiffusionThreshold;
    df0 = 1.0 / ar0;
    th1 = ar1 * this->DiffusionThreshold;
    df1 = 1.0 / ar1;
    // two edges per direction.
    sum += 2.0 * (df0 + df1);
    }
  if (this->Corners)
    {
    temp = sqrt(ar0*ar0 + ar1*ar1);
    th01 = temp * this->DiffusionThreshold;
    df01 = 1 / temp;
    // four corners per plane
    sum += 4 * (df01);
    }

  if (sum > 0.0)
    {
    temp = this->DiffusionFactor / sum;
    df0 *= temp;
    df1 *= temp;
    df01 *= temp;
    }
  else
    {
    vtkWarningMacro(<< "Iterate: NO NEIGHBORS");
    return;
    }

  // Compute the shrinking extent to loop over.
  min0 = coreExtent[0] - count;
  max0 = coreExtent[1] + count;
  min1 = coreExtent[2] - count;
  max1 = coreExtent[3] + count;
  // intersection
  min0 = (min0 > inMin0) ? min0 : inMin0;
  max0 = (max0 < inMax0) ? max0 : inMax0;
  min1 = (min1 > inMin1) ? min1 : inMin1;
  max1 = (max1 < inMax1) ? max1 : inMax1;

  vtkDebugMacro(<< "Iteration count: " << count << " ("
  << min0 << ", " << max0 << ", " << min1 << ", " << max1 << ")");

  // I apologize for explicitely diffusing each neighbor, but it is the easiest
  // way to deal with the boundary conditions.  Besides it is fast.
  // (Are you sure every one is correct?!!!)
  inPtr2 = (float *)(inData->GetScalarPointer(min0, min1, min2));
  outPtr2 = (float *)(outData->GetScalarPointer(min0, min1, min2));

  for (idxC = 0; idxC < maxC; idxC++)
    {
    inPtr2 = (float *)(inData->GetScalarPointer(min0, min1, min2));
    outPtr2 = (float *)(outData->GetScalarPointer(min0, min1, min2));
    inPtr2 += idxC;
    outPtr2 += idxC;

    for (idx2 = min2; idx2 <= max2; ++idx2, inPtr2+=inInc2, outPtr2+=outInc2)
      {
      inPtr1 = inPtr2;
      outPtr1 = outPtr2;
      for (idx1 = min1; idx1 <= max1; ++idx1, inPtr1+=inInc1, outPtr1+=outInc1)
	{
	inPtr0 = inPtr1;
	outPtr0 = outPtr1;
	for (idx0 = min0; idx0 <= max0; ++idx0, inPtr0+=inInc0, outPtr0+=outInc0)
	  {
	  // Copy center
	  *outPtr0 = *inPtr0;

	  // Special case for gradient magnitude threhsold
	  if (this->GradientMagnitudeThreshold)
	    {
	    float d0, d1;
	    // compute the gradient magnitude (central differences).
	    d0  = (idx0 != inMax0) ? inPtr0[inInc0] : *inPtr0;
	    d0 -= (idx0 != inMin0) ? inPtr0[-inInc0] : *inPtr0;
	    d0 /= ar0;
	    d1  = (idx1 != inMax1) ? inPtr0[inInc1] : *inPtr0;
	    d1 -= (idx1 != inMin1) ? inPtr0[-inInc1] : *inPtr0;
	    d1 /= ar1;
	    // If magnitude is big, don't diffuse.
	    d0 = sqrt(d0*d0 + d1*d1);
	    if (d0 > this->DiffusionThreshold)
	      {
	      // hack to not diffuse
	      th0 = th1 = th01 = 0.0;
	      }
	    else
	      {
	      // hack to diffuse
	      th0 = th1 = th01 = VTK_LARGE_FLOAT;
	      }
	    }

	  // Start diffusing
	  if (this->Edges)
	    {
	    // left
	    if (idx0 != inMin0)
	      {
	      temp = inPtr0[-inInc0] - *inPtr0;
	      if (fabs(temp) < th0)
		{
		*outPtr0 += temp * df0;
		}
	      }
	    // right
	    if (idx0 != inMax0)
	      {
	      temp = inPtr0[inInc0] - *inPtr0;
	      if (fabs(temp) < th0)
		{
		*outPtr0 += temp * df0;
		}
	      }
	    // up
	    if (idx1 != inMin1)
	      {
	      temp = inPtr0[-inInc1] - *inPtr0;
	      if (fabs(temp) < th1)
		{
		*outPtr0 += temp * df1;
		}
	      }
	    // down
	    if (idx1 != inMax1)
	      {
	      temp = inPtr0[inInc1] - *inPtr0;
	      if (fabs(temp) < th1)
		{
		*outPtr0 += temp * df1;
		}
	      }
	    }

	  if (this->Corners)
	    {
	    // left up
	    if (idx0 != inMin0 && idx1 != inMin1)
	      {
	      temp = inPtr0[-inInc0-inInc1] - *inPtr0;
	      if (fabs(temp) < th01)
		{
		*outPtr0 += temp * df01;
		}
	      }
	    // right up
	    if (idx0 != inMax0 && idx1 != inMin1)
	      {
	      temp = inPtr0[inInc0-inInc1] - *inPtr0;
	      if (fabs(temp) < th01)
		{
		*outPtr0 += temp * df01;
		}
	      }
	    // left down
	    if (idx0 != inMin0 && idx1 != inMax1)
	      {
	      temp = inPtr0[-inInc0+inInc1] - *inPtr0;
	      if (fabs(temp) < th01)
		{
		*outPtr0 += temp * df01;
		}
	      }
	    // right down
	    if (idx0 != inMax0 && idx1 != inMax1)
	      {
	      temp = inPtr0[inInc0+inInc1] - *inPtr0;
	      if (fabs(temp) < th01)
		{
		*outPtr0 += temp * df01;
		}
	      }
	    }
	  }
	}
      }
    }
}

<commit_msg>BUG: z axis ectent not handled correctly<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkImageAnisotropicDiffusion2D.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$
  Thanks:    Thanks to C. Charles Law who developed this class.

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include <math.h>
#include "vtkImageAnisotropicDiffusion2D.h"

//----------------------------------------------------------------------------
// Description:
// Construct an instance of vtkImageAnisotropicDiffusion2D fitler.
vtkImageAnisotropicDiffusion2D::vtkImageAnisotropicDiffusion2D()
{
  this->HandleBoundaries = 1;
  this->SetNumberOfIterations(4);
  this->DiffusionThreshold = 5.0;
  this->DiffusionFactor = 1;
  this->EdgesOn();
  this->CornersOn();
  this->GradientMagnitudeThresholdOff();
}

//----------------------------------------------------------------------------
void
vtkImageAnisotropicDiffusion2D::PrintSelf(ostream& os, vtkIndent indent)
{
  this->vtkImageSpatialFilter::PrintSelf(os, indent);
  os << indent << "NumberOfIterations: " << this->NumberOfIterations << "\n";
  os << indent << "DiffusionThreshold: " << this->DiffusionThreshold << "\n";
  os << indent << "DiffusionFactor: " << this->DiffusionFactor << "\n";

  if (this->Edges)
    {
    os << indent << "Edges: On\n";
    }
  else
    {
    os << indent << "Edges: Off\n";
    }

  if (this->Corners)
    {
    os << indent << "Corners: On\n";
    }
  else
    {
    os << indent << "Corners: Off\n";
    }

  if (this->GradientMagnitudeThreshold)
    {
    os << indent << "GradientMagnitudeThreshold: On\n";
    }
  else
    {
    os << indent << "GradientMagnitudeThreshold: Off\n";
    }
}

//----------------------------------------------------------------------------
// Description:
// This method sets the number of inputs which also affects the
// input neighborhood needed to compute one output pixel.
void vtkImageAnisotropicDiffusion2D::SetNumberOfIterations(int num)
{
  int temp;

  vtkDebugMacro(<< "SetNumberOfIterations: " << num);
  if (this->NumberOfIterations == num) return;

  this->Modified();
  temp = num*2 + 1;
  this->KernelSize[0] = temp;
  this->KernelSize[1] = temp;
  this->KernelMiddle[0] = num;
  this->KernelMiddle[1] = num;

  this->NumberOfIterations = num;
}

//----------------------------------------------------------------------------
// Description:
// This method contains a switch statement that calls the correct
// templated function for the input data type.  The input and output datas
// must have the same data type.
void vtkImageAnisotropicDiffusion2D::ThreadedExecute(vtkImageData *inData,
						     vtkImageData *outData,
						     int outExt[6], int id)
{
  int inExt[6];
  float *ar;
  int idx;
  vtkImageData *temp;

  this->ComputeRequiredInputUpdateExtent(inExt,outExt);

  vtkDebugMacro(<< "Execute: inData = " << inData
  << ", outData = " << outData);

  // this filter expects that input is the same type as output.
  if (inData->GetScalarType() != outData->GetScalarType())
    {
    vtkErrorMacro(<< "Execute: input ScalarType, " << inData->GetScalarType()
                  << ", must match out ScalarType " << outData->GetScalarType());
    return;
    }

  ar = inData->GetSpacing();

  // make the temporary regions to iterate over.
  vtkImageData *in = vtkImageData::New();
  in->SetExtent(inExt);
  in->SetNumberOfScalarComponents(inData->GetNumberOfScalarComponents());
  in->SetScalarType(VTK_FLOAT);
  in->CopyAndCastFrom(inData,inExt);

  vtkImageData *out = vtkImageData::New();
  out->SetExtent(inExt);
  out->SetNumberOfScalarComponents(inData->GetNumberOfScalarComponents());
  out->SetScalarType(VTK_FLOAT);

  // Loop performing the diffusion
  // Note: region extent could get smaller as the diffusion progresses
  // (but never get smaller than output region).
  for (idx = this->NumberOfIterations - 1; idx >= 0; --idx)
    {
    if (!id) this->UpdateProgress((float)(this->NumberOfIterations - idx)
				  /this->NumberOfIterations);
    this->Iterate(in, out, ar[0], ar[1], outExt, idx);
    temp = in;
    in = out;
    out = temp;
    }

  // copy results into output.
  outData->CopyAndCastFrom(in,outExt);
  in->Delete();
  out->Delete();
}

//----------------------------------------------------------------------------
// Description:
// This method performs one pass of the diffusion filter.
// The inData and outData are assumed to have data type float,
// and have the same extent.
void vtkImageAnisotropicDiffusion2D::Iterate(vtkImageData *inData,
					     vtkImageData *outData,
					     float ar0, float ar1,
					     int *coreExtent, int count)
{
  int idx0, idx1, idx2;
  int inInc0, inInc1, inInc2;
  int outInc0, outInc1, outInc2;
  int inMin0, inMax0, inMin1, inMax1, inMin2, inMax2;
  int min0, max0, min1, max1, min2, max2;
  float *inPtr0, *inPtr1, *inPtr2;
  float *outPtr0, *outPtr1, *outPtr2;
  float th0, th1, th01;
  float df0, df1, df01;
  float temp, sum;
  int idxC, maxC;

  maxC = inData->GetNumberOfScalarComponents();
  inData->GetExtent(inMin0, inMax0, inMin1, inMax1, inMin2, inMax2);
  inData->GetIncrements(inInc0, inInc1, inInc2);
  outData->GetIncrements(outInc0, outInc1, outInc2);

  // Avoid warnings.
  th0 = th1 = th01 = df0 = df1 = df01 = 0.0;

  // Compute direction specific diffusion thresholds and factors.
  sum = 0.0;
  if (this->Edges)
    {
    th0 = ar0 * this->DiffusionThreshold;
    df0 = 1.0 / ar0;
    th1 = ar1 * this->DiffusionThreshold;
    df1 = 1.0 / ar1;
    // two edges per direction.
    sum += 2.0 * (df0 + df1);
    }
  if (this->Corners)
    {
    temp = sqrt(ar0*ar0 + ar1*ar1);
    th01 = temp * this->DiffusionThreshold;
    df01 = 1 / temp;
    // four corners per plane
    sum += 4 * (df01);
    }

  if (sum > 0.0)
    {
    temp = this->DiffusionFactor / sum;
    df0 *= temp;
    df1 *= temp;
    df01 *= temp;
    }
  else
    {
    vtkWarningMacro(<< "Iterate: NO NEIGHBORS");
    return;
    }

  // Compute the shrinking extent to loop over.
  min0 = coreExtent[0] - count;
  max0 = coreExtent[1] + count;
  min1 = coreExtent[2] - count;
  max1 = coreExtent[3] + count;
  // intersection
  min0 = (min0 > inMin0) ? min0 : inMin0;
  max0 = (max0 < inMax0) ? max0 : inMax0;
  min1 = (min1 > inMin1) ? min1 : inMin1;
  max1 = (max1 < inMax1) ? max1 : inMax1;

  vtkDebugMacro(<< "Iteration count: " << count << " ("
  << min0 << ", " << max0 << ", " << min1 << ", " << max1 << ")");

  // I apologize for explicitely diffusing each neighbor, but it is the easiest
  // way to deal with the boundary conditions.  Besides it is fast.
  // (Are you sure every one is correct?!!!)
  min2 = inMin2;
  max2 = inMax2;

  inPtr2 = (float *)(inData->GetScalarPointer(min0, min1, min2));
  outPtr2 = (float *)(outData->GetScalarPointer(min0, min1, min2));

  for (idxC = 0; idxC < maxC; idxC++)
    {
    inPtr2 = (float *)(inData->GetScalarPointer(min0, min1, min2));
    outPtr2 = (float *)(outData->GetScalarPointer(min0, min1, min2));
    inPtr2 += idxC;
    outPtr2 += idxC;

    for (idx2 = min2; idx2 <= max2; ++idx2, inPtr2+=inInc2, outPtr2+=outInc2)
      {
      inPtr1 = inPtr2;
      outPtr1 = outPtr2;
      for (idx1 = min1; idx1 <= max1; ++idx1, inPtr1+=inInc1, outPtr1+=outInc1)
	{
	inPtr0 = inPtr1;
	outPtr0 = outPtr1;
	for (idx0 = min0; idx0 <= max0; ++idx0, inPtr0+=inInc0, outPtr0+=outInc0)
	  {
	  // Copy center
	  *outPtr0 = *inPtr0;

	  // Special case for gradient magnitude threhsold
	  if (this->GradientMagnitudeThreshold)
	    {
	    float d0, d1;
	    // compute the gradient magnitude (central differences).
	    d0  = (idx0 != inMax0) ? inPtr0[inInc0] : *inPtr0;
	    d0 -= (idx0 != inMin0) ? inPtr0[-inInc0] : *inPtr0;
	    d0 /= ar0;
	    d1  = (idx1 != inMax1) ? inPtr0[inInc1] : *inPtr0;
	    d1 -= (idx1 != inMin1) ? inPtr0[-inInc1] : *inPtr0;
	    d1 /= ar1;
	    // If magnitude is big, don't diffuse.
	    d0 = sqrt(d0*d0 + d1*d1);
	    if (d0 > this->DiffusionThreshold)
	      {
	      // hack to not diffuse
	      th0 = th1 = th01 = 0.0;
	      }
	    else
	      {
	      // hack to diffuse
	      th0 = th1 = th01 = VTK_LARGE_FLOAT;
	      }
	    }

	  // Start diffusing
	  if (this->Edges)
	    {
	    // left
	    if (idx0 != inMin0)
	      {
	      temp = inPtr0[-inInc0] - *inPtr0;
	      if (fabs(temp) < th0)
		{
		*outPtr0 += temp * df0;
		}
	      }
	    // right
	    if (idx0 != inMax0)
	      {
	      temp = inPtr0[inInc0] - *inPtr0;
	      if (fabs(temp) < th0)
		{
		*outPtr0 += temp * df0;
		}
	      }
	    // up
	    if (idx1 != inMin1)
	      {
	      temp = inPtr0[-inInc1] - *inPtr0;
	      if (fabs(temp) < th1)
		{
		*outPtr0 += temp * df1;
		}
	      }
	    // down
	    if (idx1 != inMax1)
	      {
	      temp = inPtr0[inInc1] - *inPtr0;
	      if (fabs(temp) < th1)
		{
		*outPtr0 += temp * df1;
		}
	      }
	    }

	  if (this->Corners)
	    {
	    // left up
	    if (idx0 != inMin0 && idx1 != inMin1)
	      {
	      temp = inPtr0[-inInc0-inInc1] - *inPtr0;
	      if (fabs(temp) < th01)
		{
		*outPtr0 += temp * df01;
		}
	      }
	    // right up
	    if (idx0 != inMax0 && idx1 != inMin1)
	      {
	      temp = inPtr0[inInc0-inInc1] - *inPtr0;
	      if (fabs(temp) < th01)
		{
		*outPtr0 += temp * df01;
		}
	      }
	    // left down
	    if (idx0 != inMin0 && idx1 != inMax1)
	      {
	      temp = inPtr0[-inInc0+inInc1] - *inPtr0;
	      if (fabs(temp) < th01)
		{
		*outPtr0 += temp * df01;
		}
	      }
	    // right down
	    if (idx0 != inMax0 && idx1 != inMax1)
	      {
	      temp = inPtr0[inInc0+inInc1] - *inPtr0;
	      if (fabs(temp) < th01)
		{
		*outPtr0 += temp * df01;
		}
	      }
	    }
	  }
	}
      }
    }
}

<|endoftext|>


<commit_before>#ifndef _PITO_INTERCEPTOR_JAIL_LIBC_HPP_
#define _PITO_INTERCEPTOR_JAIL_LIBC_HPP_

#include <pito/interceptor/jail/environment.hpp>

#include <stdarg.h>
#include <fcntl.h>

// #include <iostream>
#include <algorithm>

namespace pito { namespace interceptor { namespace jail {

struct Init {
    Init() {
        char const *begin = getenv("LD_PRELOAD");
        char const *end = begin;
        while (*(++end) != '\0') {}

        char const *colon = begin;
        do {
            colon = std::find(colon + 1, end, ':');
            // std::cout << "got preload entry (" << begin << ")" << std::endl;
            // TODO: test if range(begin,colon) matches libpito_[a-z]+.so

            begin = colon;
        } while (colon != end);
    }
};

Init init;

} } }

extern "C" {

using namespace pito::interceptor;
using namespace pito::interceptor::jail;

// include this in a handler c file to include the pito jail
int execve(const char *filename, char *const argv[], char *const envp[]) {
    enforceEnvironment(envp);
    return PITO_SUPER(execve)(filename, argv, envp);
}

int execv(const char *filename, char *const argv[]) {
    enforceEnvironment();
    return PITO_SUPER(execv)(filename, argv);
}

int execvp(const char *filename, char *const argv[]) {
    enforceEnvironment();
    return PITO_SUPER(execvp)(filename, argv);
}

}

#endif
<commit_msg>um<commit_after>#ifndef _PITO_INTERCEPTOR_JAIL_LIBC_HPP_
#define _PITO_INTERCEPTOR_JAIL_LIBC_HPP_

#include <pito/interceptor/jail/environment.hpp>
#include "config.hpp"

#include <stdarg.h>
#include <fcntl.h>

// #include <iostream>
#include <algorithm>

namespace pito { namespace interceptor { namespace jail {

struct Init {
    Init() {
#ifndef APPLE
        char const *begin = getenv("LD_PRELOAD");
        char const *end = begin;
        while (*(++end) != '\0') {}

        char const *colon = begin;
        do {
            colon = std::find(colon + 1, end, ':');
            // std::cout << "got preload entry (" << begin << ")" << std::endl;
            // TODO: test if range(begin,colon) matches libpito_[a-z]+.so

            begin = colon;
        } while (colon != end);
#endif
    }
};

Init init;

} } }

extern "C" {

using namespace pito::interceptor;
using namespace pito::interceptor::jail;

// include this in a handler c file to include the pito jail
int execve(const char *filename, char *const argv[], char *const envp[]) {
    enforceEnvironment(envp);
    return PITO_SUPER(execve)(filename, argv, envp);
}

int execv(const char *filename, char *const argv[]) {
    enforceEnvironment();
    return PITO_SUPER(execv)(filename, argv);
}

int execvp(const char *filename, char *const argv[]) {
    enforceEnvironment();
    return PITO_SUPER(execvp)(filename, argv);
}

}

#endif
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#if !defined(FUNCTIONLOCALNAME_HEADER_GUARD_1357924680)
#define FUNCTIONLOCALNAME_HEADER_GUARD_1357924680

// Base header file.  Must be first.
#include <XPath/XPathDefinitions.hpp>

#include <vector>

#include <PlatformSupport/DOMStringHelper.hpp>

// Base class header file...
#include <XPath/Function.hpp>

#include <XPath/NodeRefListBase.hpp>
#include <XPath/XObject.hpp>
#include <XPath/XObjectFactory.hpp>
#include <XPath/XPathExecutionContext.hpp>

/**
 * XPath implementation of "local-name" function.
 */
//
// These are all inline, even though
// there are virtual functions, because we expect that they will only be
// needed by the XPath class.
class XALAN_XPATH_EXPORT FunctionLocalName : public Function
{
public:

	// These methods are inherited from Function ...

	virtual XObject*
	execute(
			XPathExecutionContext&			executionContext,
			XalanNode*						context,
			int								/* opPos */,
			const XObjectArgVectorType&		args)
	{
		const XObjectArgVectorType::size_type	theSize =
			args.size();

		if(theSize > 1)
		{
			executionContext.error("The local-name() function takes zero or one arguments!",
								   context);
		}

		XalanDOMString	theData;

		if (theSize == 0)
		{
			assert(context != 0);

			theData = executionContext.getLocalNameOfNode(*context);
		}
		else
		{
			assert(args[0] != 0);

			const NodeRefListBase&	theNodeList = args[0]->nodeset();

			if (theNodeList.getLength() > 0)
			{
				theData = executionContext.getLocalNameOfNode(*theNodeList.item(0));
			}
		}

		return executionContext.getXObjectFactory().createString(theData);
	}

#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
	virtual Function*
#else
	virtual FunctionLocalName*
#endif
	clone() const
	{
		return new FunctionLocalName(*this);
	}

private:

	// Not implemented...
	FunctionLocalName&
	operator=(const FunctionLocalName&);

	bool
	operator==(const FunctionLocalName&) const;
};

#endif	// FUNCTIONLOCALNAME_HEADER_GUARD_1357924680
<commit_msg>More error checking.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#if !defined(FUNCTIONLOCALNAME_HEADER_GUARD_1357924680)
#define FUNCTIONLOCALNAME_HEADER_GUARD_1357924680

// Base header file.  Must be first.
#include <XPath/XPathDefinitions.hpp>

#include <vector>

#include <PlatformSupport/DOMStringHelper.hpp>

// Base class header file...
#include <XPath/Function.hpp>

#include <XPath/NodeRefListBase.hpp>
#include <XPath/XObject.hpp>
#include <XPath/XObjectFactory.hpp>
#include <XPath/XPathExecutionContext.hpp>

/**
 * XPath implementation of "local-name" function.
 */
//
// These are all inline, even though
// there are virtual functions, because we expect that they will only be
// needed by the XPath class.
class XALAN_XPATH_EXPORT FunctionLocalName : public Function
{
public:

	// These methods are inherited from Function ...

	virtual XObject*
	execute(
			XPathExecutionContext&			executionContext,
			XalanNode*						context,
			int								/* opPos */,
			const XObjectArgVectorType&		args)
	{
		const XObjectArgVectorType::size_type	theSize =
			args.size();

		if(theSize > 1)
		{
			executionContext.error("The local-name() function takes zero or one arguments!",
								   context);
		}

		XalanDOMString	theData;

		if (theSize == 0)
		{
			if (context == 0)
			{
				executionContext.error("The local-name() function requires a non-null context node!");
			}

			theData = executionContext.getLocalNameOfNode(*context);
		}
		else
		{
			assert(args[0] != 0);

			const NodeRefListBase&	theNodeList = args[0]->nodeset();

			if (theNodeList.getLength() > 0)
			{
				theData = executionContext.getLocalNameOfNode(*theNodeList.item(0));
			}
		}

		return executionContext.getXObjectFactory().createString(theData);
	}

#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
	virtual Function*
#else
	virtual FunctionLocalName*
#endif
	clone() const
	{
		return new FunctionLocalName(*this);
	}

private:

	// Not implemented...
	FunctionLocalName&
	operator=(const FunctionLocalName&);

	bool
	operator==(const FunctionLocalName&) const;
};

#endif	// FUNCTIONLOCALNAME_HEADER_GUARD_1357924680
<|endoftext|>


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

#include <fmt/format.h>
#include <termbox.h>
#include <spdlog/spdlog.h>
#include <pybind11/embed.h>

#include "errors.hpp"
#include "components/menu.hpp"
#include "components/logger.hpp"

namespace py = pybind11;

namespace bookwyrm {

menu::~menu()
{
    tb_shutdown();
}

void menu::display()
{
    menu_mutex_.lock();

    int code = tb_init();
    if (code < 0) {
        string err = "termbox init failed with code: " + code;
        throw component_error(err.data());
    }

    tb_set_cursor(TB_HIDE_CURSOR, TB_HIDE_CURSOR);
    tb_clear();

    menu_mutex_.unlock();

    /*
     * Let the source threads free.
     * This doesn't feel like the best place to have this,
     * but we do need to have a release in scope if we
     * ever want the threads to run.
     * TODO: find out if there is a better place for this.
     */
    py::gil_scoped_release nogil;

    struct tb_event ev;
    bool quit = false;
    while (tb_poll_event(&ev) && !quit) {
        if (ev.type == TB_EVENT_KEY) {
            switch (ev.key) {
                case TB_KEY_ESC:
                    quit = true;
                    break;
                case TB_KEY_ARROW_DOWN:
                    move(down);
                    break;
                case TB_KEY_ARROW_UP:
                    move(up);
                    break;
                case TB_KEY_SPACE:
                    toggle_select();
                    break;
            }
        }
    }
}

void menu::update()
{
    tb_clear();

    for (auto &item : items_) {
        print_item(item);
        y_++;
    }

    // print_scrollbar down here
    mvprintw(0, tb_height() - 2, fmt::format("The menu contains {} items.", item_count()));

    y_ = 0;
    tb_present();
}

void menu::print_item(const item &t)
{
    bool on_selected_item = (y_ == selected_item_);

    /*
     * Imitate an Ncurses menu, denote the selected item with a '-'
     * and by reversing fg and bg on the entry.
     * Leave x = 1 to the indicator.
     */
    if (on_selected_item) {
        tb_change_cell(0, y_, '-', 0, 0);
    } else if (is_marked(y_)) {
        tb_change_cell(0, y_, ' ', TB_REVERSE, 0);
    }

    int attrs = on_selected_item || is_marked(y_) ? TB_REVERSE : 0;
    int x = 1;

    for (char ch : t.nonexacts.title) {
        tb_change_cell(x++, y_, ch, attrs, 0);
    }
}

void menu::mvprintw(int x, int y, string str)
{
    for (char ch : str) {
        tb_change_cell(x++, y, ch, 0, 0);
    }
}

void menu::move(direction dir)
{
    bool at_first_item = selected_item_ == 0,
         at_last_item  = selected_item_ == static_cast<int>(item_count() - 1);

    switch (dir) {
        case up:
            if (at_first_item) return;
            selected_item_--;
            break;
        case down:
            if (at_last_item) return;
            selected_item_++;
            break;
    }

    update();
}

void menu::toggle_select()
{
    if (is_marked(selected_item_)) {
        unmark_item(selected_item_);
    } else {
        mark_item(selected_item_);
    }

    update();
}

} /* ns bookwyrm */
<commit_msg>menu: use the same types as termbox.h<commit_after>/*
 * Copyright (C) 2017 Tmplt <tmplt@dragons.rocks>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <fmt/format.h>
#include <termbox.h>
#include <spdlog/spdlog.h>
#include <pybind11/embed.h>

#include "errors.hpp"
#include "components/menu.hpp"
#include "components/logger.hpp"

namespace py = pybind11;

namespace bookwyrm {

menu::~menu()
{
    tb_shutdown();
}

void menu::display()
{
    menu_mutex_.lock();

    int code = tb_init();
    if (code < 0) {
        string err = "termbox init failed with code: " + code;
        throw component_error(err.data());
    }

    tb_set_cursor(TB_HIDE_CURSOR, TB_HIDE_CURSOR);
    tb_clear();

    menu_mutex_.unlock();

    /*
     * Let the source threads free.
     * This doesn't feel like the best place to have this,
     * but we do need to have a release in scope if we
     * ever want the threads to run.
     * TODO: find out if there is a better place for this.
     */
    py::gil_scoped_release nogil;

    struct tb_event ev;
    bool quit = false;
    while (tb_poll_event(&ev) && !quit) {
        if (ev.type == TB_EVENT_KEY) {
            switch (ev.key) {
                case TB_KEY_ESC:
                    quit = true;
                    break;
                case TB_KEY_ARROW_DOWN:
                    move(down);
                    break;
                case TB_KEY_ARROW_UP:
                    move(up);
                    break;
                case TB_KEY_SPACE:
                    toggle_select();
                    break;
            }
        }
    }
}

void menu::update()
{
    tb_clear();

    for (auto &item : items_) {
        print_item(item);
        y_++;
    }

    // print_scrollbar down here
    mvprintw(0, tb_height() - 2, fmt::format("The menu contains {} items.", item_count()));

    y_ = 0;
    tb_present();
}

void menu::print_item(const item &t)
{
    bool on_selected_item = (y_ == selected_item_);

    /*
     * Imitate an Ncurses menu, denote the selected item with a '-'
     * and by reversing fg and bg on the entry.
     * Leave x = 1 to the indicator.
     */
    if (on_selected_item) {
        tb_change_cell(0, y_, '-', 0, 0);
    } else if (is_marked(y_)) {
        tb_change_cell(0, y_, ' ', TB_REVERSE, 0);
    }

    uint16_t attrs = on_selected_item || is_marked(y_) ? TB_REVERSE : 0;
    int x = 1;

    for (uint32_t ch : t.nonexacts.title) {
        tb_change_cell(x++, y_, ch, attrs, 0);
    }
}

void menu::mvprintw(int x, int y, string str)
{
    for (uint32_t ch : str) {
        tb_change_cell(x++, y, ch, 0, 0);
    }
}

void menu::move(direction dir)
{
    bool at_first_item = selected_item_ == 0,
         at_last_item  = selected_item_ == static_cast<int>(item_count() - 1);

    switch (dir) {
        case up:
            if (at_first_item) return;
            selected_item_--;
            break;
        case down:
            if (at_last_item) return;
            selected_item_++;
            break;
    }

    update();
}

void menu::toggle_select()
{
    if (is_marked(selected_item_)) {
        unmark_item(selected_item_);
    } else {
        mark_item(selected_item_);
    }

    update();
}

} /* ns bookwyrm */
<|endoftext|>


<commit_before>// Filename: fog.cxx
// Created by:  mike (09Jan97)
//
////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////
#include <pandabase.h>

#include "fog.h"

#include <mathNumbers.h>

#include <stddef.h>

////////////////////////////////////////////////////////////////////
// Static variables
////////////////////////////////////////////////////////////////////
TypeHandle Fog::_type_handle;

ostream &
operator << (ostream &out, Fog::Mode mode) {
  switch (mode) {
  case Fog::M_linear:
    return out << "linear";

  case Fog::M_exponential:
    return out << "exponential";

  case Fog::M_super_exponential:
    return out << "super_exponential";

  case Fog::M_spline:
    return out << "spline";
  }

  return out << "**invalid**(" << (int)mode << ")";
}

////////////////////////////////////////////////////////////////////
//     Function: Fog::Constructor
//       Access:
//  Description:
////////////////////////////////////////////////////////////////////
Fog::Fog(Mode mode, int hardware_bits) {
  _hardware_bits = hardware_bits;
  set_mode(mode);
  set_color(Colorf(0.0, 0.0, 0.0, 1.0));
  set_range(0.0f, 100.0f);
  set_offsets(0.0f, 0.0f);
  compute_density();
}

////////////////////////////////////////////////////////////////////
//     Function: Fog::Destructor
//       Access:
//  Description:
////////////////////////////////////////////////////////////////////
Fog::~Fog(void) {
}

////////////////////////////////////////////////////////////////////
//     Function: Fog::set_mode
//       Access:
//  Description:
////////////////////////////////////////////////////////////////////
void Fog::compute_density(void) {
  _density = 1.0f;
  float opaque_multiplier;
  switch (_mode) {
  case M_linear:
    break;
  case M_exponential:
    // Multiplier = ln(2^bits)
    opaque_multiplier = MathNumbers::ln2 * _hardware_bits;
    _density = opaque_multiplier / (_opaque + _opaque_offset);
    break;
  case M_super_exponential:
    // Multiplier = ln(squrt(2^bits))
    opaque_multiplier = 0.5f * MathNumbers::ln2 * _hardware_bits;
    opaque_multiplier *= opaque_multiplier;
    _density = opaque_multiplier / (_opaque + _opaque_offset);
    break;
  case M_spline:
    // *** What's this?
    break;
  }
}

////////////////////////////////////////////////////////////////////
//     Function: Fog::output
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
void Fog::
output(ostream &out) const {
  out << "fog:" << _mode;
  switch (_mode) {
  case M_linear:
    break;
  case M_exponential:
  case M_super_exponential:
    out << "(" << _hardware_bits << "," << _density
	<< "," << _opaque << "," << _opaque_offset << ")";
    break;
  case M_spline:
    break;
  };
}
<commit_msg>default to a more usual fog color<commit_after>// Filename: fog.cxx
// Created by:  mike (09Jan97)
//
////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////
#include <pandabase.h>

#include "fog.h"

#include <mathNumbers.h>

#include <stddef.h>

////////////////////////////////////////////////////////////////////
// Static variables
////////////////////////////////////////////////////////////////////
TypeHandle Fog::_type_handle;

ostream &
operator << (ostream &out, Fog::Mode mode) {
  switch (mode) {
  case Fog::M_linear:
    return out << "linear";

  case Fog::M_exponential:
    return out << "exponential";

  case Fog::M_super_exponential:
    return out << "super_exponential";

  case Fog::M_spline:
    return out << "spline";
  }

  return out << "**invalid**(" << (int)mode << ")";
}

////////////////////////////////////////////////////////////////////
//     Function: Fog::Constructor
//       Access:
//  Description:
////////////////////////////////////////////////////////////////////
Fog::Fog(Mode mode, int hardware_bits) {
  _hardware_bits = hardware_bits;
  set_mode(mode);
  set_color(Colorf(1.0, 1.0, 1.0, 1.0));
  set_range(0.0f, 100.0f);
  set_offsets(0.0f, 0.0f);
  compute_density();
}

////////////////////////////////////////////////////////////////////
//     Function: Fog::Destructor
//       Access:
//  Description:
////////////////////////////////////////////////////////////////////
Fog::~Fog(void) {
}

////////////////////////////////////////////////////////////////////
//     Function: Fog::set_mode
//       Access:
//  Description:
////////////////////////////////////////////////////////////////////
void Fog::compute_density(void) {
  _density = 1.0f;
  float opaque_multiplier;
  switch (_mode) {
  case M_linear:
    break;
  case M_exponential:
    // Multiplier = ln(2^bits)
    opaque_multiplier = MathNumbers::ln2 * _hardware_bits;
    _density = opaque_multiplier / (_opaque + _opaque_offset);
    break;
  case M_super_exponential:
    // Multiplier = ln(squrt(2^bits))
    opaque_multiplier = 0.5f * MathNumbers::ln2 * _hardware_bits;
    opaque_multiplier *= opaque_multiplier;
    _density = opaque_multiplier / (_opaque + _opaque_offset);
    break;
  case M_spline:
    // *** What's this?
    break;
  }
}

////////////////////////////////////////////////////////////////////
//     Function: Fog::output
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
void Fog::
output(ostream &out) const {
  out << "fog:" << _mode;
  switch (_mode) {
  case M_linear:
    break;
  case M_exponential:
  case M_super_exponential:
    out << "(" << _hardware_bits << "," << _density
	<< "," << _opaque << "," << _opaque_offset << ")";
    break;
  case M_spline:
    break;
  };
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2018.  All rights reserved
 */
#ifndef _Stroika_Foundation_Memory_BlockAllocated_inl_
#define _Stroika_Foundation_Memory_BlockAllocated_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */

namespace Stroika::Foundation::Memory {

    /*
     ********************************************************************************
     ************************* BlockAllocationUseHelper<T> **************************
     ********************************************************************************
     */
    template <typename T>
    inline void* BlockAllocationUseHelper<T>::operator new (size_t n)
    {
        return BlockAllocator<T>::Allocate (n);
    }
    template <typename T>
    inline void* BlockAllocationUseHelper<T>::operator new (size_t n, int, const char*, int)
    {
        return BlockAllocator<T>::Allocate (n);
    }
    template <typename T>
    inline void BlockAllocationUseHelper<T>::operator delete (void* p)
    {
        BlockAllocator<T>::Deallocate (p);
    }
    template <typename T>
    inline void BlockAllocationUseHelper<T>::operator delete (void* p, int, const char*, int)
    {
        BlockAllocator<T>::Deallocate (p);
    }

    /*
     ********************************************************************************
     ******************* BlockAllocationUseGlobalAllocatorHelper<T> *****************
     ********************************************************************************
     */
    template <typename T>
    inline void* BlockAllocationUseGlobalAllocatorHelper<T>::operator new (size_t n)
    {
        return ::operator new (n);
    }
    template <typename T>
    inline void* BlockAllocationUseGlobalAllocatorHelper<T>::operator new (size_t n, int, const char*, int)
    {
        return ::operator new (n);
    }
    template <typename T>
    inline void BlockAllocationUseGlobalAllocatorHelper<T>::operator delete (void* p)
    {
        ::operator delete (p);
    }
    template <typename T>
    inline void BlockAllocationUseGlobalAllocatorHelper<T>::operator delete (void* p, int, const char*, int)
    {
        ::operator delete (p);
    }

    /*
     ********************************************************************************
     *************************** ManuallyBlockAllocated<T> **************************
     ********************************************************************************
     */
    template <typename T>
    template <typename... ARGS>
    inline T* ManuallyBlockAllocated<T>::New (ARGS&&... args)
    {
#if qAllowBlockAllocation
        return new (BlockAllocator<T>::Allocate (sizeof (T))) T (forward<ARGS> (args)...);
#else
        return new T (forward<ARGS> (args)...);
#endif
    }
    template <typename T>
    inline void ManuallyBlockAllocated<T>::Delete (T* p) noexcept
    {
#if qAllowBlockAllocation
        if (p != nullptr) {
            (p)->~T ();
            BlockAllocator<T>::Deallocate (p);
        }
#else
        delete p;
#endif
    }

    ////////////////////////////////////////////////////////////////////////////////////////////
    //////////////////// DEPRECATED STUFF///////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////
    /**
         *  \note DEPRECATED - USE UseBlockAllocationIfAppropriate
         */
#if qAllowBlockAllocation
#define DECLARE_USE_BLOCK_ALLOCATION_DEPRECATED(THIS_CLASS)                                                                                \
    static void* operator new (size_t n) { return (Stroika::Foundation::Memory::BlockAllocator<THIS_CLASS>::Allocate (n)); }                        \
    static void* operator new (size_t n, int, const char*, int) { return (Stroika::Foundation::Memory::BlockAllocator<THIS_CLASS>::Allocate (n)); } \
    static void  operator delete (void* p) { Stroika::Foundation::Memory::BlockAllocator<THIS_CLASS>::Deallocate (p); }                             \
    static void  operator delete (void* p, int, const char*, int) { Stroika::Foundation::Memory::BlockAllocator<THIS_CLASS>::Deallocate (p); }
#else
#define DECLARE_USE_BLOCK_ALLOCATION_DEPRECATED(THIS_CLASS)
#endif

// Deprecated in Stroika v2.1d4 - USE UseBlockAllocationIfAppropriate
#define DECLARE_USE_BLOCK_ALLOCATION(THIS_CLASS) use = "DECLARE_USE_BLOCK_ALLOCATION_DEPRECATED"

// Deprecated in Stroika v2.1d4 - USE UseBlockAllocationIfAppropriate
#if qAllowBlockAllocation
#define DECLARE_DONT_USE_BLOCK_ALLOCATION_DEPRECATED(THIS_CLASS)        \
    static void* operator new (size_t n) { return ::operator new (n); } \
    static void  operator delete (void* p) { ::operator delete (p); }
#else
#define DECLARE_DONT_USE_BLOCK_ALLOCATION_DEPRECATED(THIS_CLASS)
#endif

// Deprecated in Stroika v2.1d4 - USE BlockAllocationUseGlobalAllocatorHelper
#define DECLARE_DONT_USE_BLOCK_ALLOCATION(THIS_CLASS) use = "DECLARE_DONT_USE_BLOCK_ALLOCATION_DEPRECATED"

    /**
         * \brief  Utility class to implement special memory allocator pattern which can greatly improve performance - @see DECLARE_USE_BLOCK_ALLOCATION()
         *
         * AutomaticallyBlockAllocated<T> is a templated class designed to allow easy use
         * of a block-allocated memory strategy. This means zero overhead malloc/memory allocation for fixed
         * size blocks (with the only problem being the storage is never - or almost never - returned to the
         * free store - it doesn't leak - but cannot be used for other things. This is often a useful
         * tradeoff for things you allocate a great number of.
         *
         * You shouldn't disable it lightly. But you may wish to temporarily disable block-allocation
         * while checking for memory leaks by shutting of the qAllowBlockAllocation compile-time configuration variable.
         *
         *  If qAllowBlockAllocation true (default) - this will use the optimized block allocation store, but if qAllowBlockAllocation is
         *  false (0), this will just default to the global ::new/::delete
         *
         */
    template <typename T>
    [[deprecated ("bad idea - if you use to allocate - must retain type AutomaticallyBlockAllocated<T>* or do wrong delete - deprecated in v2.1d4")]] class AutomaticallyBlockAllocated : public UseBlockAllocationIfAppropriate<T> {
    public:
        /**
             * @todo Clean this section of code (BlockAllocated) up. See if some better way to wrap type T, with extras.
             *      something that does good job forwarding CTOR arguments (perfect forwarding?) and does a better job
             *      with stuff like operator==, operaotr<, etc... (maybe explicitly override  each)?
             */
        AutomaticallyBlockAllocated ();
        AutomaticallyBlockAllocated (const AutomaticallyBlockAllocated& t);
        AutomaticallyBlockAllocated (const T& t);
        AutomaticallyBlockAllocated (T&& t);

    public:
        nonvirtual const AutomaticallyBlockAllocated<T>& operator= (const AutomaticallyBlockAllocated& t);
        nonvirtual const AutomaticallyBlockAllocated<T>& operator= (const T& t);

    public:
        nonvirtual operator T () const;

    public:
        nonvirtual T* get ();

    private:
        T fValue_;
    };

    template <typename T>
    inline AutomaticallyBlockAllocated<T>::AutomaticallyBlockAllocated ()
        : fValue_ ()
    {
    }
    template <typename T>
    inline AutomaticallyBlockAllocated<T>::AutomaticallyBlockAllocated (const AutomaticallyBlockAllocated<T>& t)
        : fValue_ (t)
    {
    }
    template <typename T>
    inline AutomaticallyBlockAllocated<T>::AutomaticallyBlockAllocated (const T& t)
        : fValue_ (t)
    {
    }
    template <typename T>
    inline AutomaticallyBlockAllocated<T>::AutomaticallyBlockAllocated (T&& t)
        : fValue_ (move (t))
    {
    }
    template <typename T>
    inline const AutomaticallyBlockAllocated<T>& AutomaticallyBlockAllocated<T>::operator= (const AutomaticallyBlockAllocated<T>& t)
    {
        fValue_ = t.fValue_;
        return *this;
    }
    template <typename T>
    inline const AutomaticallyBlockAllocated<T>& AutomaticallyBlockAllocated<T>::operator= (const T& t)
    {
        fValue_ = t;
        return *this;
    }
    template <typename T>
    inline AutomaticallyBlockAllocated<T>::operator T () const
    {
        return fValue_;
    }
    template <typename T>
    inline T* AutomaticallyBlockAllocated<T>::get ()
    {
        return &fValue_;
    }
}
#endif /*_Stroika_Foundation_Memory_BlockAllocated_inl_*/
<commit_msg>cleanup deprecated AutomaticallyBlockAllocated<T><commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2018.  All rights reserved
 */
#ifndef _Stroika_Foundation_Memory_BlockAllocated_inl_
#define _Stroika_Foundation_Memory_BlockAllocated_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */

namespace Stroika::Foundation::Memory {

    /*
     ********************************************************************************
     ************************* BlockAllocationUseHelper<T> **************************
     ********************************************************************************
     */
    template <typename T>
    inline void* BlockAllocationUseHelper<T>::operator new (size_t n)
    {
        return BlockAllocator<T>::Allocate (n);
    }
    template <typename T>
    inline void* BlockAllocationUseHelper<T>::operator new (size_t n, int, const char*, int)
    {
        return BlockAllocator<T>::Allocate (n);
    }
    template <typename T>
    inline void BlockAllocationUseHelper<T>::operator delete (void* p)
    {
        BlockAllocator<T>::Deallocate (p);
    }
    template <typename T>
    inline void BlockAllocationUseHelper<T>::operator delete (void* p, int, const char*, int)
    {
        BlockAllocator<T>::Deallocate (p);
    }

    /*
     ********************************************************************************
     ******************* BlockAllocationUseGlobalAllocatorHelper<T> *****************
     ********************************************************************************
     */
    template <typename T>
    inline void* BlockAllocationUseGlobalAllocatorHelper<T>::operator new (size_t n)
    {
        return ::operator new (n);
    }
    template <typename T>
    inline void* BlockAllocationUseGlobalAllocatorHelper<T>::operator new (size_t n, int, const char*, int)
    {
        return ::operator new (n);
    }
    template <typename T>
    inline void BlockAllocationUseGlobalAllocatorHelper<T>::operator delete (void* p)
    {
        ::operator delete (p);
    }
    template <typename T>
    inline void BlockAllocationUseGlobalAllocatorHelper<T>::operator delete (void* p, int, const char*, int)
    {
        ::operator delete (p);
    }

    /*
     ********************************************************************************
     *************************** ManuallyBlockAllocated<T> **************************
     ********************************************************************************
     */
    template <typename T>
    template <typename... ARGS>
    inline T* ManuallyBlockAllocated<T>::New (ARGS&&... args)
    {
#if qAllowBlockAllocation
        return new (BlockAllocator<T>::Allocate (sizeof (T))) T (forward<ARGS> (args)...);
#else
        return new T (forward<ARGS> (args)...);
#endif
    }
    template <typename T>
    inline void ManuallyBlockAllocated<T>::Delete (T* p) noexcept
    {
#if qAllowBlockAllocation
        if (p != nullptr) {
            (p)->~T ();
            BlockAllocator<T>::Deallocate (p);
        }
#else
        delete p;
#endif
    }

    ////////////////////////////////////////////////////////////////////////////////////////////
    //////////////////// DEPRECATED STUFF///////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////
    /**
         *  \note DEPRECATED - USE UseBlockAllocationIfAppropriate
         */
#if qAllowBlockAllocation
#define DECLARE_USE_BLOCK_ALLOCATION_DEPRECATED(THIS_CLASS)                                                                                \
    static void* operator new (size_t n) { return (Stroika::Foundation::Memory::BlockAllocator<THIS_CLASS>::Allocate (n)); }                        \
    static void* operator new (size_t n, int, const char*, int) { return (Stroika::Foundation::Memory::BlockAllocator<THIS_CLASS>::Allocate (n)); } \
    static void  operator delete (void* p) { Stroika::Foundation::Memory::BlockAllocator<THIS_CLASS>::Deallocate (p); }                             \
    static void  operator delete (void* p, int, const char*, int) { Stroika::Foundation::Memory::BlockAllocator<THIS_CLASS>::Deallocate (p); }
#else
#define DECLARE_USE_BLOCK_ALLOCATION_DEPRECATED(THIS_CLASS)
#endif

// Deprecated in Stroika v2.1d4 - USE UseBlockAllocationIfAppropriate
#define DECLARE_USE_BLOCK_ALLOCATION(THIS_CLASS) use = "DECLARE_USE_BLOCK_ALLOCATION_DEPRECATED"

// Deprecated in Stroika v2.1d4 - USE UseBlockAllocationIfAppropriate
#if qAllowBlockAllocation
#define DECLARE_DONT_USE_BLOCK_ALLOCATION_DEPRECATED(THIS_CLASS)        \
    static void* operator new (size_t n) { return ::operator new (n); } \
    static void  operator delete (void* p) { ::operator delete (p); }
#else
#define DECLARE_DONT_USE_BLOCK_ALLOCATION_DEPRECATED(THIS_CLASS)
#endif

// Deprecated in Stroika v2.1d4 - USE BlockAllocationUseGlobalAllocatorHelper
#define DECLARE_DONT_USE_BLOCK_ALLOCATION(THIS_CLASS) use = "DECLARE_DONT_USE_BLOCK_ALLOCATION_DEPRECATED"

    /**
     * \brief  Utility class to implement special memory allocator pattern which can greatly improve performance - @see DECLARE_USE_BLOCK_ALLOCATION()
     *
     * AutomaticallyBlockAllocated<T> is a templated class designed to allow easy use
     * of a block-allocated memory strategy. This means zero overhead malloc/memory allocation for fixed
     * size blocks (with the only problem being the storage is never - or almost never - returned to the
     * free store - it doesn't leak - but cannot be used for other things. This is often a useful
     * tradeoff for things you allocate a great number of.
     *
     * You shouldn't disable it lightly. But you may wish to temporarily disable block-allocation
     * while checking for memory leaks by shutting of the qAllowBlockAllocation compile-time configuration variable.
     *
     *  If qAllowBlockAllocation true (default) - this will use the optimized block allocation store, but if qAllowBlockAllocation is
     *  false (0), this will just default to the global ::new/::delete
     *
     */
    template <typename T>
    class [[deprecated ("bad idea - if you use to allocate - must retain type AutomaticallyBlockAllocated<T>* or do wrong delete - use UseBlockAllocationIfAppropriate instead- deprecated in v2.1d4")]] AutomaticallyBlockAllocated : public UseBlockAllocationIfAppropriate<T>
    {
    public:
        AutomaticallyBlockAllocated ()
            : fValue_ ()
        {
        }
        AutomaticallyBlockAllocated (const AutomaticallyBlockAllocated& t)
            : fValue_ (t)
        {
        }
        AutomaticallyBlockAllocated (const T& t)
            : fValue_ (t)
        {
        }
        AutomaticallyBlockAllocated (T && t)
            : fValue_ (move (t))
        {
        }

    public:
        const AutomaticallyBlockAllocated<T>& operator= (const AutomaticallyBlockAllocated& t)
        {
            fValue_ = t.fValue_;
            return *this;
        }
        const AutomaticallyBlockAllocated<T>& operator= (const T& t)
        {
            fValue_ = t;
            return *this;
        }

    public:
        operator T () const
        {
            return fValue_;
        }

    public:
        T* get ()
        {
            return &fValue_;
        }

    private:
        T fValue_;
    };
}
#endif /*_Stroika_Foundation_Memory_BlockAllocated_inl_*/
<|endoftext|>


<commit_before><commit_msg>Very little refactoring in user method at Music class<commit_after><|endoftext|>


<commit_before>/*
 * eos - A 3D Morphable Model fitting library written in modern C++11/14.
 *
 * File: include/eos/fitting/blendshape_fitting.hpp
 *
 * Copyright 2015 Patrik Huber
 *
 * 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.
 */
#pragma once

#ifndef BLENDSHAPEFITTING_HPP_
#define BLENDSHAPEFITTING_HPP_

#include "eos/morphablemodel/Blendshape.hpp"

#include "Eigen/Core" // for nnls.h
#include "nnls.h"

#include "Eigen/Core"
#include "opencv2/core/core.hpp"

#include <vector>
#include <cassert>

namespace eos {
	namespace fitting {

/**
 * Fits blendshape coefficients to given 2D landmarks, given a current face shape instance.
 * It's a linear, closed-form solution fitting algorithm, with regularisation (constraining
 * the L2-norm of the coefficients). However, there is no constraint on the coefficients,
 * so negative coefficients are allowed, which, with linear blendshapes (offsets), will most
 * likely not be desired. Thus, prefer the function
 * fit_blendshapes_to_landmarks_nnls(std::vector<eos::morphablemodel::Blendshape>, cv::Mat, cv::Mat, std::vector<cv::Vec2f>, std::vector<int>).
 *
 * This algorithm is very similar to the shape fitting in fit_shape_to_landmarks_linear.
 * Instead of the PCA basis, the blendshapes are used, and instead of the mean, a current
 * face instance is used to do the fitting from.
 *
 * @param[in] blendshapes A vector with blendshapes to estimate the coefficients for.
 * @param[in] face_instance A shape instance from which the blendshape coefficients should be estimated (i.e. the current mesh without expressions, e.g. estimated from a previous PCA-model fitting). A 3m x 1 matrix.
 * @param[in] affine_camera_matrix A 3x4 affine camera matrix from model to screen-space (should probably be of type CV_32FC1 as all our calculations are done with float).
 * @param[in] landmarks 2D landmarks from an image to fit the blendshapes to.
 * @param[in] vertex_ids The vertex ids in the model that correspond to the 2D points.
 * @param[in] lambda A regularisation parameter, constraining the L2-norm of the coefficients.
 * @return The estimated blendshape-coefficients.
 */
inline std::vector<float> fit_blendshapes_to_landmarks_linear(const std::vector<eos::morphablemodel::Blendshape>& blendshapes, const Eigen::VectorXf& face_instance, cv::Mat affine_camera_matrix, const std::vector<cv::Vec2f>& landmarks, const std::vector<int>& vertex_ids, float lambda=500.0f)
{
	assert(landmarks.size() == vertex_ids.size());

	using cv::Mat;
	using Eigen::MatrixXf;

	const int num_blendshapes = blendshapes.size();
	const int num_landmarks = static_cast<int>(landmarks.size());

	// Copy all blendshapes into a "basis" matrix with each blendshape being a column:
	Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> blendshapes_as_basis = morphablemodel::to_matrix(blendshapes);
	// Above converts to a RowMajor matrix on return - for now, since the core algorithm still uses cv::Mat (and OpenCV stores data in row-major memory order).
	Mat blendshapes_basis_as_mat = Mat(blendshapes_as_basis.rows(), blendshapes_as_basis.cols(), CV_32FC1, blendshapes_as_basis.data());

	// $\hat{V} \in R^{3N\times m-1}$, subselect the rows of the eigenvector matrix $V$ associated with the $N$ feature points
	// And we insert a row of zeros after every third row, resulting in matrix $\hat{V}_h \in R^{4N\times m-1}$:
	Mat V_hat_h = Mat::zeros(4 * num_landmarks, num_blendshapes, CV_32FC1);
	int row_index = 0;
	for (int i = 0; i < num_landmarks; ++i) {
		Mat basis_rows = blendshapes_basis_as_mat.rowRange(vertex_ids[i] * 3, (vertex_ids[i] * 3) + 3);
		basis_rows.copyTo(V_hat_h.rowRange(row_index, row_index + 3));
		row_index += 4; // replace 3 rows and skip the 4th one, it has all zeros
	}
	// Form a block diagonal matrix $P \in R^{3N\times 4N}$ in which the camera matrix C (P_Affine, affine_camera_matrix) is placed on the diagonal:
	Mat P = Mat::zeros(3 * num_landmarks, 4 * num_landmarks, CV_32FC1);
	for (int i = 0; i < num_landmarks; ++i) {
		Mat submatrix_to_replace = P.colRange(4 * i, (4 * i) + 4).rowRange(3 * i, (3 * i) + 3);
		affine_camera_matrix.copyTo(submatrix_to_replace);
	}

	// The landmarks in matrix notation (in homogeneous coordinates), $3N\times 1$
	Mat y = Mat::ones(3 * num_landmarks, 1, CV_32FC1);
	for (int i = 0; i < num_landmarks; ++i) {
		y.at<float>(3 * i, 0) = landmarks[i][0];
		y.at<float>((3 * i) + 1, 0) = landmarks[i][1];
		//y.at<float>((3 * i) + 2, 0) = 1; // already 1, stays (homogeneous coordinate)
	}
	// The mean, with an added homogeneous coordinate (x_1, y_1, z_1, 1, x_2, ...)^t
	Mat v_bar = Mat::ones(4 * num_landmarks, 1, CV_32FC1);
	for (int i = 0; i < num_landmarks; ++i) {
		//cv::Vec4f model_mean = morphable_model.get_shape_model().get_mean_at_point(vertex_ids[i]);
		cv::Vec4f model_mean(face_instance(vertex_ids[i]*3), face_instance(vertex_ids[i]*3 + 1), face_instance(vertex_ids[i]*3 + 2), 1.0f);
		v_bar.at<float>(4 * i, 0) = model_mean[0];
		v_bar.at<float>((4 * i) + 1, 0) = model_mean[1];
		v_bar.at<float>((4 * i) + 2, 0) = model_mean[2];
		//v_bar.at<float>((4 * i) + 3, 0) = 1; // already 1, stays (homogeneous coordinate)
		// note: now that a Vec4f is returned, we could use copyTo?
	}

	// Bring into standard regularised quadratic form:
	Mat A = P * V_hat_h; // camera matrix times the basis
	Mat b = P * v_bar - y; // camera matrix times the mean, minus the landmarks.

	Mat AtAReg = A.t() * A + lambda * Mat::eye(num_blendshapes, num_blendshapes, CV_32FC1);
	// Solve using OpenCV:
	Mat c_s;
	bool non_singular = cv::solve(AtAReg, -A.t() * b, c_s, cv::DECOMP_SVD); // DECOMP_SVD calculates the pseudo-inverse if the matrix is not invertible.
	// Because we're using SVD, non_singular will always be true. If we were to use e.g. Cholesky, we could return an expected<T>.

	return std::vector<float>(c_s);
};

/**
 * Fits blendshape coefficients to given 2D landmarks, given a current face shape instance.
 * Uses non-negative least-squares (NNLS) to solve for the coefficients. The NNLS algorithm
 * used doesn't support any regularisation.
 *
 * This algorithm is very similar to the shape fitting in fit_shape_to_landmarks_linear.
 * Instead of the PCA basis, the blendshapes are used, and instead of the mean, a current
 * face instance is used to do the fitting from.
 *
 * @param[in] blendshapes A vector with blendshapes to estimate the coefficients for.
 * @param[in] face_instance A shape instance from which the blendshape coefficients should be estimated (i.e. the current mesh without expressions, e.g. estimated from a previous PCA-model fitting). A 3m x 1 matrix.
 * @param[in] affine_camera_matrix A 3x4 affine camera matrix from model to screen-space (should probably be of type CV_32FC1 as all our calculations are done with float).
 * @param[in] landmarks 2D landmarks from an image to fit the blendshapes to.
 * @param[in] vertex_ids The vertex ids in the model that correspond to the 2D points.
 * @return The estimated blendshape-coefficients.
 */
inline std::vector<float> fit_blendshapes_to_landmarks_nnls(const std::vector<eos::morphablemodel::Blendshape>& blendshapes, const Eigen::VectorXf& face_instance, cv::Mat affine_camera_matrix, const std::vector<cv::Vec2f>& landmarks, const std::vector<int>& vertex_ids)
{
	assert(landmarks.size() == vertex_ids.size());

	using cv::Mat;
	using Eigen::MatrixXf;

	const int num_blendshapes = blendshapes.size();
	const int num_landmarks = static_cast<int>(landmarks.size());

	// Copy all blendshapes into a "basis" matrix with each blendshape being a column:
	Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> blendshapes_as_basis = morphablemodel::to_matrix(blendshapes);
	// Above converts to a RowMajor matrix on return - for now, since the core algorithm still uses cv::Mat (and OpenCV stores data in row-major memory order).
	Mat blendshapes_basis_as_mat = Mat(blendshapes_as_basis.rows(), blendshapes_as_basis.cols(), CV_32FC1, blendshapes_as_basis.data());

	// $\hat{V} \in R^{3N\times m-1}$, subselect the rows of the eigenvector matrix $V$ associated with the $N$ feature points
	// And we insert a row of zeros after every third row, resulting in matrix $\hat{V}_h \in R^{4N\times m-1}$:
	Mat V_hat_h = Mat::zeros(4 * num_landmarks, num_blendshapes, CV_32FC1);
	int row_index = 0;
	for (int i = 0; i < num_landmarks; ++i) {
		Mat basis_rows = blendshapes_basis_as_mat.rowRange(vertex_ids[i] * 3, (vertex_ids[i] * 3) + 3);
		basis_rows.copyTo(V_hat_h.rowRange(row_index, row_index + 3));
		row_index += 4; // replace 3 rows and skip the 4th one, it has all zeros
	}
	// Form a block diagonal matrix $P \in R^{3N\times 4N}$ in which the camera matrix C (P_Affine, affine_camera_matrix) is placed on the diagonal:
	Mat P = Mat::zeros(3 * num_landmarks, 4 * num_landmarks, CV_32FC1);
	for (int i = 0; i < num_landmarks; ++i) {
		Mat submatrix_to_replace = P.colRange(4 * i, (4 * i) + 4).rowRange(3 * i, (3 * i) + 3);
		affine_camera_matrix.copyTo(submatrix_to_replace);
	}

	// The landmarks in matrix notation (in homogeneous coordinates), $3N\times 1$
	Mat y = Mat::ones(3 * num_landmarks, 1, CV_32FC1);
	for (int i = 0; i < num_landmarks; ++i) {
		y.at<float>(3 * i, 0) = landmarks[i][0];
		y.at<float>((3 * i) + 1, 0) = landmarks[i][1];
		//y.at<float>((3 * i) + 2, 0) = 1; // already 1, stays (homogeneous coordinate)
	}
	// The mean, with an added homogeneous coordinate (x_1, y_1, z_1, 1, x_2, ...)^t
	Mat v_bar = Mat::ones(4 * num_landmarks, 1, CV_32FC1);
	for (int i = 0; i < num_landmarks; ++i) {
		cv::Vec4f model_mean(face_instance(vertex_ids[i]*3), face_instance(vertex_ids[i]*3 + 1), face_instance(vertex_ids[i]*3 + 2), 1.0f);
		v_bar.at<float>(4 * i, 0) = model_mean[0];
		v_bar.at<float>((4 * i) + 1, 0) = model_mean[1];
		v_bar.at<float>((4 * i) + 2, 0) = model_mean[2];
		//v_bar.at<float>((4 * i) + 3, 0) = 1; // already 1, stays (homogeneous coordinate)
		// note: now that a Vec4f is returned, we could use copyTo?
	}

	// Bring into standard regularised quadratic form:
	Mat A = P * V_hat_h; // camera matrix times the basis
	Mat b = P * v_bar - y; // camera matrix times the mean, minus the landmarks.

	// Solve using NNLS:
	using RowMajorMatrixXf = Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
	Eigen::Map<RowMajorMatrixXf> A_Eigen(A.ptr<float>(), A.rows, A.cols);
	Eigen::Map<RowMajorMatrixXf> b_Eigen(b.ptr<float>(), b.rows, b.cols);

	Eigen::VectorXf x;
	bool non_singular = Eigen::NNLS<Eigen::MatrixXf>::solve(A_Eigen, -b_Eigen, x);
	Mat c_s(x.rows(), x.cols(), CV_32FC1, x.data()); // create an OpenCV Mat header for the Eigen data

	return std::vector<float>(c_s);
};

	} /* namespace fitting */
} /* namespace eos */

#endif /* BLENDSHAPEFITTING_HPP_ */
<commit_msg>Changed NNLS blendshape fitting to use only Eigen<commit_after>/*
 * eos - A 3D Morphable Model fitting library written in modern C++11/14.
 *
 * File: include/eos/fitting/blendshape_fitting.hpp
 *
 * Copyright 2015 Patrik Huber
 *
 * 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.
 */
#pragma once

#ifndef BLENDSHAPEFITTING_HPP_
#define BLENDSHAPEFITTING_HPP_

#include "eos/morphablemodel/Blendshape.hpp"

#include "Eigen/Core"
#include "nnls.h"

#include "opencv2/core/core.hpp"

#include <vector>
#include <cassert>

namespace eos {
	namespace fitting {

/**
 * Fits blendshape coefficients to given 2D landmarks, given a current face shape instance.
 * It's a linear, closed-form solution fitting algorithm, with regularisation (constraining
 * the L2-norm of the coefficients). However, there is no constraint on the coefficients,
 * so negative coefficients are allowed, which, with linear blendshapes (offsets), will most
 * likely not be desired. Thus, prefer the function
 * fit_blendshapes_to_landmarks_nnls(std::vector<eos::morphablemodel::Blendshape>, cv::Mat, cv::Mat, std::vector<cv::Vec2f>, std::vector<int>).
 *
 * This algorithm is very similar to the shape fitting in fit_shape_to_landmarks_linear.
 * Instead of the PCA basis, the blendshapes are used, and instead of the mean, a current
 * face instance is used to do the fitting from.
 *
 * @param[in] blendshapes A vector with blendshapes to estimate the coefficients for.
 * @param[in] face_instance A shape instance from which the blendshape coefficients should be estimated (i.e. the current mesh without expressions, e.g. estimated from a previous PCA-model fitting). A 3m x 1 matrix.
 * @param[in] affine_camera_matrix A 3x4 affine camera matrix from model to screen-space (should probably be of type CV_32FC1 as all our calculations are done with float).
 * @param[in] landmarks 2D landmarks from an image to fit the blendshapes to.
 * @param[in] vertex_ids The vertex ids in the model that correspond to the 2D points.
 * @param[in] lambda A regularisation parameter, constraining the L2-norm of the coefficients.
 * @return The estimated blendshape-coefficients.
 */
inline std::vector<float> fit_blendshapes_to_landmarks_linear(const std::vector<eos::morphablemodel::Blendshape>& blendshapes, const Eigen::VectorXf& face_instance, cv::Mat affine_camera_matrix, const std::vector<cv::Vec2f>& landmarks, const std::vector<int>& vertex_ids, float lambda=500.0f)
{
	assert(landmarks.size() == vertex_ids.size());

	using cv::Mat;
	using Eigen::MatrixXf;

	const int num_blendshapes = blendshapes.size();
	const int num_landmarks = static_cast<int>(landmarks.size());

	// Copy all blendshapes into a "basis" matrix with each blendshape being a column:
	Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> blendshapes_as_basis = morphablemodel::to_matrix(blendshapes);
	// Above converts to a RowMajor matrix on return - for now, since the core algorithm still uses cv::Mat (and OpenCV stores data in row-major memory order).
	Mat blendshapes_basis_as_mat = Mat(blendshapes_as_basis.rows(), blendshapes_as_basis.cols(), CV_32FC1, blendshapes_as_basis.data());

	// $\hat{V} \in R^{3N\times m-1}$, subselect the rows of the eigenvector matrix $V$ associated with the $N$ feature points
	// And we insert a row of zeros after every third row, resulting in matrix $\hat{V}_h \in R^{4N\times m-1}$:
	Mat V_hat_h = Mat::zeros(4 * num_landmarks, num_blendshapes, CV_32FC1);
	int row_index = 0;
	for (int i = 0; i < num_landmarks; ++i) {
		Mat basis_rows = blendshapes_basis_as_mat.rowRange(vertex_ids[i] * 3, (vertex_ids[i] * 3) + 3);
		basis_rows.copyTo(V_hat_h.rowRange(row_index, row_index + 3));
		row_index += 4; // replace 3 rows and skip the 4th one, it has all zeros
	}
	// Form a block diagonal matrix $P \in R^{3N\times 4N}$ in which the camera matrix C (P_Affine, affine_camera_matrix) is placed on the diagonal:
	Mat P = Mat::zeros(3 * num_landmarks, 4 * num_landmarks, CV_32FC1);
	for (int i = 0; i < num_landmarks; ++i) {
		Mat submatrix_to_replace = P.colRange(4 * i, (4 * i) + 4).rowRange(3 * i, (3 * i) + 3);
		affine_camera_matrix.copyTo(submatrix_to_replace);
	}

	// The landmarks in matrix notation (in homogeneous coordinates), $3N\times 1$
	Mat y = Mat::ones(3 * num_landmarks, 1, CV_32FC1);
	for (int i = 0; i < num_landmarks; ++i) {
		y.at<float>(3 * i, 0) = landmarks[i][0];
		y.at<float>((3 * i) + 1, 0) = landmarks[i][1];
		//y.at<float>((3 * i) + 2, 0) = 1; // already 1, stays (homogeneous coordinate)
	}
	// The mean, with an added homogeneous coordinate (x_1, y_1, z_1, 1, x_2, ...)^t
	Mat v_bar = Mat::ones(4 * num_landmarks, 1, CV_32FC1);
	for (int i = 0; i < num_landmarks; ++i) {
		//cv::Vec4f model_mean = morphable_model.get_shape_model().get_mean_at_point(vertex_ids[i]);
		cv::Vec4f model_mean(face_instance(vertex_ids[i]*3), face_instance(vertex_ids[i]*3 + 1), face_instance(vertex_ids[i]*3 + 2), 1.0f);
		v_bar.at<float>(4 * i, 0) = model_mean[0];
		v_bar.at<float>((4 * i) + 1, 0) = model_mean[1];
		v_bar.at<float>((4 * i) + 2, 0) = model_mean[2];
		//v_bar.at<float>((4 * i) + 3, 0) = 1; // already 1, stays (homogeneous coordinate)
		// note: now that a Vec4f is returned, we could use copyTo?
	}

	// Bring into standard regularised quadratic form:
	Mat A = P * V_hat_h; // camera matrix times the basis
	Mat b = P * v_bar - y; // camera matrix times the mean, minus the landmarks.

	Mat AtAReg = A.t() * A + lambda * Mat::eye(num_blendshapes, num_blendshapes, CV_32FC1);
	// Solve using OpenCV:
	Mat c_s;
	bool non_singular = cv::solve(AtAReg, -A.t() * b, c_s, cv::DECOMP_SVD); // DECOMP_SVD calculates the pseudo-inverse if the matrix is not invertible.
	// Because we're using SVD, non_singular will always be true. If we were to use e.g. Cholesky, we could return an expected<T>.

	return std::vector<float>(c_s);
};

/**
 * Fits blendshape coefficients to given 2D landmarks, given a current face shape instance.
 * Uses non-negative least-squares (NNLS) to solve for the coefficients. The NNLS algorithm
 * used doesn't support any regularisation.
 *
 * This algorithm is very similar to the shape fitting in fit_shape_to_landmarks_linear.
 * Instead of the PCA basis, the blendshapes are used, and instead of the mean, a current
 * face instance is used to do the fitting from.
 *
 * @param[in] blendshapes A vector with blendshapes to estimate the coefficients for.
 * @param[in] face_instance A shape instance from which the blendshape coefficients should be estimated (i.e. the current mesh without expressions, e.g. estimated from a previous PCA-model fitting). A 3m x 1 matrix.
 * @param[in] affine_camera_matrix A 3x4 affine camera matrix from model to screen-space (should probably be of type CV_32FC1 as all our calculations are done with float).
 * @param[in] landmarks 2D landmarks from an image to fit the blendshapes to.
 * @param[in] vertex_ids The vertex ids in the model that correspond to the 2D points.
 * @return The estimated blendshape-coefficients.
 */
inline std::vector<float> fit_blendshapes_to_landmarks_nnls(const std::vector<eos::morphablemodel::Blendshape>& blendshapes, const Eigen::VectorXf& face_instance, cv::Mat affine_camera_matrix, const std::vector<cv::Vec2f>& landmarks, const std::vector<int>& vertex_ids)
{
	assert(landmarks.size() == vertex_ids.size());

	using Eigen::VectorXf;
	using Eigen::MatrixXf;

	const int num_blendshapes = blendshapes.size();
	const int num_landmarks = static_cast<int>(landmarks.size());

	// Copy all blendshapes into a "basis" matrix with each blendshape being a column:
	MatrixXf blendshapes_as_basis = morphablemodel::to_matrix(blendshapes);

	// $\hat{V} \in R^{3N\times m-1}$, subselect the rows of the eigenvector matrix $V$ associated with the $N$ feature points
	// And we insert a row of zeros after every third row, resulting in matrix $\hat{V}_h \in R^{4N\times m-1}$:
	MatrixXf V_hat_h = MatrixXf::Zero(4 * num_landmarks, num_blendshapes);
	int row_index = 0;
	for (int i = 0; i < num_landmarks; ++i) {
		V_hat_h.block(row_index, 0, 3, V_hat_h.cols()) = blendshapes_as_basis.block(vertex_ids[i] * 3, 0, 3, blendshapes_as_basis.cols());
		row_index += 4; // replace 3 rows and skip the 4th one, it has all zeros
	}
	// Form a block diagonal matrix $P \in R^{3N\times 4N}$ in which the camera matrix C (P_Affine, affine_camera_matrix) is placed on the diagonal:
	MatrixXf P = MatrixXf::Zero(3 * num_landmarks, 4 * num_landmarks);
	for (int i = 0; i < num_landmarks; ++i) {
		using RowMajorMatrixXf = Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
		P.block(3 * i, 4 * i, 3, 4) = Eigen::Map<RowMajorMatrixXf>(affine_camera_matrix.ptr<float>(), affine_camera_matrix.rows, affine_camera_matrix.cols);
	}
	// The landmarks in matrix notation (in homogeneous coordinates), $3N\times 1$
	VectorXf y = VectorXf::Ones(3 * num_landmarks);
	for (int i = 0; i < num_landmarks; ++i) {
		y(3 * i) = landmarks[i][0];
		y((3 * i) + 1) = landmarks[i][1];
		//y_((3 * i) + 2) = 1; // already 1, stays (homogeneous coordinate)
	}
	// The mean, with an added homogeneous coordinate (x_1, y_1, z_1, 1, x_2, ...)^t
	VectorXf v_bar = VectorXf::Ones(4 * num_landmarks);
	for (int i = 0; i < num_landmarks; ++i) {
		v_bar(4 * i) = face_instance(vertex_ids[i] * 3);
		v_bar((4 * i) + 1) = face_instance(vertex_ids[i] * 3 + 1);
		v_bar((4 * i) + 2) = face_instance(vertex_ids[i] * 3 + 2);
		//v_bar((4 * i) + 3) = 1; // already 1, stays (homogeneous coordinate)
	}

	// Bring into standard least squares form:
	const MatrixXf A = P * V_hat_h; // camera matrix times the basis
	const MatrixXf b = P * v_bar - y; // camera matrix times the mean, minus the landmarks
	// Solve using NNLS:
	Eigen::VectorXf x;
	bool non_singular = Eigen::NNLS<MatrixXf>::solve(A, -b, x);

	return std::vector<float>(x.data(), x.data() + x.size());
};

	} /* namespace fitting */
} /* namespace eos */

#endif /* BLENDSHAPEFITTING_HPP_ */
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id: AliVZEROCalibData.cxx,                                            */

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// class for VZERO calibration                                             //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

#include "AliVZEROCalibData.h"

ClassImp(AliVZEROCalibData)

//________________________________________________________________
AliVZEROCalibData::AliVZEROCalibData()
{

}

//________________________________________________________________
AliVZEROCalibData::AliVZEROCalibData(const char* name)
{
  TString namst = "Calib_";
  namst += name;
  SetName(namst.Data());
  SetTitle(namst.Data());

}

//________________________________________________________________
AliVZEROCalibData::AliVZEROCalibData(const AliVZEROCalibData& calibda) :
  TNamed(calibda)
{
// copy constructor

  SetName(calibda.GetName());
  SetTitle(calibda.GetName());

  for(int t=0; t<128; t++) {
      fPedestal[t] = calibda.GetPedestal(t);
      fSigma[t]    = calibda.GetSigma(t);
      fGain[t]     = calibda.GetGain(t); }

  for(int t=0; t<64; t++) {
      fTimeOffset[t]   = calibda.GetTimeOffset(t);
      fTimeGain[t]     = calibda.GetTimeGain(t); }

}

//________________________________________________________________
AliVZEROCalibData &AliVZEROCalibData::operator =(const AliVZEROCalibData& calibda)
{
// assignment operator

  SetName(calibda.GetName());
  SetTitle(calibda.GetName());

  for(int t=0; t<128; t++) {
      fPedestal[t] = calibda.GetPedestal(t);
      fSigma[t]    = calibda.GetSigma(t);
      fGain[t]     = calibda.GetGain(t); }

  for(int t=0; t<64; t++) {
      fTimeOffset[t]   = calibda.GetTimeOffset(t);
      fTimeGain[t]     = calibda.GetTimeGain(t); }

  return *this;

}

//________________________________________________________________
AliVZEROCalibData::~AliVZEROCalibData()
{

}

//________________________________________________________________
void AliVZEROCalibData::SetPedestal(Float_t* Pedestal)
{
  if(Pedestal) for(int t=0; t<128; t++) fPedestal[t] = Pedestal[t];
  else for(int t=0; t<128; t++) fPedestal[t] = 0.0;
}

//________________________________________________________________
void AliVZEROCalibData::SetSigma(Float_t* Sigma)
{
  if(Sigma) for(int t=0; t<128; t++) fSigma[t] = Sigma[t];
  else for(int t=0; t<128; t++) fSigma[t] = 0.0;
}

//________________________________________________________________
void AliVZEROCalibData::SetGain(Float_t* Gain)
{
  if(Gain) for(int t=0; t<128; t++) fGain[t] = Gain[t];
  else for(int t=0; t<128; t++) fGain[t] = 0.0;
}

//________________________________________________________________
void AliVZEROCalibData::SetTimeOffset(Float_t* TimeOffset)
{
  if(TimeOffset) for(int t=0; t<64; t++) fTimeOffset[t] = TimeOffset[t];
  else for(int t=0; t<64; t++) fTimeOffset[t] = 0.0;
}

//________________________________________________________________
void AliVZEROCalibData::SetTimeGain(Float_t* TimeGain)
{
  if(TimeGain) for(int t=0; t<64; t++) fTimeGain[t] = TimeGain[t];
  else for(int t=0; t<64; t++) fTimeGain[t] = 0.0;
}
<commit_msg>implementation of dummy Reset method<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id: AliVZEROCalibData.cxx,                                            */

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// class for VZERO calibration                                             //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

#include "AliVZEROCalibData.h"

ClassImp(AliVZEROCalibData)

//________________________________________________________________
AliVZEROCalibData::AliVZEROCalibData()
{

}

//________________________________________________________________
void AliVZEROCalibData::Reset()
{

}

//________________________________________________________________
AliVZEROCalibData::AliVZEROCalibData(const char* name)
{
  TString namst = "Calib_";
  namst += name;
  SetName(namst.Data());
  SetTitle(namst.Data());

}

//________________________________________________________________
AliVZEROCalibData::AliVZEROCalibData(const AliVZEROCalibData& calibda) :
  TNamed(calibda)
{
// copy constructor

  SetName(calibda.GetName());
  SetTitle(calibda.GetName());

  for(int t=0; t<128; t++) {
      fPedestal[t] = calibda.GetPedestal(t);
      fSigma[t]    = calibda.GetSigma(t);
      fGain[t]     = calibda.GetGain(t); }

  for(int t=0; t<64; t++) {
      fTimeOffset[t]   = calibda.GetTimeOffset(t);
      fTimeGain[t]     = calibda.GetTimeGain(t); }

}

//________________________________________________________________
AliVZEROCalibData &AliVZEROCalibData::operator =(const AliVZEROCalibData& calibda)
{
// assignment operator

  SetName(calibda.GetName());
  SetTitle(calibda.GetName());

  for(int t=0; t<128; t++) {
      fPedestal[t] = calibda.GetPedestal(t);
      fSigma[t]    = calibda.GetSigma(t);
      fGain[t]     = calibda.GetGain(t); }

  for(int t=0; t<64; t++) {
      fTimeOffset[t]   = calibda.GetTimeOffset(t);
      fTimeGain[t]     = calibda.GetTimeGain(t); }

  return *this;

}

//________________________________________________________________
AliVZEROCalibData::~AliVZEROCalibData()
{

}

//________________________________________________________________
void AliVZEROCalibData::SetPedestal(Float_t* Pedestal)
{
  if(Pedestal) for(int t=0; t<128; t++) fPedestal[t] = Pedestal[t];
  else for(int t=0; t<128; t++) fPedestal[t] = 0.0;
}

//________________________________________________________________
void AliVZEROCalibData::SetSigma(Float_t* Sigma)
{
  if(Sigma) for(int t=0; t<128; t++) fSigma[t] = Sigma[t];
  else for(int t=0; t<128; t++) fSigma[t] = 0.0;
}

//________________________________________________________________
void AliVZEROCalibData::SetGain(Float_t* Gain)
{
  if(Gain) for(int t=0; t<128; t++) fGain[t] = Gain[t];
  else for(int t=0; t<128; t++) fGain[t] = 0.0;
}

//________________________________________________________________
void AliVZEROCalibData::SetTimeOffset(Float_t* TimeOffset)
{
  if(TimeOffset) for(int t=0; t<64; t++) fTimeOffset[t] = TimeOffset[t];
  else for(int t=0; t<64; t++) fTimeOffset[t] = 0.0;
}

//________________________________________________________________
void AliVZEROCalibData::SetTimeGain(Float_t* TimeGain)
{
  if(TimeGain) for(int t=0; t<64; t++) fTimeGain[t] = TimeGain[t];
  else for(int t=0; t<64; t++) fTimeGain[t] = 0.0;
}
<|endoftext|>