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

  Program:   Insight Segmentation & Registration Toolkit
  Module:    CannySegmentationLevelSetImageFilter.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

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

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

// Software Guide : BeginLatex
//
// \index{itk::Canny\-Segmentation\-LevelSet\-Image\-Filter}
//
// The \doxygen{CannySegmentationLevelSetImageFilter} defines a speed term
// that minimizes distance to the Canny edges in an image.  The initial
// level set model moves through a gradient advection field until it locks
// onto those edges.  This filter is more suitable for refining existing
// segmentations than as a region-growing algorithm.
//
// The two terms defined for the CannySegmentationLevelSetImageFilter
// are the advection term and the propagation term from
// Equation~\ref{eqn:LevelSetEquation}.  The advection term is constructed by
// minimizing the squared distance transform from the Canny edges.
//
// \begin{equation}
// \label{eqn:CannySegmentationLevelSetImageFilterAdvection}
// \mbox{min} \int D^2 \Rightarrow D \nabla D
// \end{equation}
//
// where the distance transform $D$ is calculated using a
// \doxygen{DanielssonDistanceMapImageFilter} applied to the output of the
// \doxygen{CannyEdgeDetectionImageFilter}.
//
// For cases in which some surface expansion is to be allowed, a non-zero
// value may be set for the propagation term.  The propagation term is simply
// $D$.  As with all ITK level set segmentation filters, the curvature term
// controls the smoothness of the surface.
//
// CannySegmentationLevelSetImageFilter expects two inputs.  The first is an
// initial level set in the form of an \doxygen{Image}. The second input is
// the feature image $g$ from which propagation and advection terms are
// calculated.  It is generally a good idea to do some preprocessing of the
// feature image to remove noise.
//
// Figure~\ref{fig:CannySegmentationLevelSetImageFilterDiagram} shows how the
// image processing pipeline is constructed.  We read two images: the image to
// segment and the image that contains the initial implicit surface.  The goal
// is to refine the initial model from the second input and not to grow a new
// segmentation from seed points. The \code{feature} image is preprocessed
// with a few iterations of an anisotropic diffusion filter.
//
// \begin{figure} \center
// \includegraphics[width=0.9\textwidth]{CannySegmentationLevelSetImageFilterCollaborationDiagram1.eps}
// \itkcaption[CannySegmentationLevelSetImageFilter collaboration
// diagram]{Collaboration diagram for the CannySegmentationLevelSetImageFilter
// applied to a segmentation task.}
// \label{fig:CannySegmentationLevelSetImageFilterDiagram}
// \end{figure}
//
// Let's start by including the appropriate header file.
//
// Software Guide : EndLatex

#include "itkImage.h"

// Software Guide : BeginCodeSnippet
#include "itkCannySegmentationLevelSetImageFilter.h"
#include "itkGradientAnisotropicDiffusionImageFilter.h"
// Software Guide : EndCodeSnippet

#include "itkFastMarchingImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkZeroCrossingImageFilter.h"

int main( int argc, char *argv[] )
{
  if( argc < 9 )
    {
    std::cerr << "Missing Parameters " << std::endl;
    std::cerr << "Usage: " << argv[0];
    std::cerr << " InputImage  InitialModel OutputImage";
    std::cerr << " CannyThreshold ";
    std::cerr << " CannyVariance ";
    std::cerr << " AdvectionWeight";
    std::cerr << " InitialModelIsovalue";
    std::cerr << " MaximumIterations" << std::endl;
    return 1;
    }

  //  Software Guide : BeginLatex
  //
  //  We define the image type using a particular pixel type and
  //  dimension. In this case we will use 2D \code{float} images.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef   float           InternalPixelType;
  const     unsigned int    Dimension = 2;
  typedef itk::Image< InternalPixelType, Dimension >  InternalImageType;
  // Software Guide : EndCodeSnippet

  typedef unsigned char OutputPixelType;
  typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
  typedef itk::BinaryThresholdImageFilter<
                        InternalImageType,
                        OutputImageType    >    ThresholdingFilterType;

  ThresholdingFilterType::Pointer thresholder = ThresholdingFilterType::New();

  thresholder->SetUpperThreshold( 10.0 );
  thresholder->SetLowerThreshold( 0.0 );

  thresholder->SetOutsideValue(  0  );
  thresholder->SetInsideValue(  255 );

  typedef  itk::ImageFileReader< InternalImageType > ReaderType;
  typedef  itk::ImageFileWriter<  OutputImageType  > WriterType;

  ReaderType::Pointer reader1 = ReaderType::New();
  ReaderType::Pointer reader2 = ReaderType::New();
  WriterType::Pointer writer = WriterType::New();

  reader1->SetFileName( argv[1] );
  reader2->SetFileName( argv[2] );
  writer->SetFileName(  argv[3] );

  //  Software Guide : BeginLatex
  //
  //  The input image will be processed with a few iterations of
  //  feature-preserving diffusion.  We create a filter and set the
  //  appropriate parameters.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::GradientAnisotropicDiffusionImageFilter< InternalImageType,
    InternalImageType> DiffusionFilterType;
  DiffusionFilterType::Pointer diffusion = DiffusionFilterType::New();
  diffusion->SetNumberOfIterations(5);
  diffusion->SetTimeStep(0.125);
  diffusion->SetConductanceParameter(1.0);
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The following lines define and instantiate a
  //  CannySegmentationLevelSetImageFilter.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef  itk::CannySegmentationLevelSetImageFilter< InternalImageType,
                InternalImageType > CannySegmentationLevelSetImageFilterType;
  CannySegmentationLevelSetImageFilterType::Pointer cannySegmentation =
                CannySegmentationLevelSetImageFilterType::New();
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  // As with the other ITK level set segmentation filters, the terms of the
  // CannySegmentationLevelSetImageFilter level set equation can be
  // weighted by scalars.  For this application we will modify the relative
  // weight of the advection term.  The propagation and curvature term weights
  // are set to their defaults of $0$ and $1$, respectively.
  //
  //  \index{itk::Canny\-Segmentation\-LevelSet\-Image\-Filter!SetAdvectionScaling()}
  //  \index{itk::Segmentation\-LevelSet\-ImageFilter!SetAdvectionScaling()}
  //
  //  Software Guide : EndLatex

  //  Software Guide : BeginCodeSnippet
  cannySegmentation->SetAdvectionScaling( ::atof(argv[6]) );
  cannySegmentation->SetCurvatureScaling( 1.0 );
  cannySegmentation->SetPropagationScaling( 0.0 );
  //  Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The maximum number of iterations is specified from the command line.
  //  It may not be desirable in some applications to run the filter to
  //  convergence.  Only a few iterations may be required.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  cannySegmentation->SetMaximumRMSError( 0.01 );
  cannySegmentation->SetNumberOfIterations( ::atoi(argv[8]) );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  There are two important parameters in the
  //  CannySegmentationLevelSetImageFilter to control the behavior of the
  //  Canny edge detection.  The \emph{variance} parameter controls the
  //  amount of Gaussian smoothing on the input image.  The \emph{threshold}
  //  parameter indicates the lowest allowed value in the output image.
  //  Thresholding is used to suppress Canny edges whose gradient magnitudes
  //  fall below a certain value.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  cannySegmentation->SetThreshold( ::atof(argv[4]) );
  cannySegmentation->SetVariance(  ::atof(argv[5]) );
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Finally, it is very important to specify the isovalue of the surface in
  // the initial model input image. In a binary image, for example, the
  // isosurface is found midway between the foreground and background values.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  cannySegmentation->SetIsoSurfaceValue( ::atof(argv[7]) );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The filters are now connected in a pipeline indicated in
  //  Figure~\ref{fig:CannySegmentationLevelSetImageFilterDiagram}.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  diffusion->SetInput( reader1->GetOutput() );
  cannySegmentation->SetInput( reader2->GetOutput() );
  cannySegmentation->SetFeatureImage( diffusion->GetOutput() );
  thresholder->SetInput( cannySegmentation->GetOutput() );
  writer->SetInput( thresholder->GetOutput() );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  Invoking the \code{Update()} method on the writer triggers the
  //  execution of the pipeline.  As usual, the call is placed in a
  //  \code{try/catch} block to handle any exceptions that may be thrown.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  try
    {
    writer->Update();
    }
  catch( itk::ExceptionObject & excep )
    {
    std::cerr << "Exception caught !" << std::endl;
    std::cerr << excep << std::endl;
    }
  // Software Guide : EndCodeSnippet

  // Print out some useful information
  std::cout << std::endl;
  std::cout << "Max. no. iterations: " << cannySegmentation->GetNumberOfIterations() << std::endl;
  std::cout << "Max. RMS error: " << cannySegmentation->GetMaximumRMSError() << std::endl;
  std::cout << std::endl;
  std::cout << "No. elpased iterations: " << cannySegmentation->GetElapsedIterations() << std::endl;
  std::cout << "RMS change: " << cannySegmentation->GetRMSChange() << std::endl;

  //  Software Guide : BeginLatex
  //
  //  We can use this filter to make some subtle refinements to the ventricle
  //  segmentation from the previous example that used the
  //  \doxygen{ThresholdSegmentationLevelSetImageFilter}.  The application
  //  was run using \code{Examples/Data/BrainProtonDensitySlice.png} and
  //  \code{Examples/Data/VentricleModel.png} as inputs, a \code{threshold}
  //  of $7.0$, \code{variance} of $0.1$, \code{advection weight} of $10.0$,
  //  and an initial isosurface value of $127.5$.  One case was run for $15$
  //  iterations and the second was run to convergence.  Compare the results
  //  in the two rightmost images of
  //  Figure~\ref{fig:CannySegmentationLevelSetImageFilter} with the
  //  ventricle segmentation from
  //  Figure~\ref{fig:ThresholdSegmentationLevelSetImageFilter} shown in the
  //  middle.  Jagged edges are straightened and the small spur at the upper
  //  right-hand side of the mask has been removed.
  //
  //  \begin{figure}
  //  \includegraphics[width=0.24\textwidth]{BrainProtonDensitySlice.eps}
  //  \includegraphics[width=0.24\textwidth]{ThresholdSegmentationLevelSetImageFilterVentricle.eps}
  //  \includegraphics[width=0.24\textwidth]{CannySegmentationLevelSetImageFilterVentricle1.eps}
  //  \includegraphics[width=0.24\textwidth]{CannySegmentationLevelSetImageFilterVentricle2.eps}
  //  \itkcaption[Segmentation results of CannyLevelSetImageFilter]{Results of
  //  applying the CannySegmentationLevelSetImageFilter to a prior ventricle
  //  segmentation.  Shown from left to right are the original image, the
  //  prior segmentation of the ventricle from
  //  Figure~\ref{fig:ThresholdSegmentationLevelSetImageFilter}, $15$ iterations of
  //  the CannySegmentationLevelSetImageFilter, and the
  //  CannySegmentationLevelSetImageFilter run to convergence.}
  //  \label{fig:CannySegmentationLevelSetImageFilter}
  //  \end{figure}
  //
  //  The free parameters of this filter can be adjusted to achieve a wide
  //  range of shape variations from the original model.  Finding the right
  //  parameters for your particular application is usually a process of
  //  trial and error.  As with most ITK level set segmentation filters,
  //  examining the propagation (speed) and advection images can help the
  //  process of tuning parameters.  These images are available using
  //  \code{Set/Get} methods from the filter after it has been updated.
  //
  //  Software Guide : EndLatex

  return 0;
}
<commit_msg>ENH: Command line tags for automatic generation of figures in Software guide<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    CannySegmentationLevelSetImageFilter.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

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

