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

  Library: MSVTK

  Copyright (c) Kitware Inc.

  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.txt

  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.

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

// Qt includes
#include <QIcon>
#include <QTime>
#include <QTimer>

// MSV includes
#include "msvQTimePlayerWidget.h"
#include "ui_msvQTimePlayerWidget.h"

// VTK includes
#include "vtkAlgorithm.h"
#include "vtkAlgorithmOutput.h"
#include "vtkExecutive.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMath.h"
#include "vtkNew.h"
#include "vtkSmartPointer.h"
#include "vtkStreamingDemandDrivenPipeline.h"

//------------------------------------------------------------------------------
class msvQTimePlayerWidgetPrivate : public Ui_msvQTimePlayerWidget
{
  Q_DECLARE_PUBLIC(msvQTimePlayerWidget);
protected:
  msvQTimePlayerWidget* const q_ptr;

  vtkSmartPointer<vtkAlgorithm> filter;

  bool   automaticSingleStep;             // Compute singleStep as the time between frames, true by default
  double maxFrameRate;                    // Time Playing speed factor.
  QTimer* timer;                          // Timer to process the player.
  QTime realTime;                         // Time to reference the real one.
  QAbstractAnimation::Direction direction;// Sense of lecture

public:
  msvQTimePlayerWidgetPrivate(msvQTimePlayerWidget& object);
  virtual ~msvQTimePlayerWidgetPrivate();

  virtual void setupUi(QWidget*);
  virtual void updateUi();

  struct PipelineInfoType
    {
    PipelineInfoType();

    int    numberOfTimeSteps;
    double timeRange[2];
    double lastTimeRequest;
    bool   isConnected;

    double clampTimeInterval(double, double) const; // Tranform a frameRate into a time interval
    double frameToTime(int) const;    // Convert a frame index into a time.
    int timeToFrame(double) const;    // Convert a time into its closest frame.
    double timeNextFrame() const;     // Get the time corresponding to the next frame.
    double timePreviousFrame() const; // Get the time corresponding to the previous frame.
    };
  PipelineInfoType retrievePipelineInfo();            // Get pipeline information.
  virtual void processRequest(double);                // Request Data and Update
  virtual bool isConnected();                         // Check if the pipeline is ready
  virtual void processRequest(const PipelineInfoType&, double); // Request Data and Update
  virtual void requestData(const PipelineInfoType&, double);    // Request Data by time
  virtual void updateUi(const PipelineInfoType&);               // Update the widget giving pipeline statut
};

//------------------------------------------------------------------------------
// msvQECGMainWindowPrivate methods

//------------------------------------------------------------------------------
msvQTimePlayerWidgetPrivate::msvQTimePlayerWidgetPrivate
(msvQTimePlayerWidget& object)
  : q_ptr(&object)
{
  this->automaticSingleStep = true;
  this->maxFrameRate = 60;          // 60 FPS by default
}

//------------------------------------------------------------------------------
msvQTimePlayerWidgetPrivate::~msvQTimePlayerWidgetPrivate()
{
}

//------------------------------------------------------------------------------
msvQTimePlayerWidgetPrivate::PipelineInfoType::PipelineInfoType()
{
  this->numberOfTimeSteps = 0;
  this->timeRange[0]      = this->timeRange[1] = 0;
  this->lastTimeRequest   = 0;
  this->isConnected       = false;
}

//------------------------------------------------------------------------------
msvQTimePlayerWidgetPrivate::PipelineInfoType
msvQTimePlayerWidgetPrivate::retrievePipelineInfo()
{
  PipelineInfoType pipeInfo;

  pipeInfo.isConnected = this->isConnected();
  if (!pipeInfo.isConnected)
    return pipeInfo;

  vtkStreamingDemandDrivenPipeline* sdd = vtkStreamingDemandDrivenPipeline::
    SafeDownCast(this->filter->GetExecutive());
  vtkInformation* info = sdd->GetInputInformation(0)->GetInformationObject(0);

  if (!info->Has(vtkStreamingDemandDrivenPipeline::TIME_STEPS()) ||
      !info->Has(vtkStreamingDemandDrivenPipeline::TIME_RANGE()))
    return pipeInfo;

  pipeInfo.numberOfTimeSteps =
    info->Length(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
  info->Get(vtkStreamingDemandDrivenPipeline::TIME_RANGE(), pipeInfo.timeRange);

  if (info->Has(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEPS())) {
    pipeInfo.lastTimeRequest =
      info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEPS())[0];
  }
  return pipeInfo;
}

