<commit_before>#include "LiftToAngle.h"
#include "../../../Robotmap.h"

LiftToAngle::LiftToAngle(float angle) {
	// Use requires() here to declare subsystem dependencies
	Requires(shooter);
	m_angle = angle;
}

// Called just before this Command runs the first time
void LiftToAngle::Initialize() {
}

// Called repeatedly when this Command is scheduled to run
void LiftToAngle::Execute() {
	if(shooter->AnglePotVoltage() < m_angle)
	{
		shooter->SetSpeedAngle(-0.9);
	}
	else if(shooter->AnglePotVoltage() > m_angle)
	{
		shooter->SetSpeedAngle(0.9);
	}
	SmartDashboard::PutNumber("Shooter Angle", shooter->AnglePotVoltage());
}

// Make this return true when this Command no longer needs to run execute()
bool LiftToAngle::IsFinished() {
	return ((shooter->AnglePotVoltage() > m_angle - POT_RANGE) && (shooter->AnglePotVoltage() < m_angle + POT_RANGE));
	//return false;
}

// Called once after isFinished returns true
void LiftToAngle::End() {
	shooter->SetSpeedAngle(0.0);
}

// Called when another command which requires one or more of the same
// subsystems is scheduled to run
void LiftToAngle::Interrupted() {
	shooter->SetSpeedAngle(0.0);
}
<commit_msg>Changed LiftToAngle to use proper speed value<commit_after>#include "LiftToAngle.h"
#include "../../../Robotmap.h"

LiftToAngle::LiftToAngle(float angle) {
	// Use requires() here to declare subsystem dependencies
	//Requires(shooter);
	m_angle = angle;
}

// Called just before this Command runs the first time
void LiftToAngle::Initialize() {
}

// Called repeatedly when this Command is scheduled to run
void LiftToAngle::Execute() {
	if(shooter->AnglePotVoltage() < m_angle)
	{
		shooter->SetSpeedAngle(SHOOTER_LIFT_SPEED);
	}
	else if(shooter->AnglePotVoltage() > m_angle)
	{
		shooter->SetSpeedAngle((SHOOTER_LIFT_SPEED) * -1);
	}
	SmartDashboard::PutNumber("Shooter Angle", shooter->AnglePotVoltage());
}

// Make this return true when this Command no longer needs to run execute()
bool LiftToAngle::IsFinished() {
	return ((shooter->AnglePotVoltage() > m_angle - POT_RANGE) && (shooter->AnglePotVoltage() < m_angle + POT_RANGE));
	//return false;
}

// Called once after isFinished returns true
void LiftToAngle::End() {
	shooter->SetSpeedAngle(0.0);
}

// Called when another command which requires one or more of the same
// subsystems is scheduled to run
void LiftToAngle::Interrupted() {
	shooter->SetSpeedAngle(0.0);
}
<|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.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#ifdef __BORLANDC__
#define ITK_LEAN_AND_MEAN
#endif

//  Software Guide : BeginCommandLineArgs
//    INPUTS: {ROISpot5.png}
//    OUTPUTS: {LaplacianRecursiveGaussianImageFilteroutput3.mha}
//    3
//    OUTPUTS: {LaplacianRecursiveGaussianImageFilterOutput3.png}
//  Software Guide : EndCommandLineArgs

//  Software Guide : BeginCommandLineArgs
//    INPUTS: {ROISpot5.png}
//    OUTPUTS: {LaplacianRecursiveGaussianImageFilteroutput5.mha}
//    5
//    OUTPUTS: {LaplacianRecursiveGaussianImageFilterOutput5.png}
//  Software Guide : EndCommandLineArgs

//  Software Guide : BeginLatex
//
//  This example illustrates how to use the
//  \doxygen{itk}{RecursiveGaussianImageFilter} for computing the
//  Laplacian of an
//  image.
//
//  \index{itk::RecursiveGaussianImageFilter}
//
//  Software Guide : EndLatex

#include "otbImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "itkAddImageFilter.h"

//  Software Guide : BeginLatex
//
//  The first step required to use this filter is to include its header file.
//
//  \index{itk::RecursiveGaussianImageFilter!header}
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "itkRecursiveGaussianImageFilter.h"
// Software Guide : EndCodeSnippet
#include "itkRescaleIntensityImageFilter.h"

int main( int argc, char * argv[] )
{
  if( argc < 4 )
    {
    std::cerr << "Usage: " << std::endl;
    std::cerr << argv[0] << "  inputImageFile  outputImageFile  sigma [RescaledOutputImageFile] " << std::endl;
    return EXIT_FAILURE;
    }

  //  Software Guide : BeginLatex
  //
  //  Types should be selected on the desired input and output pixel types.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef    float    InputPixelType;
  typedef    float    OutputPixelType;
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The input and output image types are instantiated using the pixel types.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef otb::Image< InputPixelType,  2 >   InputImageType;
  typedef otb::Image< OutputPixelType, 2 >   OutputImageType;
  // Software Guide : EndCodeSnippet

  typedef otb::ImageFileReader< InputImageType >  ReaderType;

  //  Software Guide : BeginLatex
  //
  //  The filter type is now instantiated using both the input image and the
  //  output image types.
  //
  //  \index{itk::RecursiveGaussianImageFilter!Instantiation}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::RecursiveGaussianImageFilter<
                        InputImageType, OutputImageType >  FilterType;
  // Software Guide : EndCodeSnippet

  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName( argv[1] );

  //  Software Guide : BeginLatex
  //
  //  This filter applies the approximation of the convolution along a single
  //  dimension. It is therefore necessary to concatenate several of these filters
  //  to produce smoothing in all directions.  In this example, we create a pair
  //  of filters since we are processing a $2D$ image.  The filters are
  //  created by invoking the \code{New()} method and assigning the result to
  //  a \doxygen{itk}{SmartPointer}.
  //
  //  We need two filters for computing the X component of the Laplacian and
  //  two other filters for computing the Y component.
  //
  //  \index{itk::RecursiveGaussianImageFilter!New()}
  //  \index{itk::RecursiveGaussianImageFilter!Pointer}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  FilterType::Pointer filterX1 = FilterType::New();
  FilterType::Pointer filterY1 = FilterType::New();

  FilterType::Pointer filterX2 = FilterType::New();
  FilterType::Pointer filterY2 = FilterType::New();
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  Since each one of the newly created filters has the potential to perform
  //  filtering along any dimension, we have to restrict each one to a
  //  particular direction. This is done with the \code{SetDirection()} method.
  //
  //  \index{RecursiveGaussianImageFilter!SetDirection()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filterX1->SetDirection( 0 );   // 0 --> X direction
  filterY1->SetDirection( 1 );   // 1 --> Y direction

  filterX2->SetDirection( 0 );   // 0 --> X direction
  filterY2->SetDirection( 1 );   // 1 --> Y direction
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The \doxygen{itk}{RecursiveGaussianImageFilter} can approximate the
  //  convolution with the Gaussian or with its first and second
  //  derivatives. We select one of these options by using the
  //  \code{SetOrder()} method. Note that the argument is an \code{enum} whose
  //  values can be \code{ZeroOrder}, \code{FirstOrder} and
  //  \code{SecondOrder}. For example, to compute the $x$ partial derivative we
  //  should select \code{FirstOrder} for $x$ and \code{ZeroOrder} for
  //  $y$. Here we want only to smooth in $x$ and $y$, so we select
  //  \code{ZeroOrder} in both directions.
  //
  //  \index{RecursiveGaussianImageFilter!SetOrder()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filterX1->SetOrder( FilterType::ZeroOrder );
  filterY1->SetOrder( FilterType::SecondOrder );

  filterX2->SetOrder( FilterType::SecondOrder );
  filterY2->SetOrder( FilterType::ZeroOrder );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  There are two typical ways of normalizing Gaussians depending on their
  //  application. For scale-space analysis it is desirable to use a
  //  normalization that will preserve the maximum value of the input. This
  //  normalization is represented by the following equation.
  //
  //  \begin{equation}
  //          \frac{ 1 }{ \sigma  \sqrt{ 2 \pi } }
  //  \end{equation}
  //
  //  In applications that use the Gaussian as a solution of the diffusion
  //  equation it is desirable to use a normalization that preserve the
  //  integral of the signal. This last approach can be seen as a conservation
  //  of mass principle. This is represented by the following equation.
  //
  //  \begin{equation}
  //          \frac{ 1 }{ \sigma^2  \sqrt{ 2 \pi } }
  //  \end{equation}
  //
  //  The \doxygen{itk}{RecursiveGaussianImageFilter} has a boolean flag that allows
  //  users to select between these two normalization options. Selection is
  //  done with the method \code{SetNormalizeAcrossScale()}. Enable this flag
  //  to analyzing an image across scale-space.  In the current example, this
  //  setting has no impact because we are actually renormalizing the output to
  //  the dynamic range of the reader, so we simply disable the flag.
  //
  //  \index{RecursiveGaussianImageFilter!SetNormalizeAcrossScale()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  const bool normalizeAcrossScale = false;
  filterX1->SetNormalizeAcrossScale( normalizeAcrossScale );
  filterY1->SetNormalizeAcrossScale( normalizeAcrossScale );
  filterX2->SetNormalizeAcrossScale( normalizeAcrossScale );
  filterY2->SetNormalizeAcrossScale( normalizeAcrossScale );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The input image can be obtained from the output of another
  //  filter. Here, an image reader is used as the source. The image is passed to
  //  the $x$ filter and then to the $y$ filter. The reason for keeping these
  //  two filters separate is that it is usual in scale-space applications to
  //  compute not only the smoothing but also combinations of derivatives at
  //  different orders and smoothing. Some factorization is possible when
  //  separate filters are used to generate the intermediate results. Here
  //  this capability is less interesting, though, since we only want to smooth
  //  the image in all directions.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filterX1->SetInput( reader->GetOutput() );
  filterY1->SetInput( filterX1->GetOutput() );

  filterY2->SetInput( reader->GetOutput() );
  filterX2->SetInput( filterY2->GetOutput() );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  It is now time to select the $\sigma$ of the Gaussian used to
  //  smooth the data.  Note that $\sigma$ must be passed to both
  //  filters and that sigma is considered to be in the units of the
  //  image spacing. That is, at the moment of applying the smoothing
  //  process, the filter will take into account the spacing values
  //  defined in the image.
  //
  //  \index{itk::RecursiveGaussianImageFilter!SetSigma()}
  //  \index{SetSigma()!itk::RecursiveGaussianImageFilter}
  //
  //  Software Guide : EndLatex

  const double sigma = atof( argv[3] );

  // Software Guide : BeginCodeSnippet
  filterX1->SetSigma( sigma );
  filterY1->SetSigma( sigma );
  filterX2->SetSigma( sigma );
  filterY2->SetSigma( sigma );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  Finally the two components of the Laplacian should be added together. The
  //  \doxygen{itk}{AddImageFilter} is used for this purpose.
  //
  //  \index{itk::AddImageFilter!Instantiation}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::AddImageFilter<
                OutputImageType,
                OutputImageType,
                OutputImageType > AddFilterType;

  AddFilterType::Pointer addFilter = AddFilterType::New();

  addFilter->SetInput1( filterY1->GetOutput() );
  addFilter->SetInput2( filterX2->GetOutput() );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The filters are triggered by invoking \code{Update()} on the Add filter
  //  at the end of the pipeline.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  try
    {
    addFilter->Update();
    }
  catch( itk::ExceptionObject & err )
    {
    std::cout << "ExceptionObject caught !" << std::endl;
    std::cout << err << std::endl;
    return EXIT_FAILURE;
    }
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The resulting image could be saved to a file using the
  //  \doxygen{otb}{ImageFileWriter} class.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef  float WritePixelType;

  typedef otb::Image< WritePixelType, 2 >    WriteImageType;

  typedef otb::ImageFileWriter< WriteImageType >  WriterType;

  WriterType::Pointer writer = WriterType::New();

  writer->SetInput( addFilter->GetOutput() );

  writer->SetFileName( argv[2] );

  writer->Update();
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  // \begin{figure}
  // \center
  // \includegraphics[width=0.44\textwidth]{LaplacianRecursiveGaussianImageFilterOutput3.eps}
  // \includegraphics[width=0.44\textwidth]{LaplacianRecursiveGaussianImageFilterOutput5.eps}
  // \itkcaption[Output of the LaplacianRecursiveGaussianImageFilter.]{Effect of the
  // LaplacianRecursiveGaussianImageFilter.}
  // \label{fig:LaplacianRecursiveGaussianImageFilterInputOutput}
  // \end{figure}
  //
  //  Figure~\ref{fig:LaplacianRecursiveGaussianImageFilterInputOutput} illustrates the
  //  effect of this filter using
  //  $\sigma$ values of $3$ (left) and $5$ (right).  The figure shows how the
  //  attenuation of noise can be regulated by selecting the appropriate
  //  standard deviation.  This type of scale-tunable filter is suitable for
  //  performing scale-space analysis.
  //
  //  Software Guide : EndLatex

  // Rescale float outputs to png for inclusion in the Software guide
  //
  if (argc > 4)
    {
    typedef unsigned char    CharPixelType;
    typedef otb::Image<CharPixelType, 2>    CharImageType;
    typedef itk::RescaleIntensityImageFilter< OutputImageType, CharImageType>
                                                            RescaleFilterType;
    RescaleFilterType::Pointer rescale = RescaleFilterType::New();
    rescale->SetInput( addFilter->GetOutput() );
    rescale->SetOutputMinimum(   0 );
    rescale->SetOutputMaximum( 255 );
    typedef otb::ImageFileWriter< CharImageType >  CharWriterType;
    CharWriterType::Pointer charWriter = CharWriterType::New();
    charWriter->SetFileName( argv[4] );
    charWriter->SetInput( rescale->GetOutput() );
    charWriter->Update();
    }

  return EXIT_SUCCESS;
}