=========================================================================*/
//  Software Guide : BeginCommandLineArgs
//    INPUTS: {BrainProtonDensitySlice.png}, {ThresholdSegmentationLevelSetImageFilterVentricle.png}
//    OUTPUTS: {CannySegmentationLevelSetImageFilterVentricle1.png}
//    7.0 0.1 10.0 127.5 15
//  Software Guide : EndCommandLineArgs

// Software Guide : BeginLatex
//
// \index{itk::Canny\-Segmentation\-LevelSet\-Image\-Filter}
//
// The \doxygen{CannySegmentationLevelSetImageFilter} defines a speed term
// that minimizes distance to the Canny edges in an image.  The initial
// level set model moves through a gradient advection field until it locks
// onto those edges.  This filter is more suitable for refining existing
// segmentations than as a region-growing algorithm.
//
// The two terms defined for the CannySegmentationLevelSetImageFilter
// are the advection term and the propagation term from
// Equation~\ref{eqn:LevelSetEquation}.  The advection term is constructed by
// minimizing the squared distance transform from the Canny edges.
//
// \begin{equation}
// \label{eqn:CannySegmentationLevelSetImageFilterAdvection}
// \mbox{min} \int D^2 \Rightarrow D \nabla D
// \end{equation}
//
// where the distance transform $D$ is calculated using a
// \doxygen{DanielssonDistanceMapImageFilter} applied to the output of the
// \doxygen{CannyEdgeDetectionImageFilter}.
//
// For cases in which some surface expansion is to be allowed, a non-zero
// value may be set for the propagation term.  The propagation term is simply
// $D$.  As with all ITK level set segmentation filters, the curvature term
// controls the smoothness of the surface.
//
// CannySegmentationLevelSetImageFilter expects two inputs.  The first is an
// initial level set in the form of an \doxygen{Image}. The second input is
// the feature image $g$ from which propagation and advection terms are
// calculated.  It is generally a good idea to do some preprocessing of the
// feature image to remove noise.
//
// Figure~\ref{fig:CannySegmentationLevelSetImageFilterDiagram} shows how the
// image processing pipeline is constructed.  We read two images: the image to
// segment and the image that contains the initial implicit surface.  The goal
// is to refine the initial model from the second input and not to grow a new
// segmentation from seed points. The \code{feature} image is preprocessed
// with a few iterations of an anisotropic diffusion filter.
//
// \begin{figure} \center
// \includegraphics[width=0.9\textwidth]{CannySegmentationLevelSetImageFilterCollaborationDiagram1.eps}
// \itkcaption[CannySegmentationLevelSetImageFilter collaboration
// diagram]{Collaboration diagram for the CannySegmentationLevelSetImageFilter
// applied to a segmentation task.}
// \label{fig:CannySegmentationLevelSetImageFilterDiagram}
// \end{figure}
//
// Let's start by including the appropriate header file.
//
// Software Guide : EndLatex

#include "itkImage.h"

// Software Guide : BeginCodeSnippet
#include "itkCannySegmentationLevelSetImageFilter.h"
#include "itkGradientAnisotropicDiffusionImageFilter.h"
// Software Guide : EndCodeSnippet

#include "itkFastMarchingImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkZeroCrossingImageFilter.h"

int main( int argc, char *argv[] )
{
  if( argc < 9 )
    {
    std::cerr << "Missing Parameters " << std::endl;
    std::cerr << "Usage: " << argv[0];
    std::cerr << " InputImage  InitialModel OutputImage";
    std::cerr << " CannyThreshold ";
    std::cerr << " CannyVariance ";
    std::cerr << " AdvectionWeight";
    std::cerr << " InitialModelIsovalue";
    std::cerr << " MaximumIterations" << std::endl;
    return 1;
    }

  //  Software Guide : BeginLatex
  //
  //  We define the image type using a particular pixel type and
  //  dimension. In this case we will use 2D \code{float} images.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef   float           InternalPixelType;
  const     unsigned int    Dimension = 2;
  typedef itk::Image< InternalPixelType, Dimension >  InternalImageType;
  // Software Guide : EndCodeSnippet

  typedef unsigned char OutputPixelType;
  typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
  typedef itk::BinaryThresholdImageFilter<
                        InternalImageType,
                        OutputImageType    >    ThresholdingFilterType;

  ThresholdingFilterType::Pointer thresholder = ThresholdingFilterType::New();

  thresholder->SetUpperThreshold( 10.0 );
  thresholder->SetLowerThreshold( 0.0 );

  thresholder->SetOutsideValue(  0  );
  thresholder->SetInsideValue(  255 );

  typedef  itk::ImageFileReader< InternalImageType > ReaderType;
  typedef  itk::ImageFileWriter<  OutputImageType  > WriterType;

  ReaderType::Pointer reader1 = ReaderType::New();
  ReaderType::Pointer reader2 = ReaderType::New();
  WriterType::Pointer writer = WriterType::New();

  reader1->SetFileName( argv[1] );
  reader2->SetFileName( argv[2] );
  writer->SetFileName(  argv[3] );

  //  Software Guide : BeginLatex
  //
  //  The input image will be processed with a few iterations of
  //  feature-preserving diffusion.  We create a filter and set the
  //  appropriate parameters.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::GradientAnisotropicDiffusionImageFilter< InternalImageType,
    InternalImageType> DiffusionFilterType;
  DiffusionFilterType::Pointer diffusion = DiffusionFilterType::New();
  diffusion->SetNumberOfIterations(5);
  diffusion->SetTimeStep(0.125);
  diffusion->SetConductanceParameter(1.0);
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The following lines define and instantiate a
  //  CannySegmentationLevelSetImageFilter.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef  itk::CannySegmentationLevelSetImageFilter< InternalImageType,
                InternalImageType > CannySegmentationLevelSetImageFilterType;
  CannySegmentationLevelSetImageFilterType::Pointer cannySegmentation =
                CannySegmentationLevelSetImageFilterType::New();
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  // As with the other ITK level set segmentation filters, the terms of the
  // CannySegmentationLevelSetImageFilter level set equation can be
  // weighted by scalars.  For this application we will modify the relative
  // weight of the advection term.  The propagation and curvature term weights
  // are set to their defaults of $0$ and $1$, respectively.
  //
  //  \index{itk::Canny\-Segmentation\-LevelSet\-Image\-Filter!SetAdvectionScaling()}
  //  \index{itk::Segmentation\-LevelSet\-ImageFilter!SetAdvectionScaling()}
  //
  //  Software Guide : EndLatex

  //  Software Guide : BeginCodeSnippet
  cannySegmentation->SetAdvectionScaling( ::atof(argv[6]) );
  cannySegmentation->SetCurvatureScaling( 1.0 );
  cannySegmentation->SetPropagationScaling( 0.0 );
  //  Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The maximum number of iterations is specified from the command line.
  //  It may not be desirable in some applications to run the filter to
  //  convergence.  Only a few iterations may be required.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  cannySegmentation->SetMaximumRMSError( 0.01 );
  cannySegmentation->SetNumberOfIterations( ::atoi(argv[8]) );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  There are two important parameters in the
  //  CannySegmentationLevelSetImageFilter to control the behavior of the
  //  Canny edge detection.  The \emph{variance} parameter controls the
  //  amount of Gaussian smoothing on the input image.  The \emph{threshold}
  //  parameter indicates the lowest allowed value in the output image.
  //  Thresholding is used to suppress Canny edges whose gradient magnitudes
  //  fall below a certain value.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  cannySegmentation->SetThreshold( ::atof(argv[4]) );
  cannySegmentation->SetVariance(  ::atof(argv[5]) );
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Finally, it is very important to specify the isovalue of the surface in
  // the initial model input image. In a binary image, for example, the
  // isosurface is found midway between the foreground and background values.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  cannySegmentation->SetIsoSurfaceValue( ::atof(argv[7]) );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The filters are now connected in a pipeline indicated in
  //  Figure~\ref{fig:CannySegmentationLevelSetImageFilterDiagram}.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  diffusion->SetInput( reader1->GetOutput() );
  cannySegmentation->SetInput( reader2->GetOutput() );
  cannySegmentation->SetFeatureImage( diffusion->GetOutput() );
  thresholder->SetInput( cannySegmentation->GetOutput() );
  writer->SetInput( thresholder->GetOutput() );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  Invoking the \code{Update()} method on the writer triggers the
  //  execution of the pipeline.  As usual, the call is placed in a
  //  \code{try/catch} block to handle any exceptions that may be thrown.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  try
    {
    writer->Update();
    }
  catch( itk::ExceptionObject & excep )
    {
    std::cerr << "Exception caught !" << std::endl;
    std::cerr << excep << std::endl;
    }
  // Software Guide : EndCodeSnippet

  // Print out some useful information
  std::cout << std::endl;
  std::cout << "Max. no. iterations: " << cannySegmentation->GetNumberOfIterations() << std::endl;
  std::cout << "Max. RMS error: " << cannySegmentation->GetMaximumRMSError() << std::endl;
  std::cout << std::endl;
  std::cout << "No. elpased iterations: " << cannySegmentation->GetElapsedIterations() << std::endl;
  std::cout << "RMS change: " << cannySegmentation->GetRMSChange() << std::endl;

  //  Software Guide : BeginLatex
  //
  //  We can use this filter to make some subtle refinements to the ventricle
  //  segmentation from the previous example that used the
  //  \doxygen{ThresholdSegmentationLevelSetImageFilter}.  The application
  //  was run using \code{Examples/Data/BrainProtonDensitySlice.png} and
  //  \code{Examples/Data/VentricleModel.png} as inputs, a \code{threshold}
  //  of $7.0$, \code{variance} of $0.1$, \code{advection weight} of $10.0$,
  //  and an initial isosurface value of $127.5$.  One case was run for $15$
  //  iterations and the second was run to convergence.  Compare the results
  //  in the two rightmost images of
  //  Figure~\ref{fig:CannySegmentationLevelSetImageFilter} with the
  //  ventricle segmentation from
  //  Figure~\ref{fig:ThresholdSegmentationLevelSetImageFilter} shown in the
  //  middle.  Jagged edges are straightened and the small spur at the upper
  //  right-hand side of the mask has been removed.
  //
  //  \begin{figure}
  //  \includegraphics[width=0.24\textwidth]{BrainProtonDensitySlice.eps}
  //  \includegraphics[width=0.24\textwidth]{ThresholdSegmentationLevelSetImageFilterVentricle.eps}
  //  \includegraphics[width=0.24\textwidth]{CannySegmentationLevelSetImageFilterVentricle1.eps}
  //  \includegraphics[width=0.24\textwidth]{CannySegmentationLevelSetImageFilterVentricle2.eps}
  //  \itkcaption[Segmentation results of CannyLevelSetImageFilter]{Results of
  //  applying the CannySegmentationLevelSetImageFilter to a prior ventricle
  //  segmentation.  Shown from left to right are the original image, the
  //  prior segmentation of the ventricle from
  //  Figure~\ref{fig:ThresholdSegmentationLevelSetImageFilter}, $15$ iterations of
  //  the CannySegmentationLevelSetImageFilter, and the
  //  CannySegmentationLevelSetImageFilter run to convergence.}
  //  \label{fig:CannySegmentationLevelSetImageFilter}
  //  \end{figure}
  //
  //  The free parameters of this filter can be adjusted to achieve a wide
  //  range of shape variations from the original model.  Finding the right
  //  parameters for your particular application is usually a process of
  //  trial and error.  As with most ITK level set segmentation filters,
  //  examining the propagation (speed) and advection images can help the
  //  process of tuning parameters.  These images are available using
  //  \code{Set/Get} methods from the filter after it has been updated.
  //
  //  Software Guide : EndLatex

  return 0;
}
<|endoftext|>


<commit_before>/**
 *  @copyright Copyright 2016 The J-PET Framework Authors. All rights reserved.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may find a copy of the License in the LICENCE file.
 *
 *  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.
 *
 *  @file JPetDBParamGetter.cpp
 */

#include "./JPetDBParamGetter.h"
#include <boost/lexical_cast.hpp>
#include <TThread.h>
#include "../DBHandler/HeaderFiles/DBHandler.h"
#include <cstdint>

const std::map<ParamObjectType, std::map<std::string, std::string>> fieldTranslations{
  {ParamObjectType::kScintillator,
    {
      {"scintillator_id", "id"},
      {"scintillator_length", "length"},
      {"scintillator_width", "width"},
      {"scintillator_height", "height"}
    }
  },
    {ParamObjectType::kPM,
      {
        {"photomultiplier_id", "id"},
        {"hvpmconnection_isrightside", "is_right_side"}
      }
    },
    {ParamObjectType::kPMCalib,
      {
        {"pm_calibration_id", "id"},
        {"pm_calibration_name", "name"},
        {"pm_calibration_opthv", "opthv"},
        {"pm_calibration_c2e_1", "c2e1"},
        {"pm_calibration_c2e_2", "c2e2"},
        {"pm_calibration_gainalpha", "gain_alpha"},
        {"pm_calibration_gainbeta", "gain_beta"},
        {"pm_calibration_assignment_id", "assignment_id"},
        {"pm_calibration_assignment_photomuliplier_id", "assignment_photomultiplier_id"}
      }
    },
    {ParamObjectType::kBarrelSlot,
      {
        {"slot_id", "id"},
        {"slot_isActive", "active"},
        {"slot_name", "name"},
        {"slot_theta1", "theta1"},
        {"slot_inFrameId", "frame_id"}
      }
    },
    {ParamObjectType::kLayer,
      {
        {"layer_id", "id"},
        {"layer_isActive", "active"},
        {"layer_name", "name"},
        {"layer_radius", "radius"}
      }
    },
    {ParamObjectType::kFrame,
      {
        {"frame_id", "id"},
        {"frame_isActive", "active"},
        {"frame_status", "status"},
        {"frame_description", "description"},
        {"frame_version", "version"},
        {"frame_creator_id", "creator_id"}
      }
    },
    {ParamObjectType::kFEB,
      {
        {"konradboard_id", "id"},
        {"konradboard_isactive", "active"},
        {"konradboard_status", "status"},
        {"konradboard_description", "description"},
        {"konradboard_version", "version"},
        {"konradboard_creator_id", "creator_id"},
        {"time_outputs_per_input", "time_outputs_per_input"},
        {"notime_outputs_per_input", "no_time_outputs_per_input"}
      }
    },
    {ParamObjectType::kTRB,
      {
        {"TRB_id", "id"}
      }
    },
    {ParamObjectType::kTOMBChannel,
      {
        {"tomb", "channel"},
        {"thr_num", "local_number"},
        {"threshold", "threshold"},
        {"feb_input", "FEB"},
        {"trb_id", "trb_id"},
        {"konradboard_id", "konradboard_id"},
        {"photomultiplier_id", "photomultiplier_id"}
      }
    },
};
const std::map<ParamObjectType, std::string> dbFunctionName{
  {ParamObjectType::kScintillator, "getDataFromScintillators"},
    {ParamObjectType::kPM, "getDataFromPhotoMultipliers"},
    {ParamObjectType::kPMCalib, "getPmCalibration"},
    {ParamObjectType::kBarrelSlot, "getBarrelSlot"},
    {ParamObjectType::kLayer, "getLayer"},
    {ParamObjectType::kFrame, "getFrame"},
    {ParamObjectType::kFEB, "getDataFromKonradBoards"},
    {ParamObjectType::kTRB, "getDataFromTRBs"},
    {ParamObjectType::kTOMBChannel, "getEverythingVsTOMB"},
};
const std::map<ParamObjectType, std::map<ParamObjectType, std::string>> dbRelationFunctionName{
  {ParamObjectType::kPM, {
                           {ParamObjectType::kFEB, "getKonradBoardsForPhotoMultiplier"},
                             {ParamObjectType::kScintillator, "getScintillatorsForPhotoMultiplier"},
                             {ParamObjectType::kBarrelSlot, "getbarrelslotforphotomultiplier"}
                         }
  },
    {ParamObjectType::kFEB, {
                              {ParamObjectType::kTRB, "getTRBsForKonradBoard"}
                            }
    },
    {ParamObjectType::kBarrelSlot, {
                                     {ParamObjectType::kLayer, "getLayerForBarrelSlot"}
                                   }
    },
    {ParamObjectType::kLayer, {
                                {ParamObjectType::kFrame, "getFrameForLayer"}
                              }
    },
    {ParamObjectType::kScintillator, {
                                       {ParamObjectType::kBarrelSlot, "getbarrelslotforscintillator"}
                                     }
    },
};
const std::map<ParamObjectType, std::map<ParamObjectType, std::string>> dbRelationFieldName{
  {ParamObjectType::kPM, {
                           {ParamObjectType::kFEB, "KonradBoard_id"},
                             {ParamObjectType::kScintillator, "Scintillator_id"},
                             {ParamObjectType::kBarrelSlot, "hvpmconnection_slot_id"}
                         }
  },
    {ParamObjectType::kFEB, {
                              {ParamObjectType::kTRB, "TRB_id"}
                            }
    },
    {ParamObjectType::kBarrelSlot, {
                                     {ParamObjectType::kLayer, "layer_id"}
                                   }
    },
    {ParamObjectType::kLayer, {
                                {ParamObjectType::kFrame, "frame_id"}
                              }
    },
    {ParamObjectType::kScintillator, {
                                       {ParamObjectType::kBarrelSlot, "slscconnection_slot_id"}
                                     }
    },
};