//------------------------------------------------------------------------------
double msvQTimePlayerWidgetPrivate::PipelineInfoType::
clampTimeInterval(double playbackSpeed, double maxFrameRate) const
{
  Q_ASSERT(playbackSpeed > 0.);

  double timeFrame = this->frameToTime(1) / playbackSpeed;
  double maxFrameratePeriod = 1000. / maxFrameRate;

  // Clamp the time interval
  return qMin(timeFrame, maxFrameratePeriod);
}

//------------------------------------------------------------------------------
double msvQTimePlayerWidgetPrivate::PipelineInfoType::frameToTime(int frame) const
{
  double period = this->timeRange[1] - this->timeRange[0];
  if (this->numberOfTimeSteps == 0 || period == 0)
    return vtkMath::Nan();

  return period / static_cast<double>(this->numberOfTimeSteps-1) * frame;
}

//------------------------------------------------------------------------------
int msvQTimePlayerWidgetPrivate::PipelineInfoType::timeToFrame(double time) const
{
  double period = this->timeRange[1] - this->timeRange[0];
  if (this->numberOfTimeSteps == 0 || period == 0)
    return -1;

  return static_cast<int>(((this->numberOfTimeSteps-1)/period)*time);
}

//------------------------------------------------------------------------------
double msvQTimePlayerWidgetPrivate::PipelineInfoType::timePreviousFrame() const
{
  int currentFrame = this->timeToFrame(this->lastTimeRequest);
  return this->frameToTime(currentFrame-1);
}

//------------------------------------------------------------------------------
double msvQTimePlayerWidgetPrivate::PipelineInfoType::timeNextFrame() const
{
  int currentFrame = this->timeToFrame(this->lastTimeRequest);
  return this->frameToTime(currentFrame+1);
}

