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

  Program:   Visualization Toolkit
  Module:    vtkAxis.cxx

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

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

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

#include "vtkAxis.h"

#include "vtkContext2D.h"
#include "vtkPen.h"
#include "vtkTextProperty.h"
#include "vtkFloatArray.h"
#include "vtkStringArray.h"
#include "vtkStdString.h"
#include "vtksys/ios/sstream"

#include "vtkObjectFactory.h"

#include "math.h"

//-----------------------------------------------------------------------------
vtkCxxRevisionMacro(vtkAxis, "1.24");

//-----------------------------------------------------------------------------
vtkStandardNewMacro(vtkAxis);

//-----------------------------------------------------------------------------
vtkAxis::vtkAxis()
{
  this->Position = vtkAxis::LEFT;
  this->Point1[0] = 0.0;
  this->Point1[1] = 0.0;
  this->Point2[0] = 10.0;
  this->Point2[1] = 10.0;
  this->TickInterval = 1.0;
  this->NumberOfTicks = 6;
  this->LabelProperties = vtkTextProperty::New();
  this->LabelProperties->SetColor(0.0, 0.0, 0.0);
  this->LabelProperties->SetFontSize(12);
  this->LabelProperties->SetFontFamilyToArial();
  this->LabelProperties->SetJustificationToCentered();
  this->TitleProperties = vtkTextProperty::New();
  this->TitleProperties->SetColor(0.0, 0.0, 0.0);
  this->TitleProperties->SetFontSize(12);
  this->TitleProperties->SetFontFamilyToArial();
  this->TitleProperties->SetBold(1);
  this->TitleProperties->SetJustificationToCentered();
  this->Minimum = 0.0;
  this->Maximum = 6.66;
  this->Title = NULL;
  this->LogScale = false;
  this->GridVisible = true;
  this->LabelsVisible = true;
  this->Precision = 2;
  this->Notation = 2; // Fixed - do the right thing...
  this->Behavior = 0;
  this->Pen = vtkPen::New();
  this->Pen->SetColor(0, 0, 0);
  this->Pen->SetWidth(1.0);
  this->GridPen = vtkPen::New();
  this->GridPen->SetColor(242, 242, 242);
  this->GridPen->SetWidth(1.0);
  this->TickPositions = vtkFloatArray::New();
  this->TickLabels = vtkStringArray::New();
}

//-----------------------------------------------------------------------------
vtkAxis::~vtkAxis()
{
  this->SetTitle(NULL);
  this->TitleProperties->Delete();
  this->LabelProperties->Delete();
  this->TickPositions->Delete();
  this->TickPositions = NULL;
  this->TickLabels->Delete();
  this->TickLabels = NULL;
  this->Pen->Delete();
  this->GridPen->Delete();
}

//-----------------------------------------------------------------------------
void vtkAxis::Update()
{
  if (!this->Visible || this->BuildTime > this->MTime)
    {
    return;
    }

  this->TickPositions->SetNumberOfTuples(0);
  this->TickLabels->SetNumberOfTuples(0);

  // Figure out what type of behavior we should follow
  if (this->Behavior < 2)
    {
    this->RecalculateTickSpacing();
    }

  // Calculate where the first tick mark should be drawn
  double tick = ceil(this->Minimum / this->TickInterval) * this->TickInterval;
  int n = (this->Maximum - this->Minimum) / this->TickInterval;

  // If there will be more than 500 tick marks it is likely a rounding issue
  // with a small range.
  if (n > 500)
    {
    vtkWarningMacro("A large number of tick marks was calculated (" << n
                    << "). This is likely an error.")
    return;
    }

  // If this check is not used, and the first tick is at 0.0 then it has the
  // negative sign bit set. This check gets rid of the negative bit but is quite
  // possibly not the best way of doing it...
  if (tick == 0.0f)
    {
    tick = 0.0f;
    }

  double scaling = 0.0;
  double origin = 0.0;
  if (this->Point1[0] == this->Point2[0]) // x1 == x2, therefore vertical
    {
    scaling = (this->Point2[1] - this->Point1[1]) /
              (this->Maximum - this->Minimum);
    origin = this->Point1[1];
    }
  else
    {
    scaling = (this->Point2[0] - this->Point1[0]) /
              (this->Maximum - this->Minimum);
    origin = this->Point1[0];
    }

  while (tick <= this->Maximum)
    {
    // Calculate the next tick mark position
    int iTick = static_cast<int>(origin + (tick - this->Minimum) * scaling);

    this->TickPositions->InsertNextValue(iTick);
    // Make a tick mark label for the tick
    double value = tick;
    if (this->LogScale)
      {
      value = pow(double(10.0), double(tick));
      }

    vtksys_ios::ostringstream ostr;
    ostr.imbue(vtkstd::locale::classic());
    if (this->Notation > 0)
      {
      ostr.precision(this->Precision);
      }
    if (this->Notation == 1)
      {
      // Scientific notation
      ostr.setf(vtksys_ios::ios::scientific, vtksys_ios::ios::floatfield);
      }
    else if (this->Notation == 2)
      {
      ostr.setf(ios::fixed, ios::floatfield);
      }
    ostr << value;

    this->TickLabels->InsertNextValue(ostr.str());

    tick += this->TickInterval;
    }
  this->BuildTime.Modified();
}

//-----------------------------------------------------------------------------
bool vtkAxis::Paint(vtkContext2D *painter)
{
  // This is where everything should be drawn, or dispatched to other methods.
  vtkDebugMacro(<< "Paint event called in vtkAxis.");

  if (!this->Visible)
    {
    return false;
    }

  painter->ApplyPen(this->Pen);

  // Draw this axis
  painter->DrawLine(this->Point1[0], this->Point1[1],
                    this->Point2[0], this->Point2[1]);
  vtkTextProperty *prop = painter->GetTextProp();

  // Draw the axis title if there is one
  if (this->Title)
    {
    int x = 0;
    int y = 0;
    painter->ApplyTextProp(this->TitleProperties);

    // Draw the axis label
    if (this->Position == vtkAxis::LEFT)
      {
      // Draw the axis label
      x = static_cast<int>(this->Point1[0] - 35);
      y = static_cast<int>(this->Point1[1] + this->Point2[1]) / 2;
      prop->SetOrientation(90.0);
      prop->SetVerticalJustificationToBottom();
      }
    else if (this->Position == vtkAxis::RIGHT)
      {
      // Draw the axis label
      x = static_cast<int>(this->Point1[0] + 45);
      y = static_cast<int>(this->Point1[1] + this->Point2[1]) / 2;
      prop->SetOrientation(90.0);
      prop->SetVerticalJustificationToTop();
      }
    else if (this->Position == vtkAxis::BOTTOM)
      {
      x = static_cast<int>(this->Point1[0] + this->Point2[0]) / 2;
      y = static_cast<int>(this->Point1[1] - 30);
      prop->SetOrientation(0.0);
      prop->SetVerticalJustificationToTop();
      }
    else if (this->Position == vtkAxis::TOP)
      {
      x = static_cast<int>(this->Point1[0] + this->Point2[0]) / 2;
      y = static_cast<int>(this->Point1[1] + 30);
      prop->SetOrientation(0.0);
      prop->SetVerticalJustificationToBottom();
      }
    else if (this->Position == vtkAxis::PARALLEL)
      {
      x = static_cast<int>(this->Point1[0]);
      y = static_cast<int>(this->Point1[1] - 10);
      prop->SetOrientation(0.0);
      prop->SetVerticalJustificationToTop();
      }

    painter->DrawString(x, y, this->Title);
    }

  // Now draw the tick marks
  painter->ApplyTextProp(this->LabelProperties);

  float *tickPos = this->TickPositions->GetPointer(0);
  vtkStdString *tickLabel = this->TickLabels->GetPointer(0);
  vtkIdType numMarks = this->TickPositions->GetNumberOfTuples();

  // There are four possible tick label positions, which should be set by the
  // class laying out the axes.
  if (this->Position == vtkAxis::LEFT || this->Position == vtkAxis::PARALLEL)
    {
    prop->SetJustificationToRight();
    prop->SetVerticalJustificationToCentered();

    // Draw the tick marks and labels
    for (vtkIdType i = 0; i < numMarks; ++i)
      {
      painter->DrawLine(this->Point1[0] - 5, tickPos[i],
                        this->Point1[0],     tickPos[i]);
      if (this->LabelsVisible)
        {
        painter->DrawString(this->Point1[0] - 7, tickPos[i], tickLabel[i]);
        }
      }
    }
  else if (this->Position == vtkAxis::RIGHT)
    {
    prop->SetJustificationToLeft();
    prop->SetVerticalJustificationToCentered();

    // Draw the tick marks and labels
    for (vtkIdType i = 0; i < numMarks; ++i)
      {
      painter->DrawLine(this->Point1[0] + 5, tickPos[i],
                        this->Point1[0],     tickPos[i]);
      if (this->LabelsVisible)
        {
        painter->DrawString(this->Point1[0] + 7, tickPos[i], tickLabel[i]);
        }
      }
    }
  else if (this->Position == vtkAxis::BOTTOM)
    {
    prop->SetJustificationToCentered();
    prop->SetVerticalJustificationToTop();

    // Draw the tick marks and labels
    for (vtkIdType i = 0; i < numMarks; ++i)
      {
      painter->DrawLine(tickPos[i], this->Point1[1] - 5,
                        tickPos[i], this->Point1[1]);
      if (this->LabelsVisible)
        {
        painter->DrawString(tickPos[i], int(this->Point1[1] - 7), tickLabel[i]);
        }
      }
    }
  else if (this->Position == vtkAxis::TOP)
    {
    prop->SetJustificationToCentered();
    prop->SetVerticalJustificationToBottom();

    // Draw the tick marks and labels
    for (vtkIdType i = 0; i < numMarks; ++i)
      {
      painter->DrawLine(tickPos[i], this->Point1[1] + 5,
                        tickPos[i], this->Point1[1]);
      if (this->LabelsVisible)
        {
        painter->DrawString(tickPos[i], int(this->Point1[1] + 7), tickLabel[i]);
        }
      }
    }

  return true;
}

//-----------------------------------------------------------------------------
void vtkAxis::AutoScale()
{
  // Calculate the min and max, set the number of ticks and the tick spacing
  this->TickInterval = this->CalculateNiceMinMax(this->Minimum, this->Maximum);
}

//-----------------------------------------------------------------------------
void vtkAxis::RecalculateTickSpacing()
{
  // Calculate the min and max, set the number of ticks and the tick spacing,
  // discard the min and max in this case. TODO: Refactor the function called.
  double min, max;
  this->TickInterval = this->CalculateNiceMinMax(min, max);
}