<commit_msg>Edit software guide<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.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#ifdef __BORLANDC__
#define ITK_LEAN_AND_MEAN
#endif

//  Software Guide : BeginCommandLineArgs
//    INPUTS: {ROISpot5.png}
//    OUTPUTS: {LaplacianRecursiveGaussianImageFilteroutput3.mha}
//    3
//    OUTPUTS: {LaplacianRecursiveGaussianImageFilterOutput3.png}
//  Software Guide : EndCommandLineArgs

//  Software Guide : BeginCommandLineArgs
//    INPUTS: {ROISpot5.png}
//    OUTPUTS: {LaplacianRecursiveGaussianImageFilteroutput5.mha}
//    5
//    OUTPUTS: {LaplacianRecursiveGaussianImageFilterOutput5.png}
//  Software Guide : EndCommandLineArgs

//  Software Guide : BeginLatex
//
//  This example illustrates how to use the
//  \doxygen{itk}{RecursiveGaussianImageFilter} for computing the
//  Laplacian of an
//  image.
//
//  \index{itk::RecursiveGaussianImageFilter}
//
//  Software Guide : EndLatex

#include "otbImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "itkAddImageFilter.h"

//  Software Guide : BeginLatex
//
//  The first step required to use this filter is to include its header file.
//
//  \index{itk::RecursiveGaussianImageFilter!header}
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "itkRecursiveGaussianImageFilter.h"
// Software Guide : EndCodeSnippet
#include "itkRescaleIntensityImageFilter.h"