std::map<int, std::map<ParamObjectType, ParamObjectsDescriptions>> JPetDBParamGetter::gBasicDataCache;
std::map<int, std::map<ParamObjectType, std::map<ParamObjectType, ParamRelationalData>>> JPetDBParamGetter::gRelationalDataCache;

void JPetDBParamGetter::clearParamCache()
{
  TThread::Lock();
  WARNING("JPetDBParamGetter cached data will be cleared");
  JPetDBParamGetter::gBasicDataCache.clear();
  JPetDBParamGetter::gRelationalDataCache.clear();
  TThread::UnLock();
}

ParamObjectsDescriptions JPetDBParamGetter::getAllBasicData(ParamObjectType type, const int runId)
{
  if (runId < 0) {
    ERROR("Run number is less than 0!");
    return ParamObjectsDescriptions();
  }
  auto & thisCache = gBasicDataCache[runId][type];
  if (thisCache.size() == 0) {
    TThread::Lock();
    std::string runIdS = boost::lexical_cast<std::string>(runId);
    auto dbResult = getDataFromDB(dbFunctionName.at(type), runIdS);
    if (dbResult.size() == 0) {
      printErrorMessageDB(dbFunctionName.at(type), runId);
      return thisCache;
    }
    for (auto row : dbResult) {
      ParamObjectDescription description;
      for (auto & translation : fieldTranslations.at(type)) {
        description[translation.second] = row[translation.first].as<std::string>();
        // Workaround to fix booleans.
        if (description[translation.second] == "t") {
          description[translation.second] = "1";
        }
        if (description[translation.second] == "f") {
          description[translation.second] = "0";
        }
      }
      // Fix id for TOMBChannel
      if (type == ParamObjectType::kTOMBChannel) {
        description["id"] = boost::lexical_cast<std::string>(JPetParamGetter::getTOMBChannelFromDescription(description["id"]));
      }
      // Workarounds because of missing stuff in DB.
      // Scintillator -- no attenuation_length
      if (type == ParamObjectType::kScintillator) {
        description["attenuation_length"] = "0";
      }
      // TRB -- no type and channel
      if (type == ParamObjectType::kTRB) {
        description["type"] = "0";
        description["channel"] = "0";
      }
      thisCache[boost::lexical_cast<int>(description["id"])] = description;
    }
    TThread::UnLock();
  }
  return thisCache;
}

ParamRelationalData JPetDBParamGetter::getAllRelationalData(ParamObjectType type1, ParamObjectType type2, const int runId)
{
  if (runId < 0) {
    ERROR("Run number is less than 0!");
    return ParamRelationalData();
  }
  auto & thisCache = gRelationalDataCache[runId][type1][type2];
  if (thisCache.size() == 0) {
    TThread::Lock();
    std::string runIdS = boost::lexical_cast<std::string>(runId);
    auto dbResult = getDataFromDB(dbFunctionName.at(type1), runIdS);
    if (dbResult.size() == 0) {
      printErrorMessageDB(dbFunctionName.at(type1), runId);
      return thisCache;
    }
    for (auto row : dbResult) {
      ParamObjectDescription description;
      for (auto & translation : fieldTranslations.at(type1)) {
        description[translation.second] = row[translation.first].as<std::string>();
      }
      if (type1 == ParamObjectType::kTOMBChannel) {
        description["id"] = boost::lexical_cast<std::string>(JPetParamGetter::getTOMBChannelFromDescription(description["id"]));
        switch (type2) {
          case ParamObjectType::kTRB:
            thisCache[boost::lexical_cast<int>(description["id"])] = boost::lexical_cast<int>(description["trb_id"]);
            break;
          case ParamObjectType::kFEB:
            thisCache[boost::lexical_cast<int>(description["id"])] = boost::lexical_cast<int>(description["konradboard_id"]);
            break;
          case ParamObjectType::kPM:
            thisCache[boost::lexical_cast<int>(description["id"])] = boost::lexical_cast<int>(description["photomultiplier_id"]);
            break;
          default:
            break;
        }
      } else {
        auto dbRelationResult = getDataFromDB(dbRelationFunctionName.at(type1).at(type2), description["id"] + "," + runIdS);
        for (auto relationRow : dbRelationResult) {
          thisCache[boost::lexical_cast<int>(description["id"])] = relationRow[dbRelationFieldName.at(type1).at(type2)].as<int>();
        }
      }
    }
    TThread::UnLock();
  }
  return thisCache;
}

std::string JPetDBParamGetter::generateSelectQuery(const std::string& sqlFun, const std::string& arguments)
{
  std::string sqlQuerry = "SELECT * FROM ";
  sqlQuerry += sqlFun;
  sqlQuerry += "(" + arguments + ");";
  return sqlQuerry;
}

/// @brief method calls the remote PostgreSQL function sqlfunction with the id argument and returns results from database
pqxx::result JPetDBParamGetter::getDataFromDB(const std::string& sqlfunction, const  std::string& arguments)
{
  //std::string l_run_id = boost::lexical_cast<std::string>(id);
  std::string l_sqlQuerry = generateSelectQuery(sqlfunction, arguments);
  DB::SERVICES::DBHandler& l_dbHandlerInstance = DB::SERVICES::DBHandler::getInstance();
  return  l_dbHandlerInstance.querry(l_sqlQuerry);
}

void JPetDBParamGetter::printErrorMessageDB(std::string sqlFunction, int p_run_id)
{
  std::string l_error(sqlFunction);
  l_error += "() query with run_id = ";
  l_error += boost::lexical_cast<std::string>(p_run_id) + " returned 0 records.";
  ERROR(l_error.c_str());
}
<commit_msg>Channel/id field for TOMBChannels<commit_after>/**
 *  @copyright Copyright 2016 The J-PET Framework Authors. All rights reserved.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may find a copy of the License in the LICENCE file.
 *
 *  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.
 *
 *  @file JPetDBParamGetter.cpp
 */

#include "./JPetDBParamGetter.h"
#include <boost/lexical_cast.hpp>
#include <TThread.h>
#include "../DBHandler/HeaderFiles/DBHandler.h"
#include <cstdint>