//-----------------------------------------------------------------------------
float vtkAxis::CalculateNiceMinMax(double &min, double &max)
{
  // First get the order of the range of the numbers
  if (this->Maximum == this->Minimum)
    {
    this->Minimum *= 0.95;
    this->Maximum *= 1.05;
    }
  double range = this->Maximum - this->Minimum;
  bool isNegative = false;
  if (range < 0.0f)
    {
    isNegative = true;
    range *= -1.0f;
    }

  // Calculate an upper limit on the number of tick marks - at least 30 pixels
  // should be between each tick mark.
  float pixelRange = this->Point1[0] == this->Point2[0] ?
                     this->Point2[1] - this->Point1[1] :
                     this->Point2[0] - this->Point1[0];
  int maxTicks = static_cast<int>(pixelRange / 50.0f);
  if (maxTicks == 0)
    {
    // The axes do not have a valid set of points - return
    return 0.0f;
    }
  double tickSpacing = range / maxTicks;

  int order = static_cast<int>(floor(log10(tickSpacing)));
  double normTickSpacing = tickSpacing * pow(10.0f, -order);
  double niceTickSpacing = this->NiceNumber(normTickSpacing, true);
  niceTickSpacing *= pow(10.0f, order);

  if (isNegative)
    {
    min = ceil(this->Minimum / niceTickSpacing) * niceTickSpacing;
    max = floor(this->Maximum / niceTickSpacing) * niceTickSpacing;
    }
  else
    {
    min = floor(this->Minimum / niceTickSpacing) * niceTickSpacing;
    max = ceil(this->Maximum / niceTickSpacing) * niceTickSpacing;
    }

  float newRange = max - min;
  this->NumberOfTicks = static_cast<int>(floor(newRange / niceTickSpacing)) + 1;

  return niceTickSpacing;
}

//-----------------------------------------------------------------------------
float vtkAxis::NiceNumber(double n, bool roundUp)
{
  if (roundUp)
    {
    if (n <= 1.0)
      {
      return 1.0;
      }
    else if (n <= 2.0)
      {
      return 2.0;
      }
    else if (n <= 5.0)
      {
      return 5.0;
      }
    else
      {
      return 10.0;
      }
    }
  else
    {
    if (n < 1.5)
      {
      return 1.0;
      }
    else if (n <= 3.0)
      {
      return 2.0;
      }
    else if (n <= 7.0)
      {
      return 5.0;
      }
    else
      {
      return 10.0;
      }
    }
}

//-----------------------------------------------------------------------------
void vtkAxis::PrintSelf(ostream &os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  if (this->Title)
    {
    os << indent << "Axis title: \"" << *this->Title << "\"" << endl;
    }
  os << indent << "Minimum point: " << this->Point1[0] << ", "
     << this->Point1[1] << endl;
  os << indent << "Maximum point: " << this->Point2[0] << ", "
     << this->Point2[1] << endl;
  os << indent << "Range: " << this->Minimum << " - " << this->Maximum << endl;
  os << indent << "Number of tick marks: " << this->NumberOfTicks << endl;

}
<commit_msg>COMP: fixed warnings<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkAxis.cxx

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

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

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

#include "vtkAxis.h"

#include "vtkContext2D.h"
#include "vtkPen.h"
#include "vtkTextProperty.h"
#include "vtkFloatArray.h"
#include "vtkStringArray.h"
#include "vtkStdString.h"
#include "vtksys/ios/sstream"

#include "vtkObjectFactory.h"

#include "math.h"

//-----------------------------------------------------------------------------
vtkCxxRevisionMacro(vtkAxis, "1.25");

//-----------------------------------------------------------------------------
vtkStandardNewMacro(vtkAxis);

//-----------------------------------------------------------------------------
vtkAxis::vtkAxis()
{
  this->Position = vtkAxis::LEFT;
  this->Point1[0] = 0.0;
  this->Point1[1] = 0.0;
  this->Point2[0] = 10.0;
  this->Point2[1] = 10.0;
  this->TickInterval = 1.0;
  this->NumberOfTicks = 6;
  this->LabelProperties = vtkTextProperty::New();
  this->LabelProperties->SetColor(0.0, 0.0, 0.0);
  this->LabelProperties->SetFontSize(12);
  this->LabelProperties->SetFontFamilyToArial();
  this->LabelProperties->SetJustificationToCentered();
  this->TitleProperties = vtkTextProperty::New();
  this->TitleProperties->SetColor(0.0, 0.0, 0.0);
  this->TitleProperties->SetFontSize(12);
  this->TitleProperties->SetFontFamilyToArial();
  this->TitleProperties->SetBold(1);
  this->TitleProperties->SetJustificationToCentered();
  this->Minimum = 0.0;
  this->Maximum = 6.66;
  this->Title = NULL;
  this->LogScale = false;
  this->GridVisible = true;
  this->LabelsVisible = true;
  this->Precision = 2;
  this->Notation = 2; // Fixed - do the right thing...
  this->Behavior = 0;
  this->Pen = vtkPen::New();
  this->Pen->SetColor(0, 0, 0);
  this->Pen->SetWidth(1.0);
  this->GridPen = vtkPen::New();
  this->GridPen->SetColor(242, 242, 242);
  this->GridPen->SetWidth(1.0);
  this->TickPositions = vtkFloatArray::New();
  this->TickLabels = vtkStringArray::New();
}

//-----------------------------------------------------------------------------
vtkAxis::~vtkAxis()
{
  this->SetTitle(NULL);
  this->TitleProperties->Delete();
  this->LabelProperties->Delete();
  this->TickPositions->Delete();
  this->TickPositions = NULL;
  this->TickLabels->Delete();
  this->TickLabels = NULL;
  this->Pen->Delete();
  this->GridPen->Delete();
}

//-----------------------------------------------------------------------------
void vtkAxis::Update()
{
  if (!this->Visible || this->BuildTime > this->MTime)
    {
    return;
    }

  this->TickPositions->SetNumberOfTuples(0);
  this->TickLabels->SetNumberOfTuples(0);

  // Figure out what type of behavior we should follow
  if (this->Behavior < 2)
    {
    this->RecalculateTickSpacing();
    }

  // Calculate where the first tick mark should be drawn
  double tick = ceil(this->Minimum / this->TickInterval) * this->TickInterval;
  int n = static_cast<int>(
    (this->Maximum - this->Minimum) / this->TickInterval);

  // If there will be more than 500 tick marks it is likely a rounding issue
  // with a small range.
  if (n > 500)
    {
    vtkWarningMacro("A large number of tick marks was calculated (" << n
                    << "). This is likely an error.")
    return;
    }

  // If this check is not used, and the first tick is at 0.0 then it has the
  // negative sign bit set. This check gets rid of the negative bit but is quite
  // possibly not the best way of doing it...
  if (tick == 0.0f)
    {
    tick = 0.0f;
    }

  double scaling = 0.0;
  double origin = 0.0;
  if (this->Point1[0] == this->Point2[0]) // x1 == x2, therefore vertical
    {
    scaling = (this->Point2[1] - this->Point1[1]) /
              (this->Maximum - this->Minimum);
    origin = this->Point1[1];
    }
  else
    {
    scaling = (this->Point2[0] - this->Point1[0]) /
              (this->Maximum - this->Minimum);
    origin = this->Point1[0];
    }

  while (tick <= this->Maximum)
    {
    // Calculate the next tick mark position
    int iTick = static_cast<int>(origin + (tick - this->Minimum) * scaling);

    this->TickPositions->InsertNextValue(iTick);
    // Make a tick mark label for the tick
    double value = tick;
    if (this->LogScale)
      {
      value = pow(double(10.0), double(tick));
      }

    vtksys_ios::ostringstream ostr;
    ostr.imbue(vtkstd::locale::classic());
    if (this->Notation > 0)
      {
      ostr.precision(this->Precision);
      }
    if (this->Notation == 1)
      {
      // Scientific notation
      ostr.setf(vtksys_ios::ios::scientific, vtksys_ios::ios::floatfield);
      }
    else if (this->Notation == 2)
      {
      ostr.setf(ios::fixed, ios::floatfield);
      }
    ostr << value;

    this->TickLabels->InsertNextValue(ostr.str());

    tick += this->TickInterval;
    }
  this->BuildTime.Modified();
}

//-----------------------------------------------------------------------------
bool vtkAxis::Paint(vtkContext2D *painter)
{
  // This is where everything should be drawn, or dispatched to other methods.
  vtkDebugMacro(<< "Paint event called in vtkAxis.");

  if (!this->Visible)
    {
    return false;
    }

  painter->ApplyPen(this->Pen);

  // Draw this axis
  painter->DrawLine(this->Point1[0], this->Point1[1],
                    this->Point2[0], this->Point2[1]);
  vtkTextProperty *prop = painter->GetTextProp();

  // Draw the axis title if there is one
  if (this->Title)
    {
    int x = 0;
    int y = 0;
    painter->ApplyTextProp(this->TitleProperties);

    // Draw the axis label
    if (this->Position == vtkAxis::LEFT)
      {
      // Draw the axis label
      x = static_cast<int>(this->Point1[0] - 35);
      y = static_cast<int>(this->Point1[1] + this->Point2[1]) / 2;
      prop->SetOrientation(90.0);
      prop->SetVerticalJustificationToBottom();
      }
    else if (this->Position == vtkAxis::RIGHT)
      {
      // Draw the axis label
      x = static_cast<int>(this->Point1[0] + 45);
      y = static_cast<int>(this->Point1[1] + this->Point2[1]) / 2;
      prop->SetOrientation(90.0);
      prop->SetVerticalJustificationToTop();
      }
    else if (this->Position == vtkAxis::BOTTOM)
      {
      x = static_cast<int>(this->Point1[0] + this->Point2[0]) / 2;
      y = static_cast<int>(this->Point1[1] - 30);
      prop->SetOrientation(0.0);
      prop->SetVerticalJustificationToTop();
      }
    else if (this->Position == vtkAxis::TOP)
      {
      x = static_cast<int>(this->Point1[0] + this->Point2[0]) / 2;
      y = static_cast<int>(this->Point1[1] + 30);
      prop->SetOrientation(0.0);
      prop->SetVerticalJustificationToBottom();
      }
    else if (this->Position == vtkAxis::PARALLEL)
      {
      x = static_cast<int>(this->Point1[0]);
      y = static_cast<int>(this->Point1[1] - 10);
      prop->SetOrientation(0.0);
      prop->SetVerticalJustificationToTop();
      }

    painter->DrawString(x, y, this->Title);
    }

  // Now draw the tick marks
  painter->ApplyTextProp(this->LabelProperties);

  float *tickPos = this->TickPositions->GetPointer(0);
  vtkStdString *tickLabel = this->TickLabels->GetPointer(0);
  vtkIdType numMarks = this->TickPositions->GetNumberOfTuples();

  // There are four possible tick label positions, which should be set by the
  // class laying out the axes.
  if (this->Position == vtkAxis::LEFT || this->Position == vtkAxis::PARALLEL)
    {
    prop->SetJustificationToRight();
    prop->SetVerticalJustificationToCentered();

    // Draw the tick marks and labels
    for (vtkIdType i = 0; i < numMarks; ++i)
      {
      painter->DrawLine(this->Point1[0] - 5, tickPos[i],
                        this->Point1[0],     tickPos[i]);
      if (this->LabelsVisible)
        {
        painter->DrawString(this->Point1[0] - 7, tickPos[i], tickLabel[i]);
        }
      }
    }
  else if (this->Position == vtkAxis::RIGHT)
    {
    prop->SetJustificationToLeft();
    prop->SetVerticalJustificationToCentered();

    // Draw the tick marks and labels
    for (vtkIdType i = 0; i < numMarks; ++i)
      {
      painter->DrawLine(this->Point1[0] + 5, tickPos[i],
                        this->Point1[0],     tickPos[i]);
      if (this->LabelsVisible)
        {
        painter->DrawString(this->Point1[0] + 7, tickPos[i], tickLabel[i]);
        }
      }
    }
  else if (this->Position == vtkAxis::BOTTOM)
    {
    prop->SetJustificationToCentered();
    prop->SetVerticalJustificationToTop();

    // Draw the tick marks and labels
    for (vtkIdType i = 0; i < numMarks; ++i)
      {
      painter->DrawLine(tickPos[i], this->Point1[1] - 5,
                        tickPos[i], this->Point1[1]);
      if (this->LabelsVisible)
        {
        painter->DrawString(tickPos[i], int(this->Point1[1] - 7), tickLabel[i]);
        }
      }
    }
  else if (this->Position == vtkAxis::TOP)
    {
    prop->SetJustificationToCentered();
    prop->SetVerticalJustificationToBottom();

    // Draw the tick marks and labels
    for (vtkIdType i = 0; i < numMarks; ++i)
      {
      painter->DrawLine(tickPos[i], this->Point1[1] + 5,
                        tickPos[i], this->Point1[1]);
      if (this->LabelsVisible)
        {
        painter->DrawString(tickPos[i], int(this->Point1[1] + 7), tickLabel[i]);
        }
      }
    }

  return true;
}