int main( int argc, char * argv[] )
{
  if( argc < 4 )
    {
    std::cerr << "Usage: " << std::endl;
    std::cerr << argv[0] << "  inputImageFile  outputImageFile  sigma [RescaledOutputImageFile] " << std::endl;
    return EXIT_FAILURE;
    }

  //  Software Guide : BeginLatex
  //
  //  Types should be selected on the desired input and output pixel types.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef    float    InputPixelType;
  typedef    float    OutputPixelType;
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The input and output image types are instantiated using the pixel types.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef otb::Image< InputPixelType,  2 >   InputImageType;
  typedef otb::Image< OutputPixelType, 2 >   OutputImageType;
  // Software Guide : EndCodeSnippet

  typedef otb::ImageFileReader< InputImageType >  ReaderType;

  //  Software Guide : BeginLatex
  //
  //  The filter type is now instantiated using both the input image and the
  //  output image types.
  //
  //  \index{itk::RecursiveGaussianImageFilter!Instantiation}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::RecursiveGaussianImageFilter<
                        InputImageType, OutputImageType >  FilterType;
  // Software Guide : EndCodeSnippet

  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName( argv[1] );

  //  Software Guide : BeginLatex
  //
  //  This filter applies the approximation of the convolution along a single
  //  dimension. It is therefore necessary to concatenate several of these filters
  //  to produce smoothing in all directions.  In this example, we create a pair
  //  of filters since we are processing a $2D$ image.  The filters are
  //  created by invoking the \code{New()} method and assigning the result to
  //  a \doxygen{itk}{SmartPointer}.
  //
  //  We need two filters for computing the X component of the Laplacian and
  //  two other filters for computing the Y component.
  //
  //  \index{itk::RecursiveGaussianImageFilter!New()}
  //  \index{itk::RecursiveGaussianImageFilter!Pointer}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  FilterType::Pointer filterX1 = FilterType::New();
  FilterType::Pointer filterY1 = FilterType::New();

  FilterType::Pointer filterX2 = FilterType::New();
  FilterType::Pointer filterY2 = FilterType::New();
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  Since each one of the newly created filters has the potential to perform
  //  filtering along any dimension, we have to restrict each one to a
  //  particular direction. This is done with the \code{SetDirection()} method.
  //
  //  \index{RecursiveGaussianImageFilter!SetDirection()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filterX1->SetDirection( 0 );   // 0 --> X direction
  filterY1->SetDirection( 1 );   // 1 --> Y direction

  filterX2->SetDirection( 0 );   // 0 --> X direction
  filterY2->SetDirection( 1 );   // 1 --> Y direction
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The \doxygen{itk}{RecursiveGaussianImageFilter} can approximate the
  //  convolution with the Gaussian or with its first and second
  //  derivatives. We select one of these options by using the
  //  \code{SetOrder()} method. Note that the argument is an \code{enum} whose
  //  values can be \code{ZeroOrder}, \code{FirstOrder} and
  //  \code{SecondOrder}. For example, to compute the $x$ partial derivative we
  //  should select \code{FirstOrder} for $x$ and \code{ZeroOrder} for
  //  $y$. Here we want only to smooth in $x$ and $y$, so we select
  //  \code{ZeroOrder} in both directions.
  //
  //  \index{RecursiveGaussianImageFilter!SetOrder()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filterX1->SetOrder( FilterType::ZeroOrder );
  filterY1->SetOrder( FilterType::SecondOrder );

  filterX2->SetOrder( FilterType::SecondOrder );
  filterY2->SetOrder( FilterType::ZeroOrder );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  There are two typical ways of normalizing Gaussians depending on their
  //  application. For scale-space analysis it is desirable to use a
  //  normalization that will preserve the maximum value of the input. This
  //  normalization is represented by the following equation.
  //
  //  \begin{equation}
  //          \frac{ 1 }{ \sigma  \sqrt{ 2 \pi } }
  //  \end{equation}
  //
  //  In applications that use the Gaussian as a solution of the diffusion
  //  equation it is desirable to use a normalization that preserve the
  //  integral of the signal. This last approach can be seen as a conservation
  //  of mass principle. This is represented by the following equation.
  //
  //  \begin{equation}
  //          \frac{ 1 }{ \sigma^2  \sqrt{ 2 \pi } }
  //  \end{equation}
  //
  //  The \doxygen{itk}{RecursiveGaussianImageFilter} has a boolean flag that allows
  //  users to select between these two normalization options. Selection is
  //  done with the method \code{SetNormalizeAcrossScale()}. Enable this flag
  //  to analyzing an image across scale-space.  In the current example, this
  //  setting has no impact because we are actually renormalizing the output to
  //  the dynamic range of the reader, so we simply disable the flag.
  //
  //  \index{RecursiveGaussianImageFilter!SetNormalizeAcrossScale()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  const bool normalizeAcrossScale = false;
  filterX1->SetNormalizeAcrossScale( normalizeAcrossScale );
  filterY1->SetNormalizeAcrossScale( normalizeAcrossScale );
  filterX2->SetNormalizeAcrossScale( normalizeAcrossScale );
  filterY2->SetNormalizeAcrossScale( normalizeAcrossScale );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The input image can be obtained from the output of another
  //  filter. Here, an image reader is used as the source. The image is passed to
  //  the $x$ filter and then to the $y$ filter. The reason for keeping these
  //  two filters separate is that it is usual in scale-space applications to
  //  compute not only the smoothing but also combinations of derivatives at
  //  different orders and smoothing. Some factorization is possible when
  //  separate filters are used to generate the intermediate results. Here
  //  this capability is less interesting, though, since we only want to smooth
  //  the image in all directions.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filterX1->SetInput( reader->GetOutput() );
  filterY1->SetInput( filterX1->GetOutput() );

  filterY2->SetInput( reader->GetOutput() );
  filterX2->SetInput( filterY2->GetOutput() );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  It is now time to select the $\sigma$ of the Gaussian used to
  //  smooth the data.  Note that $\sigma$ must be passed to both
  //  filters and that sigma is considered to be in the units of the
  //  image spacing. That is, at the moment of applying the smoothing
  //  process, the filter will take into account the spacing values
  //  defined in the image.
  //
  //  \index{itk::RecursiveGaussianImageFilter!SetSigma()}
  //  \index{SetSigma()!itk::RecursiveGaussianImageFilter}
  //
  //  Software Guide : EndLatex

  const double sigma = atof( argv[3] );

  // Software Guide : BeginCodeSnippet
  filterX1->SetSigma( sigma );
  filterY1->SetSigma( sigma );
  filterX2->SetSigma( sigma );
  filterY2->SetSigma( sigma );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  Finally the two components of the Laplacian should be added together. The
  //  \doxygen{itk}{AddImageFilter} is used for this purpose.
  //
  //  \index{itk::AddImageFilter!Instantiation}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::AddImageFilter<
                OutputImageType,
                OutputImageType,
                OutputImageType > AddFilterType;

  AddFilterType::Pointer addFilter = AddFilterType::New();

  addFilter->SetInput1( filterY1->GetOutput() );
  addFilter->SetInput2( filterX2->GetOutput() );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The filters are triggered by invoking \code{Update()} on the Add filter
  //  at the end of the pipeline.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  try
    {
    addFilter->Update();
    }
  catch( itk::ExceptionObject & err )
    {
    std::cout << "ExceptionObject caught !" << std::endl;
    std::cout << err << std::endl;
    return EXIT_FAILURE;
    }
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The resulting image could be saved to a file using the
  //  \doxygen{otb}{ImageFileWriter} class.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef  float WritePixelType;

  typedef otb::Image< WritePixelType, 2 >    WriteImageType;

  typedef otb::ImageFileWriter< WriteImageType >  WriterType;

  WriterType::Pointer writer = WriterType::New();

  writer->SetInput( addFilter->GetOutput() );

  writer->SetFileName( argv[2] );

  writer->Update();
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  // \begin{figure}
  // \center
  // \includegraphics[width=0.44\textwidth]{LaplacianRecursiveGaussianImageFilterOutput3.eps}
  // \includegraphics[width=0.44\textwidth]{LaplacianRecursiveGaussianImageFilterOutput5.eps}
  // \itkcaption[Output of the RecursiveGaussianImageFilter.]{Effect of the
  // RecursiveGaussianImageFilter.}
  // \label{fig:LaplacianRecursiveGaussianImageFilterInputOutput}
  // \end{figure}
  //
  //  Figure~\ref{fig:LaplacianRecursiveGaussianImageFilterInputOutput} illustrates the
  //  effect of this filter using
  //  $\sigma$ values of $3$ (left) and $5$ (right).  The figure shows how the
  //  attenuation of noise can be regulated by selecting the appropriate
  //  standard deviation.  This type of scale-tunable filter is suitable for
  //  performing scale-space analysis.
  //
  //  Software Guide : EndLatex

  // Rescale float outputs to png for inclusion in the Software guide
  //
  if (argc > 4)
    {
    typedef unsigned char    CharPixelType;
    typedef otb::Image<CharPixelType, 2>    CharImageType;
    typedef itk::RescaleIntensityImageFilter< OutputImageType, CharImageType>
                                                            RescaleFilterType;
    RescaleFilterType::Pointer rescale = RescaleFilterType::New();
    rescale->SetInput( addFilter->GetOutput() );
    rescale->SetOutputMinimum(   0 );
    rescale->SetOutputMaximum( 255 );
    typedef otb::ImageFileWriter< CharImageType >  CharWriterType;
    CharWriterType::Pointer charWriter = CharWriterType::New();
    charWriter->SetFileName( argv[4] );
    charWriter->SetInput( rescale->GetOutput() );
    charWriter->Update();
    }

  return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>#include "ctextencodingdetector.h"
#include "trigramfrequencytables/ctrigramfrequencytable_english.h"
#include "trigramfrequencytables/ctrigramfrequencytable_russian.h"
#include "assert/advanced_assert.h"

DISABLE_COMPILER_WARNINGS
#include <QTextCodec>
#include <QIODevice>
#include <QDebug>
#include <QFile>
#include <QTime>
RESTORE_COMPILER_WARNINGS

#include <algorithm>
#include <limits>
#include <memory>
#include <set>

static const float plausibleMatchThreshold = 0.1f;

static const CTextEncodingDetector::MatchFunction defaultMatchFunction =
		CTextEncodingDetector::MatchFunction([](const CTextParser::OccurrenceTable& arg1, const CTextParser::OccurrenceTable& arg2) -> float {

			if (arg1.trigramOccurrenceTable.empty() || arg2.trigramOccurrenceTable.empty())
				return 0.0f;
			else if (arg2.trigramOccurrenceTable.size() < arg1.trigramOccurrenceTable.size())
				return defaultMatchFunction(arg2, arg1); // Performance optimization - the outer loop must iterate the smaller of the two containers for better performance

			float deviation = 0.0f;
			for (auto& n_gram1: arg1.trigramOccurrenceTable)
			{
				auto n_gram2 = arg2.trigramOccurrenceTable.find(n_gram1.first);
				deviation += n_gram2 != arg2.trigramOccurrenceTable.end() ?
					fabs(n_gram1.second / (float) arg1.totalTrigramsCount - n_gram2->second / (float) arg2.totalTrigramsCount) :
					n_gram1.second / (float) arg1.totalTrigramsCount;
			}

			return deviation > 1e-5 ? 1.0f / deviation - 1.0f : std::numeric_limits<float>::max();
});

template <typename T>
std::vector<CTextEncodingDetector::EncodingDetectionResult> detect(T& dataOrInputDevice, std::vector<std::shared_ptr<CTrigramFrequencyTable_Base>> tablesForLanguages, CTextEncodingDetector::MatchFunction matchFunction)
{
	QTime start;
	start.start();
	auto availableCodecs = QTextCodec::availableCodecs();
	std::vector<CTextEncodingDetector::EncodingDetectionResult> match;

	if (tablesForLanguages.empty())
	{
		tablesForLanguages.emplace_back(std::make_shared<CTrigramFrequencyTable_English>());
		tablesForLanguages.emplace_back(std::make_shared<CTrigramFrequencyTable_Russian>());
	}

	if (!matchFunction)
		matchFunction = defaultMatchFunction;

	std::set<QTextCodec*> differentCodecs;
	for (const auto& codecName: availableCodecs)
		if (!QString(codecName).toLower().contains("utf-8"))
			differentCodecs.insert(QTextCodec::codecForName(codecName.data()));

	for (auto& codec: differentCodecs)
	{
		CTextParser parser;
		if (!parser.parse(dataOrInputDevice, QString(codec->name())))
			continue;

		for (auto& table: tablesForLanguages)
			match.emplace_back(CTextEncodingDetector::EncodingDetectionResult(codec->name(), table->language(), matchFunction(table->trigramOccurrenceTable(), parser.parsingResult())));
	}

	std::sort(match.begin(), match.end(), [](const CTextEncodingDetector::EncodingDetectionResult& l, const CTextEncodingDetector::EncodingDetectionResult& r){return l.match > r.match;});
	qDebug() << __FUNCTION__ << "Time taken:" << start.elapsed() << "ms";
	return match;
}

CTextEncodingDetector::DetectionResult CTextEncodingDetector::decode(const QString & textFilePath, std::vector<std::shared_ptr<CTrigramFrequencyTable_Base> > tablesForLanguages, CTextEncodingDetector::MatchFunction customMatchFunction)
{
	auto detectionResult = detect(textFilePath, tablesForLanguages, customMatchFunction);
	qDebug() << "Encoding detection result for" << textFilePath;
	for (auto& match: detectionResult)
		qDebug() << QString("%1, %2: %3").arg(match.language).arg(match.encoding).arg(match.match);

	if (!detectionResult.empty() && detectionResult.front().match > plausibleMatchThreshold)
	{
		QTextCodec * codec = QTextCodec::codecForName(detectionResult.front().encoding.toUtf8().data());
		assert_r(codec);
		if (codec)
		{
			QFile file(textFilePath);
			file.open(QIODevice::ReadOnly);
			return DetectionResult{codec->toUnicode(file.readAll()), detectionResult.front().encoding, detectionResult.front().language};
		}
	}

	return DetectionResult();
}

CTextEncodingDetector::DetectionResult CTextEncodingDetector::decode(const QByteArray & textData, std::vector<std::shared_ptr<CTrigramFrequencyTable_Base> > tablesForLanguages, CTextEncodingDetector::MatchFunction customMatchFunction)
{
	auto detectionResult = detect(textData, tablesForLanguages, customMatchFunction);
	qDebug() << "Encoding detection result:";
	for (auto& match: detectionResult)
		qDebug() << QString("%1, %2: %3").arg(match.language).arg(match.encoding).arg(match.match);

	if (!detectionResult.empty() && detectionResult.front().match > plausibleMatchThreshold)
	{
		QTextCodec * codec = QTextCodec::codecForName(detectionResult.front().encoding.toUtf8().data());
		assert_r(codec);
		if (codec)
			return DetectionResult{codec->toUnicode(textData), detectionResult.front().encoding, detectionResult.front().language};
	}

	return DetectionResult();
}

CTextEncodingDetector::DetectionResult CTextEncodingDetector::decode(QIODevice & textDevice, std::vector<std::shared_ptr<CTrigramFrequencyTable_Base> > tablesForLanguages, CTextEncodingDetector::MatchFunction customMatchFunction)
{
	auto detectionResult = detect(textDevice, tablesForLanguages, customMatchFunction);
	qDebug() << "Encoding detection result:";
	for (auto& match: detectionResult)
		qDebug() << QString("%1, %2: %3").arg(match.language).arg(match.encoding).arg(match.match);

	if (!detectionResult.empty() && detectionResult.front().match > plausibleMatchThreshold)
	{
		QTextCodec * codec = QTextCodec::codecForName(detectionResult.front().encoding.toUtf8().data());
		assert_r(codec);
		if (codec)
			return DetectionResult{codec->toUnicode(textDevice.readAll()), detectionResult.front().encoding, detectionResult.front().language};
	}

	return DetectionResult();
}

std::vector<CTextEncodingDetector::EncodingDetectionResult> CTextEncodingDetector::detect(const QString & textFilePath, std::vector<std::shared_ptr<CTrigramFrequencyTable_Base> > tablesForLanguages, MatchFunction customMatchFunction)
{
	return ::detect(textFilePath, tablesForLanguages, customMatchFunction);
}

std::vector<CTextEncodingDetector::EncodingDetectionResult> CTextEncodingDetector::detect(const QByteArray & textData, std::vector<std::shared_ptr<CTrigramFrequencyTable_Base> > tablesForLanguages, MatchFunction customMatchFunction)
{
	return ::detect(textData, tablesForLanguages, customMatchFunction);
}

std::vector<CTextEncodingDetector::EncodingDetectionResult> CTextEncodingDetector::detect(QIODevice & textDevice, std::vector<std::shared_ptr<CTrigramFrequencyTable_Base> > tablesForLanguages, MatchFunction customMatchFunction)
{
	return ::detect(textDevice, tablesForLanguages, customMatchFunction);
}
<commit_msg>OS X build fix<commit_after>#include "ctextencodingdetector.h"
#include "trigramfrequencytables/ctrigramfrequencytable_english.h"
#include "trigramfrequencytables/ctrigramfrequencytable_russian.h"
#include "assert/advanced_assert.h"

DISABLE_COMPILER_WARNINGS
#include <QTextCodec>
#include <QIODevice>
#include <QDebug>
#include <QFile>
#include <QTime>
RESTORE_COMPILER_WARNINGS

#include <algorithm>
#include <limits>
#include <memory>
#include <set>

#include <math.h>

const float plausibleMatchThreshold = 0.1f;

static const CTextEncodingDetector::MatchFunction defaultMatchFunction =
		CTextEncodingDetector::MatchFunction([](const CTextParser::OccurrenceTable& arg1, const CTextParser::OccurrenceTable& arg2) -> float {

			if (arg1.trigramOccurrenceTable.empty() || arg2.trigramOccurrenceTable.empty())
				return 0.0f;
			else if (arg2.trigramOccurrenceTable.size() < arg1.trigramOccurrenceTable.size())
				return defaultMatchFunction(arg2, arg1); // Performance optimization - the outer loop must iterate the smaller of the two containers for better performance

			float deviation = 0.0f;
			for (auto& n_gram1: arg1.trigramOccurrenceTable)
			{
				auto n_gram2 = arg2.trigramOccurrenceTable.find(n_gram1.first);
				deviation += n_gram2 != arg2.trigramOccurrenceTable.end() ?
					fabs(n_gram1.second / (float) arg1.totalTrigramsCount - n_gram2->second / (float) arg2.totalTrigramsCount) :
					n_gram1.second / (float) arg1.totalTrigramsCount;
			}

			return deviation > 1e-5 ? 1.0f / deviation - 1.0f : std::numeric_limits<float>::max();
});

template <typename T>
std::vector<CTextEncodingDetector::EncodingDetectionResult> detect(T& dataOrInputDevice, std::vector<std::shared_ptr<CTrigramFrequencyTable_Base>> tablesForLanguages, CTextEncodingDetector::MatchFunction matchFunction)
{
	QTime start;
	start.start();
	auto availableCodecs = QTextCodec::availableCodecs();
	std::vector<CTextEncodingDetector::EncodingDetectionResult> match;

	if (tablesForLanguages.empty())
	{
		tablesForLanguages.emplace_back(std::make_shared<CTrigramFrequencyTable_English>());
		tablesForLanguages.emplace_back(std::make_shared<CTrigramFrequencyTable_Russian>());
	}

	if (!matchFunction)
		matchFunction = defaultMatchFunction;

	std::set<QTextCodec*> differentCodecs;
	for (const auto& codecName: availableCodecs)
		if (!QString(codecName).toLower().contains("utf-8"))
			differentCodecs.insert(QTextCodec::codecForName(codecName.data()));

	for (auto& codec: differentCodecs)
	{
		CTextParser parser;
		if (!parser.parse(dataOrInputDevice, QString(codec->name())))
			continue;

		for (auto& table: tablesForLanguages)
			match.emplace_back(CTextEncodingDetector::EncodingDetectionResult(codec->name(), table->language(), matchFunction(table->trigramOccurrenceTable(), parser.parsingResult())));
	}

	std::sort(match.begin(), match.end(), [](const CTextEncodingDetector::EncodingDetectionResult& l, const CTextEncodingDetector::EncodingDetectionResult& r){return l.match > r.match;});
	qDebug() << __FUNCTION__ << "Time taken:" << start.elapsed() << "ms";
	return match;
}

CTextEncodingDetector::DetectionResult CTextEncodingDetector::decode(const QString & textFilePath, std::vector<std::shared_ptr<CTrigramFrequencyTable_Base> > tablesForLanguages, CTextEncodingDetector::MatchFunction customMatchFunction)
{
	auto detectionResult = detect(textFilePath, tablesForLanguages, customMatchFunction);
	qDebug() << "Encoding detection result for" << textFilePath;
	for (auto& match: detectionResult)
		qDebug() << QString("%1, %2: %3").arg(match.language).arg(match.encoding).arg(match.match);

	if (!detectionResult.empty() && detectionResult.front().match > plausibleMatchThreshold)
	{
		QTextCodec * codec = QTextCodec::codecForName(detectionResult.front().encoding.toUtf8().data());
		assert_r(codec);
		if (codec)
		{
			QFile file(textFilePath);
			file.open(QIODevice::ReadOnly);
			return DetectionResult{codec->toUnicode(file.readAll()), detectionResult.front().encoding, detectionResult.front().language};
		}
	}

	return DetectionResult();
}

CTextEncodingDetector::DetectionResult CTextEncodingDetector::decode(const QByteArray & textData, std::vector<std::shared_ptr<CTrigramFrequencyTable_Base> > tablesForLanguages, CTextEncodingDetector::MatchFunction customMatchFunction)
{
	auto detectionResult = detect(textData, tablesForLanguages, customMatchFunction);
	qDebug() << "Encoding detection result:";
	for (auto& match: detectionResult)
		qDebug() << QString("%1, %2: %3").arg(match.language).arg(match.encoding).arg(match.match);

	if (!detectionResult.empty() && detectionResult.front().match > plausibleMatchThreshold)
	{
		QTextCodec * codec = QTextCodec::codecForName(detectionResult.front().encoding.toUtf8().data());
		assert_r(codec);
		if (codec)
			return DetectionResult{codec->toUnicode(textData), detectionResult.front().encoding, detectionResult.front().language};
	}

	return DetectionResult();
}

CTextEncodingDetector::DetectionResult CTextEncodingDetector::decode(QIODevice & textDevice, std::vector<std::shared_ptr<CTrigramFrequencyTable_Base> > tablesForLanguages, CTextEncodingDetector::MatchFunction customMatchFunction)
{
	auto detectionResult = detect(textDevice, tablesForLanguages, customMatchFunction);
	qDebug() << "Encoding detection result:";
	for (auto& match: detectionResult)
		qDebug() << QString("%1, %2: %3").arg(match.language).arg(match.encoding).arg(match.match);

	if (!detectionResult.empty() && detectionResult.front().match > plausibleMatchThreshold)
	{
		QTextCodec * codec = QTextCodec::codecForName(detectionResult.front().encoding.toUtf8().data());
		assert_r(codec);
		if (codec)
			return DetectionResult{codec->toUnicode(textDevice.readAll()), detectionResult.front().encoding, detectionResult.front().language};
	}

	return DetectionResult();
}

std::vector<CTextEncodingDetector::EncodingDetectionResult> CTextEncodingDetector::detect(const QString & textFilePath, std::vector<std::shared_ptr<CTrigramFrequencyTable_Base> > tablesForLanguages, MatchFunction customMatchFunction)
{
	return ::detect(textFilePath, tablesForLanguages, customMatchFunction);
}

std::vector<CTextEncodingDetector::EncodingDetectionResult> CTextEncodingDetector::detect(const QByteArray & textData, std::vector<std::shared_ptr<CTrigramFrequencyTable_Base> > tablesForLanguages, MatchFunction customMatchFunction)
{
	return ::detect(textData, tablesForLanguages, customMatchFunction);
}

std::vector<CTextEncodingDetector::EncodingDetectionResult> CTextEncodingDetector::detect(QIODevice & textDevice, std::vector<std::shared_ptr<CTrigramFrequencyTable_Base> > tablesForLanguages, MatchFunction customMatchFunction)
{
	return ::detect(textDevice, tablesForLanguages, customMatchFunction);
}
<|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 "otbWrapperQtWidgetChoiceParameter.h"

#include "otbWrapperQtWidgetParameterLabel.h"
#include "otbWrapperQtWidgetParameterFactory.h"

namespace otb
{
namespace Wrapper
{

QtWidgetChoiceParameter::QtWidgetChoiceParameter(ChoiceParameter* param, QtWidgetModel* m)
: QtWidgetParameterBase(param, m),
  m_ChoiceParam(param)
{
}

QtWidgetChoiceParameter::~QtWidgetChoiceParameter()
{
}

void QtWidgetChoiceParameter::DoUpdateGUI()
{
  // Update the combobox value
  unsigned int value = m_ChoiceParam->GetValue( );
  m_ComboBox->setCurrentIndex(value);

  // Update the choice subparameters
  WidgetListIteratorType it = m_WidgetList.begin();
  for (it = m_WidgetList.begin(); it != m_WidgetList.end(); ++it)
    {
    (*it)->UpdateGUI();
    }
}

void QtWidgetChoiceParameter::DoCreateWidget()
{
  m_ComboBox = new QComboBox;
  m_ComboBox->setToolTip(m_ChoiceParam->GetDescription());

  m_StackWidget = new QStackedWidget;

  for (unsigned int i = 0; i < m_ChoiceParam->GetNbChoices(); ++i)
    {
    QString key = QString::fromStdString( m_ChoiceParam->GetChoiceName(i) );
    m_ComboBox->addItem( key, QVariant(key) );

    ParameterGroup::Pointer param = m_ChoiceParam->GetChoiceParameterGroupByIndex(i);
    if (param.IsNotNull())
      {
      QtWidgetParameterBase* widget = QtWidgetParameterFactory::CreateQtWidget( param, GetModel() );
      m_StackWidget->addWidget(widget);
      m_WidgetList.push_back(widget);
      }
    }

  connect( m_ComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(SetValue(int)) );
  connect( m_ComboBox, SIGNAL(currentIndexChanged(int)), m_StackWidget, SLOT(setCurrentIndex(int)) );
  connect( m_ComboBox, SIGNAL(currentIndexChanged(int)), GetModel(), SLOT(NotifyUpdate()) );

  m_VLayout = new QVBoxLayout;
  m_VLayout->addWidget(m_ComboBox);
  m_VLayout->addWidget(m_StackWidget);
  m_VLayout->addStretch();

  this->setLayout(m_VLayout);
}

void QtWidgetChoiceParameter::SetValue(int value)
{
  m_ChoiceParam->SetValue( value );
}

}
}
<commit_msg>ENH: update the StackWidget when something changed in the GUI<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 "otbWrapperQtWidgetChoiceParameter.h"

#include "otbWrapperQtWidgetParameterLabel.h"
#include "otbWrapperQtWidgetParameterFactory.h"

namespace otb
{
namespace Wrapper
{

QtWidgetChoiceParameter::QtWidgetChoiceParameter(ChoiceParameter* param, QtWidgetModel* m)
: QtWidgetParameterBase(param, m),
  m_ChoiceParam(param)
{
}

QtWidgetChoiceParameter::~QtWidgetChoiceParameter()
{
}

void QtWidgetChoiceParameter::DoUpdateGUI()
{
  // Update the combobox value
  unsigned int value = m_ChoiceParam->GetValue( );
  m_ComboBox->setCurrentIndex(value);

  // Update the choice subparameters
  WidgetListIteratorType it = m_WidgetList.begin();
  for (it = m_WidgetList.begin(); it != m_WidgetList.end(); ++it)
    {
    (*it)->UpdateGUI();
    }
}

void QtWidgetChoiceParameter::DoCreateWidget()
{
  m_ComboBox = new QComboBox;
  m_ComboBox->setToolTip(m_ChoiceParam->GetDescription());

  m_StackWidget = new QStackedWidget;

  for (unsigned int i = 0; i < m_ChoiceParam->GetNbChoices(); ++i)
    {
    QString key = QString::fromStdString( m_ChoiceParam->GetChoiceName(i) );
    m_ComboBox->addItem( key, QVariant(key) );

    ParameterGroup::Pointer param = m_ChoiceParam->GetChoiceParameterGroupByIndex(i);
    if (param.IsNotNull())
      {
      QtWidgetParameterBase* widget = QtWidgetParameterFactory::CreateQtWidget( param, GetModel() );
      m_StackWidget->addWidget(widget);
      m_WidgetList.push_back(widget);
      }
    }

  connect( m_ComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(SetValue(int)) );
  connect( m_ComboBox, SIGNAL(currentIndexChanged(int)), m_StackWidget, SLOT(setCurrentIndex(int)) );
  connect( m_ComboBox, SIGNAL(currentIndexChanged(int)), GetModel(), SLOT(NotifyUpdate()) );
  connect( GetModel(), SIGNAL(UpdateGui()), this, SLOT(UpdateGUI() ) );

  m_VLayout = new QVBoxLayout;
  m_VLayout->addWidget(m_ComboBox);
  m_VLayout->addWidget(m_StackWidget);
  m_VLayout->addStretch();

  this->setLayout(m_VLayout);
}

void QtWidgetChoiceParameter::SetValue(int value)
{
  m_ChoiceParam->SetValue( value );
}

}
}
<|endoftext|>


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

  Library: CppMicroServices

  Copyright (c) German Cancer Research Center,
    Division of Medical and Biological Informatics

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

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

#include <usConfig.h>

#include <iterator>
#include <stdexcept>

#ifdef US_ENABLE_SERVICE_FACTORY_SUPPORT
#include US_BASECLASS_HEADER
#endif

#include "usServiceRegistry_p.h"
#include "usServiceFactory.h"
#include "usServiceRegistry_p.h"
#include "usServiceRegistrationPrivate.h"
#include "usModulePrivate.h"
#include "usCoreModuleContext_p.h"

US_BEGIN_NAMESPACE

typedef MutexLock<ServiceRegistry::MutexType> MutexLocker;

struct ServiceRegistrationComparator
{
  bool operator()(const ServiceRegistration& a, const ServiceRegistration& b) const
  {
    return a < b;
  }
};

ServiceProperties ServiceRegistry::CreateServiceProperties(const ServiceProperties& in,
                                                           const std::list<std::string>& classes,
                                                           long sid)
{
  static long nextServiceID = 1;
  ServiceProperties props(in);

  if (!classes.empty())
  {
    props.insert(std::make_pair(ServiceConstants::OBJECTCLASS(), classes));
  }

  props.insert(std::make_pair(ServiceConstants::SERVICE_ID(), sid != -1 ? sid : nextServiceID++));

  return props;
}

ServiceRegistry::ServiceRegistry(CoreModuleContext* coreCtx)
  : core(coreCtx)
{

}

ServiceRegistry::~ServiceRegistry()
{
  Clear();
}

void ServiceRegistry::Clear()
{
  services.clear();
  serviceRegistrations.clear();
  classServices.clear();
  core = 0;
}

ServiceRegistration ServiceRegistry::RegisterService(ModulePrivate* module,
                                                     const std::list<std::string>& classes,
                                                     US_BASECLASS_NAME* service,
                                                     const ServiceProperties& properties)
{
  if (service == 0)
  {
    throw std::invalid_argument("Can't register 0 as a service");
  }

  // Check if service implements claimed classes and that they exist.
  for (std::list<std::string>::const_iterator i = classes.begin();
       i != classes.end(); ++i)
  {
    if (i->empty())
    {
      throw std::invalid_argument("Can't register as null class");
    }

    #ifdef US_ENABLE_SERVICE_FACTORY_SUPPORT
    if (!(dynamic_cast<ServiceFactory*>(service)))
    #endif
    {
      if (!CheckServiceClass(service, *i))
      {
        std::string msg;
        std::stringstream ss(msg);
        ss << "Service class " << us_service_impl_name(service) << " is not an instance of "
               << (*i) << ". Maybe you forgot to export the RTTI information for the interface.";
        throw std::invalid_argument(msg);
      }
    }
  }

  ServiceRegistration res(module, service,
                          CreateServiceProperties(properties, classes));
  {
    MutexLocker lock(mutex);
    services.insert(std::make_pair(res, classes));
    serviceRegistrations.push_back(res);
    for (std::list<std::string>::const_iterator i = classes.begin();
         i != classes.end(); ++i)
    {
      std::list<ServiceRegistration>& s = classServices[*i];
      std::list<ServiceRegistration>::iterator ip =
          std::lower_bound(s.begin(), s.end(), res, ServiceRegistrationComparator());
      s.insert(ip, res);
    }
  }

  ServiceReference r = res.GetReference();
  ServiceListeners::ServiceListenerEntries listeners;
  module->coreCtx->listeners.GetMatchingServiceListeners(r, listeners);
  module->coreCtx->listeners.ServiceChanged(listeners,
                                            ServiceEvent(ServiceEvent::REGISTERED, r));
  return res;
}

void ServiceRegistry::UpdateServiceRegistrationOrder(const ServiceRegistration& sr,
                                                     const std::list<std::string>& classes)
{
  MutexLocker lock(mutex);
  for (std::list<std::string>::const_iterator i = classes.begin();
       i != classes.end(); ++i)
  {
    std::list<ServiceRegistration>& s = classServices[*i];
    std::remove(s.begin(), s.end(), sr);
    s.insert(std::lower_bound(s.begin(), s.end(), sr, ServiceRegistrationComparator()), sr);
  }
}

bool ServiceRegistry::CheckServiceClass(US_BASECLASS_NAME* , const std::string& ) const
{
  //return service->inherits(cls.toAscii());
  // No possibility to check inheritance based on string literals.
  return true;
}

void ServiceRegistry::Get(const std::string& clazz,
                          std::list<ServiceRegistration>& serviceRegs) const
{
  MutexLocker lock(mutex);
  MapClassServices::const_iterator i = classServices.find(clazz);
  if (i != classServices.end())
  {
    serviceRegs = i->second;
  }
}

ServiceReference ServiceRegistry::Get(ModulePrivate* module, const std::string& clazz) const
{
  MutexLocker lock(mutex);
  try
  {
    std::list<ServiceReference> srs;
    Get_unlocked(clazz, "", module, srs);
    US_DEBUG << "get service ref " << clazz << " for module "
             << module->info.name << " = " << srs.size() << " refs";

    if (!srs.empty())
    {
      return srs.front();
    }
  }
  catch (const std::invalid_argument& )
  { }

  return ServiceReference();
}

void ServiceRegistry::Get(const std::string& clazz, const std::string& filter,
                          ModulePrivate* module, std::list<ServiceReference>& res) const
{
  MutexLocker lock(mutex);
  Get_unlocked(clazz, filter, module, res);
}

void ServiceRegistry::Get_unlocked(const std::string& clazz, const std::string& filter,
                          ModulePrivate* /*module*/, std::list<ServiceReference>& res) const
{
  std::list<ServiceRegistration>::const_iterator s;
  std::list<ServiceRegistration>::const_iterator send;
  std::list<ServiceRegistration> v;
  LDAPExpr ldap;
  if (clazz.empty())
  {
    if (!filter.empty())
    {
      ldap = LDAPExpr(filter);
      LDAPExpr::ObjectClassSet matched;
      if (ldap.GetMatchedObjectClasses(matched))
      {
        v.clear();
        for(LDAPExpr::ObjectClassSet::const_iterator className = matched.begin();
            className != matched.end(); ++className)
        {
          MapClassServices::const_iterator i = classServices.find(*className);
          if (i != classServices.end())
          {
            std::copy(i->second.begin(), i->second.end(), std::back_inserter(v));
          }
        }
        if (!v.empty())
        {
          s = v.begin();
          send = v.end();
        }
        else
        {
          return;
        }
      }
      else
      {
        s = serviceRegistrations.begin();
        send = serviceRegistrations.end();
      }
    }
    else
    {
      s = serviceRegistrations.begin();
      send = serviceRegistrations.end();
    }
  }
  else
  {
    MapClassServices::const_iterator it = classServices.find(clazz);
    if (it != classServices.end())
    {
      s = it->second.begin();
      send = it->second.end();
    }
    else
    {
      return;
    }
    if (!filter.empty())
    {
      ldap = LDAPExpr(filter);
    }
  }

  for (; s != send; ++s)
  {
    ServiceReference sri = s->GetReference();

    if (filter.empty() || ldap.Evaluate(s->d->properties, false))
    {
      res.push_back(sri);
    }
  }
}

void ServiceRegistry::RemoveServiceRegistration(const ServiceRegistration& sr)
{
  MutexLocker lock(mutex);

  const std::list<std::string>& classes = ref_any_cast<std::list<std::string> >(
        sr.d->properties[ServiceConstants::OBJECTCLASS()]);
  services.erase(sr);
  serviceRegistrations.remove(sr);
  for (std::list<std::string>::const_iterator i = classes.begin();
       i != classes.end(); ++i)
  {
    std::list<ServiceRegistration>& s = classServices[*i];
    if (s.size() > 1)
    {
      s.erase(std::remove(s.begin(), s.end(), sr), s.end());
    }
    else
    {
      classServices.erase(*i);
    }
  }
}

void ServiceRegistry::GetRegisteredByModule(ModulePrivate* p,
                                            std::list<ServiceRegistration>& res) const
{
  MutexLocker lock(mutex);

  for (std::list<ServiceRegistration>::const_iterator i = serviceRegistrations.begin();
       i != serviceRegistrations.end(); ++i)
  {
    if (i->d->module == p)
    {
      res.push_back(*i);
    }
  }
}

void ServiceRegistry::GetUsedByModule(Module* p,
                                      std::list<ServiceRegistration>& res) const
{
  MutexLocker lock(mutex);

  for (std::list<ServiceRegistration>::const_iterator i = serviceRegistrations.begin();
       i != serviceRegistrations.end(); ++i)
  {
    if (i->d->IsUsedByModule(p))
    {
      res.push_back(*i);
    }
  }
}

US_END_NAMESPACE

<commit_msg>Default comparison operator is already operator<.<commit_after>/*=============================================================================

  Library: CppMicroServices

  Copyright (c) German Cancer Research Center,
    Division of Medical and Biological Informatics

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

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

#include <usConfig.h>

#include <iterator>
#include <stdexcept>

#ifdef US_ENABLE_SERVICE_FACTORY_SUPPORT
#include US_BASECLASS_HEADER
#endif

#include "usServiceRegistry_p.h"
#include "usServiceFactory.h"
#include "usServiceRegistry_p.h"
#include "usServiceRegistrationPrivate.h"
#include "usModulePrivate.h"
#include "usCoreModuleContext_p.h"

US_BEGIN_NAMESPACE

typedef MutexLock<ServiceRegistry::MutexType> MutexLocker;

ServiceProperties ServiceRegistry::CreateServiceProperties(const ServiceProperties& in,
                                                           const std::list<std::string>& classes,
                                                           long sid)
{
  static long nextServiceID = 1;
  ServiceProperties props(in);

  if (!classes.empty())
  {
    props.insert(std::make_pair(ServiceConstants::OBJECTCLASS(), classes));
  }

  props.insert(std::make_pair(ServiceConstants::SERVICE_ID(), sid != -1 ? sid : nextServiceID++));

  return props;
}

ServiceRegistry::ServiceRegistry(CoreModuleContext* coreCtx)
  : core(coreCtx)
{

}

ServiceRegistry::~ServiceRegistry()
{
  Clear();
}

void ServiceRegistry::Clear()
{
  services.clear();
  serviceRegistrations.clear();
  classServices.clear();
  core = 0;
}

ServiceRegistration ServiceRegistry::RegisterService(ModulePrivate* module,
                                                     const std::list<std::string>& classes,
                                                     US_BASECLASS_NAME* service,
                                                     const ServiceProperties& properties)
{
  if (service == 0)
  {
    throw std::invalid_argument("Can't register 0 as a service");
  }

  // Check if service implements claimed classes and that they exist.
  for (std::list<std::string>::const_iterator i = classes.begin();
       i != classes.end(); ++i)
  {
    if (i->empty())
    {
      throw std::invalid_argument("Can't register as null class");
    }

    #ifdef US_ENABLE_SERVICE_FACTORY_SUPPORT
    if (!(dynamic_cast<ServiceFactory*>(service)))
    #endif
    {
      if (!CheckServiceClass(service, *i))
      {
        std::string msg;
        std::stringstream ss(msg);
        ss << "Service class " << us_service_impl_name(service) << " is not an instance of "
               << (*i) << ". Maybe you forgot to export the RTTI information for the interface.";
        throw std::invalid_argument(msg);
      }
    }
  }

  ServiceRegistration res(module, service,
                          CreateServiceProperties(properties, classes));
  {
    MutexLocker lock(mutex);
    services.insert(std::make_pair(res, classes));
    serviceRegistrations.push_back(res);
    for (std::list<std::string>::const_iterator i = classes.begin();
         i != classes.end(); ++i)
    {
      std::list<ServiceRegistration>& s = classServices[*i];
      std::list<ServiceRegistration>::iterator ip =
          std::lower_bound(s.begin(), s.end(), res);
      s.insert(ip, res);
    }
  }

  ServiceReference r = res.GetReference();
  ServiceListeners::ServiceListenerEntries listeners;
  module->coreCtx->listeners.GetMatchingServiceListeners(r, listeners);
  module->coreCtx->listeners.ServiceChanged(listeners,
                                            ServiceEvent(ServiceEvent::REGISTERED, r));
  return res;
}

void ServiceRegistry::UpdateServiceRegistrationOrder(const ServiceRegistration& sr,
                                                     const std::list<std::string>& classes)
{
  MutexLocker lock(mutex);
  for (std::list<std::string>::const_iterator i = classes.begin();
       i != classes.end(); ++i)
  {
    std::list<ServiceRegistration>& s = classServices[*i];
    s.erase(std::remove(s.begin(), s.end(), sr), s.end());
    s.insert(std::lower_bound(s.begin(), s.end(), sr), sr);
  }
}

bool ServiceRegistry::CheckServiceClass(US_BASECLASS_NAME* , const std::string& ) const
{
  //return service->inherits(cls.toAscii());
  // No possibility to check inheritance based on string literals.
  return true;
}

void ServiceRegistry::Get(const std::string& clazz,
                          std::list<ServiceRegistration>& serviceRegs) const
{
  MutexLocker lock(mutex);
  MapClassServices::const_iterator i = classServices.find(clazz);
  if (i != classServices.end())
  {
    serviceRegs = i->second;
  }
}

ServiceReference ServiceRegistry::Get(ModulePrivate* module, const std::string& clazz) const
{
  MutexLocker lock(mutex);
  try
  {
    std::list<ServiceReference> srs;
    Get_unlocked(clazz, "", module, srs);
    US_DEBUG << "get service ref " << clazz << " for module "
             << module->info.name << " = " << srs.size() << " refs";

    if (!srs.empty())
    {
      return srs.front();
    }
  }
  catch (const std::invalid_argument& )
  { }

  return ServiceReference();
}

void ServiceRegistry::Get(const std::string& clazz, const std::string& filter,
                          ModulePrivate* module, std::list<ServiceReference>& res) const
{
  MutexLocker lock(mutex);
  Get_unlocked(clazz, filter, module, res);
}

void ServiceRegistry::Get_unlocked(const std::string& clazz, const std::string& filter,
                          ModulePrivate* /*module*/, std::list<ServiceReference>& res) const
{
  std::list<ServiceRegistration>::const_iterator s;
  std::list<ServiceRegistration>::const_iterator send;
  std::list<ServiceRegistration> v;
  LDAPExpr ldap;
  if (clazz.empty())
  {
    if (!filter.empty())
    {
      ldap = LDAPExpr(filter);
      LDAPExpr::ObjectClassSet matched;
      if (ldap.GetMatchedObjectClasses(matched))
      {
        v.clear();
        for(LDAPExpr::ObjectClassSet::const_iterator className = matched.begin();
            className != matched.end(); ++className)
        {
          MapClassServices::const_iterator i = classServices.find(*className);
          if (i != classServices.end())
          {
            std::copy(i->second.begin(), i->second.end(), std::back_inserter(v));
          }
        }
        if (!v.empty())
        {
          s = v.begin();
          send = v.end();
        }
        else
        {
          return;
        }
      }
      else
      {
        s = serviceRegistrations.begin();
        send = serviceRegistrations.end();
      }
    }
    else
    {
      s = serviceRegistrations.begin();
      send = serviceRegistrations.end();
    }
  }
  else
  {
    MapClassServices::const_iterator it = classServices.find(clazz);
    if (it != classServices.end())
    {
      s = it->second.begin();
      send = it->second.end();
    }
    else
    {
      return;
    }
    if (!filter.empty())
    {
      ldap = LDAPExpr(filter);
    }
  }

  for (; s != send; ++s)
  {
    ServiceReference sri = s->GetReference();

    if (filter.empty() || ldap.Evaluate(s->d->properties, false))
    {
      res.push_back(sri);
    }
  }
}