const std::map<ParamObjectType, std::map<std::string, std::string>> fieldTranslations{
  {ParamObjectType::kScintillator,
    {
      {"scintillator_id", "id"},
      {"scintillator_length", "length"},
      {"scintillator_width", "width"},
      {"scintillator_height", "height"}
    }
  },
    {ParamObjectType::kPM,
      {
        {"photomultiplier_id", "id"},
        {"hvpmconnection_isrightside", "is_right_side"}
      }
    },
    {ParamObjectType::kPMCalib,
      {
        {"pm_calibration_id", "id"},
        {"pm_calibration_name", "name"},
        {"pm_calibration_opthv", "opthv"},
        {"pm_calibration_c2e_1", "c2e1"},
        {"pm_calibration_c2e_2", "c2e2"},
        {"pm_calibration_gainalpha", "gain_alpha"},
        {"pm_calibration_gainbeta", "gain_beta"},
        {"pm_calibration_assignment_id", "assignment_id"},
        {"pm_calibration_assignment_photomuliplier_id", "assignment_photomultiplier_id"}
      }
    },
    {ParamObjectType::kBarrelSlot,
      {
        {"slot_id", "id"},
        {"slot_isActive", "active"},
        {"slot_name", "name"},
        {"slot_theta1", "theta1"},
        {"slot_inFrameId", "frame_id"}
      }
    },
    {ParamObjectType::kLayer,
      {
        {"layer_id", "id"},
        {"layer_isActive", "active"},
        {"layer_name", "name"},
        {"layer_radius", "radius"}
      }
    },
    {ParamObjectType::kFrame,
      {
        {"frame_id", "id"},
        {"frame_isActive", "active"},
        {"frame_status", "status"},
        {"frame_description", "description"},
        {"frame_version", "version"},
        {"frame_creator_id", "creator_id"}
      }
    },
    {ParamObjectType::kFEB,
      {
        {"konradboard_id", "id"},
        {"konradboard_isactive", "active"},
        {"konradboard_status", "status"},
        {"konradboard_description", "description"},
        {"konradboard_version", "version"},
        {"konradboard_creator_id", "creator_id"},
        {"time_outputs_per_input", "time_outputs_per_input"},
        {"notime_outputs_per_input", "no_time_outputs_per_input"}
      }
    },
    {ParamObjectType::kTRB,
      {
        {"TRB_id", "id"}
      }
    },
    {ParamObjectType::kTOMBChannel,
      {
        {"tomb", "channel"},
        {"thr_num", "local_number"},
        {"threshold", "threshold"},
        {"feb_input", "FEB"},
        {"trb_id", "trb_id"},
        {"konradboard_id", "konradboard_id"},
        {"photomultiplier_id", "photomultiplier_id"}
      }
    },
};
const std::map<ParamObjectType, std::string> dbFunctionName{
  {ParamObjectType::kScintillator, "getDataFromScintillators"},
    {ParamObjectType::kPM, "getDataFromPhotoMultipliers"},
    {ParamObjectType::kPMCalib, "getPmCalibration"},
    {ParamObjectType::kBarrelSlot, "getBarrelSlot"},
    {ParamObjectType::kLayer, "getLayer"},
    {ParamObjectType::kFrame, "getFrame"},
    {ParamObjectType::kFEB, "getDataFromKonradBoards"},
    {ParamObjectType::kTRB, "getDataFromTRBs"},
    {ParamObjectType::kTOMBChannel, "getEverythingVsTOMB"},
};
const std::map<ParamObjectType, std::map<ParamObjectType, std::string>> dbRelationFunctionName{
  {ParamObjectType::kPM, {
                           {ParamObjectType::kFEB, "getKonradBoardsForPhotoMultiplier"},
                             {ParamObjectType::kScintillator, "getScintillatorsForPhotoMultiplier"},
                             {ParamObjectType::kBarrelSlot, "getbarrelslotforphotomultiplier"}
                         }
  },
    {ParamObjectType::kFEB, {
                              {ParamObjectType::kTRB, "getTRBsForKonradBoard"}
                            }
    },
    {ParamObjectType::kBarrelSlot, {
                                     {ParamObjectType::kLayer, "getLayerForBarrelSlot"}
                                   }
    },
    {ParamObjectType::kLayer, {
                                {ParamObjectType::kFrame, "getFrameForLayer"}
                              }
    },
    {ParamObjectType::kScintillator, {
                                       {ParamObjectType::kBarrelSlot, "getbarrelslotforscintillator"}
                                     }
    },
};
const std::map<ParamObjectType, std::map<ParamObjectType, std::string>> dbRelationFieldName{
  {ParamObjectType::kPM, {
                           {ParamObjectType::kFEB, "KonradBoard_id"},
                             {ParamObjectType::kScintillator, "Scintillator_id"},
                             {ParamObjectType::kBarrelSlot, "hvpmconnection_slot_id"}
                         }
  },
    {ParamObjectType::kFEB, {
                              {ParamObjectType::kTRB, "TRB_id"}
                            }
    },
    {ParamObjectType::kBarrelSlot, {
                                     {ParamObjectType::kLayer, "layer_id"}
                                   }
    },
    {ParamObjectType::kLayer, {
                                {ParamObjectType::kFrame, "frame_id"}
                              }
    },
    {ParamObjectType::kScintillator, {
                                       {ParamObjectType::kBarrelSlot, "slscconnection_slot_id"}
                                     }
    },
};

std::map<int, std::map<ParamObjectType, ParamObjectsDescriptions>> JPetDBParamGetter::gBasicDataCache;
std::map<int, std::map<ParamObjectType, std::map<ParamObjectType, ParamRelationalData>>> JPetDBParamGetter::gRelationalDataCache;

void JPetDBParamGetter::clearParamCache()
{
  TThread::Lock();
  WARNING("JPetDBParamGetter cached data will be cleared");
  JPetDBParamGetter::gBasicDataCache.clear();
  JPetDBParamGetter::gRelationalDataCache.clear();
  TThread::UnLock();
}

ParamObjectsDescriptions JPetDBParamGetter::getAllBasicData(ParamObjectType type, const int runId)
{
  if (runId < 0) {
    ERROR("Run number is less than 0!");
    return ParamObjectsDescriptions();
  }
  auto & thisCache = gBasicDataCache[runId][type];
  if (thisCache.size() == 0) {
    TThread::Lock();
    std::string runIdS = boost::lexical_cast<std::string>(runId);
    auto dbResult = getDataFromDB(dbFunctionName.at(type), runIdS);
    if (dbResult.size() == 0) {
      printErrorMessageDB(dbFunctionName.at(type), runId);
      return thisCache;
    }
    for (auto row : dbResult) {
      ParamObjectDescription description;
      for (auto & translation : fieldTranslations.at(type)) {
        description[translation.second] = row[translation.first].as<std::string>();
        // Workaround to fix booleans.
        if (description[translation.second] == "t") {
          description[translation.second] = "1";
        }
        if (description[translation.second] == "f") {
          description[translation.second] = "0";
        }
      }
      // Fix id for TOMBChannel
      if (type == ParamObjectType::kTOMBChannel) {
        description["channel"] = boost::lexical_cast<std::string>(JPetParamGetter::getTOMBChannelFromDescription(description["channel"]));
        //The id field is needed for caching
        description["id"] = description["channel"];
      }
      // Workarounds because of missing stuff in DB.
      // Scintillator -- no attenuation_length
      if (type == ParamObjectType::kScintillator) {
        description["attenuation_length"] = "0";
      }
      // TRB -- no type and channel
      if (type == ParamObjectType::kTRB) {
        description["type"] = "0";
        description["channel"] = "0";
      }
      thisCache[boost::lexical_cast<int>(description["id"])] = description;
    }
    TThread::UnLock();
  }
  return thisCache;
}

ParamRelationalData JPetDBParamGetter::getAllRelationalData(ParamObjectType type1, ParamObjectType type2, const int runId)
{
  if (runId < 0) {
    ERROR("Run number is less than 0!");
    return ParamRelationalData();
  }
  auto & thisCache = gRelationalDataCache[runId][type1][type2];
  if (thisCache.size() == 0) {
    TThread::Lock();
    std::string runIdS = boost::lexical_cast<std::string>(runId);
    auto dbResult = getDataFromDB(dbFunctionName.at(type1), runIdS);
    if (dbResult.size() == 0) {
      printErrorMessageDB(dbFunctionName.at(type1), runId);
      return thisCache;
    }
    for (auto row : dbResult) {
      ParamObjectDescription description;
      for (auto & translation : fieldTranslations.at(type1)) {
        description[translation.second] = row[translation.first].as<std::string>();
      }
      if (type1 == ParamObjectType::kTOMBChannel) {
        description["channel"] = boost::lexical_cast<std::string>(JPetParamGetter::getTOMBChannelFromDescription(description["channel"]));
        //The id field is needed for caching
        description["id"] = description["channel"];
        switch (type2) {
          case ParamObjectType::kTRB:
            thisCache[boost::lexical_cast<int>(description["id"])] = boost::lexical_cast<int>(description["trb_id"]);
            break;
          case ParamObjectType::kFEB:
            thisCache[boost::lexical_cast<int>(description["id"])] = boost::lexical_cast<int>(description["konradboard_id"]);
            break;
          case ParamObjectType::kPM:
            thisCache[boost::lexical_cast<int>(description["id"])] = boost::lexical_cast<int>(description["photomultiplier_id"]);
            break;
          default:
            break;
        }
      } else {
        auto dbRelationResult = getDataFromDB(dbRelationFunctionName.at(type1).at(type2), description["id"] + "," + runIdS);
        for (auto relationRow : dbRelationResult) {
          thisCache[boost::lexical_cast<int>(description["id"])] = relationRow[dbRelationFieldName.at(type1).at(type2)].as<int>();
        }
      }
    }
    TThread::UnLock();
  }
  return thisCache;
}

std::string JPetDBParamGetter::generateSelectQuery(const std::string& sqlFun, const std::string& arguments)
{
  std::string sqlQuerry = "SELECT * FROM ";
  sqlQuerry += sqlFun;
  sqlQuerry += "(" + arguments + ");";
  return sqlQuerry;
}