//-----------------------------------------------------------------------------
void vtkAxis::AutoScale()
{
  // Calculate the min and max, set the number of ticks and the tick spacing
  this->TickInterval = this->CalculateNiceMinMax(this->Minimum, this->Maximum);
}

//-----------------------------------------------------------------------------
void vtkAxis::RecalculateTickSpacing()
{
  // Calculate the min and max, set the number of ticks and the tick spacing,
  // discard the min and max in this case. TODO: Refactor the function called.
  double min, max;
  this->TickInterval = this->CalculateNiceMinMax(min, max);
}

//-----------------------------------------------------------------------------
float vtkAxis::CalculateNiceMinMax(double &min, double &max)
{
  // First get the order of the range of the numbers
  if (this->Maximum == this->Minimum)
    {
    this->Minimum *= 0.95;
    this->Maximum *= 1.05;
    }
  double range = this->Maximum - this->Minimum;
  bool isNegative = false;
  if (range < 0.0f)
    {
    isNegative = true;
    range *= -1.0f;
    }

  // Calculate an upper limit on the number of tick marks - at least 30 pixels
  // should be between each tick mark.
  float pixelRange = this->Point1[0] == this->Point2[0] ?
                     this->Point2[1] - this->Point1[1] :
                     this->Point2[0] - this->Point1[0];
  int maxTicks = static_cast<int>(pixelRange / 50.0f);
  if (maxTicks == 0)
    {
    // The axes do not have a valid set of points - return
    return 0.0f;
    }
  double tickSpacing = range / maxTicks;

  int order = static_cast<int>(floor(log10(tickSpacing)));
  double normTickSpacing = tickSpacing * pow(10.0f, -order);
  double niceTickSpacing = this->NiceNumber(normTickSpacing, true);
  niceTickSpacing *= pow(10.0f, order);

  if (isNegative)
    {
    min = ceil(this->Minimum / niceTickSpacing) * niceTickSpacing;
    max = floor(this->Maximum / niceTickSpacing) * niceTickSpacing;
    }
  else
    {
    min = floor(this->Minimum / niceTickSpacing) * niceTickSpacing;
    max = ceil(this->Maximum / niceTickSpacing) * niceTickSpacing;
    }

  float newRange = max - min;
  this->NumberOfTicks = static_cast<int>(floor(newRange / niceTickSpacing)) + 1;

  return niceTickSpacing;
}

//-----------------------------------------------------------------------------
float vtkAxis::NiceNumber(double n, bool roundUp)
{
  if (roundUp)
    {
    if (n <= 1.0)
      {
      return 1.0;
      }
    else if (n <= 2.0)
      {
      return 2.0;
      }
    else if (n <= 5.0)
      {
      return 5.0;
      }
    else
      {
      return 10.0;
      }
    }
  else
    {
    if (n < 1.5)
      {
      return 1.0;
      }
    else if (n <= 3.0)
      {
      return 2.0;
      }
    else if (n <= 7.0)
      {
      return 5.0;
      }
    else
      {
      return 10.0;
      }
    }
}

//-----------------------------------------------------------------------------
void vtkAxis::PrintSelf(ostream &os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  if (this->Title)
    {
    os << indent << "Axis title: \"" << *this->Title << "\"" << endl;
    }
  os << indent << "Minimum point: " << this->Point1[0] << ", "
     << this->Point1[1] << endl;
  os << indent << "Maximum point: " << this->Point2[0] << ", "
     << this->Point2[1] << endl;
  os << indent << "Range: " << this->Minimum << " - " << this->Maximum << endl;
  os << indent << "Number of tick marks: " << this->NumberOfTicks << endl;

}
<|endoftext|>


<commit_before>/* Rapicorn-Python Bindings
 * Copyright (C) 2008 Tim Janik
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * A copy of the GNU Lesser General Public License should ship along
 * with this library; if not, see http://www.gnu.org/copyleft/.
 */
#include "pyrope.hh" // must be included first to configure std headers

/* construct conventional Python module initializer name */
#define MODULE_NAME             pyRapicorn
#define MODULE_NAME_STRING      STRINGIFY (MODULE_NAME)
#define MODULE_INIT_FUNCTION    RAPICORN_CPP_PASTE2 (init, MODULE_NAME)

static PyObject *rapicorn_exception = NULL;

static bool pyrope_trampoline_switch (unsigned int, PyObject*, PyObject*, PyObject**); // generated

static PyObject*
pyrope_trampoline (PyObject *self,
                   PyObject *args)
{
  PyObject *arg0 = NULL, *ret = NULL;
  uint32 method_id = 0;
  if (PyTuple_Size (args) < 1)
    goto error;
  arg0 = PyTuple_GET_ITEM (args, 0);
  if (!arg0 || PyErr_Occurred())
    goto error;
  method_id = PyInt_AsLong (arg0);
  if (PyErr_Occurred())
    goto error;
  if (pyrope_trampoline_switch (method_id, self, args, &ret) && ret)
    return ret;
 error:
  if (!PyErr_Occurred())
    return PyErr_Format (PyExc_NotImplementedError, "method call failed: 0x%08x", method_id);
  return NULL;
}

static PyObject*
pyrope_printout (PyObject *self,
                 PyObject *args)
{
  const char *stringarg = NULL;
  if (!PyArg_ParseTuple (args, "s", &stringarg))
    return NULL;
  printout ("%s", stringarg);
  return None_INCREF();
}

static PyMethodDef pyrope_vtable[] = {
  { "printout",                 pyrope_printout,                METH_VARARGS,
    "Rapicorn::printout() - print to stdout." },
  { "__pyrope_trampoline__",    pyrope_trampoline,              METH_VARARGS,
    "Rapicorn function invokation trampoline." },
  { NULL, } // sentinel
};
static const char rapicorn_doc[] = "Rapicorn Python Language Binding Module.";

PyMODINIT_FUNC
MODULE_INIT_FUNCTION (void) // conventional dlmodule initializer
{
  // register module
  PyObject *m = Py_InitModule3 (MODULE_NAME_STRING, pyrope_vtable, (char*) rapicorn_doc);
  if (!m)
    return;

  // register Rypicorn exception
  if (!rapicorn_exception)
    rapicorn_exception = PyErr_NewException ((char*) MODULE_NAME_STRING ".exception", NULL, NULL);
  if (!rapicorn_exception)
    return;
  Py_INCREF (rapicorn_exception);
  PyModule_AddObject (m, "exception", rapicorn_exception);

  // retrieve argv[0]
  char *argv0;
  {
    PyObject *sysmod = PyImport_ImportModule ("sys");
    PyObject *astr   = sysmod ? PyObject_GetAttrString (sysmod, "argv") : NULL;
    PyObject *arg0   = astr ? PySequence_GetItem (astr, 0) : NULL;
    argv0            = arg0 ? strdup (PyString_AsString (arg0)) : NULL;
    Py_XDECREF (arg0);
    Py_XDECREF (astr);
    Py_XDECREF (sysmod);
    if (!argv0)
      return; // exception set
  }

  // initialize Rapicorn with dummy argv, hardcode X11 temporarily
  {
    int dummyargc = 1;
    char *dummyargs[] = { NULL, NULL };
    dummyargs[0] = argv0[0] ? argv0 : (char*) "Python>>>";
    char **dummyargv = dummyargs;
    Application::init_with_x11 (&dummyargc, &dummyargv, dummyargs[0]);
  }
  free (argv0);
}

// === include generated stubs ===
#include "protocol-pb2.cc"

static bool
pyrope_send_message (uint32                                  msgid,
                     Rapicorn::Rope::RemoteProcedure_Record &rec)
{
  return false;
#define HAVE_PYROPE_SEND_MESSAGE 1
}

#include "pycstub.cc"
<commit_msg>ROPE: added debugging stub to send_message<commit_after>/* Rapicorn-Python Bindings
 * Copyright (C) 2008 Tim Janik
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * A copy of the GNU Lesser General Public License should ship along
 * with this library; if not, see http://www.gnu.org/copyleft/.
 */
#include "pyrope.hh" // must be included first to configure std headers

/* construct conventional Python module initializer name */
#define MODULE_NAME             pyRapicorn
#define MODULE_NAME_STRING      STRINGIFY (MODULE_NAME)
#define MODULE_INIT_FUNCTION    RAPICORN_CPP_PASTE2 (init, MODULE_NAME)

static PyObject *rapicorn_exception = NULL;

static bool pyrope_trampoline_switch (unsigned int, PyObject*, PyObject*, PyObject**); // generated

static PyObject*
pyrope_trampoline (PyObject *self,
                   PyObject *args)
{
  PyObject *arg0 = NULL, *ret = NULL;
  uint32 method_id = 0;
  if (PyTuple_Size (args) < 1)
    goto error;
  arg0 = PyTuple_GET_ITEM (args, 0);
  if (!arg0 || PyErr_Occurred())
    goto error;
  method_id = PyInt_AsLong (arg0);
  if (PyErr_Occurred())
    goto error;
  if (pyrope_trampoline_switch (method_id, self, args, &ret) && ret)
    return ret;
 error:
  if (!PyErr_Occurred())
    return PyErr_Format (PyExc_NotImplementedError, "method call failed: 0x%08x", method_id);
  return NULL;
}