void ServiceRegistry::RemoveServiceRegistration(const ServiceRegistration& sr)
{
  MutexLocker lock(mutex);

  const std::list<std::string>& classes = ref_any_cast<std::list<std::string> >(
        sr.d->properties[ServiceConstants::OBJECTCLASS()]);
  services.erase(sr);
  serviceRegistrations.remove(sr);
  for (std::list<std::string>::const_iterator i = classes.begin();
       i != classes.end(); ++i)
  {
    std::list<ServiceRegistration>& s = classServices[*i];
    if (s.size() > 1)
    {
      s.erase(std::remove(s.begin(), s.end(), sr), s.end());
    }
    else
    {
      classServices.erase(*i);
    }
  }
}

void ServiceRegistry::GetRegisteredByModule(ModulePrivate* p,
                                            std::list<ServiceRegistration>& res) const
{
  MutexLocker lock(mutex);

  for (std::list<ServiceRegistration>::const_iterator i = serviceRegistrations.begin();
       i != serviceRegistrations.end(); ++i)
  {
    if (i->d->module == p)
    {
      res.push_back(*i);
    }
  }
}

void ServiceRegistry::GetUsedByModule(Module* p,
                                      std::list<ServiceRegistration>& res) const
{
  MutexLocker lock(mutex);

  for (std::list<ServiceRegistration>::const_iterator i = serviceRegistrations.begin();
       i != serviceRegistrations.end(); ++i)
  {
    if (i->d->IsUsedByModule(p))
    {
      res.push_back(*i);
    }
  }
}