/// @brief method calls the remote PostgreSQL function sqlfunction with the id argument and returns results from database
pqxx::result JPetDBParamGetter::getDataFromDB(const std::string& sqlfunction, const  std::string& arguments)
{
  //std::string l_run_id = boost::lexical_cast<std::string>(id);
  std::string l_sqlQuerry = generateSelectQuery(sqlfunction, arguments);
  DB::SERVICES::DBHandler& l_dbHandlerInstance = DB::SERVICES::DBHandler::getInstance();
  return  l_dbHandlerInstance.querry(l_sqlQuerry);
}

void JPetDBParamGetter::printErrorMessageDB(std::string sqlFunction, int p_run_id)
{
  std::string l_error(sqlFunction);
  l_error += "() query with run_id = ";
  l_error += boost::lexical_cast<std::string>(p_run_id) + " returned 0 records.";
  ERROR(l_error.c_str());
}
<|endoftext|>


<commit_before>#include "../utils/geom.hpp"
#include <vector>
#include <cstdio>

class Image;

struct VisGraph {
	VisGraph(void) { }

	VisGraph(std::vector<Polygon> &ps) {
		layers.push_back(ps);
		computegraph();
	}

	VisGraph(FILE*);

	void draw(Image&, double scale=1, unsigned int z = 0) const;

	void output(FILE*) const;

	// Add a layer and return its z-value.
	unsigned int pushlayer(std::vector<Polygon>&);

	// Add a vertex to the graph.
	unsigned int add(double, double, unsigned int z = 0);

	// Link two vertices.
	void link(unsigned int, unsigned int, double);

	// Is the given point outside all polygons?
	bool isoutside(double, double, unsigned int z = 0);

	struct Vert;

	struct Edge {
		Edge(unsigned int _src, unsigned int _dst, double _dist) :
			src(_src), dst(_dst), dist(_dist) { }
		unsigned int src, dst;
		double dist;
	};

	struct Vert {
		Vert(void) { }

		Vert(unsigned int _vid, const Point &_pt, unsigned int _z, unsigned int _polyno,
				unsigned int _vertno) :
			pt(_pt), vid(_vid), z(_z), polyno(_polyno), vertno(_vertno) { }

		void input(std::vector<Vert>&, unsigned int, FILE*);
		void output(FILE *out) const;

		Point pt;
		unsigned int vid;
		unsigned int z, polyno, vertno;	// polyno within z-layer
		std::vector<Edge> succs;
	};

	const Vert &vertex(unsigned int i) const { return verts[i]; }

private:
	void computegraph(void);
	void computeverts(unsigned int);
	void linkverts(unsigned int);
	void linkvert(unsigned int, unsigned int);
	bool consecutive(unsigned int, unsigned int);	// On same poly-side?

	std::vector< std::vector<Polygon> > layers;
	std::vector<Vert> verts;
};<commit_msg>visnav: add a comment describing the z-layering.<commit_after>#include "../utils/geom.hpp"
#include <vector>
#include <cstdio>

class Image;

// A multiple-layer visibility graph.  Each z-layer is
// composed of a bunch of polygons in 2d space.  The
// vertices of each layer are linked based on visibility.
// Additional vertices and links can be added to link the
// different layers too.
struct VisGraph {
	VisGraph(void) { }

	VisGraph(std::vector<Polygon> &ps) {
		layers.push_back(ps);
		computegraph();
	}

	VisGraph(FILE*);

	void draw(Image&, double scale=1, unsigned int z = 0) const;

	void output(FILE*) const;

	// Add a layer and return its z-value.
	unsigned int pushlayer(std::vector<Polygon>&);

	// Add a vertex to the graph.
	unsigned int add(double, double, unsigned int z = 0);

	// Link two vertices.
	void link(unsigned int, unsigned int, double);

	// Is the given point outside all polygons?
	bool isoutside(double, double, unsigned int z = 0);

	struct Vert;

	struct Edge {
		Edge(unsigned int _src, unsigned int _dst, double _dist) :
			src(_src), dst(_dst), dist(_dist) { }
		unsigned int src, dst;
		double dist;
	};

	struct Vert {
		Vert(void) { }

		Vert(unsigned int _vid, const Point &_pt, unsigned int _z, unsigned int _polyno,
				unsigned int _vertno) :
			pt(_pt), vid(_vid), z(_z), polyno(_polyno), vertno(_vertno) { }

		void input(std::vector<Vert>&, unsigned int, FILE*);
		void output(FILE *out) const;

		Point pt;
		unsigned int vid;
		unsigned int z, polyno, vertno;	// polyno within z-layer
		std::vector<Edge> succs;
	};

	const Vert &vertex(unsigned int i) const { return verts[i]; }

private:
	void computegraph(void);
	void computeverts(unsigned int);
	void linkverts(unsigned int);
	void linkvert(unsigned int, unsigned int);
	bool consecutive(unsigned int, unsigned int);	// On same poly-side?

	std::vector< std::vector<Polygon> > layers;
	std::vector<Vert> verts;
};<|endoftext|>


<commit_before>/*  This file is part of the KDE project.

Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).

This library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2.1 or 3 of the License.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifdef HAVE_LIBV4L2

#include "v4l2devices.h"

#include <linux/videodev2.h>
#include <libv4l2.h>
#include <fcntl.h>

#include <QtCore/QDebug>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QDir>

QT_BEGIN_NAMESPACE

namespace Phonon {
namespace VLC {
namespace V4L2Support {

typedef enum {
    IO_METHOD_AUTO,
    IO_METHOD_READ,
    IO_METHOD_MMAP,
    IO_METHOD_USERPTR,
} io_method;

struct demux_sys_t {
    char *psz_device;  /* Main device from MRL */
    int  i_fd;

    char *psz_requested_chroma;

    /* Video */
    io_method io;

    int i_cache;

    struct v4l2_capability dev_cap;

    int i_input;
    struct v4l2_input *p_inputs;
    int i_selected_input;

    int i_standard;
    struct v4l2_standard *p_standards;
    v4l2_std_id i_selected_standard_id;

    int i_audio;
    /* V4L2 devices cannot have more than 32 audio inputs */
    struct v4l2_audio p_audios[32];
    int i_selected_audio_input;

    int i_tuner;
    struct v4l2_tuner *p_tuners;

    int i_codec;
    struct v4l2_fmtdesc *p_codecs;

    struct buffer_t *p_buffers;
    unsigned int i_nbuffers;

    int i_width;
    int i_height;
    unsigned int i_aspect;
    float f_fps;            /* <= 0.0 mean to grab at full rate */
    int64_t i_video_pts;    /* only used when f_fps > 0 */
    int i_fourcc;
    uint32_t i_block_flags;

    /* es_out_id_t *p_es; */
    void *p_es;

    /* Tuner */
    int i_cur_tuner;
    int i_frequency;
    int i_audio_mode;

    /* Controls */
    char *psz_set_ctrls;

    /* */
    int (*pf_open)(const char *, int, ...);
    int (*pf_close)(int);
    int (*pf_dup)(int);
    int (*pf_ioctl)(int, unsigned long int, ...);
    ssize_t (*pf_read)(int, void *, size_t );
    void *(*pf_mmap)(void *, size_t, int, int, int, off_t);
    int (*pf_munmap)(void *, size_t);
    bool b_libv4l2;
};

/*
Tries to open a v4l device specified by devicePath, and queries it's capabilities.
Depending on the device capabilities, it is added to the capture device lists
*/
static bool probeDevice(QByteArray devicePath,
                        QList<DeviceInfo> & videoCaptureDevices,
                        QList<DeviceInfo> & audioCaptureDevices)
{
    int i_index;
    int i_standard;
    int i_fd;
    QByteArray nameId;

    struct demux_sys_t deviceInfo;
    memset(&deviceInfo, 0, sizeof(deviceInfo));

    // Open device
    if ((i_fd = v4l2_open(devicePath.constData(), O_RDWR)) < 0) {
        qCritical() << Q_FUNC_INFO << "Cannot open video device" << devicePath;
        if (i_fd >= 0)
            v4l2_close(i_fd);
        return false;
    }

    int libv4l2_fd;
    libv4l2_fd = v4l2_fd_open(i_fd, V4L2_ENABLE_ENUM_FMT_EMULATION);
    if (libv4l2_fd != -1)
        i_fd = libv4l2_fd;

    // Get device capabilites
    if (v4l2_ioctl(i_fd, VIDIOC_QUERYCAP, &deviceInfo.dev_cap) < 0) {
        qCritical() << Q_FUNC_INFO << "Cannot get video capabilities for" << devicePath;
        if (i_fd >= 0)
            v4l2_close(i_fd);
        return false;
    }

    // Probe video inputs
    if (deviceInfo.dev_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
        qDebug() << "found video capture device" << devicePath;
        nameId = (devicePath.startsWith("/dev/") ? devicePath.mid(5) : devicePath);
        DeviceInfo vd(nameId, devicePath);
        vd.v4l = true;
        videoCaptureDevices << vd;
    }

    // Probe audio inputs
    if (deviceInfo.dev_cap.capabilities & V4L2_CAP_AUDIO) {
        qDebug() << "found audio capture device" << devicePath;
        nameId = (devicePath.startsWith("/dev/") ? devicePath.mid(5) : devicePath);
        DeviceInfo ad(nameId, devicePath);
        ad.v4l = true;
        audioCaptureDevices << ad;
    }

    if (i_fd >= 0)
        v4l2_close(i_fd);
    return true;
}