static PyObject*
pyrope_printout (PyObject *self,
                 PyObject *args)
{
  const char *stringarg = NULL;
  if (!PyArg_ParseTuple (args, "s", &stringarg))
    return NULL;
  printout ("%s", stringarg);
  return None_INCREF();
}

static PyMethodDef pyrope_vtable[] = {
  { "printout",                 pyrope_printout,                METH_VARARGS,
    "Rapicorn::printout() - print to stdout." },
  { "__pyrope_trampoline__",    pyrope_trampoline,              METH_VARARGS,
    "Rapicorn function invokation trampoline." },
  { NULL, } // sentinel
};
static const char rapicorn_doc[] = "Rapicorn Python Language Binding Module.";

PyMODINIT_FUNC
MODULE_INIT_FUNCTION (void) // conventional dlmodule initializer
{
  // register module
  PyObject *m = Py_InitModule3 (MODULE_NAME_STRING, pyrope_vtable, (char*) rapicorn_doc);
  if (!m)
    return;

  // register Rypicorn exception
  if (!rapicorn_exception)
    rapicorn_exception = PyErr_NewException ((char*) MODULE_NAME_STRING ".exception", NULL, NULL);
  if (!rapicorn_exception)
    return;
  Py_INCREF (rapicorn_exception);
  PyModule_AddObject (m, "exception", rapicorn_exception);

  // retrieve argv[0]
  char *argv0;
  {
    PyObject *sysmod = PyImport_ImportModule ("sys");
    PyObject *astr   = sysmod ? PyObject_GetAttrString (sysmod, "argv") : NULL;
    PyObject *arg0   = astr ? PySequence_GetItem (astr, 0) : NULL;
    argv0            = arg0 ? strdup (PyString_AsString (arg0)) : NULL;
    Py_XDECREF (arg0);
    Py_XDECREF (astr);
    Py_XDECREF (sysmod);
    if (!argv0)
      return; // exception set
  }

  // initialize Rapicorn with dummy argv, hardcode X11 temporarily
  {
    int dummyargc = 1;
    char *dummyargs[] = { NULL, NULL };
    dummyargs[0] = argv0[0] ? argv0 : (char*) "Python>>>";
    char **dummyargv = dummyargs;
    Application::init_with_x11 (&dummyargc, &dummyargv, dummyargs[0]);
  }
  free (argv0);
}

// === include generated stubs ===
#include "protocol-pb2.cc"
#include <google/protobuf/text_format.h>

static bool
pyrope_send_message (uint32                                  msgid,
                     Rapicorn::Rope::RemoteProcedure_Record &rec)
{
  // FIXME: debugging stub
  std::string string;
  if (!google::protobuf::TextFormat::PrintToString (rec, &string))
    string = "<ERROR/>";
  printf ("Remote Procedure Call, id=0x%08x:\n%s\n", msgid, string.c_str());

  return false;
#define HAVE_PYROPE_SEND_MESSAGE 1
}

#include "pycstub.cc"
<|endoftext|>


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

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

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

=========================================================================*/
#include "otbGlView.h"
#ifdef _WIN32
#include <windows.h>
#endif

#include <GL/glew.h>

#include <algorithm>
#include <cstring>
#include <cassert>