US_END_NAMESPACE

<|endoftext|>


<commit_before>#include "code/ylikuutio/ontology/symbiosis.hpp"
#include "code/ylikuutio/ontology/symbiont_species.hpp"
#include "code/ylikuutio/ontology/symbiosis_struct.hpp"
#include "code/ylikuutio/command_line/command_line_master.hpp"
#include "code/ylikuutio/string/ylikuutio_string.hpp"

#include "assimp/scene.h"
#include "assimp/Exporter.hpp"
#include "assimp/types.h"

#define SDL_main main

#include "SDL.h"

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp> // glm
#endif

// Include standard headers
#include <algorithm>     // std::transform
#include <cstddef>       // std::size_t
#include <cstdlib>       // EXIT_FAILURE, EXIT_SUCCESS
#include <iostream>      // std::cout, std::cin, std::cerr
#include <limits>        // std::numeric_limits
#include <string>        // std::string
#include <vector>        // std::vector

// `yli_convert` is a command-line tool to load and export 3D data between different formats.
//
// parameters:
// required:
// `--in=foo`  load 3D data from file `foo`.
// `--in foo`  load 3D data from file `foo`.
// `--out=bar` export 3D data into file `bar`.
// `--out bar` export 3D data into file `bar`.
//
// optional:
// `--informat=baz` assume file format `baz` (if `--informat` is left out, file format is deduced from the filename extension).
// `--informat baz` assume file format `baz` (if `--informat` is left out, file format is deduced from the filename extension).
// `--outformat=qux` export 3D data into file `qux` (if `--outformat` is left out, file format is deduced from the filename extension).
// `--outformat qux` export 3D data into file `qux` (if `--outformat` is left out, file format is deduced from the filename extension).
// `--intexture=quux` use texture data into file `quux` as the material for all meshes (eg. `.obj` input file).
// `--intexture quux` use texture data into file `quux` as the material for all meshes (eg. `.obj` input file).

