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

  Program:   Insight Segmentation & Registration Toolkit

  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.

=========================================================================*/
#ifndef _itkGeometricJacobianDeterminantImageFilter_hxx
#define _itkGeometricJacobianDeterminantImageFilter_hxx

#include "itkGeometricJacobianDeterminantImageFilter.h"

#include "itkContinuousIndex.h"
#include "itkImageRegionIteratorWithIndex.h"
#include "itkNeighborhoodAlgorithm.h"
#include "itkProgressReporter.h"
#include "itkVectorCastImageFilter.h"
#include "itkZeroFluxNeumannBoundaryCondition.h"

#include "vnl/vnl_cross.h"

namespace itk
{

template <typename TInputImage, typename TRealType, typename TOutputImage>
GeometricJacobianDeterminantImageFilter<TInputImage, TRealType, TOutputImage>
::GeometricJacobianDeterminantImageFilter()
{
  this->m_Interpolator = ITK_NULLPTR;
  this->m_UndisplacedVolume = 0.0;
}

template <typename TInputImage, typename TRealType, typename TOutputImage>
void
GeometricJacobianDeterminantImageFilter<TInputImage, TRealType, TOutputImage>
::GenerateInputRequestedRegion() throw( InvalidRequestedRegionError )
{
  // call the superclass' implementation of this method
  Superclass::GenerateInputRequestedRegion();

  // get pointers to the input and output
  InputImagePointer  inputPtr =
    const_cast< InputImageType * >( this->GetInput() );
  OutputImagePointer outputPtr = this->GetOutput();

  if ( !inputPtr || !outputPtr )
    {
    return;
    }

  // get a copy of the input requested region (should equal the output
  // requested region)
  typename TInputImage::RegionType inputRequestedRegion;
  inputRequestedRegion = inputPtr->GetRequestedRegion();

  this->m_NeighborhoodRadius.Fill( 1 );

  // pad the input requested region by the operator radius
  inputRequestedRegion.PadByRadius( this->m_NeighborhoodRadius );

  // crop the input requested region at the input's largest possible region
  if ( inputRequestedRegion.Crop( inputPtr->GetLargestPossibleRegion() ) )
    {
    inputPtr->SetRequestedRegion( inputRequestedRegion );
    return;
    }
  else
    {
    // Couldn't crop the region (requested region is outside the largest
    // possible region).  Throw an exception.

    // store what we tried to request (prior to trying to crop)
    inputPtr->SetRequestedRegion( inputRequestedRegion );

    // build an exception
    InvalidRequestedRegionError e( __FILE__, __LINE__ );
    e.SetLocation( ITK_LOCATION );
    e.SetDescription( "Requested region is outside the largest possible region." );
    e.SetDataObject( inputPtr );
    throw e;
    }
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
void
GeometricJacobianDeterminantImageFilter<TInputImage, TRealType, TOutputImage>
::BeforeThreadedGenerateData()
{
  /** If the input needs casting to a real-valued vector type, create the
      appropriate image and set the m_RealValuedInputImage pointer to this
      image.  Otherwise just point to the input image. */
  if ( typeid( typename InputImageType::PixelType ) != typeid( RealVectorType ) )
    {
    typename VectorCastImageFilter<TInputImage, RealVectorImageType>::Pointer
      caster = VectorCastImageFilter<TInputImage, RealVectorImageType>::New();
    caster->SetInput( this->GetInput() );
    caster->Update();
    this->m_RealValuedInputImage = caster->GetOutput();
    }
  else
    {
    this->m_RealValuedInputImage
      = dynamic_cast<const RealVectorImageType *>( this->GetInput() );
    }

  this->m_Interpolator = InterpolatorType::New();
  this->m_Interpolator->SetInputImage( this->m_RealValuedInputImage );

  PointType origin( 0.0 );

  if( ImageDimension == 2 )
    {
    this->InitializeTriangularDeltaPoints();

    PointType pointA = origin + this->m_DeltaTriangularPointA;
    PointType pointB = origin + this->m_DeltaTriangularPointB;
    PointType pointC = origin + this->m_DeltaTriangularPointC;

    this->m_UndisplacedVolume = this->CalculateTriangularArea( pointA, pointB, pointC );
    }
  else if( ImageDimension == 3 )
    {
    this->InitializeTetrahedralDeltaPoints();

    PointType pointA = origin + this->m_DeltaTetrahedralPointA;
    PointType pointB = origin + this->m_DeltaTetrahedralPointB;
    PointType pointC = origin + this->m_DeltaTetrahedralPointC;
    PointType pointD = origin + this->m_DeltaTetrahedralPointD;

    this->m_UndisplacedVolume = this->CalculateTetrahedralVolume( pointA, pointB, pointC, pointD );
    }
  else
    {
    itkExceptionMacro( "Computations are only valid for ImageDimension = 2 or 3" );
    }
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
void
GeometricJacobianDeterminantImageFilter<TInputImage, TRealType, TOutputImage>
::InitializeTetrahedralDeltaPoints()
{
  // cf http://en.wikipedia.org/wiki/Tetrahedron#Formulas_for_a_regular_tetrahedron

  typename InputImageType::PointType originPoint;

  ContinuousIndex<RealType, ImageDimension> cidx;
  cidx.Fill( 0.0 );

  this->m_RealValuedInputImage->TransformContinuousIndexToPhysicalPoint( cidx, originPoint );

  typename InputImageType::PointType deltaPoint;

  cidx[0] = 0.5;
  cidx[1] = 0.0;
  cidx[2] = -0.5 / std::sqrt( 2.0 );

  this->m_RealValuedInputImage->TransformContinuousIndexToPhysicalPoint( cidx, deltaPoint );

  this->m_DeltaTetrahedralPointA = deltaPoint - originPoint;

  cidx[0] = -0.5;
  cidx[1] = 0.0;
  cidx[2] = -0.5 / std::sqrt( 2.0 );

  this->m_RealValuedInputImage->TransformContinuousIndexToPhysicalPoint( cidx, deltaPoint );

  this->m_DeltaTetrahedralPointB = deltaPoint - originPoint;

  cidx[0] = 0.0;
  cidx[1] = 0.5;
  cidx[2] = 0.5 / std::sqrt( 2.0 );

  this->m_RealValuedInputImage->TransformContinuousIndexToPhysicalPoint( cidx, deltaPoint );

  this->m_DeltaTetrahedralPointC = deltaPoint - originPoint;

  cidx[0] = 0.0;
  cidx[1] = -0.5;
  cidx[2] = 0.5 / std::sqrt( 2.0 );

  this->m_RealValuedInputImage->TransformContinuousIndexToPhysicalPoint( cidx, deltaPoint );

  this->m_DeltaTetrahedralPointD = deltaPoint - originPoint;
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
void
GeometricJacobianDeterminantImageFilter<TInputImage, TRealType, TOutputImage>
::InitializeTriangularDeltaPoints()
{
  typename InputImageType::PointType originPoint;

  ContinuousIndex<RealType, ImageDimension> cidx;
  cidx.Fill( 0.0 );

  this->m_RealValuedInputImage->TransformContinuousIndexToPhysicalPoint( cidx, originPoint );

  typename InputImageType::PointType deltaPoint;

  cidx[0] = 0.0;
  cidx[1] = 0.25 * std::sqrt( 3.0 );

  this->m_RealValuedInputImage->TransformContinuousIndexToPhysicalPoint( cidx, deltaPoint );

  this->m_DeltaTriangularPointA = deltaPoint - originPoint;

  cidx[0] = -0.5;
  cidx[1] = -0.25 * std::sqrt( 3.0 );

  this->m_RealValuedInputImage->TransformContinuousIndexToPhysicalPoint( cidx, deltaPoint );

  this->m_DeltaTriangularPointB = deltaPoint - originPoint;

  cidx[0] = 0.5;
  cidx[1] = -0.25 * std::sqrt( 3.0 );

  this->m_RealValuedInputImage->TransformContinuousIndexToPhysicalPoint( cidx, deltaPoint );

  this->m_DeltaTriangularPointC = deltaPoint - originPoint;
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
void
GeometricJacobianDeterminantImageFilter< TInputImage, TRealType, TOutputImage >
::ThreadedGenerateData( const OutputImageRegionType& outputRegionForThread,
                        ThreadIdType threadId )
{
  ZeroFluxNeumannBoundaryCondition<RealVectorImageType> nbc;
  ConstNeighborhoodIteratorType bit;
  ImageRegionIteratorWithIndex<TOutputImage> it;

  typename OutputImageType::Pointer outputPtr = this->GetOutput();

  // Find the data-set boundary "faces"
  typename NeighborhoodAlgorithm::
    ImageBoundaryFacesCalculator<RealVectorImageType>::FaceListType faceList;
  NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<RealVectorImageType> bC;
  faceList = bC( dynamic_cast<const RealVectorImageType *>
                   ( this->m_RealValuedInputImage.GetPointer() ),
                 outputRegionForThread, this->m_NeighborhoodRadius );

  typename NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<RealVectorImageType>::
    FaceListType::iterator fit;

  // Support progress methods/callbacks
  ProgressReporter progress( this, threadId, outputRegionForThread.GetNumberOfPixels() );

  // Process each of the data set faces.  The iterator is reinitialized on each
  // face so that it can determine whether or not to check for boundary
  // conditions.
  for ( fit = faceList.begin(); fit != faceList.end(); ++fit )
    {
    bit = ConstNeighborhoodIteratorType( this->m_NeighborhoodRadius,
                                         dynamic_cast<const RealVectorImageType *>
                                           ( m_RealValuedInputImage.GetPointer() ),
                                         *fit );
    it = ImageRegionIteratorWithIndex<TOutputImage>( outputPtr, *fit );
    bit.OverrideBoundaryCondition( &nbc );
    bit.GoToBegin();

    while ( ! bit.IsAtEnd() )
      {
      typename InputImageType::IndexType index = it.GetIndex();
      PointType imagePoint;
      outputPtr->TransformIndexToPhysicalPoint( index, imagePoint );

      RealType displacedVolume = 0.0;
      if( ImageDimension == 2 )
        {
        typename InterpolatorType::PointType pointA;
        pointA.CastFrom( imagePoint + this->m_DeltaTriangularPointA );
        typename InterpolatorType::PointType pointB;
        pointB.CastFrom( imagePoint + this->m_DeltaTriangularPointB );
        typename InterpolatorType::PointType pointC;
        pointC.CastFrom( imagePoint + this->m_DeltaTriangularPointC );

        PointType displacedPointA = pointA + this->m_Interpolator->Evaluate( pointA );
        PointType displacedPointB = pointB + this->m_Interpolator->Evaluate( pointB );
        PointType displacedPointC = pointC + this->m_Interpolator->Evaluate( pointC );

        displacedVolume = this->CalculateTriangularArea( displacedPointA, displacedPointB, displacedPointC );

        }
      else if( ImageDimension == 3 )
        {
        typename InterpolatorType::PointType pointA;
        pointA.CastFrom( imagePoint + this->m_DeltaTetrahedralPointA );
        typename InterpolatorType::PointType pointB;
        pointB.CastFrom( imagePoint + this->m_DeltaTetrahedralPointB );
        typename InterpolatorType::PointType pointC;
        pointC.CastFrom( imagePoint + this->m_DeltaTetrahedralPointC );
        typename InterpolatorType::PointType pointD;
        pointD.CastFrom( imagePoint + this->m_DeltaTetrahedralPointD );

        PointType displacedPointA = pointA + this->m_Interpolator->Evaluate( pointA );
        PointType displacedPointB = pointB + this->m_Interpolator->Evaluate( pointB );
        PointType displacedPointC = pointC + this->m_Interpolator->Evaluate( pointC );
        PointType displacedPointD = pointD + this->m_Interpolator->Evaluate( pointD );

        displacedVolume = this->CalculateTetrahedralVolume( displacedPointA, displacedPointB, displacedPointC, displacedPointD );
        }

      RealType volumeDifferential = displacedVolume / this->m_UndisplacedVolume;
      it.Set( volumeDifferential );
      ++bit;
      ++it;
      progress.CompletedPixel();
      }
    }
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
typename
GeometricJacobianDeterminantImageFilter< TInputImage, TRealType, TOutputImage >::RealType
GeometricJacobianDeterminantImageFilter< TInputImage, TRealType, TOutputImage >
::CalculateTetrahedralVolume( PointType a, PointType b, PointType c, PointType d )
{
  vnl_vector_ref<double> ad = ( a - d ).GetVnlVector();
  vnl_vector_ref<double> bd = ( b - d ).GetVnlVector();
  vnl_vector_ref<double> cd = ( c - d ).GetVnlVector();

  vnl_vector<double> bdxcd = vnl_cross_3d( bd, cd );

  RealType volume = vnl_math_abs( ad[0] * bdxcd[0] +  ad[1] * bdxcd[1] + ad[2] * bdxcd[2] ) / 6.0;

  return volume;
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
typename
GeometricJacobianDeterminantImageFilter< TInputImage, TRealType, TOutputImage >::RealType
GeometricJacobianDeterminantImageFilter< TInputImage, TRealType, TOutputImage >
::CalculateTriangularArea( PointType a, PointType b, PointType c )
{
  RealVectorType ab = ( a - b );
  RealVectorType ac = ( a - c );

  RealType area = 0.5 * vnl_math_abs( ab[0] * ac[1] - ac[0] * ab[1] );

  return area;
}

template <typename TInputImage, typename TRealType, typename TOutputImage>
void
GeometricJacobianDeterminantImageFilter<TInputImage, TRealType, TOutputImage>
::PrintSelf( std::ostream& os, Indent indent ) const
{
  Superclass::PrintSelf(os,indent);

  os << indent << "m_RealValuedInputImage = "
     << m_RealValuedInputImage.GetPointer()
     << std::endl;
}

} // end namespace itk

#endif
<commit_msg>BUG: wrong vnl_vector type causing problems on Centos7.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit

  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.

=========================================================================*/
#ifndef _itkGeometricJacobianDeterminantImageFilter_hxx
#define _itkGeometricJacobianDeterminantImageFilter_hxx

#include "itkGeometricJacobianDeterminantImageFilter.h"

#include "itkContinuousIndex.h"
#include "itkImageRegionIteratorWithIndex.h"
#include "itkNeighborhoodAlgorithm.h"
#include "itkProgressReporter.h"
#include "itkVectorCastImageFilter.h"
#include "itkZeroFluxNeumannBoundaryCondition.h"

#include "vnl/vnl_cross.h"

namespace itk
{

template <typename TInputImage, typename TRealType, typename TOutputImage>
GeometricJacobianDeterminantImageFilter<TInputImage, TRealType, TOutputImage>
::GeometricJacobianDeterminantImageFilter()
{
  this->m_Interpolator = ITK_NULLPTR;
  this->m_UndisplacedVolume = 0.0;
}

template <typename TInputImage, typename TRealType, typename TOutputImage>
void
GeometricJacobianDeterminantImageFilter<TInputImage, TRealType, TOutputImage>
::GenerateInputRequestedRegion() throw( InvalidRequestedRegionError )
{
  // call the superclass' implementation of this method
  Superclass::GenerateInputRequestedRegion();

  // get pointers to the input and output
  InputImagePointer  inputPtr =
    const_cast< InputImageType * >( this->GetInput() );
  OutputImagePointer outputPtr = this->GetOutput();

  if ( !inputPtr || !outputPtr )
    {
    return;
    }

  // get a copy of the input requested region (should equal the output
  // requested region)
  typename TInputImage::RegionType inputRequestedRegion;
  inputRequestedRegion = inputPtr->GetRequestedRegion();

  this->m_NeighborhoodRadius.Fill( 1 );

  // pad the input requested region by the operator radius
  inputRequestedRegion.PadByRadius( this->m_NeighborhoodRadius );

  // crop the input requested region at the input's largest possible region
  if ( inputRequestedRegion.Crop( inputPtr->GetLargestPossibleRegion() ) )
    {
    inputPtr->SetRequestedRegion( inputRequestedRegion );
    return;
    }
  else
    {
    // Couldn't crop the region (requested region is outside the largest
    // possible region).  Throw an exception.

    // store what we tried to request (prior to trying to crop)
    inputPtr->SetRequestedRegion( inputRequestedRegion );

    // build an exception
    InvalidRequestedRegionError e( __FILE__, __LINE__ );
    e.SetLocation( ITK_LOCATION );
    e.SetDescription( "Requested region is outside the largest possible region." );
    e.SetDataObject( inputPtr );
    throw e;
    }
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
void
GeometricJacobianDeterminantImageFilter<TInputImage, TRealType, TOutputImage>
::BeforeThreadedGenerateData()
{
  /** If the input needs casting to a real-valued vector type, create the
      appropriate image and set the m_RealValuedInputImage pointer to this
      image.  Otherwise just point to the input image. */
  if ( typeid( typename InputImageType::PixelType ) != typeid( RealVectorType ) )
    {
    typename VectorCastImageFilter<TInputImage, RealVectorImageType>::Pointer
      caster = VectorCastImageFilter<TInputImage, RealVectorImageType>::New();
    caster->SetInput( this->GetInput() );
    caster->Update();
    this->m_RealValuedInputImage = caster->GetOutput();
    }
  else
    {
    this->m_RealValuedInputImage
      = dynamic_cast<const RealVectorImageType *>( this->GetInput() );
    }

  this->m_Interpolator = InterpolatorType::New();
  this->m_Interpolator->SetInputImage( this->m_RealValuedInputImage );

  PointType origin( 0.0 );

  if( ImageDimension == 2 )
    {
    this->InitializeTriangularDeltaPoints();

    PointType pointA = origin + this->m_DeltaTriangularPointA;
    PointType pointB = origin + this->m_DeltaTriangularPointB;
    PointType pointC = origin + this->m_DeltaTriangularPointC;

    this->m_UndisplacedVolume = this->CalculateTriangularArea( pointA, pointB, pointC );
    }
  else if( ImageDimension == 3 )
    {
    this->InitializeTetrahedralDeltaPoints();

    PointType pointA = origin + this->m_DeltaTetrahedralPointA;
    PointType pointB = origin + this->m_DeltaTetrahedralPointB;
    PointType pointC = origin + this->m_DeltaTetrahedralPointC;
    PointType pointD = origin + this->m_DeltaTetrahedralPointD;

    this->m_UndisplacedVolume = this->CalculateTetrahedralVolume( pointA, pointB, pointC, pointD );
    }
  else
    {
    itkExceptionMacro( "Computations are only valid for ImageDimension = 2 or 3" );
    }
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
void
GeometricJacobianDeterminantImageFilter<TInputImage, TRealType, TOutputImage>
::InitializeTetrahedralDeltaPoints()
{
  // cf http://en.wikipedia.org/wiki/Tetrahedron#Formulas_for_a_regular_tetrahedron

  typename InputImageType::PointType originPoint;

  ContinuousIndex<RealType, ImageDimension> cidx;
  cidx.Fill( 0.0 );

  this->m_RealValuedInputImage->TransformContinuousIndexToPhysicalPoint( cidx, originPoint );

  typename InputImageType::PointType deltaPoint;

  cidx[0] = 0.5;
  cidx[1] = 0.0;
  cidx[2] = -0.5 / std::sqrt( 2.0 );

  this->m_RealValuedInputImage->TransformContinuousIndexToPhysicalPoint( cidx, deltaPoint );

  this->m_DeltaTetrahedralPointA = deltaPoint - originPoint;

  cidx[0] = -0.5;
  cidx[1] = 0.0;
  cidx[2] = -0.5 / std::sqrt( 2.0 );

  this->m_RealValuedInputImage->TransformContinuousIndexToPhysicalPoint( cidx, deltaPoint );

  this->m_DeltaTetrahedralPointB = deltaPoint - originPoint;

  cidx[0] = 0.0;
  cidx[1] = 0.5;
  cidx[2] = 0.5 / std::sqrt( 2.0 );

  this->m_RealValuedInputImage->TransformContinuousIndexToPhysicalPoint( cidx, deltaPoint );

  this->m_DeltaTetrahedralPointC = deltaPoint - originPoint;

  cidx[0] = 0.0;
  cidx[1] = -0.5;
  cidx[2] = 0.5 / std::sqrt( 2.0 );

  this->m_RealValuedInputImage->TransformContinuousIndexToPhysicalPoint( cidx, deltaPoint );

  this->m_DeltaTetrahedralPointD = deltaPoint - originPoint;
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
void
GeometricJacobianDeterminantImageFilter<TInputImage, TRealType, TOutputImage>
::InitializeTriangularDeltaPoints()
{
  typename InputImageType::PointType originPoint;

  ContinuousIndex<RealType, ImageDimension> cidx;
  cidx.Fill( 0.0 );

  this->m_RealValuedInputImage->TransformContinuousIndexToPhysicalPoint( cidx, originPoint );

  typename InputImageType::PointType deltaPoint;

  cidx[0] = 0.0;
  cidx[1] = 0.25 * std::sqrt( 3.0 );

  this->m_RealValuedInputImage->TransformContinuousIndexToPhysicalPoint( cidx, deltaPoint );

  this->m_DeltaTriangularPointA = deltaPoint - originPoint;

  cidx[0] = -0.5;
  cidx[1] = -0.25 * std::sqrt( 3.0 );

  this->m_RealValuedInputImage->TransformContinuousIndexToPhysicalPoint( cidx, deltaPoint );

  this->m_DeltaTriangularPointB = deltaPoint - originPoint;

  cidx[0] = 0.5;
  cidx[1] = -0.25 * std::sqrt( 3.0 );

  this->m_RealValuedInputImage->TransformContinuousIndexToPhysicalPoint( cidx, deltaPoint );

  this->m_DeltaTriangularPointC = deltaPoint - originPoint;
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
void
GeometricJacobianDeterminantImageFilter< TInputImage, TRealType, TOutputImage >
::ThreadedGenerateData( const OutputImageRegionType& outputRegionForThread,
                        ThreadIdType threadId )
{
  ZeroFluxNeumannBoundaryCondition<RealVectorImageType> nbc;
  ConstNeighborhoodIteratorType bit;
  ImageRegionIteratorWithIndex<TOutputImage> it;

  typename OutputImageType::Pointer outputPtr = this->GetOutput();

  // Find the data-set boundary "faces"
  typename NeighborhoodAlgorithm::
    ImageBoundaryFacesCalculator<RealVectorImageType>::FaceListType faceList;
  NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<RealVectorImageType> bC;
  faceList = bC( dynamic_cast<const RealVectorImageType *>
                   ( this->m_RealValuedInputImage.GetPointer() ),
                 outputRegionForThread, this->m_NeighborhoodRadius );

  typename NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<RealVectorImageType>::
    FaceListType::iterator fit;

  // Support progress methods/callbacks
  ProgressReporter progress( this, threadId, outputRegionForThread.GetNumberOfPixels() );

  // Process each of the data set faces.  The iterator is reinitialized on each
  // face so that it can determine whether or not to check for boundary
  // conditions.
  for ( fit = faceList.begin(); fit != faceList.end(); ++fit )
    {
    bit = ConstNeighborhoodIteratorType( this->m_NeighborhoodRadius,
                                         dynamic_cast<const RealVectorImageType *>
                                           ( m_RealValuedInputImage.GetPointer() ),
                                         *fit );
    it = ImageRegionIteratorWithIndex<TOutputImage>( outputPtr, *fit );
    bit.OverrideBoundaryCondition( &nbc );
    bit.GoToBegin();

    while ( ! bit.IsAtEnd() )
      {
      typename InputImageType::IndexType index = it.GetIndex();
      PointType imagePoint;
      outputPtr->TransformIndexToPhysicalPoint( index, imagePoint );

      RealType displacedVolume = 0.0;
      if( ImageDimension == 2 )
        {
        typename InterpolatorType::PointType pointA;
        pointA.CastFrom( imagePoint + this->m_DeltaTriangularPointA );
        typename InterpolatorType::PointType pointB;
        pointB.CastFrom( imagePoint + this->m_DeltaTriangularPointB );
        typename InterpolatorType::PointType pointC;
        pointC.CastFrom( imagePoint + this->m_DeltaTriangularPointC );

        PointType displacedPointA = pointA + this->m_Interpolator->Evaluate( pointA );
        PointType displacedPointB = pointB + this->m_Interpolator->Evaluate( pointB );
        PointType displacedPointC = pointC + this->m_Interpolator->Evaluate( pointC );

        displacedVolume = this->CalculateTriangularArea( displacedPointA, displacedPointB, displacedPointC );

        }
      else if( ImageDimension == 3 )
        {
        typename InterpolatorType::PointType pointA;
        pointA.CastFrom( imagePoint + this->m_DeltaTetrahedralPointA );
        typename InterpolatorType::PointType pointB;
        pointB.CastFrom( imagePoint + this->m_DeltaTetrahedralPointB );
        typename InterpolatorType::PointType pointC;
        pointC.CastFrom( imagePoint + this->m_DeltaTetrahedralPointC );
        typename InterpolatorType::PointType pointD;
        pointD.CastFrom( imagePoint + this->m_DeltaTetrahedralPointD );

        PointType displacedPointA = pointA + this->m_Interpolator->Evaluate( pointA );
        PointType displacedPointB = pointB + this->m_Interpolator->Evaluate( pointB );
        PointType displacedPointC = pointC + this->m_Interpolator->Evaluate( pointC );
        PointType displacedPointD = pointD + this->m_Interpolator->Evaluate( pointD );
        displacedVolume = this->CalculateTetrahedralVolume( displacedPointA, displacedPointB, displacedPointC, displacedPointD );
        }
      RealType volumeDifferential = displacedVolume / ( this->m_UndisplacedVolume );
      it.Set( volumeDifferential );
      ++bit;
      ++it;
      progress.CompletedPixel();
      }
    }
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
typename
GeometricJacobianDeterminantImageFilter< TInputImage, TRealType, TOutputImage >::RealType
GeometricJacobianDeterminantImageFilter< TInputImage, TRealType, TOutputImage >
::CalculateTetrahedralVolume( PointType a, PointType b, PointType c, PointType d )
{
  vnl_vector<double> ad = ( a - d ).GetVnlVector();
  vnl_vector<double> bd = ( b - d ).GetVnlVector();
  vnl_vector<double> cd = ( c - d ).GetVnlVector();
  vnl_vector<double> bdxcd = vnl_cross_3d( bd, cd );
  RealType volume = vnl_math_abs( ad[0] * bdxcd[0] +  ad[1] * bdxcd[1] + ad[2] * bdxcd[2] ) / 6.0;
  return volume;
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
typename
GeometricJacobianDeterminantImageFilter< TInputImage, TRealType, TOutputImage >::RealType
GeometricJacobianDeterminantImageFilter< TInputImage, TRealType, TOutputImage >
::CalculateTriangularArea( PointType a, PointType b, PointType c )
{
  RealVectorType ab = ( a - b );
  RealVectorType ac = ( a - c );

  RealType area = 0.5 * vnl_math_abs( ab[0] * ac[1] - ac[0] * ab[1] );

  return area;
}

template <typename TInputImage, typename TRealType, typename TOutputImage>
void
GeometricJacobianDeterminantImageFilter<TInputImage, TRealType, TOutputImage>
::PrintSelf( std::ostream& os, Indent indent ) const
{
  Superclass::PrintSelf(os,indent);

  os << indent << "m_RealValuedInputImage = "
     << m_RealValuedInputImage.GetPointer()
     << std::endl;
}

} // end namespace itk

#endif
<|endoftext|>


<commit_before>// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/eval/eval/gbdt.h>
#include <vespa/eval/eval/vm_forest.h>
#include <vespa/eval/eval/llvm/deinline_forest.h>
#include <vespa/eval/eval/llvm/compiled_function.h>
#include <vespa/eval/eval/function.h>
#include <vespa/vespalib/util/benchmark_timer.h>
#include <vespa/vespalib/util/stringfmt.h>
#include "model.cpp"

using namespace vespalib::eval;
using namespace vespalib::eval::nodes;
using namespace vespalib::eval::gbdt;

//-----------------------------------------------------------------------------

struct CompileStrategy {
    virtual const char *name() const = 0;
    virtual const char *code_name() const = 0;
    virtual CompiledFunction compile(const Function &function) const = 0;
    bool is_same(const CompileStrategy &rhs) const {
        return (this == &rhs);
    }
    virtual ~CompileStrategy() {}
};

struct NullStrategy : CompileStrategy {
    virtual const char *name() const {
        return "none";
    }
    virtual const char *code_name() const {
        return "Optimize::none";
    }
    virtual CompiledFunction compile(const Function &function) const {
        return CompiledFunction(function, PassParams::ARRAY, Optimize::none);
    }
};
NullStrategy none;

struct VMForestStrategy : CompileStrategy {
    virtual const char *name() const {
        return "vm-forest";
    }
    virtual const char *code_name() const {
        return "VMForest::optimize_chain";
    }
    virtual CompiledFunction compile(const Function &function) const {
        return CompiledFunction(function, PassParams::ARRAY, VMForest::optimize_chain);
    }
};
VMForestStrategy vm_forest;

struct DeinlineForestStrategy : CompileStrategy {
    virtual const char *name() const {
        return "deinline-forest";
    }
    virtual const char *code_name() const {
        return "DeinlineForest::optimize_chain";
    }
    virtual CompiledFunction compile(const Function &function) const {
        return CompiledFunction(function, PassParams::ARRAY, DeinlineForest::optimize_chain);
    }
};
DeinlineForestStrategy deinline_forest;

//-----------------------------------------------------------------------------

struct Option {
    size_t id;
    const CompileStrategy &strategy;
    bool is_same(const Option &rhs) const { return strategy.is_same(rhs.strategy); }
    const char *name() const { return strategy.name(); }
    CompiledFunction compile(const Function &function) const { return strategy.compile(function); }
    const char *code_name() const { return strategy.code_name(); }
};

std::vector<Option> all_options({{0, none},{1, vm_forest}});

//-----------------------------------------------------------------------------

struct Result {
    double us;
    size_t opt_idx;
    bool operator<(const Result &rhs) {
        return (us < rhs.us);
    }
};

struct Segment {
    double min;
    Option option;
    vespalib::string build() const {
        return vespalib::make_string("{%g, %zu}", min, option.id);
    }
};

struct Plan {
    std::vector<Segment> segments;
    void add(const Segment &seg) {
        if (segments.empty()) {
            segments.push_back(seg);
        } else {
            if (!segments.back().option.is_same(seg.option)) {
                segments.push_back(seg);
            }
        }
    }
    vespalib::string build() const {
        vespalib::string plan;
        plan.append("{");
        for (size_t i = 0; i < segments.size(); ++i) {
            if (i > 0) {
                plan.append(", ");
            }
            plan += segments[i].build();
        }
        plan.append("}");
        return plan;
    }
};

//-----------------------------------------------------------------------------

bool crop(const std::vector<Option> &options, const Option &opt, size_t &end) {
    for (size_t i = 0; i < end; ++i) {
        if (options[i].is_same(opt)) {
            end = i;
            return true;
        }
    }
    return false;
}

std::vector<Option> keep_contested(const std::vector<Option> &a,
                                   const std::vector<Option> &b)
{
    size_t end = b.size();
    std::vector<Option> ret;
    for (size_t i = 0; (i < a.size()) && (end > 0); ++i) {
        if (crop(b, a[i], end)) {
            ret.push_back(a[i]);
        }
    }
    return ret;
}

std::vector<Option> find_order(const ForestParams &params,
                               const std::vector<Option> &options,
                               size_t num_trees)
{
    std::vector<Result> results;
    Function forest = make_forest(params, num_trees);
    for (size_t i = 0; i < options.size(); ++i) {
        CompiledFunction compiled_function = options[i].compile(forest);
        std::vector<double> inputs(compiled_function.num_params(), 0.5);
        results.push_back({compiled_function.estimate_cost_us(inputs), i});
        fprintf(stderr, "  %20s@%6zu: %16g us (inputs: %zu)\n",
                options[i].name(), num_trees, results.back().us,
                inputs.size());
    }
    std::sort(results.begin(), results.end());
    std::vector<Option> ret;
    for (auto result: results) {
        ret.push_back(options[result.opt_idx]);
    }
    return ret;
}

double expected_path(const ForestParams &params, size_t num_trees) {
    return ForestStats(extract_trees(make_forest(params, num_trees).root())).total_expected_path_length;
}

void explore_segment(const ForestParams &params,
                     const std::vector<Option> &min_order,
                     const std::vector<Option> &max_order,
                     size_t min_trees, size_t max_trees,
                     Plan &plan_out)
{
    assert(min_trees != max_trees);
    std::vector<Option> options = keep_contested(min_order, max_order);
    assert(!options.empty());
    if (options.size() == 1) {
        plan_out.add(Segment{expected_path(params, min_trees), options[0]});
    } else {
        if ((max_trees - min_trees) == 1) {
            plan_out.add(Segment{expected_path(params, min_trees), min_order[0]});
            plan_out.add(Segment{expected_path(params, max_trees), max_order[0]});
        } else {
            size_t num_trees = (min_trees + max_trees) / 2;
            std::vector<Option> order = find_order(params, options, num_trees);
            explore_segment(params, min_order, order, min_trees, num_trees, plan_out);
            explore_segment(params, order, max_order, num_trees, max_trees, plan_out);
        }
    }
}

Plan find_plan(const ForestParams &params, std::initializer_list<size_t> limits) {
    Plan plan;
    auto num_trees = limits.begin();
    size_t min_trees = *num_trees++;
    std::vector<Option> min_order = find_order(params, all_options, min_trees);
    while (num_trees != limits.end()) {
        size_t max_trees = *num_trees++;
        std::vector<Option> max_order = find_order(params, all_options, max_trees);
        explore_segment(params, min_order, max_order, min_trees, max_trees, plan);
        std::swap(min_trees, max_trees);
        std::swap(min_order, max_order);
    }
    return plan;
}

//-----------------------------------------------------------------------------

void dump_options(const std::vector<Option> &options) {
    fprintf(stdout, "std::vector<Optimize::Chain> options({");
    for (size_t i = 0; i < options.size(); ++i) {
        if (i > 0) {
            fprintf(stdout, ", ");
        }
        fprintf(stdout, "%s", options[i].code_name());
    }
    fprintf(stdout, "});\n");
    fflush(stdout);
}

void dump_param_values(const char *name, const std::vector<size_t> &values) {
    fprintf(stdout, "std::vector<size_t> %s({", name);
    for (size_t i = 0; i < values.size(); ++i) {
        if (i > 0) {
            fprintf(stdout, ", ");
        }
        fprintf(stdout, "%zu", values[i]);
    }
    fprintf(stdout, "});\n");
    fflush(stdout);
}

void dump_plan(const ForestParams &params, const Plan &plan) {
    fprintf(stdout, "{{%zu, %zu}, %s}",
            params.less_percent, params.tree_size,
            plan.build().c_str());
}

//-----------------------------------------------------------------------------

TEST("find optimization plans") {
    std::vector<size_t> less_percent_values({90, 100});
    std::vector<size_t> tree_size_values(
            {2, 3, 4, 5, 6, 7, 8,
                    9,  10, 11, 12,  13,  14,  15,  16,
                    18, 20, 22, 24,  26,  28,  30,  32,
                    36, 40, 44, 48,  52,  56,  60,  64,
                    72, 80, 88, 96, 104, 112, 120, 128});

    dump_options(all_options);
    dump_param_values("less_percent_values", less_percent_values);
    dump_param_values("tree_size_values", tree_size_values);

    size_t num_plans = 0;
    fprintf(stdout, "std::map<Params,Plan> plan_repo({");
    for (size_t less_percent: less_percent_values) {
        for (size_t tree_size: tree_size_values) {
            ForestParams params(1234u, less_percent, tree_size);
            fprintf(stdout, "%s\n", (num_plans++ == 0) ? "" : ",");
            fflush(stdout);
            fprintf(stdout, "  ");
            Plan plan = find_plan(params, {8, 512});
            dump_plan(params, plan);
        }
    }
    fprintf(stdout, "});\n");
}

//-----------------------------------------------------------------------------

TEST_MAIN() { TEST_RUN_ALL(); }
<commit_msg>also log lazy time/factor in explore benchmark<commit_after>// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/eval/eval/gbdt.h>
#include <vespa/eval/eval/vm_forest.h>
#include <vespa/eval/eval/llvm/deinline_forest.h>
#include <vespa/eval/eval/llvm/compiled_function.h>
#include <vespa/eval/eval/function.h>
#include <vespa/vespalib/util/benchmark_timer.h>
#include <vespa/vespalib/util/stringfmt.h>
#include "model.cpp"

using namespace vespalib::eval;
using namespace vespalib::eval::nodes;
using namespace vespalib::eval::gbdt;

double budget = 2.0;

//-----------------------------------------------------------------------------

struct CompileStrategy {
    virtual const char *name() const = 0;
    virtual const char *code_name() const = 0;
    virtual CompiledFunction compile(const Function &function) const = 0;
    virtual CompiledFunction compile_lazy(const Function &function) const = 0;
    bool is_same(const CompileStrategy &rhs) const {
        return (this == &rhs);
    }
    virtual ~CompileStrategy() {}
};

struct NullStrategy : CompileStrategy {
    const char *name() const override {
        return "none";
    }
    const char *code_name() const override {
        return "Optimize::none";
    }
    CompiledFunction compile(const Function &function) const override {
        return CompiledFunction(function, PassParams::ARRAY, Optimize::none);
    }
    CompiledFunction compile_lazy(const Function &function) const override {
        return CompiledFunction(function, PassParams::LAZY, Optimize::none);
    }
};
NullStrategy none;

struct VMForestStrategy : CompileStrategy {
    const char *name() const override {
        return "vm-forest";
    }
    const char *code_name() const override {
        return "VMForest::optimize_chain";
    }
    CompiledFunction compile(const Function &function) const override {
        return CompiledFunction(function, PassParams::ARRAY, VMForest::optimize_chain);
    }
    CompiledFunction compile_lazy(const Function &function) const override {
        return CompiledFunction(function, PassParams::LAZY, VMForest::optimize_chain);
    }
};
VMForestStrategy vm_forest;

struct DeinlineForestStrategy : CompileStrategy {
    const char *name() const override {
        return "deinline-forest";
    }
    const char *code_name() const override {
        return "DeinlineForest::optimize_chain";
    }
    CompiledFunction compile(const Function &function) const override {
        return CompiledFunction(function, PassParams::ARRAY, DeinlineForest::optimize_chain);
    }
    CompiledFunction compile_lazy(const Function &function) const override {
        return CompiledFunction(function, PassParams::LAZY, DeinlineForest::optimize_chain);
    }
};
DeinlineForestStrategy deinline_forest;

//-----------------------------------------------------------------------------

struct Option {
    size_t id;
    const CompileStrategy &strategy;
    bool is_same(const Option &rhs) const { return strategy.is_same(rhs.strategy); }
    const char *name() const { return strategy.name(); }
    CompiledFunction compile(const Function &function) const { return strategy.compile(function); }
    CompiledFunction compile_lazy(const Function &function) const { return strategy.compile_lazy(function); }
    const char *code_name() const { return strategy.code_name(); }
};

std::vector<Option> all_options({{0, none},{1, vm_forest}});

//-----------------------------------------------------------------------------

struct Result {
    double us;
    size_t opt_idx;
    bool operator<(const Result &rhs) {
        return (us < rhs.us);
    }
};

struct Segment {
    double min;
    Option option;
    vespalib::string build() const {
        return vespalib::make_string("{%g, %zu}", min, option.id);
    }
};

struct Plan {
    std::vector<Segment> segments;
    void add(const Segment &seg) {
        if (segments.empty()) {
            segments.push_back(seg);
        } else {
            if (!segments.back().option.is_same(seg.option)) {
                segments.push_back(seg);
            }
        }
    }
    vespalib::string build() const {
        vespalib::string plan;
        plan.append("{");
        for (size_t i = 0; i < segments.size(); ++i) {
            if (i > 0) {
                plan.append(", ");
            }
            plan += segments[i].build();
        }
        plan.append("}");
        return plan;
    }
};

//-----------------------------------------------------------------------------

bool crop(const std::vector<Option> &options, const Option &opt, size_t &end) {
    for (size_t i = 0; i < end; ++i) {
        if (options[i].is_same(opt)) {
            end = i;
            return true;
        }
    }
    return false;
}

std::vector<Option> keep_contested(const std::vector<Option> &a,
                                   const std::vector<Option> &b)
{
    size_t end = b.size();
    std::vector<Option> ret;
    for (size_t i = 0; (i < a.size()) && (end > 0); ++i) {
        if (crop(b, a[i], end)) {
            ret.push_back(a[i]);
        }
    }
    return ret;
}

std::vector<Option> find_order(const ForestParams &params,
                               const std::vector<Option> &options,
                               size_t num_trees)
{
    std::vector<Result> results;
    Function forest = make_forest(params, num_trees);
    for (size_t i = 0; i < options.size(); ++i) {
        CompiledFunction compiled_function = options[i].compile(forest);
        CompiledFunction compiled_function_lazy = options[i].compile_lazy(forest);
        std::vector<double> inputs(compiled_function.num_params(), 0.5);
        results.push_back({compiled_function.estimate_cost_us(inputs, budget), i});
        double lazy_time = compiled_function_lazy.estimate_cost_us(inputs, budget);
        double lazy_factor = lazy_time / results.back().us;
        fprintf(stderr, "  %20s@%6zu: %16g us (inputs: %zu) [lazy: %g us, factor: %g]\n",
                options[i].name(), num_trees, results.back().us,
                inputs.size(), lazy_time, lazy_factor);
    }
    std::sort(results.begin(), results.end());
    std::vector<Option> ret;
    for (auto result: results) {
        ret.push_back(options[result.opt_idx]);
    }
    return ret;
}

double expected_path(const ForestParams &params, size_t num_trees) {
    return ForestStats(extract_trees(make_forest(params, num_trees).root())).total_expected_path_length;
}

void explore_segment(const ForestParams &params,
                     const std::vector<Option> &min_order,
                     const std::vector<Option> &max_order,
                     size_t min_trees, size_t max_trees,
                     Plan &plan_out)
{
    assert(min_trees != max_trees);
    std::vector<Option> options = keep_contested(min_order, max_order);
    assert(!options.empty());
    if (options.size() == 1) {
        plan_out.add(Segment{expected_path(params, min_trees), options[0]});
    } else {
        if ((max_trees - min_trees) == 1) {
            plan_out.add(Segment{expected_path(params, min_trees), min_order[0]});
            plan_out.add(Segment{expected_path(params, max_trees), max_order[0]});
        } else {
            size_t num_trees = (min_trees + max_trees) / 2;
            std::vector<Option> order = find_order(params, options, num_trees);
            explore_segment(params, min_order, order, min_trees, num_trees, plan_out);
            explore_segment(params, order, max_order, num_trees, max_trees, plan_out);
        }
    }
}

Plan find_plan(const ForestParams &params, std::initializer_list<size_t> limits) {
    Plan plan;
    auto num_trees = limits.begin();
    size_t min_trees = *num_trees++;
    std::vector<Option> min_order = find_order(params, all_options, min_trees);
    while (num_trees != limits.end()) {
        size_t max_trees = *num_trees++;
        std::vector<Option> max_order = find_order(params, all_options, max_trees);
        explore_segment(params, min_order, max_order, min_trees, max_trees, plan);
        std::swap(min_trees, max_trees);
        std::swap(min_order, max_order);
    }
    return plan;
}

//-----------------------------------------------------------------------------

void dump_options(const std::vector<Option> &options) {
    fprintf(stdout, "std::vector<Optimize::Chain> options({");
    for (size_t i = 0; i < options.size(); ++i) {
        if (i > 0) {
            fprintf(stdout, ", ");
        }
        fprintf(stdout, "%s", options[i].code_name());
    }
    fprintf(stdout, "});\n");
    fflush(stdout);
}

void dump_param_values(const char *name, const std::vector<size_t> &values) {
    fprintf(stdout, "std::vector<size_t> %s({", name);
    for (size_t i = 0; i < values.size(); ++i) {
        if (i > 0) {
            fprintf(stdout, ", ");
        }
        fprintf(stdout, "%zu", values[i]);
    }
    fprintf(stdout, "});\n");
    fflush(stdout);
}

void dump_plan(const ForestParams &params, const Plan &plan) {
    fprintf(stdout, "{{%zu, %zu}, %s}",
            params.less_percent, params.tree_size,
            plan.build().c_str());
}

//-----------------------------------------------------------------------------

TEST("find optimization plans") {
    std::vector<size_t> less_percent_values({90, 100});
    std::vector<size_t> tree_size_values(
            {2, 3, 4, 5, 6, 7, 8,
                    9,  10, 11, 12,  13,  14,  15,  16,
                    18, 20, 22, 24,  26,  28,  30,  32,
                    36, 40, 44, 48,  52,  56,  60,  64,
                    72, 80, 88, 96, 104, 112, 120, 128});

    dump_options(all_options);
    dump_param_values("less_percent_values", less_percent_values);
    dump_param_values("tree_size_values", tree_size_values);

    size_t num_plans = 0;
    fprintf(stdout, "std::map<Params,Plan> plan_repo({");
    for (size_t less_percent: less_percent_values) {
        for (size_t tree_size: tree_size_values) {
            ForestParams params(1234u, less_percent, tree_size);
            fprintf(stdout, "%s\n", (num_plans++ == 0) ? "" : ",");
            fflush(stdout);
            fprintf(stdout, "  ");
            Plan plan = find_plan(params, {8, 512});
            dump_plan(params, plan);
        }
    }
    fprintf(stdout, "});\n");
}

//-----------------------------------------------------------------------------

TEST_MAIN() { TEST_RUN_ALL(); }
<|endoftext|>


<commit_before>#include "basicopenglview.h"

// this version demonstrates using the mouse to inout some points and draw lines between them

BasicOpenGLView::BasicOpenGLView(QWidget *parent)
      : QGLWidget(parent), polygons(QVector< QVector<QVector3D> >())
{
    clearon = false;
    mousedown = false;
    lastpt = -1;
    csv = NULL;  // represents an unselected vertex
    //polygons = QVector< QVector<QVector3D> >();
    srand (time(NULL));
    newPoly();
    qDebug() << "NEW HERE";
}

void BasicOpenGLView::initializeGL()
{
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);  // white
    glShadeModel( GL_FLAT );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    glPointSize(5);
}

void BasicOpenGLView::resizeGL(int width, int height)
{
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0.0,GLdouble(width),0,GLdouble(height),-10.0,10.0);
    //glOrtho(-(GLdouble)width/2.0, (GLdouble)width/2.0, -(GLdouble)height/2.0, (GLdouble)height/2.0, -10.0,10.0);

    glMatrixMode(GL_MODELVIEW);
  //  qDebug()<< "resize\n";
}

void BasicOpenGLView::paintGL()
{

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    drawFigure();

    //QGLWidget::swapBuffers();
}

void BasicOpenGLView::mousePressEvent(QMouseEvent *e)
{

    if (mousedown) return;
    mousedown = true;
    csv = NULL;

    if (e->button() == Qt::RightButton)
        addPoint( e->x(), height()-e->y() );
    if (e->button() == Qt::LeftButton)
        movePoint(e->x(), height()-e->y() );
    update();
}

void BasicOpenGLView::mouseMoveEvent(QMouseEvent *e)
{
    if (mousedown) movePoint(e->x(), height()-e->y());
    update();
}

void BasicOpenGLView::mouseReleaseEvent(QMouseEvent *e)
{
    // finished move point
    movePoint(e->x(), height()-e->y());
    mousedown = false;
    update();
}

void BasicOpenGLView::movePoint(int x, int y)
{
    if (mousedown) {
        if (csv == NULL)    // If no vertex selected
            select(x, y);  // Look for vertex selected
        if (csv != NULL) {  // If vertex selected
            csv->setX(x);
            csv->setY(y);
        }
    }
}

void BasicOpenGLView::addPoint(int x, int y)
{
    int i;
    for (i = 0; i < polygons.size(); i++) {
        if ( polygons.at(i).size() > 0 && ( (polygons.at(i).at(0).x()-RADIUS) < x && (polygons.at(i).at(0).x()+RADIUS) > x )
                                       && ( (polygons.at(i).at(0).y()-RADIUS) < y && (polygons.at(i).at(0).y()+RADIUS) > y ) ) {
            newPoly();
            return;
        }
    }
    polygons.last().append(QVector3D(x, y, 1));
}

void BasicOpenGLView::select(int x, int y)
{
    int i, j;
    for (i = 0; i < polygons.size(); i++) {
        for (j = 0; j < polygons.at(i).size(); j++) {
            if (   ( (polygons.at(i).at(j).x()-RADIUS) < x && (polygons.at(i).at(j).x()+RADIUS) > x )
                && ( (polygons.at(i).at(j).y()-RADIUS) < y && (polygons.at(i).at(j).y()+RADIUS) > y ) ) {
                csv = &(polygons[i][j]);
            }
        }
    }
}

void BasicOpenGLView::clearme()
{
    //for (int i = 0; i < polygons.size(); i++)
    //    polygons.at(i).clear();
    // THIS IS NOT A DEEP CLEAR, FIX THIS
    polygons.clear();
    polyColors.clear();
    newPoly();

    update();
}

void BasicOpenGLView::drawCircle(double radius, double xcen, double ycen, bool line)
{
   GLint i;
   static GLfloat circcoords[100][2];

   // qDebug()<<"drawing circle "<< radius SEP xcen SEP ycen NL;
   for(i=0;i<100;i++) {
     circcoords[i][0]=radius*cos(i*2*M_PI/100.0)+xcen;
     circcoords[i][1]=radius*sin(i*2*M_PI/100.0)+ycen;
   }
   if (line)   glBegin(GL_LINES); else glBegin(GL_POLYGON);
      for(i=0;i<100;i++)
         glVertex2fv(&circcoords[i][0]);
   glEnd();
}

void BasicOpenGLView::drawLine(double x0, double y0, double x1, double y1 )
{
    glBegin(GL_LINES);
    glVertex2f(x0, y0);
    glVertex2f(x1, y1);
    glEnd();
}

void BasicOpenGLView::drawFigure()
{
    // draw a line between each pair of points
    int x0,x1,y0,y1,i,j, firstX, firstY;
    int numPolys = polygons.size();

    for (i = 0; i < numPolys; i++)
    {
        if (polygons.at(i).size() <= 1)
            ;
        else
        {
            firstX = polygons.at(i).at(0).x();
            firstY = polygons.at(i).at(0).y();
            x0 = firstX;
            y0 = firstY;

            glColor3f(polyColors[i][0], polyColors[i][1], polyColors[i][2]);
            for (j = 1; j < polygons.at(i).size(); j++) {
                x1 = polygons.at(i).at(j).x();
                y1 = polygons.at(i).at(j).y();
                drawLine(x0, y0, x1, y1);
                x0 = x1;  y0 = y1;
            }

            // If this is a closed polygon, draw the last line
            if (i != (numPolys - 1))
                drawLine(x1, y1, firstX, firstY);
        }

        glColor3f(polyColors[i][0], polyColors[i][1], polyColors[i][2]);
        for (j = 0; j < polygons.at(i).size(); j++)
            drawCircle( (double)RADIUS, polygons.at(i).at(j).x(), polygons.at(i).at(j).y(), false);
    }
}

void BasicOpenGLView::newPoly()
{
    polygons.append(QVector<QVector3D>());
    polyColors.append(QVector<double>(3));
    polyColors.last()[0] = ((double) rand() / (RAND_MAX));
    polyColors.last()[1] = ((double) rand() / (RAND_MAX));
    polyColors.last()[2] = ((double) rand() / (RAND_MAX));
    update();
}
<commit_msg>Master branch gets ahead<commit_after>#include "basicopenglview.h"

// this version demonstrates using the mouse to inout some points and draw lines between them

BasicOpenGLView::BasicOpenGLView(QWidget *parent)
      : QGLWidget(parent), polygons(QVector< QVector<QVector3D> >())
{
    clearon = false;
    mousedown = false;
    lastpt = -1;
    csv = NULL;  // represents an unselected vertex
    //polygons = QVector< QVector<QVector3D> >();
    srand (time(NULL));
    newPoly();
    qDebug() << "NEW HERE";
    qDebug() << "Move Master Along, separate from pointer branch";
}

void BasicOpenGLView::initializeGL()
{
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);  // white
    glShadeModel( GL_FLAT );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    glPointSize(5);
}

void BasicOpenGLView::resizeGL(int width, int height)
{
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0.0,GLdouble(width),0,GLdouble(height),-10.0,10.0);
    //glOrtho(-(GLdouble)width/2.0, (GLdouble)width/2.0, -(GLdouble)height/2.0, (GLdouble)height/2.0, -10.0,10.0);

    glMatrixMode(GL_MODELVIEW);
  //  qDebug()<< "resize\n";
}

void BasicOpenGLView::paintGL()
{

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    drawFigure();

    //QGLWidget::swapBuffers();
}

void BasicOpenGLView::mousePressEvent(QMouseEvent *e)
{

    if (mousedown) return;
    mousedown = true;
    csv = NULL;

    if (e->button() == Qt::RightButton)
        addPoint( e->x(), height()-e->y() );
    if (e->button() == Qt::LeftButton)
        movePoint(e->x(), height()-e->y() );
    update();
}

void BasicOpenGLView::mouseMoveEvent(QMouseEvent *e)
{
    if (mousedown) movePoint(e->x(), height()-e->y());
    update();
}

void BasicOpenGLView::mouseReleaseEvent(QMouseEvent *e)
{
    // finished move point
    movePoint(e->x(), height()-e->y());
    mousedown = false;
    update();
}

void BasicOpenGLView::movePoint(int x, int y)
{
    if (mousedown) {
        if (csv == NULL)    // If no vertex selected
            select(x, y);  // Look for vertex selected
        if (csv != NULL) {  // If vertex selected
            csv->setX(x);
            csv->setY(y);
        }
    }
}

void BasicOpenGLView::addPoint(int x, int y)
{
    int i;
    for (i = 0; i < polygons.size(); i++) {
        if ( polygons.at(i).size() > 0 && ( (polygons.at(i).at(0).x()-RADIUS) < x && (polygons.at(i).at(0).x()+RADIUS) > x )
                                       && ( (polygons.at(i).at(0).y()-RADIUS) < y && (polygons.at(i).at(0).y()+RADIUS) > y ) ) {
            newPoly();
            return;
        }
    }
    polygons.last().append(QVector3D(x, y, 1));
}

void BasicOpenGLView::select(int x, int y)
{
    int i, j;
    for (i = 0; i < polygons.size(); i++) {
        for (j = 0; j < polygons.at(i).size(); j++) {
            if (   ( (polygons.at(i).at(j).x()-RADIUS) < x && (polygons.at(i).at(j).x()+RADIUS) > x )
                && ( (polygons.at(i).at(j).y()-RADIUS) < y && (polygons.at(i).at(j).y()+RADIUS) > y ) ) {
                csv = &(polygons[i][j]);
            }
        }
    }
}

void BasicOpenGLView::clearme()
{
    //for (int i = 0; i < polygons.size(); i++)
    //    polygons.at(i).clear();
    // THIS IS NOT A DEEP CLEAR, FIX THIS
    polygons.clear();
    polyColors.clear();
    newPoly();

    update();
}

void BasicOpenGLView::drawCircle(double radius, double xcen, double ycen, bool line)
{
   GLint i;
   static GLfloat circcoords[100][2];

   // qDebug()<<"drawing circle "<< radius SEP xcen SEP ycen NL;
   for(i=0;i<100;i++) {
     circcoords[i][0]=radius*cos(i*2*M_PI/100.0)+xcen;
     circcoords[i][1]=radius*sin(i*2*M_PI/100.0)+ycen;
   }
   if (line)   glBegin(GL_LINES); else glBegin(GL_POLYGON);
      for(i=0;i<100;i++)
         glVertex2fv(&circcoords[i][0]);
   glEnd();
}

void BasicOpenGLView::drawLine(double x0, double y0, double x1, double y1 )
{
    glBegin(GL_LINES);
    glVertex2f(x0, y0);
    glVertex2f(x1, y1);
    glEnd();
}

void BasicOpenGLView::drawFigure()
{
    // draw a line between each pair of points
    int x0,x1,y0,y1,i,j, firstX, firstY;
    int numPolys = polygons.size();

    for (i = 0; i < numPolys; i++)
    {
        if (polygons.at(i).size() <= 1)
            ;
        else
        {
            firstX = polygons.at(i).at(0).x();
            firstY = polygons.at(i).at(0).y();
            x0 = firstX;
            y0 = firstY;

            glColor3f(polyColors[i][0], polyColors[i][1], polyColors[i][2]);
            for (j = 1; j < polygons.at(i).size(); j++) {
                x1 = polygons.at(i).at(j).x();
                y1 = polygons.at(i).at(j).y();
                drawLine(x0, y0, x1, y1);
                x0 = x1;  y0 = y1;
            }

            // If this is a closed polygon, draw the last line
            if (i != (numPolys - 1))
                drawLine(x1, y1, firstX, firstY);
        }

        glColor3f(polyColors[i][0], polyColors[i][1], polyColors[i][2]);
        for (j = 0; j < polygons.at(i).size(); j++)
            drawCircle( (double)RADIUS, polygons.at(i).at(j).x(), polygons.at(i).at(j).y(), false);
    }
}

void BasicOpenGLView::newPoly()
{
    polygons.append(QVector<QVector3D>());
    polyColors.append(QVector<double>(3));
    polyColors.last()[0] = ((double) rand() / (RAND_MAX));
    polyColors.last()[1] = ((double) rand() / (RAND_MAX));
    polyColors.last()[2] = ((double) rand() / (RAND_MAX));
    update();
}
<|endoftext|>


<commit_before>#include <iostream>
#include <cmath>
#include <genecis/container/array.h>
#include <genecis/signal/sample_rate.h>
#include <genecis/signal/fourier_transform.h>

using namespace genecis::container ;
using namespace genecis::signal ;
using namespace std ;

double sinc( double x ) {
	double result = 1 ;
	if( x != 0 ) result = sin(x) / x ;
	return result ;
}

template<class Cplx, class Real>
void convert_real( const Cplx& input, Real& output ) {
	typedef typename Cplx::size_type	size_type ;
	size_type s( input.size() ) ;
	for(size_type i=0; i<s; ++i)
		output(i) = std::abs(input(i)) ;
}

int main() {

	typedef double				value_type ;
	typedef complex<value_type>	complex_num ;
	typedef array<complex_num>	container_cplx ;
	typedef array<value_type>	container_real ;
	typedef size_t				size_type ;

	size_type N = 10 ;

	value_type sig[10] ;
	for(size_type i=0; i<N; ++i) {
		sig[i] = (i<5) ? 1 : 0 ;
	}

	container_real input( sig, N ) ;
	container_real impulse ;
	container_cplx output ;

	fourier_transform::discrete( input, output ) ;

	cout << "input signal:" << input << endl ;
	cout << "dft signal:" << output << endl ;

	fourier_transform::inverse( output, impulse ) ;
	cout << "inverse dft signal:" << impulse << endl ;

}
<commit_msg>Updated test for output testing.<commit_after>#include <ctime>
#include <cstdlib>
#include <genecis/container/array.h>
#include <genecis/signal/sample_rate.h>
#include <genecis/signal/fourier_transform.h>

using namespace genecis::container ;
using namespace genecis::signal ;
using namespace std ;

double sinc( double x ) {
	double result = 1 ;
	if( x != 0 ) result = sin(x) / x ;
	return result ;
}

template<class Cplx, class Real>
void convert_real( const Cplx& input, Real& output ) {
	typedef typename Cplx::size_type	size_type ;
	size_type s( input.size() ) ;
	for(size_type i=0; i<s; ++i)
		output(i) = std::abs(input(i)) ;
}

int main() {

	typedef double				value_type ;
	typedef complex<value_type>	complex_num ;
	typedef array<complex_num>	container_cplx ;
	typedef array<value_type>	container_real ;
	typedef size_t				size_type ;

	size_type N = 100 ;

	value_type sig[100] ;
	srand(time(0)) ;
	for(size_type i=0; i<N; ++i) {
		sig[i] = std::sin(30*2*M_PI*i/100) + rand()%2 - 1/2 ;
	}

	container_real input( sig, N ) ;
	container_real impulse ;
	container_cplx output ;

	fourier_transform::discrete( input, output ) ;

	impulse.resize( N ) ;
	convert_real( output, impulse ) ;
	cout << "real dft sig:" << impulse << endl ;
	cout << "input signal:" << input << endl ;
//	cout << "dft signal:" << output << endl ;
//
//	fourier_transform::inverse( output, impulse ) ;
//	cout << "inverse dft signal:" << impulse << endl ;

}
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

This program 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 of the License, or (at your option) any later
version.

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

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"
#include "OgreCompositorChain.h"
#include "OgreCompositionTechnique.h"
#include "OgreCompositorInstance.h"
#include "OgreCompositionTargetPass.h"
#include "OgreCompositionPass.h"
#include "OgreViewport.h"
#include "OgreCamera.h"
#include "OgreRenderTarget.h"
#include "OgreLogManager.h"
#include "OgreCompositorManager.h"
#include "OgreSceneManager.h"
#include "OgreRenderQueueInvocation.h"
namespace Ogre {
CompositorChain::CompositorChain(Viewport *vp):
    mViewport(vp),
	mOriginalScene(0),
    mDirty(true),
	mAnyCompositorsEnabled(false)
{
	mOldClearEveryFrameBuffers = mViewport->getClearBuffers();
    assert(mViewport);
}
//-----------------------------------------------------------------------
CompositorChain::~CompositorChain()
{
	destroyResources();
}
//-----------------------------------------------------------------------
void CompositorChain::destroyResources(void)
{
	clearCompiledState();

	if (mViewport)
	{
		removeAllCompositors();
		/// Destroy "original scene" compositor instance
		if (mOriginalScene)
		{
			mViewport->getTarget()->removeListener(this);
			mOriginalScene->getTechnique()->destroyInstance(mOriginalScene);
			mOriginalScene = 0;
		}
		mViewport = 0;
	}
}
//-----------------------------------------------------------------------
CompositorInstance* CompositorChain::addCompositor(CompositorPtr filter, size_t addPosition, size_t technique)
{
	// Init on demand
	if (!mOriginalScene)
	{
		mViewport->getTarget()->addListener(this);

		/// Create base "original scene" compositor
		CompositorPtr base = CompositorManager::getSingleton().load("Ogre/Scene",
			ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
		mOriginalScene = base->getSupportedTechnique(0)->createInstance(this);
	}

	filter->touch();
    if(technique >= filter->getNumSupportedTechniques())
    {
        /// Warn user
        LogManager::getSingleton().logMessage(
            "CompositorChain: Compositor " + filter->getName() + " has no supported techniques.", LML_CRITICAL
        );
        return 0;
    }
    CompositionTechnique *tech = filter->getSupportedTechnique(technique);
    CompositorInstance *t = tech->createInstance(this);

    if(addPosition == LAST)
        addPosition = mInstances.size();
    else
        assert(addPosition <= mInstances.size() && "Index out of bounds.");
    mInstances.insert(mInstances.begin()+addPosition, t);

    mDirty = true;
	mAnyCompositorsEnabled = true;
    return t;
}
//-----------------------------------------------------------------------
void CompositorChain::removeCompositor(size_t index)
{
    assert (index < mInstances.size() && "Index out of bounds.");
    Instances::iterator i = mInstances.begin() + index;
    (*i)->getTechnique()->destroyInstance(*i);
    mInstances.erase(i);

    mDirty = true;
}
//-----------------------------------------------------------------------
size_t CompositorChain::getNumCompositors()
{
    return mInstances.size();
}
//-----------------------------------------------------------------------
void CompositorChain::removeAllCompositors()
{
    Instances::iterator i, iend;
    iend = mInstances.end();
    for (i = mInstances.begin(); i != iend; ++i)
    {
        (*i)->getTechnique()->destroyInstance(*i);
    }
    mInstances.clear();

    mDirty = true;
}
//-----------------------------------------------------------------------
void CompositorChain::_removeInstance(CompositorInstance *i)
{
	mInstances.erase(std::find(mInstances.begin(), mInstances.end(), i));
	i->getTechnique()->destroyInstance(i);
}
//-----------------------------------------------------------------------
void CompositorChain::_queuedOperation(CompositorInstance::RenderSystemOperation* op)
{
	mRenderSystemOperations.push_back(op);

}
//-----------------------------------------------------------------------
CompositorInstance *CompositorChain::getCompositor(size_t index)
{
    assert (index < mInstances.size() && "Index out of bounds.");
    return mInstances[index];
}

//-----------------------------------------------------------------------
CompositorChain::InstanceIterator CompositorChain::getCompositors()
{
    return InstanceIterator(mInstances.begin(), mInstances.end());
}
//-----------------------------------------------------------------------
void CompositorChain::setCompositorEnabled(size_t position, bool state)
{
    getCompositor(position)->setEnabled(state);
}
//-----------------------------------------------------------------------
void CompositorChain::preRenderTargetUpdate(const RenderTargetEvent& evt)
{
	/// Compile if state is dirty
	if(mDirty)
		_compile();

	// Do nothing if no compositors enabled
	if (!mAnyCompositorsEnabled)
	{
		return;
	}

	/// Update dependent render targets; this is done in the preRenderTarget
	/// and not the preViewportUpdate for a reason: at this time, the
	/// target Rendertarget will not yet have been set as current.
	/// ( RenderSystem::setViewport(...) ) if it would have been, the rendering
	/// order would be screwed up and problems would arise with copying rendertextures.
    Camera *cam = mViewport->getCamera();
    /// Iterate over compiled state
    CompositorInstance::CompiledState::iterator i;
    for(i=mCompiledState.begin(); i!=mCompiledState.end(); ++i)
    {
		/// Skip if this is a target that should only be initialised initially
		if(i->onlyInitial && i->hasBeenRendered)
			continue;
		i->hasBeenRendered = true;
		/// Setup and render
        preTargetOperation(*i, i->target->getViewport(0), cam);
        i->target->update();
        postTargetOperation(*i, i->target->getViewport(0), cam);
    }
}
//-----------------------------------------------------------------------
void CompositorChain::preViewportUpdate(const RenderTargetViewportEvent& evt)
{
	// Only set up if there is at least one compositor enabled, and it's this viewport
    if(evt.source != mViewport || !mAnyCompositorsEnabled)
        return;

	// set original scene details from viewport
	CompositionPass* pass = mOriginalScene->getTechnique()->getOutputTargetPass()->getPass(0);
	CompositionTargetPass* passParent = pass->getParent();
	if (pass->getClearBuffers() != mViewport->getClearBuffers() ||
		pass->getClearColour() != mViewport->getBackgroundColour() ||
		passParent->getVisibilityMask() != mViewport->getVisibilityMask() ||
		passParent->getMaterialScheme() != mViewport->getMaterialScheme() ||
		passParent->getShadowsEnabled() != mViewport->getShadowsEnabled())
	{
		// recompile if viewport settings are different
		pass->setClearBuffers(mViewport->getClearBuffers());
		pass->setClearColour(mViewport->getBackgroundColour());
		passParent->setVisibilityMask(mViewport->getVisibilityMask());
		passParent->setMaterialScheme(mViewport->getMaterialScheme());
		passParent->setShadowsEnabled(mViewport->getShadowsEnabled());
		_compile();
	}

	Camera *cam = mViewport->getCamera();
	/// Prepare for output operation
	preTargetOperation(mOutputOperation, mViewport, cam);
}
//-----------------------------------------------------------------------
void CompositorChain::preTargetOperation(CompositorInstance::TargetOperation &op, Viewport *vp, Camera *cam)
{
    SceneManager *sm = cam->getSceneManager();
	/// Set up render target listener
	mOurListener.setOperation(&op, sm, sm->getDestinationRenderSystem());
	mOurListener.notifyViewport(vp);
	/// Register it
	sm->addRenderQueueListener(&mOurListener);
	/// Set visiblity mask
	mOldVisibilityMask = sm->getVisibilityMask();
	sm->setVisibilityMask(op.visibilityMask);
	/// Set whether we find visibles
	mOldFindVisibleObjects = sm->getFindVisibleObjects();
	sm->setFindVisibleObjects(op.findVisibleObjects);
    /// Set LOD bias level
    mOldLodBias = cam->getLodBias();
    cam->setLodBias(cam->getLodBias() * op.lodBias);
	/// Set material scheme
	mOldMaterialScheme = vp->getMaterialScheme();
	vp->setMaterialScheme(op.materialScheme);
	/// Set shadows enabled
	mOldShadowsEnabled = vp->getShadowsEnabled();
	vp->setShadowsEnabled(op.shadowsEnabled);
    /// XXX TODO
    //vp->setClearEveryFrame( true );
    //vp->setOverlaysEnabled( false );
    //vp->setBackgroundColour( op.clearColour );
}
//-----------------------------------------------------------------------
void CompositorChain::postTargetOperation(CompositorInstance::TargetOperation &op, Viewport *vp, Camera *cam)
{
    SceneManager *sm = cam->getSceneManager();
	/// Unregister our listener
	sm->removeRenderQueueListener(&mOurListener);
	/// Restore default scene and camera settings
	sm->setVisibilityMask(mOldVisibilityMask);
	sm->setFindVisibleObjects(mOldFindVisibleObjects);
    cam->setLodBias(mOldLodBias);
	vp->setMaterialScheme(mOldMaterialScheme);
	vp->setShadowsEnabled(mOldShadowsEnabled);
}
//-----------------------------------------------------------------------
void CompositorChain::postViewportUpdate(const RenderTargetViewportEvent& evt)
{
	// Only tidy up if there is at least one compositor enabled, and it's this viewport
    if(evt.source != mViewport || !mAnyCompositorsEnabled)
        return;

	postTargetOperation(mOutputOperation, mViewport, mViewport->getCamera());
}
//-----------------------------------------------------------------------
void CompositorChain::viewportRemoved(const RenderTargetViewportEvent& evt)
{
	// check this is the viewport we're attached to (multi-viewport targets)
	if (evt.source == mViewport)
	{
		// this chain is now orphaned
		// can't delete it since held from outside, but release all resources being used
		destroyResources();
	}

}
//-----------------------------------------------------------------------
void CompositorChain::clearCompiledState()
{
	for (RenderSystemOperations::iterator i = mRenderSystemOperations.begin();
		i != mRenderSystemOperations.end(); ++i)
	{
		OGRE_DELETE *i;
	}
	mRenderSystemOperations.clear();

	/// Clear compiled state
	mCompiledState.clear();
	mOutputOperation = CompositorInstance::TargetOperation(0);

}
//-----------------------------------------------------------------------
void CompositorChain::_compile()
{
	clearCompiledState();

	bool compositorsEnabled = false;

    /// Set previous CompositorInstance for each compositor in the list
    CompositorInstance *lastComposition = mOriginalScene;
	mOriginalScene->mPreviousInstance = 0;
	CompositionPass* pass = mOriginalScene->getTechnique()->getOutputTargetPass()->getPass(0);
	pass->setClearBuffers(mViewport->getClearBuffers());
	pass->setClearColour(mViewport->getBackgroundColour());
    for(Instances::iterator i=mInstances.begin(); i!=mInstances.end(); ++i)
    {
        if((*i)->getEnabled())
        {
			compositorsEnabled = true;
            (*i)->mPreviousInstance = lastComposition;
            lastComposition = (*i);
        }
    }

    /// Compile misc targets
    lastComposition->_compileTargetOperations(mCompiledState);

    /// Final target viewport (0)
	mOutputOperation.renderSystemOperations.clear();
    lastComposition->_compileOutputOperation(mOutputOperation);

	// Deal with viewport settings
	if (compositorsEnabled != mAnyCompositorsEnabled)
	{
		mAnyCompositorsEnabled = compositorsEnabled;
		if (mAnyCompositorsEnabled)
		{
			// Save old viewport clearing options
			mOldClearEveryFrameBuffers = mViewport->getClearBuffers();
			// Don't clear anything every frame since we have our own clear ops
			mViewport->setClearEveryFrame(false);
		}
		else
		{
			// Reset clearing options
			mViewport->setClearEveryFrame(mOldClearEveryFrameBuffers > 0,
				mOldClearEveryFrameBuffers);
		}
	}

    mDirty = false;
}
//-----------------------------------------------------------------------
void CompositorChain::_markDirty()
{
    mDirty = true;
}
//-----------------------------------------------------------------------
Viewport *CompositorChain::getViewport()
{
    return mViewport;
}
//---------------------------------------------------------------------
void CompositorChain::_notifyViewport(Viewport* vp)
{
	mViewport = vp;
}
//-----------------------------------------------------------------------
void CompositorChain::RQListener::renderQueueStarted(uint8 id,
	const String& invocation, bool& skipThisQueue)
{
	// Skip when not matching viewport
	// shadows update is nested within main viewport update
	if (mSceneManager->getCurrentViewport() != mViewport)
		return;

	flushUpTo(id);
	/// If noone wants to render this queue, skip it
	/// Don't skip the OVERLAY queue because that's handled seperately
	if(!mOperation->renderQueues.test(id) && id!=RENDER_QUEUE_OVERLAY)
	{
		skipThisQueue = true;
	}
}
//-----------------------------------------------------------------------
void CompositorChain::RQListener::renderQueueEnded(uint8 id,
	const String& invocation, bool& repeatThisQueue)
{
}
//-----------------------------------------------------------------------
void CompositorChain::RQListener::setOperation(CompositorInstance::TargetOperation *op,SceneManager *sm,RenderSystem *rs)
{
	mOperation = op;
	mSceneManager = sm;
	mRenderSystem = rs;
	currentOp = op->renderSystemOperations.begin();
	lastOp = op->renderSystemOperations.end();
}
//-----------------------------------------------------------------------
void CompositorChain::RQListener::flushUpTo(uint8 id)
{
	/// Process all RenderSystemOperations up to and including render queue id.
    /// Including, because the operations for RenderQueueGroup x should be executed
	/// at the beginning of the RenderQueueGroup render for x.
	while(currentOp != lastOp && currentOp->first <= id)
	{
		currentOp->second->execute(mSceneManager, mRenderSystem);
		++currentOp;
	}
}
//-----------------------------------------------------------------------
}
<commit_msg>Patch 2690400: default material scheme when compiling compositors, so that quad materials get assigned correctly<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

This program 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 of the License, or (at your option) any later
version.

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

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"
#include "OgreCompositorChain.h"
#include "OgreCompositionTechnique.h"
#include "OgreCompositorInstance.h"
#include "OgreCompositionTargetPass.h"
#include "OgreCompositionPass.h"
#include "OgreViewport.h"
#include "OgreCamera.h"
#include "OgreRenderTarget.h"
#include "OgreLogManager.h"
#include "OgreCompositorManager.h"
#include "OgreSceneManager.h"
#include "OgreRenderQueueInvocation.h"
#include "OgreMaterialManager.h"

namespace Ogre {
CompositorChain::CompositorChain(Viewport *vp):
    mViewport(vp),
	mOriginalScene(0),
    mDirty(true),
	mAnyCompositorsEnabled(false)
{
	mOldClearEveryFrameBuffers = mViewport->getClearBuffers();
    assert(mViewport);
}
//-----------------------------------------------------------------------
CompositorChain::~CompositorChain()
{
	destroyResources();
}
//-----------------------------------------------------------------------
void CompositorChain::destroyResources(void)
{
	clearCompiledState();

	if (mViewport)
	{
		removeAllCompositors();
		/// Destroy "original scene" compositor instance
		if (mOriginalScene)
		{
			mViewport->getTarget()->removeListener(this);
			mOriginalScene->getTechnique()->destroyInstance(mOriginalScene);
			mOriginalScene = 0;
		}
		mViewport = 0;
	}
}
//-----------------------------------------------------------------------
CompositorInstance* CompositorChain::addCompositor(CompositorPtr filter, size_t addPosition, size_t technique)
{
	// Init on demand
	if (!mOriginalScene)
	{
		mViewport->getTarget()->addListener(this);

		/// Create base "original scene" compositor
		CompositorPtr base = CompositorManager::getSingleton().load("Ogre/Scene",
			ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
		mOriginalScene = base->getSupportedTechnique(0)->createInstance(this);
	}

	filter->touch();
    if(technique >= filter->getNumSupportedTechniques())
    {
        /// Warn user
        LogManager::getSingleton().logMessage(
            "CompositorChain: Compositor " + filter->getName() + " has no supported techniques.", LML_CRITICAL
        );
        return 0;
    }
    CompositionTechnique *tech = filter->getSupportedTechnique(technique);
    CompositorInstance *t = tech->createInstance(this);

    if(addPosition == LAST)
        addPosition = mInstances.size();
    else
        assert(addPosition <= mInstances.size() && "Index out of bounds.");
    mInstances.insert(mInstances.begin()+addPosition, t);

    mDirty = true;
	mAnyCompositorsEnabled = true;
    return t;
}
//-----------------------------------------------------------------------
void CompositorChain::removeCompositor(size_t index)
{
    assert (index < mInstances.size() && "Index out of bounds.");
    Instances::iterator i = mInstances.begin() + index;
    (*i)->getTechnique()->destroyInstance(*i);
    mInstances.erase(i);

    mDirty = true;
}
//-----------------------------------------------------------------------
size_t CompositorChain::getNumCompositors()
{
    return mInstances.size();
}
//-----------------------------------------------------------------------
void CompositorChain::removeAllCompositors()
{
    Instances::iterator i, iend;
    iend = mInstances.end();
    for (i = mInstances.begin(); i != iend; ++i)
    {
        (*i)->getTechnique()->destroyInstance(*i);
    }
    mInstances.clear();

    mDirty = true;
}
//-----------------------------------------------------------------------
void CompositorChain::_removeInstance(CompositorInstance *i)
{
	mInstances.erase(std::find(mInstances.begin(), mInstances.end(), i));
	i->getTechnique()->destroyInstance(i);
}
//-----------------------------------------------------------------------
void CompositorChain::_queuedOperation(CompositorInstance::RenderSystemOperation* op)
{
	mRenderSystemOperations.push_back(op);

}
//-----------------------------------------------------------------------
CompositorInstance *CompositorChain::getCompositor(size_t index)
{
    assert (index < mInstances.size() && "Index out of bounds.");
    return mInstances[index];
}

//-----------------------------------------------------------------------
CompositorChain::InstanceIterator CompositorChain::getCompositors()
{
    return InstanceIterator(mInstances.begin(), mInstances.end());
}
//-----------------------------------------------------------------------
void CompositorChain::setCompositorEnabled(size_t position, bool state)
{
    getCompositor(position)->setEnabled(state);
}
//-----------------------------------------------------------------------
void CompositorChain::preRenderTargetUpdate(const RenderTargetEvent& evt)
{
	/// Compile if state is dirty
	if(mDirty)
		_compile();

	// Do nothing if no compositors enabled
	if (!mAnyCompositorsEnabled)
	{
		return;
	}

	/// Update dependent render targets; this is done in the preRenderTarget
	/// and not the preViewportUpdate for a reason: at this time, the
	/// target Rendertarget will not yet have been set as current.
	/// ( RenderSystem::setViewport(...) ) if it would have been, the rendering
	/// order would be screwed up and problems would arise with copying rendertextures.
    Camera *cam = mViewport->getCamera();
    /// Iterate over compiled state
    CompositorInstance::CompiledState::iterator i;
    for(i=mCompiledState.begin(); i!=mCompiledState.end(); ++i)
    {
		/// Skip if this is a target that should only be initialised initially
		if(i->onlyInitial && i->hasBeenRendered)
			continue;
		i->hasBeenRendered = true;
		/// Setup and render
        preTargetOperation(*i, i->target->getViewport(0), cam);
        i->target->update();
        postTargetOperation(*i, i->target->getViewport(0), cam);
    }
}
//-----------------------------------------------------------------------
void CompositorChain::preViewportUpdate(const RenderTargetViewportEvent& evt)
{
	// Only set up if there is at least one compositor enabled, and it's this viewport
    if(evt.source != mViewport || !mAnyCompositorsEnabled)
        return;

	// set original scene details from viewport
	CompositionPass* pass = mOriginalScene->getTechnique()->getOutputTargetPass()->getPass(0);
	CompositionTargetPass* passParent = pass->getParent();
	if (pass->getClearBuffers() != mViewport->getClearBuffers() ||
		pass->getClearColour() != mViewport->getBackgroundColour() ||
		passParent->getVisibilityMask() != mViewport->getVisibilityMask() ||
		passParent->getMaterialScheme() != mViewport->getMaterialScheme() ||
		passParent->getShadowsEnabled() != mViewport->getShadowsEnabled())
	{
		// recompile if viewport settings are different
		pass->setClearBuffers(mViewport->getClearBuffers());
		pass->setClearColour(mViewport->getBackgroundColour());
		passParent->setVisibilityMask(mViewport->getVisibilityMask());
		passParent->setMaterialScheme(mViewport->getMaterialScheme());
		passParent->setShadowsEnabled(mViewport->getShadowsEnabled());
		_compile();
	}

	Camera *cam = mViewport->getCamera();
	/// Prepare for output operation
	preTargetOperation(mOutputOperation, mViewport, cam);
}
//-----------------------------------------------------------------------
void CompositorChain::preTargetOperation(CompositorInstance::TargetOperation &op, Viewport *vp, Camera *cam)
{
    SceneManager *sm = cam->getSceneManager();
	/// Set up render target listener
	mOurListener.setOperation(&op, sm, sm->getDestinationRenderSystem());
	mOurListener.notifyViewport(vp);
	/// Register it
	sm->addRenderQueueListener(&mOurListener);
	/// Set visiblity mask
	mOldVisibilityMask = sm->getVisibilityMask();
	sm->setVisibilityMask(op.visibilityMask);
	/// Set whether we find visibles
	mOldFindVisibleObjects = sm->getFindVisibleObjects();
	sm->setFindVisibleObjects(op.findVisibleObjects);
    /// Set LOD bias level
    mOldLodBias = cam->getLodBias();
    cam->setLodBias(cam->getLodBias() * op.lodBias);
	/// Set material scheme
	mOldMaterialScheme = vp->getMaterialScheme();
	vp->setMaterialScheme(op.materialScheme);
	/// Set shadows enabled
	mOldShadowsEnabled = vp->getShadowsEnabled();
	vp->setShadowsEnabled(op.shadowsEnabled);
    /// XXX TODO
    //vp->setClearEveryFrame( true );
    //vp->setOverlaysEnabled( false );
    //vp->setBackgroundColour( op.clearColour );
}
//-----------------------------------------------------------------------
void CompositorChain::postTargetOperation(CompositorInstance::TargetOperation &op, Viewport *vp, Camera *cam)
{
    SceneManager *sm = cam->getSceneManager();
	/// Unregister our listener
	sm->removeRenderQueueListener(&mOurListener);
	/// Restore default scene and camera settings
	sm->setVisibilityMask(mOldVisibilityMask);
	sm->setFindVisibleObjects(mOldFindVisibleObjects);
    cam->setLodBias(mOldLodBias);
	vp->setMaterialScheme(mOldMaterialScheme);
	vp->setShadowsEnabled(mOldShadowsEnabled);
}
//-----------------------------------------------------------------------
void CompositorChain::postViewportUpdate(const RenderTargetViewportEvent& evt)
{
	// Only tidy up if there is at least one compositor enabled, and it's this viewport
    if(evt.source != mViewport || !mAnyCompositorsEnabled)
        return;

	postTargetOperation(mOutputOperation, mViewport, mViewport->getCamera());
}
//-----------------------------------------------------------------------
void CompositorChain::viewportRemoved(const RenderTargetViewportEvent& evt)
{
	// check this is the viewport we're attached to (multi-viewport targets)
	if (evt.source == mViewport)
	{
		// this chain is now orphaned
		// can't delete it since held from outside, but release all resources being used
		destroyResources();
	}

}
//-----------------------------------------------------------------------
void CompositorChain::clearCompiledState()
{
	for (RenderSystemOperations::iterator i = mRenderSystemOperations.begin();
		i != mRenderSystemOperations.end(); ++i)
	{
		OGRE_DELETE *i;
	}
	mRenderSystemOperations.clear();

	/// Clear compiled state
	mCompiledState.clear();
	mOutputOperation = CompositorInstance::TargetOperation(0);

}
//-----------------------------------------------------------------------
void CompositorChain::_compile()
{
	clearCompiledState();

	bool compositorsEnabled = false;

	// force default scheme so materials for compositor quads will determined correctly
	MaterialManager& matMgr = MaterialManager::getSingleton();
	String prevMaterialScheme = matMgr.getActiveScheme();
	matMgr.setActiveScheme(MaterialManager::DEFAULT_SCHEME_NAME);

    /// Set previous CompositorInstance for each compositor in the list
    CompositorInstance *lastComposition = mOriginalScene;
	mOriginalScene->mPreviousInstance = 0;
	CompositionPass* pass = mOriginalScene->getTechnique()->getOutputTargetPass()->getPass(0);
	pass->setClearBuffers(mViewport->getClearBuffers());
	pass->setClearColour(mViewport->getBackgroundColour());
    for(Instances::iterator i=mInstances.begin(); i!=mInstances.end(); ++i)
    {
        if((*i)->getEnabled())
        {
			compositorsEnabled = true;
            (*i)->mPreviousInstance = lastComposition;
            lastComposition = (*i);
        }
    }

    /// Compile misc targets
    lastComposition->_compileTargetOperations(mCompiledState);

    /// Final target viewport (0)
	mOutputOperation.renderSystemOperations.clear();
    lastComposition->_compileOutputOperation(mOutputOperation);

	// Deal with viewport settings
	if (compositorsEnabled != mAnyCompositorsEnabled)
	{
		mAnyCompositorsEnabled = compositorsEnabled;
		if (mAnyCompositorsEnabled)
		{
			// Save old viewport clearing options
			mOldClearEveryFrameBuffers = mViewport->getClearBuffers();
			// Don't clear anything every frame since we have our own clear ops
			mViewport->setClearEveryFrame(false);
		}
		else
		{
			// Reset clearing options
			mViewport->setClearEveryFrame(mOldClearEveryFrameBuffers > 0,
				mOldClearEveryFrameBuffers);
		}
	}

	// restore material scheme
	matMgr.setActiveScheme(prevMaterialScheme);

    mDirty = false;
}
//-----------------------------------------------------------------------
void CompositorChain::_markDirty()
{
    mDirty = true;
}
//-----------------------------------------------------------------------
Viewport *CompositorChain::getViewport()
{
    return mViewport;
}
//---------------------------------------------------------------------
void CompositorChain::_notifyViewport(Viewport* vp)
{
	mViewport = vp;
}
//-----------------------------------------------------------------------
void CompositorChain::RQListener::renderQueueStarted(uint8 id,
	const String& invocation, bool& skipThisQueue)
{
	// Skip when not matching viewport
	// shadows update is nested within main viewport update
	if (mSceneManager->getCurrentViewport() != mViewport)
		return;

	flushUpTo(id);
	/// If noone wants to render this queue, skip it
	/// Don't skip the OVERLAY queue because that's handled seperately
	if(!mOperation->renderQueues.test(id) && id!=RENDER_QUEUE_OVERLAY)
	{
		skipThisQueue = true;
	}
}
//-----------------------------------------------------------------------
void CompositorChain::RQListener::renderQueueEnded(uint8 id,
	const String& invocation, bool& repeatThisQueue)
{
}
//-----------------------------------------------------------------------
void CompositorChain::RQListener::setOperation(CompositorInstance::TargetOperation *op,SceneManager *sm,RenderSystem *rs)
{
	mOperation = op;
	mSceneManager = sm;
	mRenderSystem = rs;
	currentOp = op->renderSystemOperations.begin();
	lastOp = op->renderSystemOperations.end();
}
//-----------------------------------------------------------------------
void CompositorChain::RQListener::flushUpTo(uint8 id)
{
	/// Process all RenderSystemOperations up to and including render queue id.
    /// Including, because the operations for RenderQueueGroup x should be executed
	/// at the beginning of the RenderQueueGroup render for x.
	while(currentOp != lastOp && currentOp->first <= id)
	{
		currentOp->second->execute(mSceneManager, mRenderSystem);
		++currentOp;
	}
}
//-----------------------------------------------------------------------
}
<|endoftext|>


<commit_before>#include <vector>
#include "toml.h"
#include <random>
#include <iostream>
#include <cmath>
#include "xoroshiro128plus.h"
#include "statistics.h"
#include "properties.h"

inline void metropolis_sweep(std::vector<std::vector<double> >& lattice,
                             xoroshiro128plus& gen,
                             std::uniform_real_distribution<double>& delta_dist,
                             std::uniform_real_distribution<double>& real_dist,
                             double beta){
    int L = lattice.size();
    int i_plus, j_plus, i_minus, j_minus;
    int n0, n1, n2, n3;
    double sigma_old, sigma_new;
    double delta_E, p_accept;
    N_ATTEMPTED_FLIPS += L*L;

    for (int i=0; i<L; i++){
        for (int j=0; j<L; j++){
            delta_E = 0.0;
            i_plus  = (i != L-1) ? i+1: 0;
            i_minus = (i != 0  ) ? i-1: L-1;
            j_plus  = (j != L-1) ? j+1: 0;
            j_minus = (j != 0  ) ? j-1: L-1;

            //neighboring angles
            n0 = lattice[i_plus][j];
            n1 = lattice[i_minus][j];
            n2 = lattice[i][j_plus];
            n3 = lattice[i][j_minus];

            //delta_E = E(sigma_new) - E(sigma)
            sigma_old = lattice[i][j];
            sigma_new = sigma_old - delta_dist(gen);

            //E(sigma_new)
            delta_E += (-cos(sigma_new - n0));
            delta_E += (-cos(sigma_new - n1));
            delta_E += (-cos(sigma_new - n2));
            delta_E += (-cos(sigma_new - n3));
            //-E(sigma_old)
            delta_E -= (-cos(sigma_old - n0));
            delta_E -= (-cos(sigma_old - n1));
            delta_E -= (-cos(sigma_old - n2));
            delta_E -= (-cos(sigma_old - n3));

            if (delta_E <= 0){
                //good change
                lattice[i][j] = sigma_new;
                N_ACCEPTED_FLIPS++;
            }else{
                p_accept = exp(-beta*delta_E);
                if (p_accept > real_dist(gen)){
                    lattice[i][j] = sigma_new;
                    N_ACCEPTED_FLIPS++;
                }
            }
        }
    }
};

inline void microcanonical_sweep(std::vector<std::vector<double> >& lattice){

};
inline void cluster_sweep(){};

///////////////////////
//Standard metropolis//
///////////////////////
void metropolis(int n_steps_therm, int n_steps_prod, int side_length, double beta, std::string outfile, int outfreq, int conf_outfreq, double delta){
    //store lattice as 2d array
    std::vector<std::vector<double> > lattice;

    //Initialize 128 bits of random state
    std::random_device rd;
    std::array<uint32_t,4> seed;
    seed[0] = rd();
    seed[1] = rd();
    seed[2] = rd();
    seed[3] = rd();
    xoroshiro128plus gen(seed);

    std::uniform_real_distribution<double> angle_dist(0.0, 2*M_PI);
    std::uniform_real_distribution<double> delta_dist(-delta/2.0, delta/2.0);
    std::uniform_real_distribution<double> real_dist(0.0, 1.0);
    std::vector<double> energies;

    //setup lattice (hot start)
    for (int i=0; i<side_length; i++){
        std::vector<double> line;
        for (int j=0; j<side_length; j++){
            line.push_back(angle_dist(gen));
        }
        line.shrink_to_fit();
        lattice.push_back(line);
    }
    lattice.shrink_to_fit();

    //thermalize
    std::cout << lattice[0][0] << std::endl;
    for (int n=0; n<n_steps_therm; n++){
        metropolis_sweep(lattice, gen, delta_dist, real_dist, beta);

        std::cout << lattice[0][0] << std::endl;

    }
    //production run
    for (int n=0; n<n_steps_prod; n++){
        metropolis_sweep(lattice, gen, delta_dist, real_dist, beta);
        if (n%outfreq == 0){
        }
        if (n%conf_outfreq == 0){
            write_configuration(lattice, outfile + ".conf" + std::to_string(n));
        }
    }
};

<commit_msg>fixed error<commit_after>#include <vector>
#include "toml.h"
#include <random>
#include <iostream>
#include <cmath>
#include "xoroshiro128plus.h"
#include "statistics.h"
#include "properties.h"

inline void metropolis_sweep(std::vector<std::vector<double> >& lattice,
                             xoroshiro128plus& gen,
                             std::uniform_real_distribution<double>& delta_dist,
                             std::uniform_real_distribution<double>& real_dist,
                             double beta){
    int L = lattice.size();
    int i_plus, j_plus, i_minus, j_minus;
    std::vector<double> nb_angles = {0.0, 0.0, 0.0, 0.0};
    double sigma_old, sigma_new;
    double delta_E, p_accept;
    N_ATTEMPTED_FLIPS += L*L;

    for (int i=0; i<L; i++){
        for (int j=0; j<L; j++){
            delta_E = 0.0;
            i_plus  = (i != L-1) ? i+1: 0;
            i_minus = (i != 0  ) ? i-1: L-1;
            j_plus  = (j != L-1) ? j+1: 0;
            j_minus = (j != 0  ) ? j-1: L-1;

            //neighboring angles
            nb_angles[0] = lattice[i_plus][j];
            nb_angles[1] = lattice[i_minus][j];
            nb_angles[2] = lattice[i][j_plus];
            nb_angles[3] = lattice[i][j_minus];

            //delta_E = E(sigma_new) - E(sigma)
            sigma_old = lattice[i][j];
            sigma_new = sigma_old - delta_dist(gen);

            for (int nb=0; nb<4; nb++){
                delta_E += cos(sigma_old - nb_angles[nb]) - cos(sigma_new - nb_angles[nb]);
            }

            if (delta_E <= 0){
                //good change
                lattice[i][j] = sigma_new;
                N_ACCEPTED_FLIPS++;
            }else{
                p_accept = exp(-beta*delta_E);
                if (p_accept > real_dist(gen)){
                    lattice[i][j] = sigma_new;
                    N_ACCEPTED_FLIPS++;
                }
            }
        }
    }
};

inline void microcanonical_sweep(std::vector<std::vector<double> >& lattice){
    int L = lattice.size();
    int i_plus, j_plus, i_minus, j_minus;
    int n0, n1, n2, n3;

    std::vector<double> Vx;

    for (int i=0; i<L; i++){
        for (int j=0; j<L; j++){

            i_plus  = (i != L-1) ? i+1: 0;
            i_minus = (i != 0  ) ? i-1: L-1;
            j_plus  = (j != L-1) ? j+1: 0;
            j_minus = (j != 0  ) ? j-1: L-1;

            //neighboring angles

        }
    }

};
inline void cluster_sweep(){};

///////////////////////
//Standard metropolis//
///////////////////////
void metropolis(int n_steps_therm, int n_steps_prod, int side_length, double beta, std::string outfile, int outfreq, int conf_outfreq, double delta){
    //store lattice as 2d array
    std::vector<std::vector<double> > lattice;

    //Initialize 128 bits of random state
    std::random_device rd;
    std::array<uint32_t,4> seed;
    seed[0] = rd();
    seed[1] = rd();
    seed[2] = rd();
    seed[3] = rd();
    xoroshiro128plus gen(seed);

    std::uniform_real_distribution<double> angle_dist(0.0, 2*M_PI);
    std::uniform_real_distribution<double> delta_dist(-delta/2.0, delta/2.0);
    std::uniform_real_distribution<double> real_dist(0.0, 1.0);
    std::vector<double> energies;

    //setup lattice (hot start)
    for (int i=0; i<side_length; i++){
        std::vector<double> line;
        for (int j=0; j<side_length; j++){
            line.push_back(angle_dist(gen));
        }
        line.shrink_to_fit();
        lattice.push_back(line);
    }
    lattice.shrink_to_fit();

    //thermalize
    std::cout << lattice[0][0] << std::endl;
    for (int n=0; n<n_steps_therm; n++){
        metropolis_sweep(lattice, gen, delta_dist, real_dist, beta);

        std::cout << lattice[0][0] << std::endl;

    }
    //production run
    for (int n=0; n<n_steps_prod; n++){
        metropolis_sweep(lattice, gen, delta_dist, real_dist, beta);
        if (n%outfreq == 0){
        }
        if (n%conf_outfreq == 0){
            write_configuration(lattice, outfile + ".conf" + std::to_string(n));
        }
    }
};

<|endoftext|>