namespace otb
{

const char * GlView::REQUIRED_GL_VERSION = "2.0.0";
const char * GlView::REQUIRED_GLSL_VERSION = "1.2";

const char *
GlView
::GLVersion()
{
  const GLubyte * glVersionStr = glGetString( GL_VERSION );

  if( glVersionStr==NULL )
    {
    std::ostringstream oss;

    oss << "Failed to query OpenGL version string (error: "
        << glGetError()
        << ").";

    throw std::runtime_error( oss.str() );
    }

  return reinterpret_cast< const char * >( glVersionStr );
}

const char *
GlView
::GLSLVersion()
{
  const GLubyte * slVersionStr = glGetString( GL_SHADING_LANGUAGE_VERSION );

  if( slVersionStr==NULL )
    {
    std::ostringstream oss;

    oss << "Failed to query OpenGL shading language version string (error: "
        << glGetError()
        << ").";

    throw std::runtime_error( oss.str() );
    }

  return reinterpret_cast< const char * >( slVersionStr );
}

bool
GlView
::CheckGLCapabilities( const char * & glVersion, const char * & glslVersion )
{
  // Get OpenGL version.
  glVersion = GlView::GLVersion();

  // If OpenGL version is at least 2.0, get (and return) GLSL version
  // (before checking against OpenGL required version).
  if( GlView::VerCmp( glVersion, "2.0" )<0 )
    glslVersion = NULL;
  else
    glslVersion = GlView::GLSLVersion();

  // Now, Check OpenGL version against required version.
  if( GlView::VerCmp( glVersion, GlView::REQUIRED_GL_VERSION )<0 )
    return false;

  //
  // Then, check OpenGL SL version against required version.
  if( GlView::VerCmp( glslVersion, GlView::REQUIRED_GLSL_VERSION )<0 )
    return false;

  //
  // Finally, Ok.
  return true;
}

bool
GlView
::SplitVersion( const char * version,
                int& major,
                int& minor,
                int& release )
{
  //
  // Special case: empty strings returns 0.0.0 and true.
  if( version==NULL || strlen( version )==0 )
    {
    major = 0;
    minor = 0;
    release = 0;

    return true;
    }

  //
  // Parse major part.

  major = atoi( version );

  if( major<1 )
    {
    major = 0;

    return false;
    }

  //
  // Parse minor part.

  minor = 0;

  const char * minorStr = strchr( version, '.' );

  if( minorStr==NULL )
    return false;

  minor = atoi( ++minorStr );

  //
  // Parse release part.

  release = 0;

  const char * releaseStr = strchr( minorStr, '.' );

  // In this case, it is Ok to return because version of the form
  // Major.minor are handled.
  if( releaseStr==NULL )
    return true;

  release = atoi( ++releaseStr );

  //
  // Ok.
  return true;
}

int
GlView
::VerCmp( const char * version, const char * required )
{
  //
  // Split version.

  int verMaj = -1;
  int verMin = -1;
  int verRel = -1;

  if( !GlView::SplitVersion( version, verMaj, verMin, verRel ) )
    throw std::invalid_argument( version );

  //
  // Split required version.

  int reqMaj = -1;
  int reqMin = -1;
  int reqRel = -1;

  if( !GlView::SplitVersion( required, reqMaj, reqMin, reqRel ) )
    throw std::runtime_error( required );

  //
  // Compare splitted versions.

  if( verMaj<reqMaj )
    return -1;

  else if( verMaj>reqMaj )
    return 1;

  else // if( verMaj==reqMaj )
    {
    if( verMin<reqMin )
      return -1;

    else if( verMin>reqMin )
      return 1;

    else // if( verMin==reqMin )
      {
      if( verRel<reqRel)
        return -1;

      else if( verRel>reqRel )
        return 1;

      else // if( verRel==reqRel )
        return 0;
      }
    }
}

GlView::GlView()
  : m_Settings(ViewSettings::New()),
    m_Actors(),
    m_RenderingOrder()
{}

GlView::~GlView()
{}

void GlView::Initialize(unsigned int sx, unsigned int sy)
{
  m_Settings = ViewSettings::New();

  this->ClearActors();

  this->Resize(sx,sy);

}

void GlView::Resize(unsigned int sx, unsigned int sy)
{
 ViewSettings::SizeType size;
  size[0] = sx;
  size[1] = sy;
  m_Settings->SetViewportSize(size);
}

void GlView::BeforeRendering()
{
  // First, get all actors informed of new settings
  for(ActorMapType::iterator it = m_Actors.begin();
      it!=m_Actors.end();++it)
    {
    if(it->second->GetVisible())
      {
      it->second->ProcessViewSettings();
      }
    }

  // Second, get opengl ready

  // Reset viewport
  glViewport(0, 0, (GLint)m_Settings->GetViewportSize()[0], (GLint)m_Settings->GetViewportSize()[1]);

  // Clear back-buffer(s) before rendering
  glClear( GL_COLOR_BUFFER_BIT );

  // Setup projection according to view settings
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();

  double ulx, uly, lrx, lry;

  m_Settings->GetViewportExtent(ulx,uly,lrx,lry);

  glOrtho(ulx, lrx, lry, uly, -1, 1);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  glPushMatrix();

  // glScalef(m_Settings->GetSpacing()[0],m_Settings->GetSpacing()[1],1);
}

void GlView::AfterRendering()
{
  m_Settings->SetGeometryChanged(false);
  glPopMatrix();
}

std::string GlView::AddActor(ActorType * actor, const std::string& key)
{
  std::string newKey = key;

  if(newKey == "")
    {
    std::ostringstream oss;
    oss<<"Actor"<<m_Actors.size()+1<<std::endl;
    newKey = oss.str();
    }

  if(m_Actors.count(newKey)!=0)
    {
    itkExceptionMacro(<<"An actor with key "<<newKey<<" already exists, please choose another key");
    }

  actor->SetSettings(m_Settings);
  m_Actors[newKey] = actor;
  m_RenderingOrder.push_back(newKey);

  return newKey;
}

bool GlView::RemoveActor(const std::string & key)
{
  if(m_Actors.count(key) == 0)
    {
    return false;
    }

  m_Actors.erase(key);

  StringVectorType::iterator it = std::find(m_RenderingOrder.begin(),m_RenderingOrder.end(),key);

  if(it!=m_RenderingOrder.end())
    {
    m_RenderingOrder.erase(it);
    }
  return true;
}

void GlView::ClearActors()
{
  m_Actors.clear();
  m_RenderingOrder.clear();
}

GlView::ActorType::Pointer GlView::GetActor(const std::string & key)
{
  if(m_Actors.count(key)==0)
    {
    itkExceptionMacro(<<"No actor found with key"<<key);
    }

  return m_Actors[key];
}

void GlView::LightRender()
{
  for(StringVectorType::reverse_iterator it = m_RenderingOrder.rbegin();
      it!=m_RenderingOrder.rend();++it)
    {
    ActorMapType::iterator actIt = m_Actors.find(*it);

    if(actIt != m_Actors.end() && actIt->second->GetVisible())
      {
      actIt->second->Render();
      }
    }
}

void GlView::HeavyRender()
{
  // TODO: Light render/ heavy render could be optimized
  for(StringVectorType::reverse_iterator it = m_RenderingOrder.rbegin();
      it!=m_RenderingOrder.rend();++it)
    {
    ActorMapType::iterator actIt = m_Actors.find(*it);

    if(actIt != m_Actors.end() && actIt->second->GetVisible())
      {
      actIt->second->UpdateData();
      }
    }

  this->LightRender();
}

void GlView::RotateRenderingOrder(bool down)
{
  if(m_RenderingOrder.size()>1)
    {
    if(down)
      {
      std::rotate(m_RenderingOrder.rbegin(),m_RenderingOrder.rbegin()+1,m_RenderingOrder.rend());
      }
    else
      {
      std::rotate(m_RenderingOrder.begin(),m_RenderingOrder.begin()+1,m_RenderingOrder.end());
      }
    }

}

// Move actor in rendering order
void GlView::MoveActorInRenderingOrder(std::string key, bool down)
{
  StringVectorType::iterator it = std::find(m_RenderingOrder.begin(),m_RenderingOrder.end(),key);

  if(it!=m_RenderingOrder.end())
    {
    if(down && it+1 != m_RenderingOrder.end())
      {
      std::swap(*it,*(it+1));
      }
    else if(!down && it != m_RenderingOrder.begin())
      {
      std::swap((*it),*(it-1));
      }
    }
}

// Move actor to the end of rendering order (either front if front
// is set to true or back if front is set to false)
void GlView::MoveActorToEndOfRenderingOrder(std::string key, bool front)
{
  StringVectorType::iterator it = std::find(m_RenderingOrder.begin(),m_RenderingOrder.end(),key);

  if(it!=m_RenderingOrder.end())
    {
    if(front)
      {
      m_RenderingOrder.erase(it);
      m_RenderingOrder.insert(m_RenderingOrder.begin(),key);
      }
    else
      {
      m_RenderingOrder.erase(it);
      m_RenderingOrder.push_back(key);
      }
    }
}
}
<commit_msg>ENH: Changed GlView::REQUIRED_GLSL_VERSION to 1.20 (see https://en.wikipedia.org/wiki/GLSL#Versions).<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

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

=========================================================================*/
#include "otbGlView.h"
#ifdef _WIN32
#include <windows.h>
#endif

#include <GL/glew.h>

#include <algorithm>
#include <cstring>
#include <cassert>

namespace otb
{

const char * GlView::REQUIRED_GL_VERSION = "2.0.0";
const char * GlView::REQUIRED_GLSL_VERSION = "1.20";

const char *
GlView
::GLVersion()
{
  const GLubyte * glVersionStr = glGetString( GL_VERSION );

  if( glVersionStr==NULL )
    {
    std::ostringstream oss;

    oss << "Failed to query OpenGL version string (error: "
        << glGetError()
        << ").";

    throw std::runtime_error( oss.str() );
    }

  return reinterpret_cast< const char * >( glVersionStr );
}

const char *
GlView
::GLSLVersion()
{
  const GLubyte * slVersionStr = glGetString( GL_SHADING_LANGUAGE_VERSION );

  if( slVersionStr==NULL )
    {
    std::ostringstream oss;

    oss << "Failed to query OpenGL shading language version string (error: "
        << glGetError()
        << ").";

    throw std::runtime_error( oss.str() );
    }

  return reinterpret_cast< const char * >( slVersionStr );
}

bool
GlView
::CheckGLCapabilities( const char * & glVersion, const char * & glslVersion )
{
  // Get OpenGL version.
  glVersion = GlView::GLVersion();

  // If OpenGL version is at least 2.0, get (and return) GLSL version
  // (before checking against OpenGL required version).
  if( GlView::VerCmp( glVersion, "2.0" )<0 )
    glslVersion = NULL;
  else
    glslVersion = GlView::GLSLVersion();

  // Now, Check OpenGL version against required version.
  if( GlView::VerCmp( glVersion, GlView::REQUIRED_GL_VERSION )<0 )
    return false;

  //
  // Then, check OpenGL SL version against required version.
  if( GlView::VerCmp( glslVersion, GlView::REQUIRED_GLSL_VERSION )<0 )
    return false;

  //
  // Finally, Ok.
  return true;
}

bool
GlView
::SplitVersion( const char * version,
                int& major,
                int& minor,
                int& release )
{
  //
  // Special case: empty strings returns 0.0.0 and true.
  if( version==NULL || strlen( version )==0 )
    {
    major = 0;
    minor = 0;
    release = 0;

    return true;
    }

  //
  // Parse major part.

  major = atoi( version );

  if( major<1 )
    {
    major = 0;

    return false;
    }

  //
  // Parse minor part.

  minor = 0;

  const char * minorStr = strchr( version, '.' );

  if( minorStr==NULL )
    return false;

  minor = atoi( ++minorStr );

  //
  // Parse release part.

  release = 0;

  const char * releaseStr = strchr( minorStr, '.' );

  // In this case, it is Ok to return because version of the form
  // Major.minor are handled.
  if( releaseStr==NULL )
    return true;

  release = atoi( ++releaseStr );

  //
  // Ok.
  return true;
}

int
GlView
::VerCmp( const char * version, const char * required )
{
  //
  // Split version.

  int verMaj = -1;
  int verMin = -1;
  int verRel = -1;

  if( !GlView::SplitVersion( version, verMaj, verMin, verRel ) )
    throw std::invalid_argument( version );

  //
  // Split required version.

  int reqMaj = -1;
  int reqMin = -1;
  int reqRel = -1;

  if( !GlView::SplitVersion( required, reqMaj, reqMin, reqRel ) )
    throw std::runtime_error( required );

  //
  // Compare splitted versions.

  if( verMaj<reqMaj )
    return -1;

  else if( verMaj>reqMaj )
    return 1;

  else // if( verMaj==reqMaj )
    {
    if( verMin<reqMin )
      return -1;

    else if( verMin>reqMin )
      return 1;

    else // if( verMin==reqMin )
      {
      if( verRel<reqRel)
        return -1;

      else if( verRel>reqRel )
        return 1;

      else // if( verRel==reqRel )
        return 0;
      }
    }
}

GlView::GlView()
  : m_Settings(ViewSettings::New()),
    m_Actors(),
    m_RenderingOrder()
{}

GlView::~GlView()
{}

void GlView::Initialize(unsigned int sx, unsigned int sy)
{
  m_Settings = ViewSettings::New();

  this->ClearActors();

  this->Resize(sx,sy);

}

void GlView::Resize(unsigned int sx, unsigned int sy)
{
 ViewSettings::SizeType size;
  size[0] = sx;
  size[1] = sy;
  m_Settings->SetViewportSize(size);
}

void GlView::BeforeRendering()
{
  // First, get all actors informed of new settings
  for(ActorMapType::iterator it = m_Actors.begin();
      it!=m_Actors.end();++it)
    {
    if(it->second->GetVisible())
      {
      it->second->ProcessViewSettings();
      }
    }

  // Second, get opengl ready

  // Reset viewport
  glViewport(0, 0, (GLint)m_Settings->GetViewportSize()[0], (GLint)m_Settings->GetViewportSize()[1]);

  // Clear back-buffer(s) before rendering
  glClear( GL_COLOR_BUFFER_BIT );

  // Setup projection according to view settings
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();

  double ulx, uly, lrx, lry;

  m_Settings->GetViewportExtent(ulx,uly,lrx,lry);

  glOrtho(ulx, lrx, lry, uly, -1, 1);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  glPushMatrix();

  // glScalef(m_Settings->GetSpacing()[0],m_Settings->GetSpacing()[1],1);
}

void GlView::AfterRendering()
{
  m_Settings->SetGeometryChanged(false);
  glPopMatrix();
}

std::string GlView::AddActor(ActorType * actor, const std::string& key)
{
  std::string newKey = key;

  if(newKey == "")
    {
    std::ostringstream oss;
    oss<<"Actor"<<m_Actors.size()+1<<std::endl;
    newKey = oss.str();
    }

  if(m_Actors.count(newKey)!=0)
    {
    itkExceptionMacro(<<"An actor with key "<<newKey<<" already exists, please choose another key");
    }

  actor->SetSettings(m_Settings);
  m_Actors[newKey] = actor;
  m_RenderingOrder.push_back(newKey);

  return newKey;
}

bool GlView::RemoveActor(const std::string & key)
{
  if(m_Actors.count(key) == 0)
    {
    return false;
    }

  m_Actors.erase(key);

  StringVectorType::iterator it = std::find(m_RenderingOrder.begin(),m_RenderingOrder.end(),key);

  if(it!=m_RenderingOrder.end())
    {
    m_RenderingOrder.erase(it);
    }
  return true;
}

void GlView::ClearActors()
{
  m_Actors.clear();
  m_RenderingOrder.clear();
}

GlView::ActorType::Pointer GlView::GetActor(const std::string & key)
{
  if(m_Actors.count(key)==0)
    {
    itkExceptionMacro(<<"No actor found with key"<<key);
    }

  return m_Actors[key];
}

void GlView::LightRender()
{
  for(StringVectorType::reverse_iterator it = m_RenderingOrder.rbegin();
      it!=m_RenderingOrder.rend();++it)
    {
    ActorMapType::iterator actIt = m_Actors.find(*it);

    if(actIt != m_Actors.end() && actIt->second->GetVisible())
      {
      actIt->second->Render();
      }
    }
}

void GlView::HeavyRender()
{
  // TODO: Light render/ heavy render could be optimized
  for(StringVectorType::reverse_iterator it = m_RenderingOrder.rbegin();
      it!=m_RenderingOrder.rend();++it)
    {
    ActorMapType::iterator actIt = m_Actors.find(*it);

    if(actIt != m_Actors.end() && actIt->second->GetVisible())
      {
      actIt->second->UpdateData();
      }
    }

  this->LightRender();
}

void GlView::RotateRenderingOrder(bool down)
{
  if(m_RenderingOrder.size()>1)
    {
    if(down)
      {
      std::rotate(m_RenderingOrder.rbegin(),m_RenderingOrder.rbegin()+1,m_RenderingOrder.rend());
      }
    else
      {
      std::rotate(m_RenderingOrder.begin(),m_RenderingOrder.begin()+1,m_RenderingOrder.end());
      }
    }

}

// Move actor in rendering order
void GlView::MoveActorInRenderingOrder(std::string key, bool down)
{
  StringVectorType::iterator it = std::find(m_RenderingOrder.begin(),m_RenderingOrder.end(),key);

  if(it!=m_RenderingOrder.end())
    {
    if(down && it+1 != m_RenderingOrder.end())
      {
      std::swap(*it,*(it+1));
      }
    else if(!down && it != m_RenderingOrder.begin())
      {
      std::swap((*it),*(it-1));
      }
    }
}

// Move actor to the end of rendering order (either front if front
// is set to true or back if front is set to false)
void GlView::MoveActorToEndOfRenderingOrder(std::string key, bool front)
{
  StringVectorType::iterator it = std::find(m_RenderingOrder.begin(),m_RenderingOrder.end(),key);

  if(it!=m_RenderingOrder.end())
    {
    if(front)
      {
      m_RenderingOrder.erase(it);
      m_RenderingOrder.insert(m_RenderingOrder.begin(),key);
      }
    else
      {
      m_RenderingOrder.erase(it);
      m_RenderingOrder.push_back(key);
      }
    }
}
}
<|endoftext|>


<commit_before>#pragma once

#include "backlog.hpp"
#include "detail/util.hpp"
#include "detail/filter.hpp"

namespace sts
{
  class scroller
  {
    public:
      scroller() = delete;
      scroller(backlog &bl, std::size_t const step)
        : backlog_{ bl }
        , step_{ step }
      { }

      template <typename It>
      void write(It const &begin, It end)
      {
        auto const size(std::distance(begin, end));
        if(::write(STDOUT_FILENO, &*begin, size) != size)
        { throw std::runtime_error{ "partial/failed write (stdout)" }; }

        end = detail::filter(*this, begin, end);
        backlog_.write(begin, end);

        auto &impl(backlog_.get_impl());
        auto const line_markers_size(impl.line_markers_.size());
        auto const rows(impl.tty_.get().size.ws_row);
        if(following_ && line_markers_size > rows)
        { scroll_pos_ = line_markers_size - rows; }
      }

      void up()
      {
        if(!scroll_pos_)
        { return; }

        following_ = false;
        scroll_pos_ -= std::min(step_, scroll_pos_);
        redraw();
      }

      void down()
      {
        auto &impl(backlog_.get_impl());
        if(scroll_pos_ + impl.tty_.get().size.ws_row >= impl.line_markers_.size())
        {
          following_ = true;
          return;
        }
        ssize_t const diff
        {
          static_cast<ssize_t>(scroll_pos_ + impl.tty_.get().size.ws_row) -
          static_cast<ssize_t>(impl.line_markers_.size())
        };
        scroll_pos_ += std::min(step_, static_cast<std::size_t>(std::abs(diff)));
        redraw();
      }

      void follow()
      {
        auto &impl(backlog_.get_impl());
        if(following_)
        { return; }

        scroll_pos_ = impl.line_markers_.size() - impl.tty_.get().size.ws_row;
        following_ = true;
        redraw();
      }

      void clear()
      {
        static std::string const clear{ "\x1B[H\x1B[2J" };
        static ssize_t const clear_size(clear.size());
        if(::write(STDOUT_FILENO, clear.c_str(), clear.size()) != clear_size)
        { throw std::runtime_error{ "unable to clear screen" }; }
      }

    private:
      void redraw()
      {
        clear();

        auto &impl(backlog_.get_impl());
        std::size_t const rows{ impl.tty_.get().size.ws_row };
        for(std::size_t i{ scroll_pos_ };
            i < scroll_pos_ + std::min(impl.line_markers_.size(), rows);
            ++i)
        {
          ssize_t size((impl.line_markers_[i].second -
                        impl.line_markers_[i].first) + 1);
          if(i == scroll_pos_ + std::min(impl.line_markers_.size() - 1,
                                         rows - 1))
          { --size; }
          if(::write(STDOUT_FILENO, &impl.buf_[impl.line_markers_[i].first],
                     size) != size)
          { throw std::runtime_error{ "partial/failed write (stdout)" }; }
        }
      }

      template <typename T, typename It>
      friend It detail::filter(T&, It, It);

      backlog &backlog_;
      std::size_t scroll_pos_{};
      std::size_t const step_{};
      bool following_{ true };
  };
}
<commit_msg>Only write to stdout if we're following<commit_after>#pragma once

#include "backlog.hpp"
#include "detail/util.hpp"
#include "detail/filter.hpp"

namespace sts
{
  class scroller
  {
    public:
      scroller() = delete;
      scroller(backlog &bl, std::size_t const step)
        : backlog_{ bl }
        , step_{ step }
      { }

      template <typename It>
      void write(It const &begin, It end)
      {
        auto const size(std::distance(begin, end));
        if(following_ && ::write(STDOUT_FILENO, &*begin, size) != size)
        { throw std::runtime_error{ "partial/failed write (stdout)" }; }

        end = detail::filter(*this, begin, end);
        backlog_.write(begin, end);

        auto &impl(backlog_.get_impl());
        auto const line_markers_size(impl.line_markers_.size());
        auto const rows(impl.tty_.get().size.ws_row);
        if(following_ && line_markers_size > rows)
        { scroll_pos_ = line_markers_size - rows; }
      }

      void up()
      {
        if(!scroll_pos_)
        { return; }

        following_ = false;
        scroll_pos_ -= std::min(step_, scroll_pos_);
        redraw();
      }

      void down()
      {
        auto &impl(backlog_.get_impl());
        if(scroll_pos_ + impl.tty_.get().size.ws_row >= impl.line_markers_.size())
        {
          following_ = true;
          return;
        }
        ssize_t const diff
        {
          static_cast<ssize_t>(scroll_pos_ + impl.tty_.get().size.ws_row) -
          static_cast<ssize_t>(impl.line_markers_.size())
        };
        scroll_pos_ += std::min(step_, static_cast<std::size_t>(std::abs(diff)));
        redraw();
      }

      void follow()
      {
        auto &impl(backlog_.get_impl());
        if(following_)
        { return; }

        scroll_pos_ = impl.line_markers_.size() - impl.tty_.get().size.ws_row;
        following_ = true;
        redraw();
      }

      void clear()
      {
        static std::string const clear{ "\x1B[H\x1B[2J" };
        static ssize_t const clear_size(clear.size());
        if(::write(STDOUT_FILENO, clear.c_str(), clear.size()) != clear_size)
        { throw std::runtime_error{ "unable to clear screen" }; }
      }

    private:
      void redraw()
      {
        clear();

        auto &impl(backlog_.get_impl());
        std::size_t const rows{ impl.tty_.get().size.ws_row };
        for(std::size_t i{ scroll_pos_ };
            i < scroll_pos_ + std::min(impl.line_markers_.size(), rows);
            ++i)
        {
          ssize_t size((impl.line_markers_[i].second -
                        impl.line_markers_[i].first) + 1);
          if(i == scroll_pos_ + std::min(impl.line_markers_.size() - 1,
                                         rows - 1))
          { --size; }
          if(::write(STDOUT_FILENO, &impl.buf_[impl.line_markers_[i].first],
                     size) != size)
          { throw std::runtime_error{ "partial/failed write (stdout)" }; }
        }
      }

      template <typename T, typename It>
      friend It detail::filter(T&, It, It);

      backlog &backlog_;
      std::size_t scroll_pos_{};
      std::size_t const step_{};
      bool following_{ true };
  };
}
<|endoftext|>


<commit_before><commit_msg>Use variable-length array idiom for SfxType::aAttrib<commit_after><|endoftext|>


<commit_before>/*!
  @file DCDData.hpp
  @brief definition of a class that is a set of data dcd file contains.

  definition of class DCDData that is a set of data dcd file contains.
  The data is composed of header information(timestep, delta_t, etc...)
  and trajectory(array of array of Vector3d). This behaves like
  std::vector<std::vector<Vector3d>> with iterator, front()/back(), at/[].

  @author Toru Niina (niina.toru.68u@gmail.com)
  @date 2016-06-09 15:00
  @copyright Toru Niina 2016 on MIT License
*/

#ifndef COFFEE_MILL_DCD_DATA
#define COFFEE_MILL_DCD_DATA
#include "detail/scalar_type_extractor.hpp"
#include <vector>
#include <string>

namespace mill
{

template<typename realT>
struct DCDHeader
{
    using real_type    = realT;
    using comment_type = std::vector<std::string>;

    void append_comment(const std::string& comm)
    {
        if(comm.size() == 80)
        {
            comment.push_back(comm);
        }
        else if(comm.size() < 80)
        {
            std::size_t diff = 80 - comm.size();
            std::size_t pre  = diff / 2;
            std::size_t post = diff - pre;
            comment.push_back(
                    std::string(pre, '=') + comm + std::string(post, '='));
        }
        else if(comm.size() > 80)
        {
            auto iter = comm.cbegin();

            while(std::distance(iter, comm.cend()) > 80)
            {
                comment.push_back(std::string(iter, iter + 80));
                iter = iter + 80;
            }
            append_comment(std::string(iter, comm.cend()));
        }
        return;
    }

    std::size_t  nset;       //!< number of frames.
    std::size_t  istart;     //!< initial step of traj. nomally zero
    std::size_t  nstep_save; //!< interval of saving snapshot
    std::size_t  nstep;      //!< total step number of the traj
    std::size_t  nunit;      //!< total unit(chains) number
    std::size_t  verCHARMM;  //!< version of CHARMM. in cafemol, 24
    std::size_t  nparticle;  //!< total number of particle
    real_type    delta_t;    //!< delta t.
    std::string  signeture;  //!< CORD or VELO
    comment_type comment;    //!< header comment. vector of string.
};

template<typename vectorT>
class DCDData
{
  public:

    using vector_type     = vectorT;
    using real_type       = typename scalar_type_extractor<vector_type>::type;
    using position_type   = vector_type;
    using time_type       = real_type;
    using size_type       = std::size_t;
    using index_type      = size_type;
    using snapshot_type   = std::vector<position_type>;
    using trajectory_type = std::vector<snapshot_type>;
    using iterator        = typename trajectory_type::iterator;
    using const_iterator  = typename trajectory_type::const_iterator;
    using header_type     = DCDHeader<real_type>;
    using comment_type    = typename header_type::comment_type;

  public:

    DCDData(){}
    explicit DCDData(size_type size) : trajectory_(size){}

    ~DCDData() = default;

    int  nset() const {return header_.nset;}
    int& nset()       {return header_.nset;}
    int  istart() const {return header_.istart;}
    int& istart()       {return header_.istart;}
    int  nstep_save() const {return header_.nstep_save;}
    int& nstep_save()       {return header_.nstep_save;}
    int  nstep() const {return header_.nstep;}
    int& nstep()       {return header_.nstep;}
    int  nunit() const {return header_.nunit;}
    int& nunit()       {return header_.nunit;}
    int  verCHARMM() const {return header_.verCHARMM;}
    int& verCHARMM()       {return header_.verCHARMM;}
    int  nparticle() const {return header_.nparticle;}
    int& nparticle()       {return header_.nparticle;}
    time_type  delta_t() const {return header_.delta_t;}
    time_type& delta_t()       {return header_.delta_t;}
    std::string const& signeture() const {return header_.signeture;}
    std::string      & signeture()       {return header_.signeture;}
    comment_type const& comment() const {return header_.comment;}
    comment_type      & comment()       {return header_.comment;}
    header_type const& header() const {return header_;}
    header_type      & header()       {return header_;}

    snapshot_type const& front() const {return trajectory_.front();}
    snapshot_type      & front()       {return trajectory_.front();}
    snapshot_type const& back() const {return trajectory_.back();}
    snapshot_type      & back()       {return trajectory_.back();}

    snapshot_type const& operator[](index_type i) const {return trajectory_[i];}
    snapshot_type      & operator[](index_type i)       {return trajectory_[i];}
    snapshot_type const& at(index_type i) const {return trajectory_.at(i);}
    snapshot_type      & at(index_type i)       {return trajectory_.at(i);}

    trajectory_type const& traj() const {return trajectory_;}
    trajectory_type      & traj()       {return trajectory_;}

    bool      empty() const {return trajectory_.empty();}
    size_type size() const {return trajectory_.size();}

    iterator begin() {return trajectory_.begin();}
    iterator end()   {return trajectory_.end();}
    const_iterator cbegin() const {return trajectory_.cbegin();}
    const_iterator cend()   const {return trajectory_.cend();}

    //! add comment to header. make the comment length 80 with char '='.
    void append_comment(const std::string& message)
    {
        header_.append_comment(message);
    }

  private:

    header_type     header_;
    trajectory_type trajectory_; //!< trajectory data.
};

}

#endif /* COFFEE_MILL_DCD_DATA */
<commit_msg>change DCDData data type from size_t to int<commit_after>/*!
  @file DCDData.hpp
  @brief definition of a class that is a set of data dcd file contains.

  definition of class DCDData that is a set of data dcd file contains.
  The data is composed of header information(timestep, delta_t, etc...)
  and trajectory(array of array of Vector3d). This behaves like
  std::vector<std::vector<Vector3d>> with iterator, front()/back(), at/[].

  @author Toru Niina (niina.toru.68u@gmail.com)
  @date 2016-06-09 15:00
  @copyright Toru Niina 2016 on MIT License
*/

#ifndef COFFEE_MILL_DCD_DATA
#define COFFEE_MILL_DCD_DATA
#include "detail/scalar_type_extractor.hpp"
#include <vector>
#include <string>

namespace mill
{

template<typename realT>
struct DCDHeader
{
    using real_type    = realT;
    using comment_type = std::vector<std::string>;

    void append_comment(const std::string& comm)
    {
        if(comm.size() == 80)
        {
            comment.push_back(comm);
        }
        else if(comm.size() < 80)
        {
            std::size_t diff = 80 - comm.size();
            std::size_t pre  = diff / 2;
            std::size_t post = diff - pre;
            comment.push_back(
                    std::string(pre, '=') + comm + std::string(post, '='));
        }
        else if(comm.size() > 80)
        {
            auto iter = comm.cbegin();

            while(std::distance(iter, comm.cend()) > 80)
            {
                comment.push_back(std::string(iter, iter + 80));
                iter = iter + 80;
            }
            append_comment(std::string(iter, comm.cend()));
        }
        return;
    }

    int nset;       //!< number of frames.
    int istart;     //!< initial step of traj. nomally zero
    int nstep_save; //!< interval of saving snapshot
    int nstep;      //!< total step number of the traj
    int nunit;      //!< total unit(chains) number
    int verCHARMM;  //!< version of CHARMM. in cafemol, 24
    int nparticle;  //!< total number of particle
    real_type    delta_t;    //!< delta t.
    std::string  signeture;  //!< CORD or VELO
    comment_type comment;    //!< header comment. vector of string.
};

template<typename vectorT>
class DCDData
{
  public:

    using vector_type     = vectorT;
    using real_type       = typename scalar_type_extractor<vector_type>::type;
    using position_type   = vector_type;
    using time_type       = real_type;
    using size_type       = std::size_t;
    using index_type      = size_type;
    using snapshot_type   = std::vector<position_type>;
    using trajectory_type = std::vector<snapshot_type>;
    using iterator        = typename trajectory_type::iterator;
    using const_iterator  = typename trajectory_type::const_iterator;
    using header_type     = DCDHeader<real_type>;
    using comment_type    = typename header_type::comment_type;

  public:

    DCDData(){}
    explicit DCDData(size_type size) : trajectory_(size){}

    ~DCDData() = default;

    int  nset() const {return header_.nset;}
    int& nset()       {return header_.nset;}
    int  istart() const {return header_.istart;}
    int& istart()       {return header_.istart;}
    int  nstep_save() const {return header_.nstep_save;}
    int& nstep_save()       {return header_.nstep_save;}
    int  nstep() const {return header_.nstep;}
    int& nstep()       {return header_.nstep;}
    int  nunit() const {return header_.nunit;}
    int& nunit()       {return header_.nunit;}
    int  verCHARMM() const {return header_.verCHARMM;}
    int& verCHARMM()       {return header_.verCHARMM;}
    int  nparticle() const {return header_.nparticle;}
    int& nparticle()       {return header_.nparticle;}
    time_type  delta_t() const {return header_.delta_t;}
    time_type& delta_t()       {return header_.delta_t;}
    std::string const& signeture() const {return header_.signeture;}
    std::string      & signeture()       {return header_.signeture;}
    comment_type const& comment() const {return header_.comment;}
    comment_type      & comment()       {return header_.comment;}
    header_type const& header() const {return header_;}
    header_type      & header()       {return header_;}

    snapshot_type const& front() const {return trajectory_.front();}
    snapshot_type      & front()       {return trajectory_.front();}
    snapshot_type const& back() const {return trajectory_.back();}
    snapshot_type      & back()       {return trajectory_.back();}

    snapshot_type const& operator[](index_type i) const {return trajectory_[i];}
    snapshot_type      & operator[](index_type i)       {return trajectory_[i];}
    snapshot_type const& at(index_type i) const {return trajectory_.at(i);}
    snapshot_type      & at(index_type i)       {return trajectory_.at(i);}

    trajectory_type const& traj() const {return trajectory_;}
    trajectory_type      & traj()       {return trajectory_;}

    bool      empty() const {return trajectory_.empty();}
    size_type size() const {return trajectory_.size();}

    iterator begin() {return trajectory_.begin();}
    iterator end()   {return trajectory_.end();}
    const_iterator cbegin() const {return trajectory_.cbegin();}
    const_iterator cend()   const {return trajectory_.cend();}

    //! add comment to header. make the comment length 80 with char '='.
    void append_comment(const std::string& message)
    {
        header_.append_comment(message);
    }

  private:

    header_type     header_;
    trajectory_type trajectory_; //!< trajectory data.
};

}

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


<commit_before>#include <string>
#include <vector>
#include <stdexcept>

#include "Monitor_BFER.hpp"
#include "Tools/Perf/common/mutual_info.h"
#include "Tools/Perf/common/hamming_distance.h"
#include "Tools/Math/utils.h"

using namespace aff3ct::module;

template <typename B, typename R>
Monitor_BFER<B,R>
::Monitor_BFER(const int K, const int N, const unsigned max_fe, const int n_frames)
: Monitor(K, N, n_frames),
  max_fe(max_fe),
  n_bit_errors(0),
  n_frame_errors(0),
  n_analyzed_frames(0),
  MI_sum(0)
{
	const std::string name = "Monitor_BFER";
	this->set_name(name);

	auto &p1 = this->create_task("check_errors");
	auto &ps_U = this->template create_socket_in<B>(p1, "U", this->K * this->n_frames);
	auto &ps_V = this->template create_socket_in<B>(p1, "V", this->K * this->n_frames);
	this->create_codelet(p1, [this, &ps_U, &ps_V]() -> int
	{
		return this->check_errors(static_cast<B*>(ps_U.get_dataptr()),
		                          static_cast<B*>(ps_V.get_dataptr()));
	});

	auto &p2 = this->create_task("get_mutual_info");
	auto &ps_X = this->template create_socket_in<B>(p2, "X", this->N * this->n_frames);
	auto &ps_Y = this->template create_socket_in<R>(p2, "Y", this->N * this->n_frames);
	this->create_codelet(p2, [this, &ps_X, &ps_Y]() -> int
	{
		return this->get_mutual_info(static_cast<B*>(ps_X.get_dataptr()),
		                             static_cast<R*>(ps_Y.get_dataptr()));
	});
}

template <typename B, typename R>
int Monitor_BFER<B,R>
::check_errors(const B *U, const B *V, const int frame_id)
{
	const auto f_start = (frame_id < 0) ? 0 : frame_id % this->n_frames;
	const auto f_stop  = (frame_id < 0) ? this->n_frames : f_start +1;

	int n_be = 0;
	for (auto f = f_start; f < f_stop; f++)
		n_be += this->_check_errors(U + f * this->K,
		                            V + f * this->K,
		                            f);

	return n_be;
}

template <typename B, typename R>
R Monitor_BFER<B,R>
::get_mutual_info(const B *X, const R *Y, const int frame_id)
{
	const auto f_start = (frame_id < 0) ? 0 : frame_id % this->n_frames;
	const auto f_stop  = (frame_id < 0) ? this->n_frames : f_start +1;

	R MI_sum = 0;
	for (auto f = f_start; f < f_stop; f++)
		MI_sum += this->_get_mutual_info(X + f * this->K,
		                                 Y + f * this->K,
		                                 f);

	return MI_sum / (R)this->n_frames * 10000;
}

template <typename B, typename R>
int Monitor_BFER<B,R>
::_check_errors(const B *U, const B *V, const int frame_id)
{
	int bit_errors_count = tools::hamming_distance(U, V, this->K);

	if (bit_errors_count)
	{
		n_bit_errors += bit_errors_count;
		n_frame_errors++;

		for (auto c : this->callbacks_fe)
			c(bit_errors_count, frame_id);

		if (this->fe_limit_achieved() && frame_id == this->n_frames -1)
			for (auto c : this->callbacks_fe_limit_achieved)
				c();
	}

	n_analyzed_frames++;

	if (frame_id == this->n_frames -1)
		for (auto c : this->callbacks_check)
			c();

	return bit_errors_count;
}

template <typename B, typename R>
R Monitor_BFER<B,R>
::_get_mutual_info(const B *X, const R *Y, const int frame_id)
{
	throw tools::runtime_error(__FILE__, __LINE__, __func__, "The mutual_info_histo calculation does not support this type.");
}

#include "Tools/types.h"
#if defined(MULTI_PREC) | defined (PREC_32_BIT)
namespace aff3ct
{
namespace module
{
template <>
Q_32 Monitor_BFER<B_32,Q_32>
::_get_mutual_info(const B_32 *X, const Q_32 *Y, const int frame_id)
{
	auto mi = tools::mutual_info_histo(X, Y, this->N);
	MI_sum += mi;
	return mi;
}
}
}
#endif

#if defined(MULTI_PREC) | defined (PREC_64_BIT)
namespace aff3ct
{
namespace module
{
template <>
Q_64 Monitor_BFER<B_64,Q_64>
::_get_mutual_info(const B_64 *X, const Q_64 *Y, const int frame_id)
{
	auto mi = tools::mutual_info_histo(X, Y, this->N);
	MI_sum += mi;
	return mi;
}
}
}
#endif

template <typename B, typename R>
bool Monitor_BFER<B,R>
::fe_limit_achieved()
{
	return (get_n_fe() >= get_fe_limit()) || Monitor::interrupt;
}

template <typename B, typename R>
unsigned Monitor_BFER<B,R>
::get_fe_limit() const
{
	return max_fe;
}

template <typename B, typename R>
unsigned long long Monitor_BFER<B,R>
::get_n_analyzed_fra() const
{
	return n_analyzed_frames;
}

template <typename B, typename R>
unsigned long long Monitor_BFER<B,R>
::get_n_fe() const
{
	return n_frame_errors;
}

template <typename B, typename R>
unsigned long long Monitor_BFER<B,R>
::get_n_be() const
{
	return n_bit_errors;
}

template <typename B, typename R>
float Monitor_BFER<B,R>
::get_fer() const
{
	auto t_fer = 0.f;
	if (this->get_n_be() != 0)
		t_fer = (float)this->get_n_fe() / (float)this->get_n_analyzed_fra();
	else
		t_fer = (1.f) / ((float)this->get_n_analyzed_fra());

	return t_fer;
}

template <typename B, typename R>
float Monitor_BFER<B,R>
::get_ber() const
{
	auto t_ber = 0.f;
	if (this->get_n_be() != 0)
		t_ber = (float)this->get_n_be() / (float)this->get_n_analyzed_fra() / (float)this->get_K();
	else
		t_ber = (1.f) / ((float)this->get_n_analyzed_fra()) / this->get_K();

	return t_ber;
}

template <typename B, typename R>
R Monitor_BFER<B,R>
::get_MI() const
{
	return this->MI_sum / (R)this->n_analyzed_frames;
}

template <typename B, typename R>
R Monitor_BFER<B,R>
::get_MI_sum() const
{
	return this->MI_sum;
}

template <typename B, typename R>
void Monitor_BFER<B,R>
::add_handler_fe(std::function<void(unsigned, int)> callback)
{
	this->callbacks_fe.push_back(callback);
}

template <typename B, typename R>
void Monitor_BFER<B,R>
::add_handler_check(std::function<void(void)> callback)
{
	this->callbacks_check.push_back(callback);
}

template <typename B, typename R>
void Monitor_BFER<B,R>
::add_handler_fe_limit_achieved(std::function<void(void)> callback)
{
	this->callbacks_fe_limit_achieved.push_back(callback);
}

template <typename B, typename R>
void Monitor_BFER<B,R>
::reset()
{
	Monitor::reset();

	this->n_bit_errors      = 0;
	this->n_frame_errors    = 0;
	this->n_analyzed_frames = 0;
	this->MI_sum            = 0;
}

template <typename B, typename R>
void Monitor_BFER<B,R>
::clear_callbacks()
{
	this->callbacks_fe               .clear();
	this->callbacks_check            .clear();
	this->callbacks_fe_limit_achieved.clear();
}

// ==================================================================================== explicit template instantiation
#include "Tools/types.h"
#ifdef MULTI_PREC
template class aff3ct::module::Monitor_BFER<B_8, Q_8>;
template class aff3ct::module::Monitor_BFER<B_16,Q_16>;
template class aff3ct::module::Monitor_BFER<B_32,Q_32>;
template class aff3ct::module::Monitor_BFER<B_64,Q_64>;
#else
template class aff3ct::module::Monitor_BFER<B,Q>;
#endif
// ==================================================================================== explicit template instantiation
<commit_msg>Fix monitor BFER<commit_after>#include <string>
#include <vector>
#include <stdexcept>

#include "Monitor_BFER.hpp"
#include "Tools/Perf/common/mutual_info.h"
#include "Tools/Perf/common/hamming_distance.h"
#include "Tools/Math/utils.h"

using namespace aff3ct::module;

template <typename B, typename R>
Monitor_BFER<B,R>
::Monitor_BFER(const int K, const int N, const unsigned max_fe, const int n_frames)
: Monitor(K, N, n_frames),
  max_fe(max_fe),
  n_bit_errors(0),
  n_frame_errors(0),
  n_analyzed_frames(0),
  MI_sum(0)
{
	const std::string name = "Monitor_BFER";
	this->set_name(name);

	auto &p1 = this->create_task("check_errors", (int)mnt::tsk::check_errors);
	auto &ps_U = this->template create_socket_in<B>(p1, "U", this->K * this->n_frames);
	auto &ps_V = this->template create_socket_in<B>(p1, "V", this->K * this->n_frames);
	this->create_codelet(p1, [this, &ps_U, &ps_V]() -> int
	{
		return this->check_errors(static_cast<B*>(ps_U.get_dataptr()),
		                          static_cast<B*>(ps_V.get_dataptr()));
	});

	auto &p2 = this->create_task("get_mutual_info", (int)mnt::tsk::get_mutual_info);
	auto &ps_X = this->template create_socket_in<B>(p2, "X", this->N * this->n_frames);
	auto &ps_Y = this->template create_socket_in<R>(p2, "Y", this->N * this->n_frames);
	this->create_codelet(p2, [this, &ps_X, &ps_Y]() -> int
	{
		return this->get_mutual_info(static_cast<B*>(ps_X.get_dataptr()),
		                             static_cast<R*>(ps_Y.get_dataptr()));
	});
}

template <typename B, typename R>
int Monitor_BFER<B,R>
::check_errors(const B *U, const B *V, const int frame_id)
{
	const auto f_start = (frame_id < 0) ? 0 : frame_id % this->n_frames;
	const auto f_stop  = (frame_id < 0) ? this->n_frames : f_start +1;

	int n_be = 0;
	for (auto f = f_start; f < f_stop; f++)
		n_be += this->_check_errors(U + f * this->K,
		                            V + f * this->K,
		                            f);

	return n_be;
}

template <typename B, typename R>
R Monitor_BFER<B,R>
::get_mutual_info(const B *X, const R *Y, const int frame_id)
{
	const auto f_start = (frame_id < 0) ? 0 : frame_id % this->n_frames;
	const auto f_stop  = (frame_id < 0) ? this->n_frames : f_start +1;

	R MI_sum = 0;
	for (auto f = f_start; f < f_stop; f++)
		MI_sum += this->_get_mutual_info(X + f * this->K,
		                                 Y + f * this->K,
		                                 f);

	return MI_sum / (R)this->n_frames * 10000;
}

template <typename B, typename R>
int Monitor_BFER<B,R>
::_check_errors(const B *U, const B *V, const int frame_id)
{
	int bit_errors_count = tools::hamming_distance(U, V, this->K);

	if (bit_errors_count)
	{
		n_bit_errors += bit_errors_count;
		n_frame_errors++;

		for (auto c : this->callbacks_fe)
			c(bit_errors_count, frame_id);

		if (this->fe_limit_achieved() && frame_id == this->n_frames -1)
			for (auto c : this->callbacks_fe_limit_achieved)
				c();
	}

	n_analyzed_frames++;

	if (frame_id == this->n_frames -1)
		for (auto c : this->callbacks_check)
			c();

	return bit_errors_count;
}

template <typename B, typename R>
R Monitor_BFER<B,R>
::_get_mutual_info(const B *X, const R *Y, const int frame_id)
{
	throw tools::runtime_error(__FILE__, __LINE__, __func__, "The mutual_info_histo calculation does not support this type.");
}

#include "Tools/types.h"
#if defined(MULTI_PREC) | defined (PREC_32_BIT)
namespace aff3ct
{
namespace module
{
template <>
Q_32 Monitor_BFER<B_32,Q_32>
::_get_mutual_info(const B_32 *X, const Q_32 *Y, const int frame_id)
{
	auto mi = tools::mutual_info_histo(X, Y, this->N);
	MI_sum += mi;
	return mi;
}
}
}
#endif

#if defined(MULTI_PREC) | defined (PREC_64_BIT)
namespace aff3ct
{
namespace module
{
template <>
Q_64 Monitor_BFER<B_64,Q_64>
::_get_mutual_info(const B_64 *X, const Q_64 *Y, const int frame_id)
{
	auto mi = tools::mutual_info_histo(X, Y, this->N);
	MI_sum += mi;
	return mi;
}
}
}
#endif

template <typename B, typename R>
bool Monitor_BFER<B,R>
::fe_limit_achieved()
{
	return (get_n_fe() >= get_fe_limit()) || Monitor::interrupt;
}

template <typename B, typename R>
unsigned Monitor_BFER<B,R>
::get_fe_limit() const
{
	return max_fe;
}

template <typename B, typename R>
unsigned long long Monitor_BFER<B,R>
::get_n_analyzed_fra() const
{
	return n_analyzed_frames;
}

template <typename B, typename R>
unsigned long long Monitor_BFER<B,R>
::get_n_fe() const
{
	return n_frame_errors;
}

template <typename B, typename R>
unsigned long long Monitor_BFER<B,R>
::get_n_be() const
{
	return n_bit_errors;
}

template <typename B, typename R>
float Monitor_BFER<B,R>
::get_fer() const
{
	auto t_fer = 0.f;
	if (this->get_n_be() != 0)
		t_fer = (float)this->get_n_fe() / (float)this->get_n_analyzed_fra();
	else
		t_fer = (1.f) / ((float)this->get_n_analyzed_fra());

	return t_fer;
}

template <typename B, typename R>
float Monitor_BFER<B,R>
::get_ber() const
{
	auto t_ber = 0.f;
	if (this->get_n_be() != 0)
		t_ber = (float)this->get_n_be() / (float)this->get_n_analyzed_fra() / (float)this->get_K();
	else
		t_ber = (1.f) / ((float)this->get_n_analyzed_fra()) / this->get_K();

	return t_ber;
}

template <typename B, typename R>
R Monitor_BFER<B,R>
::get_MI() const
{
	return this->MI_sum / (R)this->n_analyzed_frames;
}

template <typename B, typename R>
R Monitor_BFER<B,R>
::get_MI_sum() const
{
	return this->MI_sum;
}

template <typename B, typename R>
void Monitor_BFER<B,R>
::add_handler_fe(std::function<void(unsigned, int)> callback)
{
	this->callbacks_fe.push_back(callback);
}

template <typename B, typename R>
void Monitor_BFER<B,R>
::add_handler_check(std::function<void(void)> callback)
{
	this->callbacks_check.push_back(callback);
}

template <typename B, typename R>
void Monitor_BFER<B,R>
::add_handler_fe_limit_achieved(std::function<void(void)> callback)
{
	this->callbacks_fe_limit_achieved.push_back(callback);
}

template <typename B, typename R>
void Monitor_BFER<B,R>
::reset()
{
	Monitor::reset();

	this->n_bit_errors      = 0;
	this->n_frame_errors    = 0;
	this->n_analyzed_frames = 0;
	this->MI_sum            = 0;
}

template <typename B, typename R>
void Monitor_BFER<B,R>
::clear_callbacks()
{
	this->callbacks_fe               .clear();
	this->callbacks_check            .clear();
	this->callbacks_fe_limit_achieved.clear();
}

// ==================================================================================== explicit template instantiation
#include "Tools/types.h"
#ifdef MULTI_PREC
template class aff3ct::module::Monitor_BFER<B_8, Q_8>;
template class aff3ct::module::Monitor_BFER<B_16,Q_16>;
template class aff3ct::module::Monitor_BFER<B_32,Q_32>;
template class aff3ct::module::Monitor_BFER<B_64,Q_64>;
#else
template class aff3ct::module::Monitor_BFER<B,Q>;
#endif
// ==================================================================================== explicit template instantiation
<|endoftext|>