namespace yli
{
    namespace ontology
    {
        class Universe;
    }
}

int main(const int argc, const char* argv[])
{
    yli::command_line::CommandLineMaster command_line_master(argc, argv);
    command_line_master.print_keys_and_values();

    if (!command_line_master.is_key("in"))
    {
        std::cerr << "ERROR: --in parameter is required!\n\nexample:\n\nyli_convert --in=foo --out=bar\n";
        exit(EXIT_FAILURE);
    }

    if (!command_line_master.is_key("out"))
    {
        std::cerr << "ERROR: --out parameter is required!\n\nexample:\n\nyli_convert --in=foo --out=bar\n";
        exit(EXIT_FAILURE);
    }

    const std::string in_file = command_line_master.get_value("in");
    const std::string out_file = command_line_master.get_value("out");

    std::string in_file_format = ""; // dummy value.

    if (command_line_master.is_key("informat"))
    {
        in_file_format = command_line_master.get_value("informat");
    }
    else
    {
        const char separator = '.';
        yli::string::extract_last_part_of_string(in_file, in_file_format, separator);
    }

    if (in_file_format.empty())
    {
        std::cerr << "ERROR: --informat is empty!\n";
        exit(EXIT_FAILURE);
    }

    std::cout << "in file format is " << in_file_format << "\n";

    std::string out_file_format = ""; // dummy value.

    if (command_line_master.is_key("outformat"))
    {
        out_file_format = command_line_master.get_value("outformat");
    }
    else
    {
        const char separator = '.';
        yli::string::extract_last_part_of_string(out_file, out_file_format, separator);
    }

    if (out_file_format.empty())
    {
        std::cerr << "ERROR: --outformat is empty!\n";
        exit(EXIT_FAILURE);
    }

    std::cout << "out file format is " << out_file_format << "\n";

    // OK, all required input is given in the correct format.

    // convert in file format & out file format into lowercase.
    std::transform(in_file_format.begin(), in_file_format.end(), in_file_format.begin(), ::tolower);
    std::transform(out_file_format.begin(), out_file_format.end(), out_file_format.begin(), ::tolower);

    if (in_file_format != "obj" && in_file_format != "fbx")
    {
        std::cerr << "ERROR: unsupported in file format: " << in_file_format << "\n";
        exit(EXIT_FAILURE);
    }

    // Always load the 3D object into a `yli::ontology::Symbiosis`.
    SymbiosisStruct symbiosis_struct;
    symbiosis_struct.model_filename = in_file;
    symbiosis_struct.model_file_format = in_file_format;
    symbiosis_struct.triangulation_type = "bilinear_interpolation";
    symbiosis_struct.parent = nullptr;           // no parent.
    symbiosis_struct.vram_buffer_in_use = false; // do not use VRAM buffer.
    yli::ontology::Universe* const universe = nullptr;
    yli::ontology::Symbiosis const symbiosis = yli::ontology::Symbiosis(universe, symbiosis_struct);

    // Assimp usage example:
    // https://github.com/assimp/assimp/issues/203

    aiScene ai_scene;
    ai_scene.mRootNode = new aiNode();
    ai_scene.mNumMaterials = symbiosis.get_number_of_symbiont_materials();
    ai_scene.mMaterials = new aiMaterial*[ai_scene.mNumMaterials];
    ai_scene.mNumMeshes = symbiosis.get_number_of_symbiont_species();
    ai_scene.mMeshes = new aiMesh*[ai_scene.mNumMeshes];
    ai_scene.mRootNode->mNumMeshes = symbiosis.get_number_of_symbiont_species();
    ai_scene.mRootNode->mMeshes = new unsigned int[symbiosis.get_number_of_symbiont_species()];

    std::cout << "Number of `SymbiontMaterial`s: " << symbiosis.get_number_of_symbiont_materials() << "\n";

    for (std::size_t symbiont_material_i = 0; symbiont_material_i < symbiosis.get_number_of_symbiont_materials(); symbiont_material_i++)
    {
        std::cout << "Processing `SymbiontMaterial` " << symbiont_material_i << "\n";
        yli::ontology::SymbiontMaterial* symbiont_material = symbiosis.get_symbiont_material(symbiont_material_i);

        ai_scene.mMaterials[symbiont_material_i] = new aiMaterial();

        if (symbiont_material == nullptr)
        {
            std::cerr << "ERROR: `yli_convert`: `symbiont_material` is `nullptr`!\n";
            continue;
        }

        if (symbiont_material->get_childID() == std::numeric_limits<std::size_t>::max())
        {
            // childID is the default (invalid) value, not a real childID!
            std::cerr << "ERROR: `yli_convert`: `childID` is `std::numeric_limits<std::size_t>::max()`!\n";
            continue;
        }
    }

    for (std::size_t symbiont_species_i = 0; symbiont_species_i < symbiosis.get_number_of_symbiont_species(); symbiont_species_i++)
    {
        ai_scene.mRootNode->mMeshes[symbiont_species_i] = symbiont_species_i;
        ai_scene.mMeshes[symbiont_species_i] = new aiMesh();

        const yli::ontology::SymbiontSpecies* const symbiont_species = symbiosis.get_symbiont_species(symbiont_species_i);

        if (symbiont_species == nullptr)
        {
            std::cerr << "ERROR: `yli_convert`: `symbiont_species` is `nullptr`!\n";
            continue;
        }

        const yli::ontology::SymbiontMaterial* const symbiont_material = static_cast<yli::ontology::SymbiontMaterial*>(symbiont_species->get_parent());

        if (symbiont_material == nullptr)
        {
            continue;
        }

        ai_scene.mMeshes[symbiont_species_i]->mMaterialIndex = symbiont_material->get_childID();

        std::vector<glm::vec3> vertices = symbiont_species->get_vertices();
        std::vector<glm::vec3> normals = symbiont_species->get_normals();
        std::vector<glm::vec2> uvs = symbiont_species->get_uvs();

        const std::size_t number_of_vertices = vertices.size();

        ai_scene.mMeshes[symbiont_species_i]->mNumVertices = number_of_vertices;
        ai_scene.mMeshes[symbiont_species_i]->mVertices = new aiVector3D[number_of_vertices];
        ai_scene.mMeshes[symbiont_species_i]->mNormals = new aiVector3D[number_of_vertices];
        ai_scene.mMeshes[symbiont_species_i]->mTextureCoords[0] = new aiVector3D[number_of_vertices];
        ai_scene.mMeshes[symbiont_species_i]->mNumUVComponents[0] = number_of_vertices;

        for (std::size_t vertex_i = 0; vertex_i < number_of_vertices; vertex_i++)
        {
            ai_scene.mMeshes[symbiont_species_i]->mVertices[vertex_i] = aiVector3D(vertices[vertex_i].x, vertices[vertex_i].y, vertices[vertex_i].z);
            ai_scene.mMeshes[symbiont_species_i]->mNormals[vertex_i] = aiVector3D(normals[vertex_i].x, normals[vertex_i].y, normals[vertex_i].z);
            ai_scene.mMeshes[symbiont_species_i]->mTextureCoords[0][vertex_i] = aiVector3D(uvs[vertex_i].x, uvs[vertex_i].y, 0);
        }

        const std::size_t number_of_faces = number_of_vertices / 3;
        std::cout << "Number of faces: " << number_of_faces << "\n";

        ai_scene.mMeshes[symbiont_species_i]->mFaces = new aiFace[number_of_faces];
        ai_scene.mMeshes[symbiont_species_i]->mNumFaces = number_of_faces;

        for (std::size_t face_i = 0; face_i < number_of_faces; face_i++)
        {
            ai_scene.mMeshes[symbiont_species_i]->mFaces[face_i].mIndices = new unsigned int[3];
            ai_scene.mMeshes[symbiont_species_i]->mFaces[face_i].mNumIndices = 3;
            ai_scene.mMeshes[symbiont_species_i]->mFaces[face_i].mIndices[0] = 3 * face_i;
            ai_scene.mMeshes[symbiont_species_i]->mFaces[face_i].mIndices[1] = 3 * face_i + 1;
            ai_scene.mMeshes[symbiont_species_i]->mFaces[face_i].mIndices[2] = 3 * face_i + 2;
        }
    }

    std::cout << "Creating Assimp::Exporter ...\n";
    Assimp::Exporter assimp_exporter = Assimp::Exporter();
    std::cout << "Exporting to " << out_file << " ...\n";
    const aiReturn export_ai_return = assimp_exporter.Export(&ai_scene, out_file_format, out_file);

    if (export_ai_return == aiReturn_SUCCESS)
    {
        std::cout << "Export to " << out_file << " successful.\n";
    }
    else if (export_ai_return == aiReturn_FAILURE)
    {
        std::cerr << "ERROR: Export to " << out_file << " failed.\n";
    }
    else if (export_ai_return == aiReturn_OUTOFMEMORY)
    {
        std::cerr << "ERROR: Export to " << out_file << " failed: out of memory.\n";
    }
    else if (export_ai_return == _AI_ENFORCE_ENUM_SIZE)
    {
        std::cerr << "ERROR: Export to " << out_file << " failed: _AI_ENFORCE_ENUM_SIZE.\n";
    }
    else
    {
        std::cerr << "ERROR: Export to " << out_file << " failed: unknown error.\n";
    }
}
<commit_msg>`yli_convert`: cleaning up code.<commit_after>#include "code/ylikuutio/ontology/symbiosis.hpp"
#include "code/ylikuutio/ontology/symbiont_species.hpp"
#include "code/ylikuutio/ontology/symbiosis_struct.hpp"
#include "code/ylikuutio/command_line/command_line_master.hpp"
#include "code/ylikuutio/string/ylikuutio_string.hpp"