bool scanDevices(QList<DeviceInfo> & videoCaptureDevices, QList<DeviceInfo> & audioCaptureDevices)
{
    QDir deviceDir("/dev");
    if (!deviceDir.isReadable()) {
        qCritical() << Q_FUNC_INFO << "Unable to read /dev";
        return false;
    }

    // Search trough /dev/videoX for valid V4L devices
    QStringList nameFilters;
    nameFilters << "video*";
    deviceDir.setFilter(QDir::System);
    deviceDir.setNameFilters(nameFilters);

    QStringList devicePaths = deviceDir.entryList();
    foreach (QString dn, devicePaths) {
        dn = deviceDir.filePath(dn);

        // Get information about the device from V4L, and append it to the capture device lists
        probeDevice(dn.toLatin1(), videoCaptureDevices, audioCaptureDevices);
    }

    return true;
}

}
}
} // namespace Phonon::VLC::V4L2Support

QT_END_NAMESPACE

#endif // HAVE_LIBV4L2
<commit_msg>Add better device name and a device description for the v4l2 devices<commit_after>/*  This file is part of the KDE project.

Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).

This library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2.1 or 3 of the License.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifdef HAVE_LIBV4L2

#include "v4l2devices.h"

#include <linux/videodev2.h>
#include <libv4l2.h>
#include <fcntl.h>

#include <QtCore/QDebug>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QDir>

QT_BEGIN_NAMESPACE

namespace Phonon {
namespace VLC {
namespace V4L2Support {

typedef enum {
    IO_METHOD_AUTO,
    IO_METHOD_READ,
    IO_METHOD_MMAP,
    IO_METHOD_USERPTR,
} io_method;

struct demux_sys_t {
    char *psz_device;  /* Main device from MRL */
    int  i_fd;

    char *psz_requested_chroma;

    /* Video */
    io_method io;

    int i_cache;

    struct v4l2_capability dev_cap;

    int i_input;
    struct v4l2_input *p_inputs;
    int i_selected_input;

    int i_standard;
    struct v4l2_standard *p_standards;
    v4l2_std_id i_selected_standard_id;

    int i_audio;
    /* V4L2 devices cannot have more than 32 audio inputs */
    struct v4l2_audio p_audios[32];
    int i_selected_audio_input;

    int i_tuner;
    struct v4l2_tuner *p_tuners;

    int i_codec;
    struct v4l2_fmtdesc *p_codecs;

    struct buffer_t *p_buffers;
    unsigned int i_nbuffers;

    int i_width;
    int i_height;
    unsigned int i_aspect;
    float f_fps;            /* <= 0.0 mean to grab at full rate */
    int64_t i_video_pts;    /* only used when f_fps > 0 */
    int i_fourcc;
    uint32_t i_block_flags;

    /* es_out_id_t *p_es; */
    void *p_es;

    /* Tuner */
    int i_cur_tuner;
    int i_frequency;
    int i_audio_mode;

    /* Controls */
    char *psz_set_ctrls;

    /* */
    int (*pf_open)(const char *, int, ...);
    int (*pf_close)(int);
    int (*pf_dup)(int);
    int (*pf_ioctl)(int, unsigned long int, ...);
    ssize_t (*pf_read)(int, void *, size_t );
    void *(*pf_mmap)(void *, size_t, int, int, int, off_t);
    int (*pf_munmap)(void *, size_t);
    bool b_libv4l2;
};

/*
Tries to open a v4l device specified by devicePath, and queries it's capabilities.
Depending on the device capabilities, it is added to the capture device lists
*/
static bool probeDevice(QByteArray devicePath,
                        QList<DeviceInfo> & videoCaptureDevices,
                        QList<DeviceInfo> & audioCaptureDevices)
{
    int i_index;
    int i_standard;
    int i_fd;
    QByteArray nameId;

    struct demux_sys_t deviceInfo;
    memset(&deviceInfo, 0, sizeof(deviceInfo));

    // Open device
    if ((i_fd = v4l2_open(devicePath.constData(), O_RDWR)) < 0) {
        qCritical() << Q_FUNC_INFO << "Cannot open video device" << devicePath;
        if (i_fd >= 0)
            v4l2_close(i_fd);
        return false;
    }

    int libv4l2_fd;
    libv4l2_fd = v4l2_fd_open(i_fd, V4L2_ENABLE_ENUM_FMT_EMULATION);
    if (libv4l2_fd != -1)
        i_fd = libv4l2_fd;

    // Get device capabilites
    if (v4l2_ioctl(i_fd, VIDIOC_QUERYCAP, &deviceInfo.dev_cap) < 0) {
        qCritical() << Q_FUNC_INFO << "Cannot get video capabilities for" << devicePath;
        if (i_fd >= 0)
            v4l2_close(i_fd);
        return false;
    }

    // Probe video inputs
    if (deviceInfo.dev_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
        qDebug() << "found video capture device" << devicePath;
        nameId = QByteArray((const char*) deviceInfo.dev_cap.card).trimmed();
        DeviceInfo vd(nameId, devicePath);
        vd.description = "Video For Linux 2 Video Device, using driver ";
        vd.description.append(QByteArray((const char*) deviceInfo.dev_cap.driver).trimmed());
        vd.v4l = true;
        videoCaptureDevices << vd;
    }

    // Probe audio inputs
    if (deviceInfo.dev_cap.capabilities & V4L2_CAP_AUDIO) {
        qDebug() << "found audio capture device" << devicePath;
        nameId = QByteArray((const char*) deviceInfo.dev_cap.card).trimmed();
        DeviceInfo ad(nameId, devicePath);
        ad.description = "Video For Linux 2 Audio Device, using driver ";
        ad.description.append(QByteArray((const char*) deviceInfo.dev_cap.driver).trimmed());
        ad.v4l = true;
        audioCaptureDevices << ad;
    }

    if (i_fd >= 0)
        v4l2_close(i_fd);
    return true;
}

bool scanDevices(QList<DeviceInfo> & videoCaptureDevices, QList<DeviceInfo> & audioCaptureDevices)
{
    QDir deviceDir("/dev");
    if (!deviceDir.isReadable()) {
        qCritical() << Q_FUNC_INFO << "Unable to read /dev";
        return false;
    }

    // Search trough /dev/videoX for valid V4L devices
    QStringList nameFilters;
    nameFilters << "video*";
    deviceDir.setFilter(QDir::System);
    deviceDir.setNameFilters(nameFilters);

    QStringList devicePaths = deviceDir.entryList();
    foreach (QString dn, devicePaths) {
        dn = deviceDir.filePath(dn);

        // Get information about the device from V4L, and append it to the capture device lists
        probeDevice(dn.toLatin1(), videoCaptureDevices, audioCaptureDevices);
    }

    return true;
}

}
}
} // namespace Phonon::VLC::V4L2Support

QT_END_NAMESPACE

#endif // HAVE_LIBV4L2
<|endoftext|>