//------------------------------------------------------------------------------
void msvQTimePlayerWidgetPrivate::setupUi(QWidget* widget)<commit_msg>Fix rounding error in msvQTimePlayerWidget<commit_after>/*==============================================================================

  Library: MSVTK

  Copyright (c) Kitware Inc.

  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.txt

  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.

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

// Qt includes
#include <QIcon>
#include <QTime>
#include <QTimer>

// MSV includes
#include "msvQTimePlayerWidget.h"
#include "ui_msvQTimePlayerWidget.h"

// VTK includes
#include "vtkAlgorithm.h"
#include "vtkAlgorithmOutput.h"
#include "vtkExecutive.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMath.h"
#include "vtkNew.h"
#include "vtkSmartPointer.h"
#include "vtkStreamingDemandDrivenPipeline.h"

//------------------------------------------------------------------------------
class msvQTimePlayerWidgetPrivate : public Ui_msvQTimePlayerWidget
{
  Q_DECLARE_PUBLIC(msvQTimePlayerWidget);
protected:
  msvQTimePlayerWidget* const q_ptr;

  vtkSmartPointer<vtkAlgorithm> filter;

  bool   automaticSingleStep;             // Compute singleStep as the time between frames, true by default
  double maxFrameRate;                    // Time Playing speed factor.
  QTimer* timer;                          // Timer to process the player.
  QTime realTime;                         // Time to reference the real one.
  QAbstractAnimation::Direction direction;// Sense of lecture

public:
  msvQTimePlayerWidgetPrivate(msvQTimePlayerWidget& object);
  virtual ~msvQTimePlayerWidgetPrivate();

  virtual void setupUi(QWidget*);
  virtual void updateUi();

  struct PipelineInfoType
    {
    PipelineInfoType();

    int    numberOfTimeSteps;
    double timeRange[2];
    double lastTimeRequest;
    bool   isConnected;

    double clampTimeInterval(double, double) const; // Tranform a frameRate into a time interval
    double frameToTime(int) const;    // Convert a frame index into a time.
    int timeToFrame(double) const;    // Convert a time into its closest frame.
    double timeNextFrame() const;     // Get the time corresponding to the next frame.
    double timePreviousFrame() const; // Get the time corresponding to the previous frame.
    };
  PipelineInfoType retrievePipelineInfo();            // Get pipeline information.
  virtual void processRequest(double);                // Request Data and Update
  virtual bool isConnected();                         // Check if the pipeline is ready
  virtual void processRequest(const PipelineInfoType&, double); // Request Data and Update
  virtual void requestData(const PipelineInfoType&, double);    // Request Data by time
  virtual void updateUi(const PipelineInfoType&);               // Update the widget giving pipeline statut
};

//------------------------------------------------------------------------------
// msvQECGMainWindowPrivate methods

//------------------------------------------------------------------------------
msvQTimePlayerWidgetPrivate::msvQTimePlayerWidgetPrivate
(msvQTimePlayerWidget& object)
  : q_ptr(&object)
{
  this->automaticSingleStep = true;
  this->maxFrameRate = 60;          // 60 FPS by default
}

//------------------------------------------------------------------------------
msvQTimePlayerWidgetPrivate::~msvQTimePlayerWidgetPrivate()
{
}

//------------------------------------------------------------------------------
msvQTimePlayerWidgetPrivate::PipelineInfoType::PipelineInfoType()
{
  this->numberOfTimeSteps = 0;
  this->timeRange[0]      = this->timeRange[1] = 0;
  this->lastTimeRequest   = 0;
  this->isConnected       = false;
}

//------------------------------------------------------------------------------
msvQTimePlayerWidgetPrivate::PipelineInfoType
msvQTimePlayerWidgetPrivate::retrievePipelineInfo()
{
  PipelineInfoType pipeInfo;

  pipeInfo.isConnected = this->isConnected();
  if (!pipeInfo.isConnected)
    return pipeInfo;

  vtkStreamingDemandDrivenPipeline* sdd = vtkStreamingDemandDrivenPipeline::
    SafeDownCast(this->filter->GetExecutive());
  vtkInformation* info = sdd->GetInputInformation(0)->GetInformationObject(0);

  if (!info->Has(vtkStreamingDemandDrivenPipeline::TIME_STEPS()) ||
      !info->Has(vtkStreamingDemandDrivenPipeline::TIME_RANGE()))
    return pipeInfo;

  pipeInfo.numberOfTimeSteps =
    info->Length(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
  info->Get(vtkStreamingDemandDrivenPipeline::TIME_RANGE(), pipeInfo.timeRange);

  if (info->Has(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEPS())) {
    pipeInfo.lastTimeRequest =
      info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEPS())[0];
  }
  return pipeInfo;
}

//------------------------------------------------------------------------------
double msvQTimePlayerWidgetPrivate::PipelineInfoType::
clampTimeInterval(double playbackSpeed, double maxFrameRate) const
{
  Q_ASSERT(playbackSpeed > 0.);

  double timeFrame = this->frameToTime(1) / playbackSpeed;
  double maxFrameratePeriod = 1000. / maxFrameRate;

  // Clamp the time interval
  return qMin(timeFrame, maxFrameratePeriod);
}

//------------------------------------------------------------------------------
double msvQTimePlayerWidgetPrivate::PipelineInfoType::frameToTime(int frame) const
{
  double period = this->timeRange[1] - this->timeRange[0];
  if (this->numberOfTimeSteps == 0 || period == 0)
    return vtkMath::Nan();

  return period / static_cast<double>(this->numberOfTimeSteps-1) * frame;
}

//------------------------------------------------------------------------------
int msvQTimePlayerWidgetPrivate::PipelineInfoType::timeToFrame(double time) const
{
  double period = this->timeRange[1] - this->timeRange[0];
  if (this->numberOfTimeSteps == 0 || period == 0)
    return -1;

  unsigned int frame = qRound(((this->numberOfTimeSteps-1)/period)*time);
  return frame;
}

//------------------------------------------------------------------------------
double msvQTimePlayerWidgetPrivate::PipelineInfoType::timePreviousFrame() const
{
  int currentFrame = this->timeToFrame(this->lastTimeRequest);
  return this->frameToTime(currentFrame-1);
}

//------------------------------------------------------------------------------
double msvQTimePlayerWidgetPrivate::PipelineInfoType::timeNextFrame() const
{
  int currentFrame = this->timeToFrame(this->lastTimeRequest);
  return this->frameToTime(currentFrame+1);
}

//------------------------------------------------------------------------------
void msvQTimePlayerWidgetPrivate::setupUi(QWidget* widget)
{'fraction_non_alphanumeric': 0.2408399400042854, 'fraction_numerical': 0.005142489822155561, 'mean_word_length': 2.4068126520681266, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 82, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '809588', 'n_tokens_mistral': 3663, 'n_tokens_neox': 3550, 'n_words': 863}