#include "assimp/scene.h"
#include "assimp/Exporter.hpp"
#include "assimp/types.h"

#define SDL_main main

#include "SDL.h"

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp> // glm
#endif

// Include standard headers
#include <algorithm>     // std::transform
#include <cstddef>       // std::size_t
#include <cstdlib>       // EXIT_FAILURE, EXIT_SUCCESS
#include <iostream>      // std::cout, std::cin, std::cerr
#include <limits>        // std::numeric_limits
#include <string>        // std::string
#include <vector>        // std::vector

// `yli_convert` is a command-line tool to load and export 3D data between different formats.
//
// parameters:
// required:
// `--in=foo`  load 3D data from file `foo`.
// `--in foo`  load 3D data from file `foo`.
// `--out=bar` export 3D data into file `bar`.
// `--out bar` export 3D data into file `bar`.
//
// optional:
// `--informat=baz` assume file format `baz` (if `--informat` is left out, file format is deduced from the filename extension).
// `--informat baz` assume file format `baz` (if `--informat` is left out, file format is deduced from the filename extension).
// `--outformat=qux` export 3D data into file `qux` (if `--outformat` is left out, file format is deduced from the filename extension).
// `--outformat qux` export 3D data into file `qux` (if `--outformat` is left out, file format is deduced from the filename extension).
// `--intexture=quux` use texture data into file `quux` as the material for all meshes (eg. `.obj` input file).
// `--intexture quux` use texture data into file `quux` as the material for all meshes (eg. `.obj` input file).