<commit_before>/* The MIT License

Copyright (c) 2011 Sahab Yazdani

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

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

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

#ifdef WIN32
// needed by opengl
#define NOMINMAX
#include <windows.h>
#endif // WIN32

// stl
#include <string>
#include <memory>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <cmath>

// boost
#include <boost/timer.hpp>

// PNG library
#include <picopng.h>

// stippler library
#include <istippler.h>

// local
#include "parse_arguments.h"

void write_configuration( std::ostream &output, const Voronoi::StipplingParameters &parameters ) {
	using std::endl;
	using std::abs;
	using std::numeric_limits;

	output << "Generating " << parameters.points << " stipples." << endl;
	output << "Options: ";
	if ( parameters.useColour ) {
		output << "Coloured stipples";
	} else {
		output << "Black stipples";
	}

	if ( parameters.noOverlap ) {
		output << ", Non-overlapping stipples";
	} else {
		output << ", overlapping stipples";
	}

	if ( parameters.fixedRadius ) {
		output << ", Fixed radius";
	} else {
		output << ", Variable radius";
	}

	output << ", Subpixel density of " << parameters.subpixels;

	if ( abs( parameters.sizingFactor - 1.0f ) > numeric_limits<float>::epsilon() ) {
		output << ", Sizing factor of " << parameters.sizingFactor;
	}

	if ( abs( parameters.threshold - 0.1f ) > numeric_limits<float>::epsilon() ) {
		output << ", Displacement Threshold of " << parameters.threshold;
	}

	output << endl;
}

void render( STIPPLER_HANDLE stippler, const Voronoi::StipplingParameters &parameters ) {
	StipplePoint *points = new StipplePoint[parameters.points];

	stippler_getStipples(stippler, points);

	using namespace std;

	ofstream outputStream( parameters.outputFile.c_str() );

	if ( !outputStream.is_open() ) {
		stringstream s;
		s << "Unable to open output file " << parameters.outputFile;
		throw runtime_error(s.str());
	}

	PNG::PNGFile *png = PNG::load( parameters.inputFile );
	unsigned long w = png->w, h = png->h;
	PNG::freePng(png);

	outputStream << "<?xml version=\"1.0\" ?>" << endl;
	outputStream << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">" << endl;
	outputStream << "<svg width=\"" << w << "\" height=\"" << h << "\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">" << endl;

	float radius;
	for ( unsigned int i = 0; i < parameters.points; ++i ) {
		if ( parameters.fixedRadius ) {
			radius = 0.5f; // gives circles with 1px diameter
		} else {
			radius = points[i].radius;
		}
		radius *= parameters.sizingFactor;

		if ( !parameters.useColour ) {
			points[i].r = points[i].g = points[i].b = 0;
		}

		outputStream << "<circle cx=\"" << points[i].x << "\" cy=\"" << points[i].y << "\" r=\"" << radius << "\" fill=\"rgb(" << (unsigned int)points[i].r << "," << (unsigned int)points[i].g << "," << (unsigned int)points[i].b << ")\" />" << endl;
	}
	outputStream << "</svg>" << endl;

	outputStream.close();

	delete[] points;
}

int main( int argc, char *argv[] ) {
	using std::auto_ptr;
	using std::exception;
	using std::ofstream;
	using std::cout;
	using std::cerr;
	using std::endl;
	using std::setprecision;
	using std::setiosflags;
	using std::ios;
	using std::min;
	using boost::timer;

	auto_ptr<Voronoi::StipplingParameters> parameters;

	stippler_lib_init();
	::atexit(stippler_lib_destroy);

	try {
		parameters = parseArguments( argc, argv );
		if (parameters.get() == NULL) {
			stippler_lib_destroy();
			return 0;
		}
	} catch ( exception const &e ) {
		return -1;
	}

	STIPPLER_HANDLE stippler;

	ofstream log;
	if ( parameters->createLogs ) {
		log.open( "log.txt" );
	}

	stippler = create_stippler( parameters.get() );
	if (stippler == NULL) {
		delete[] parameters.get()->inputFile;
		cerr << stippler_getLastError() << endl;

		return -1;
	}

	write_configuration( cout, *(parameters.get()) );
	if ( parameters->createLogs ) {
		write_configuration( log, *(parameters.get()) );
	}

	int iteration = 0;
	float t = parameters->threshold + 1.0f;
	do {
		timer profiler;

		stippler_distribute(stippler);

		if ( parameters->createLogs ) {
			log << "Iteration " << (++iteration) << " completed in " << profiler.elapsed() << " seconds." << endl;
			cout << "Iteration " << iteration << " completed in " << profiler.elapsed() << " seconds." << endl;
		}

		t = stippler_getAverageDisplacement( stippler );

		if ( parameters->createLogs ) {
			log << "Current Displacement: " << t << endl;
			cout << "Current Displacement: " << t << endl;
		}

		cout << setiosflags(ios::fixed) << setprecision(2) << min((parameters->threshold / t * 100), 100.0f) << "% Complete" << endl;
	} while ( t > parameters->threshold );

	// render final result to SVG
	try {
		render( stippler, *(parameters.get()) );
	} catch (exception const &e) {
		cerr << e.what();
	}

	delete[] parameters.get()->inputFile;

	if ( parameters->createLogs ) {
		log.close();
	}

	destroy_stippler( stippler );

	return 0;
}
<commit_msg>Issue #14: Display total elapsed time at the end of the computation.<commit_after>/* The MIT License

Copyright (c) 2011 Sahab Yazdani

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

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

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

#ifdef WIN32
// needed by opengl
#define NOMINMAX
#include <windows.h>
#endif // WIN32

// stl
#include <string>
#include <memory>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <cmath>

// boost
#include <boost/timer.hpp>

// PNG library
#include <picopng.h>

// stippler library
#include <istippler.h>

// local
#include "parse_arguments.h"

void write_configuration( std::ostream &output, const Voronoi::StipplingParameters &parameters ) {
	using std::endl;
	using std::abs;
	using std::numeric_limits;

	output << "Generating " << parameters.points << " stipples." << endl;
	output << "Options: ";
	if ( parameters.useColour ) {
		output << "Coloured stipples";
	} else {
		output << "Black stipples";
	}

	if ( parameters.noOverlap ) {
		output << ", Non-overlapping stipples";
	} else {
		output << ", overlapping stipples";
	}

	if ( parameters.fixedRadius ) {
		output << ", Fixed radius";
	} else {
		output << ", Variable radius";
	}

	output << ", Subpixel density of " << parameters.subpixels;

	if ( abs( parameters.sizingFactor - 1.0f ) > numeric_limits<float>::epsilon() ) {
		output << ", Sizing factor of " << parameters.sizingFactor;
	}

	if ( abs( parameters.threshold - 0.1f ) > numeric_limits<float>::epsilon() ) {
		output << ", Displacement Threshold of " << parameters.threshold;
	}

	output << endl;
}

void render( STIPPLER_HANDLE stippler, const Voronoi::StipplingParameters &parameters ) {
	StipplePoint *points = new StipplePoint[parameters.points];

	stippler_getStipples(stippler, points);

	using namespace std;

	ofstream outputStream( parameters.outputFile.c_str() );

	if ( !outputStream.is_open() ) {
		stringstream s;
		s << "Unable to open output file " << parameters.outputFile;
		throw runtime_error(s.str());
	}

	PNG::PNGFile *png = PNG::load( parameters.inputFile );
	unsigned long w = png->w, h = png->h;
	PNG::freePng(png);

	outputStream << "<?xml version=\"1.0\" ?>" << endl;
	outputStream << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">" << endl;
	outputStream << "<svg width=\"" << w << "\" height=\"" << h << "\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">" << endl;

	float radius;
	for ( unsigned int i = 0; i < parameters.points; ++i ) {
		if ( parameters.fixedRadius ) {
			radius = 0.5f; // gives circles with 1px diameter
		} else {
			radius = points[i].radius;
		}
		radius *= parameters.sizingFactor;

		if ( !parameters.useColour ) {
			points[i].r = points[i].g = points[i].b = 0;
		}

		outputStream << "<circle cx=\"" << points[i].x << "\" cy=\"" << points[i].y << "\" r=\"" << radius << "\" fill=\"rgb(" << (unsigned int)points[i].r << "," << (unsigned int)points[i].g << "," << (unsigned int)points[i].b << ")\" />" << endl;
	}
	outputStream << "</svg>" << endl;

	outputStream.close();

	delete[] points;
}

int main( int argc, char *argv[] ) {
	using std::auto_ptr;
	using std::exception;
	using std::ofstream;
	using std::cout;
	using std::cerr;
	using std::endl;
	using std::setprecision;
	using std::setiosflags;
	using std::ios;
	using std::min;
	using boost::timer;

	timer total_profiler;

	auto_ptr<Voronoi::StipplingParameters> parameters;

	stippler_lib_init();
	::atexit(stippler_lib_destroy);

	try {
		parameters = parseArguments( argc, argv );
		if (parameters.get() == NULL) {
			stippler_lib_destroy();
			return 0;
		}
	} catch ( exception const &e ) {
		return -1;
	}

	STIPPLER_HANDLE stippler;

	ofstream log;
	if ( parameters->createLogs ) {
		log.open( "log.txt" );
	}

	stippler = create_stippler( parameters.get() );
	if (stippler == NULL) {
		delete[] parameters.get()->inputFile;
		cerr << stippler_getLastError() << endl;

		return -1;
	}

	write_configuration( cout, *(parameters.get()) );
	if ( parameters->createLogs ) {
		write_configuration( log, *(parameters.get()) );
	}

	int iteration = 0;
	float t = parameters->threshold + 1.0f;
	timer iteration_profiler;

	do {
		iteration_profiler.restart();

		stippler_distribute(stippler);

		t = stippler_getAverageDisplacement( stippler );

		if ( parameters->createLogs ) {
			log << "Current Displacement: " << t << endl;
			cout << "Current Displacement: " << t << endl;
		}

		cout << setiosflags(ios::fixed) << setprecision(2) << min((parameters->threshold / t * 100), 100.0f) << "% Complete" << endl;

		if ( parameters->createLogs ) {
			log << "Iteration " << (++iteration) << " completed in " << iteration_profiler.elapsed() << " seconds." << endl;
			cout << "Iteration " << iteration << " completed in " << iteration_profiler.elapsed() << " seconds." << endl;
		}
	} while ( t > parameters->threshold );

	// render final result to SVG
	try {
		render( stippler, *(parameters.get()) );
	} catch (exception const &e) {
		cerr << e.what();
	}

	delete[] parameters.get()->inputFile;

	if ( parameters->createLogs ) {
		log.close();
	}

	destroy_stippler( stippler );

	cout << "Completed in " << total_profiler.elapsed() << " seconds." << endl;

	return 0;
}
<|endoftext|>