namespace yli
{
    namespace ontology
    {
        class Universe;
    }
}

int main(const int argc, const char* argv[])
{
    yli::command_line::CommandLineMaster command_line_master(argc, argv);
    command_line_master.print_keys_and_values();

    if (!command_line_master.is_key("in"))
    {
        std::cerr << "ERROR: --in parameter is required!\n\nexample:\n\nyli_convert --in=foo --out=bar\n";
        exit(EXIT_FAILURE);
    }

    if (!command_line_master.is_key("out"))
    {
        std::cerr << "ERROR: --out parameter is required!\n\nexample:\n\nyli_convert --in=foo --out=bar\n";
        exit(EXIT_FAILURE);
    }

    const std::string in_file = command_line_master.get_value("in");
    const std::string out_file = command_line_master.get_value("out");

    std::string in_file_format = ""; // dummy value.

    if (command_line_master.is_key("informat"))
    {
        in_file_format = command_line_master.get_value("informat");
    }
    else
    {
        const char separator = '.';
        yli::string::extract_last_part_of_string(in_file, in_file_format, separator);
    }

    if (in_file_format.empty())
    {
        std::cerr << "ERROR: --informat is empty!\n";
        exit(EXIT_FAILURE);
    }

    std::cout << "in file format is " << in_file_format << "\n";

    std::string out_file_format = ""; // dummy value.

    if (command_line_master.is_key("outformat"))
    {
        out_file_format = command_line_master.get_value("outformat");
    }
    else
    {
        const char separator = '.';
        yli::string::extract_last_part_of_string(out_file, out_file_format, separator);
    }

    if (out_file_format.empty())
    {
        std::cerr << "ERROR: --outformat is empty!\n";
        exit(EXIT_FAILURE);
    }

    std::cout << "out file format is " << out_file_format << "\n";

    // OK, all required input is given in the correct format.

    // convert in file format & out file format into lowercase.
    std::transform(in_file_format.begin(), in_file_format.end(), in_file_format.begin(), ::tolower);
    std::transform(out_file_format.begin(), out_file_format.end(), out_file_format.begin(), ::tolower);

    if (in_file_format != "obj" && in_file_format != "fbx")
    {
        std::cerr << "ERROR: unsupported in file format: " << in_file_format << "\n";
        exit(EXIT_FAILURE);
    }

    // Always load the 3D object into a `yli::ontology::Symbiosis`.
    SymbiosisStruct symbiosis_struct;
    symbiosis_struct.model_filename = in_file;
    symbiosis_struct.model_file_format = in_file_format;
    symbiosis_struct.triangulation_type = "bilinear_interpolation";
    symbiosis_struct.parent = nullptr;           // no parent.
    symbiosis_struct.vram_buffer_in_use = false; // do not use VRAM buffer.
    yli::ontology::Universe* const universe = nullptr;
    const yli::ontology::Symbiosis symbiosis = yli::ontology::Symbiosis(universe, symbiosis_struct);

    // Assimp usage example:
    // https://github.com/assimp/assimp/issues/203

    aiScene ai_scene;
    ai_scene.mRootNode = new aiNode();
    ai_scene.mNumMaterials = symbiosis.get_number_of_symbiont_materials();
    ai_scene.mMaterials = new aiMaterial*[ai_scene.mNumMaterials];
    ai_scene.mNumMeshes = symbiosis.get_number_of_symbiont_species();
    ai_scene.mMeshes = new aiMesh*[ai_scene.mNumMeshes];
    ai_scene.mRootNode->mNumMeshes = symbiosis.get_number_of_symbiont_species();
    ai_scene.mRootNode->mMeshes = new unsigned int[symbiosis.get_number_of_symbiont_species()];

    std::cout << "Number of `SymbiontMaterial`s: " << symbiosis.get_number_of_symbiont_materials() << "\n";

    for (std::size_t symbiont_material_i = 0; symbiont_material_i < symbiosis.get_number_of_symbiont_materials(); symbiont_material_i++)
    {
        std::cout << "Processing `SymbiontMaterial` " << symbiont_material_i << "\n";
        yli::ontology::SymbiontMaterial* symbiont_material = symbiosis.get_symbiont_material(symbiont_material_i);

        ai_scene.mMaterials[symbiont_material_i] = new aiMaterial();

        if (symbiont_material == nullptr)
        {
            std::cerr << "ERROR: `yli_convert`: `symbiont_material` is `nullptr`!\n";
            continue;
        }

        if (symbiont_material->get_childID() == std::numeric_limits<std::size_t>::max())
        {
            // childID is the default (invalid) value, not a real childID!
            std::cerr << "ERROR: `yli_convert`: `childID` is `std::numeric_limits<std::size_t>::max()`!\n";
            continue;
        }
    }

    for (std::size_t symbiont_species_i = 0; symbiont_species_i < symbiosis.get_number_of_symbiont_species(); symbiont_species_i++)
    {
        ai_scene.mRootNode->mMeshes[symbiont_species_i] = symbiont_species_i;
        ai_scene.mMeshes[symbiont_species_i] = new aiMesh();

        const yli::ontology::SymbiontSpecies* const symbiont_species = symbiosis.get_symbiont_species(symbiont_species_i);

        if (symbiont_species == nullptr)
        {
            std::cerr << "ERROR: `yli_convert`: `symbiont_species` is `nullptr`!\n";
            continue;
        }

        const yli::ontology::SymbiontMaterial* const symbiont_material = static_cast<yli::ontology::SymbiontMaterial*>(symbiont_species->get_parent());

        if (symbiont_material == nullptr)
        {
            continue;
        }

        ai_scene.mMeshes[symbiont_species_i]->mMaterialIndex = symbiont_material->get_childID();

        std::vector<glm::vec3> vertices = symbiont_species->get_vertices();
        std::vector<glm::vec3> normals = symbiont_species->get_normals();
        std::vector<glm::vec2> uvs = symbiont_species->get_uvs();

        const std::size_t number_of_vertices = vertices.size();

        ai_scene.mMeshes[symbiont_species_i]->mNumVertices = number_of_vertices;
        ai_scene.mMeshes[symbiont_species_i]->mVertices = new aiVector3D[number_of_vertices];
        ai_scene.mMeshes[symbiont_species_i]->mNormals = new aiVector3D[number_of_vertices];
        ai_scene.mMeshes[symbiont_species_i]->mTextureCoords[0] = new aiVector3D[number_of_vertices];
        ai_scene.mMeshes[symbiont_species_i]->mNumUVComponents[0] = number_of_vertices;

        for (std::size_t vertex_i = 0; vertex_i < number_of_vertices; vertex_i++)
        {
            ai_scene.mMeshes[symbiont_species_i]->mVertices[vertex_i] = aiVector3D(vertices[vertex_i].x, vertices[vertex_i].y, vertices[vertex_i].z);
            ai_scene.mMeshes[symbiont_species_i]->mNormals[vertex_i] = aiVector3D(normals[vertex_i].x, normals[vertex_i].y, normals[vertex_i].z);
            ai_scene.mMeshes[symbiont_species_i]->mTextureCoords[0][vertex_i] = aiVector3D(uvs[vertex_i].x, uvs[vertex_i].y, 0);
        }

        const std::size_t number_of_faces = number_of_vertices / 3;
        std::cout << "Number of faces: " << number_of_faces << "\n";

        ai_scene.mMeshes[symbiont_species_i]->mFaces = new aiFace[number_of_faces];
        ai_scene.mMeshes[symbiont_species_i]->mNumFaces = number_of_faces;

        for (std::size_t face_i = 0; face_i < number_of_faces; face_i++)
        {
            ai_scene.mMeshes[symbiont_species_i]->mFaces[face_i].mIndices = new unsigned int[3];
            ai_scene.mMeshes[symbiont_species_i]->mFaces[face_i].mNumIndices = 3;
            ai_scene.mMeshes[symbiont_species_i]->mFaces[face_i].mIndices[0] = 3 * face_i;
            ai_scene.mMeshes[symbiont_species_i]->mFaces[face_i].mIndices[1] = 3 * face_i + 1;
            ai_scene.mMeshes[symbiont_species_i]->mFaces[face_i].mIndices[2] = 3 * face_i + 2;
        }
    }

    std::cout << "Creating Assimp::Exporter ...\n";
    Assimp::Exporter assimp_exporter = Assimp::Exporter();
    std::cout << "Exporting to " << out_file << " ...\n";
    const aiReturn export_ai_return = assimp_exporter.Export(&ai_scene, out_file_format, out_file);

    if (export_ai_return == aiReturn_SUCCESS)
    {
        std::cout << "Export to " << out_file << " successful.\n";
    }
    else if (export_ai_return == aiReturn_FAILURE)
    {
        std::cerr << "ERROR: Export to " << out_file << " failed.\n";
    }
    else if (export_ai_return == aiReturn_OUTOFMEMORY)
    {
        std::cerr << "ERROR: Export to " << out_file << " failed: out of memory.\n";
    }
    else if (export_ai_return == _AI_ENFORCE_ENUM_SIZE)
    {
        std::cerr << "ERROR: Export to " << out_file << " failed: _AI_ENFORCE_ENUM_SIZE.\n";
    }
    else
    {
        std::cerr << "ERROR: Export to " << out_file << " failed: unknown error.\n";
    }
}
<|endoftext|>