<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#ifndef __itkBSplineBaseTransform_hxx
#define __itkBSplineBaseTransform_hxx

#include "itkBSplineBaseTransform.h"

#include "itkContinuousIndex.h"
#include "itkImageRegionIterator.h"
#include "itkImageRegionConstIteratorWithIndex.h"

namespace itk
{

// Constructor with default arguments
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::BSplineBaseTransform() : Superclass( 0 ),
  m_CoefficientImages( this->ArrayOfImagePointerGeneratorHelper() )
{
  this->m_InternalParametersBuffer = ParametersType( 0 );

  // Instantiate a weights function
  this->m_WeightsFunction = WeightsFunctionType::New();
}

// Destructor
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::~BSplineBaseTransform()
{
}

// Set the parameters
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
void
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::SetIdentity()
{
  if( this->m_InternalParametersBuffer.Size() != this->GetNumberOfParameters() )
    {
    this->m_InternalParametersBuffer.SetSize( this->GetNumberOfParameters() );
    }
  this->m_InternalParametersBuffer.Fill( 0.0 );

  this->SetParameters( this->m_InternalParametersBuffer );
  this->Modified();
}

// Set the parameters
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
void
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::SetParameters( const ParametersType & parameters )
{
  // check if the number of parameters match the
  // expected number of parameters
  if( parameters.Size() != this->GetNumberOfParameters() )
    {
    itkExceptionMacro( << "Mismatch between parameters size "
                       << parameters.Size() << " and expected number of parameters "
                       << this->GetNumberOfParameters()
                       << ( this->m_CoefficientImages[0]->GetLargestPossibleRegion().GetNumberOfPixels() == 0 ?
                            ". \nSince the size of the grid region is 0, perhaps you forgot to "
                            "SetGridRegion or SetFixedParameters before setting the Parameters."
                            : "" ) );
    }

  if( &parameters != &( this->m_InternalParametersBuffer ) )
    {
    // Clean up this->m_InternalParametersBuffer because we will
    // use an externally supplied set of parameters as the buffer
    this->m_InternalParametersBuffer = parameters;
    }

  // Wrap flat array as images of coefficients
  this->WrapAsImages();

  // Modified is always called since we just have a pointer to the
  // parameters and cannot know if the parameters have changed.
  this->Modified();
}

// Set the parameters by value
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
void
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::SetParametersByValue( const ParametersType & parameters )
{
  // check if the number of parameters match the
  // expected number of parameters
  if( parameters.Size() != this->GetNumberOfParameters() )
    {
    itkExceptionMacro( << "Mismatched between parameters size "
                       << parameters.size() << " and region size "
                       << this->GetNumberOfParameters() );
    }

  // copy parameters to this->m_InternalParametersBuffer
  this->m_InternalParametersBuffer = parameters;
  this->SetParameters( this->m_InternalParametersBuffer );
}

template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
void
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::SetFixedParametersFromTransformDomainInformation() const
{
  //  Fixed Parameters store the following information:
  //  Grid Size
  //  Grid Origin
  //  Grid Spacing
  //  Grid Direction
  //  The size of each of these is equal to NDimensions

  this->m_FixedParameters.SetSize( NDimensions * ( NDimensions + 3 ) );

  this->SetFixedParametersGridSizeFromTransformDomainInformation();
  this->SetFixedParametersGridOriginFromTransformDomainInformation();
  this->SetFixedParametersGridSpacingFromTransformDomainInformation();
  this->SetFixedParametersGridDirectionFromTransformDomainInformation();

  this->Modified();
}

/**
 * UpdateTransformParameters
 */
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
void
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::UpdateTransformParameters( const DerivativeType & update, TScalar factor )
{
  NumberOfParametersType numberOfParameters = this->GetNumberOfParameters();

  if( update.Size() != numberOfParameters )
    {
    itkExceptionMacro("Parameter update size, " << update.Size() << ", must "
                      " be same as transform parameter size, "
                                                << numberOfParameters << std::endl);
    }

  /* Make sure m_Parameters is updated to reflect the current values in
   * the transform's other parameter-related variables. This is effective for
   * managing the parallel variables used for storing parameter data,
   * but inefficient. However for small global transforms, shouldn't be
   * too bad. Dense-field transform will want to make sure m_Parameters
   * is always updated whenever the transform is changed, so GetParameters
   * can be skipped in their implementations of UpdateTransformParameters. */

  if( factor == 1.0 )
    {
    for( NumberOfParametersType k = 0; k < numberOfParameters; k++ )
      {
      this->m_InternalParametersBuffer[k] += update[k];
      }
    }
  else
    {
    for( NumberOfParametersType k = 0; k < numberOfParameters; k++ )
      {
      this->m_InternalParametersBuffer[k] += update[k] * factor;
      }
    }

  /* Call SetParameters with the updated parameters.
   * SetParameters in most transforms is used to assign the input params
   * to member variables, possibly with some processing. The member variables
   * are then used in TransformPoint.
   * In the case of dense-field transforms that are updated in blocks from
   * a threaded implementation, SetParameters doesn't do this, and is
   * optimized to not copy the input parameters when == m_Parameters.
   */
  this->SetParameters( this->m_InternalParametersBuffer );

  /* Call Modified, following behavior of other transform when their
   * parameters change, e.g. MatrixOffsetTransformBase */
  this->Modified();
}

// Wrap flat parameters as images
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
void
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::WrapAsImages()
{
  /**
   * Wrap flat parameters array into SpaceDimension number of ITK images
   * NOTE: For efficiency, parameters are not copied locally. The parameters
   * are assumed to be maintained by the caller.
   */
  PixelType *dataPointer = const_cast<PixelType *>( this->m_InternalParametersBuffer.data_block() );
  const NumberOfParametersType numberOfPixels = this->GetNumberOfParametersPerDimension();

  for( unsigned int j = 0; j < SpaceDimension; j++ )
    {
    this->m_CoefficientImages[j]->GetPixelContainer()->
      SetImportPointer( dataPointer + j * numberOfPixels, numberOfPixels );
    }
}

// Get the parameters
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
const typename BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>::ParametersType &
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::GetParameters() const
{
  return this->m_InternalParametersBuffer;
}

// Get the parameters
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
const typename BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>::ParametersType &
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::GetFixedParameters() const
{
  // HACK:  This should not be necessary if the
  //       class is kept in a consistent state
  //  this->SetFixedParametersFromCoefficientImageInformation();
  return this->m_FixedParameters;
}

// Print self
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
void
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::PrintSelf( std::ostream & os, Indent indent ) const
{
  this->Superclass::PrintSelf(os, indent);

  os << indent << "CoefficientImage: [ ";
  for( unsigned int j = 0; j < SpaceDimension - 1; j++ )
    {
    os << this->m_CoefficientImages[j].GetPointer() << ", ";
    }
  os << this->m_CoefficientImages[SpaceDimension - 1].GetPointer()
     << " ]" << std::endl;
}

/** Get Jacobian at a point. A very specialized function just for BSplines */
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
void
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::ComputeJacobianFromBSplineWeightsWithRespectToPosition(
  const InputPointType & point, WeightsType & weights,
  ParameterIndexArrayType & indexes ) const
{
  ContinuousIndexType index;

  this->m_CoefficientImages[0]->TransformPhysicalPointToContinuousIndex( point, index );

  // NOTE: if the support region does not lie totally within the grid
  // we assume zero displacement and return the input point
  if( !this->InsideValidRegion( index ) )
    {
    weights.Fill( 0.0 );
    indexes.Fill( 0 );
    return;
    }

  // Compute interpolation weights
  IndexType supportIndex;
  this->m_WeightsFunction->Evaluate(index, weights, supportIndex);

  // For each dimension, copy the weight to the support region
  RegionType supportRegion;
  SizeType   supportSize;
  supportSize.Fill( SplineOrder + 1 );
  supportRegion.SetSize( supportSize );
  supportRegion.SetIndex( supportIndex );
  unsigned long counter = 0;

  typedef ImageRegionIterator<ImageType> IteratorType;

  IteratorType coeffIterator = IteratorType(
      this->m_CoefficientImages[0], supportRegion );
  const ParametersValueType *basePointer =
    this->m_CoefficientImages[0]->GetBufferPointer();
  while( !coeffIterator.IsAtEnd() )
    {
    indexes[counter] = &( coeffIterator.Value() ) - basePointer;

    // go to next coefficient in the support region
    ++counter;
    ++coeffIterator;
    }
}

template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
unsigned int
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::GetNumberOfAffectedWeights() const
{
  return this->m_WeightsFunction->GetNumberOfWeights();
}

// This helper class is used to work around a race condition where the dynamically
// generated images must exist before the references to the sub-sections are created.
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
typename BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>::CoefficientImageArray
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::ArrayOfImagePointerGeneratorHelper(void) const
{
  CoefficientImageArray tempArrayOfPointers;

  for( unsigned int j = 0; j < SpaceDimension; j++ )
    {
    tempArrayOfPointers[j] = ImageType::New();
    }
  return tempArrayOfPointers;
}

// Transform a point
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
typename BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::OutputPointType
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::TransformPoint(const InputPointType & point) const
{
  WeightsType             weights( this->m_WeightsFunction->GetNumberOfWeights() );
  ParameterIndexArrayType indices( this->m_WeightsFunction->GetNumberOfWeights() );
  OutputPointType         outputPoint;
  bool                    inside;

  this->TransformPoint( point, outputPoint, weights, indices, inside );

  return outputPoint;
}

} // namespace
#endif
<commit_msg>STYLE: Fix initialization list in BSplineBaseTransform constructor<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#ifndef __itkBSplineBaseTransform_hxx
#define __itkBSplineBaseTransform_hxx

#include "itkBSplineBaseTransform.h"

#include "itkContinuousIndex.h"
#include "itkImageRegionIterator.h"
#include "itkImageRegionConstIteratorWithIndex.h"

namespace itk
{

// Constructor with default arguments
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::BSplineBaseTransform() :
  Superclass( 0 ),
  m_CoefficientImages( this->ArrayOfImagePointerGeneratorHelper() )
{
  this->m_InternalParametersBuffer = ParametersType( 0 );

  // Instantiate a weights function
  this->m_WeightsFunction = WeightsFunctionType::New();
}

// Destructor
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::~BSplineBaseTransform()
{
}

// Set the parameters
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
void
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::SetIdentity()
{
  if( this->m_InternalParametersBuffer.Size() != this->GetNumberOfParameters() )
    {
    this->m_InternalParametersBuffer.SetSize( this->GetNumberOfParameters() );
    }
  this->m_InternalParametersBuffer.Fill( 0.0 );

  this->SetParameters( this->m_InternalParametersBuffer );
  this->Modified();
}

// Set the parameters
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
void
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::SetParameters( const ParametersType & parameters )
{
  // check if the number of parameters match the
  // expected number of parameters
  if( parameters.Size() != this->GetNumberOfParameters() )
    {
    itkExceptionMacro( << "Mismatch between parameters size "
                       << parameters.Size() << " and expected number of parameters "
                       << this->GetNumberOfParameters()
                       << ( this->m_CoefficientImages[0]->GetLargestPossibleRegion().GetNumberOfPixels() == 0 ?
                            ". \nSince the size of the grid region is 0, perhaps you forgot to "
                            "SetGridRegion or SetFixedParameters before setting the Parameters."
                            : "" ) );
    }

  if( &parameters != &( this->m_InternalParametersBuffer ) )
    {
    // Clean up this->m_InternalParametersBuffer because we will
    // use an externally supplied set of parameters as the buffer
    this->m_InternalParametersBuffer = parameters;
    }

  // Wrap flat array as images of coefficients
  this->WrapAsImages();

  // Modified is always called since we just have a pointer to the
  // parameters and cannot know if the parameters have changed.
  this->Modified();
}

// Set the parameters by value
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
void
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::SetParametersByValue( const ParametersType & parameters )
{
  // check if the number of parameters match the
  // expected number of parameters
  if( parameters.Size() != this->GetNumberOfParameters() )
    {
    itkExceptionMacro( << "Mismatched between parameters size "
                       << parameters.size() << " and region size "
                       << this->GetNumberOfParameters() );
    }

  // copy parameters to this->m_InternalParametersBuffer
  this->m_InternalParametersBuffer = parameters;
  this->SetParameters( this->m_InternalParametersBuffer );
}

template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
void
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::SetFixedParametersFromTransformDomainInformation() const
{
  //  Fixed Parameters store the following information:
  //  Grid Size
  //  Grid Origin
  //  Grid Spacing
  //  Grid Direction
  //  The size of each of these is equal to NDimensions

  this->m_FixedParameters.SetSize( NDimensions * ( NDimensions + 3 ) );

  this->SetFixedParametersGridSizeFromTransformDomainInformation();
  this->SetFixedParametersGridOriginFromTransformDomainInformation();
  this->SetFixedParametersGridSpacingFromTransformDomainInformation();
  this->SetFixedParametersGridDirectionFromTransformDomainInformation();

  this->Modified();
}

/**
 * UpdateTransformParameters
 */
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
void
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::UpdateTransformParameters( const DerivativeType & update, TScalar factor )
{
  NumberOfParametersType numberOfParameters = this->GetNumberOfParameters();

  if( update.Size() != numberOfParameters )
    {
    itkExceptionMacro("Parameter update size, " << update.Size() << ", must "
                      " be same as transform parameter size, "
                                                << numberOfParameters << std::endl);
    }

  /* Make sure m_Parameters is updated to reflect the current values in
   * the transform's other parameter-related variables. This is effective for
   * managing the parallel variables used for storing parameter data,
   * but inefficient. However for small global transforms, shouldn't be
   * too bad. Dense-field transform will want to make sure m_Parameters
   * is always updated whenever the transform is changed, so GetParameters
   * can be skipped in their implementations of UpdateTransformParameters. */

  if( factor == 1.0 )
    {
    for( NumberOfParametersType k = 0; k < numberOfParameters; k++ )
      {
      this->m_InternalParametersBuffer[k] += update[k];
      }
    }
  else
    {
    for( NumberOfParametersType k = 0; k < numberOfParameters; k++ )
      {
      this->m_InternalParametersBuffer[k] += update[k] * factor;
      }
    }

  /* Call SetParameters with the updated parameters.
   * SetParameters in most transforms is used to assign the input params
   * to member variables, possibly with some processing. The member variables
   * are then used in TransformPoint.
   * In the case of dense-field transforms that are updated in blocks from
   * a threaded implementation, SetParameters doesn't do this, and is
   * optimized to not copy the input parameters when == m_Parameters.
   */
  this->SetParameters( this->m_InternalParametersBuffer );

  /* Call Modified, following behavior of other transform when their
   * parameters change, e.g. MatrixOffsetTransformBase */
  this->Modified();
}

// Wrap flat parameters as images
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
void
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::WrapAsImages()
{
  /**
   * Wrap flat parameters array into SpaceDimension number of ITK images
   * NOTE: For efficiency, parameters are not copied locally. The parameters
   * are assumed to be maintained by the caller.
   */
  PixelType *dataPointer = const_cast<PixelType *>( this->m_InternalParametersBuffer.data_block() );
  const NumberOfParametersType numberOfPixels = this->GetNumberOfParametersPerDimension();

  for( unsigned int j = 0; j < SpaceDimension; j++ )
    {
    this->m_CoefficientImages[j]->GetPixelContainer()->
      SetImportPointer( dataPointer + j * numberOfPixels, numberOfPixels );
    }
}

// Get the parameters
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
const typename BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>::ParametersType &
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::GetParameters() const
{
  return this->m_InternalParametersBuffer;
}

// Get the parameters
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
const typename BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>::ParametersType &
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::GetFixedParameters() const
{
  // HACK:  This should not be necessary if the
  //       class is kept in a consistent state
  //  this->SetFixedParametersFromCoefficientImageInformation();
  return this->m_FixedParameters;
}

// Print self
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
void
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::PrintSelf( std::ostream & os, Indent indent ) const
{
  this->Superclass::PrintSelf(os, indent);

  os << indent << "CoefficientImage: [ ";
  for( unsigned int j = 0; j < SpaceDimension - 1; j++ )
    {
    os << this->m_CoefficientImages[j].GetPointer() << ", ";
    }
  os << this->m_CoefficientImages[SpaceDimension - 1].GetPointer()
     << " ]" << std::endl;
}

/** Get Jacobian at a point. A very specialized function just for BSplines */
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
void
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::ComputeJacobianFromBSplineWeightsWithRespectToPosition(
  const InputPointType & point, WeightsType & weights,
  ParameterIndexArrayType & indexes ) const
{
  ContinuousIndexType index;

  this->m_CoefficientImages[0]->TransformPhysicalPointToContinuousIndex( point, index );

  // NOTE: if the support region does not lie totally within the grid
  // we assume zero displacement and return the input point
  if( !this->InsideValidRegion( index ) )
    {
    weights.Fill( 0.0 );
    indexes.Fill( 0 );
    return;
    }

  // Compute interpolation weights
  IndexType supportIndex;
  this->m_WeightsFunction->Evaluate(index, weights, supportIndex);

  // For each dimension, copy the weight to the support region
  RegionType supportRegion;
  SizeType   supportSize;
  supportSize.Fill( SplineOrder + 1 );
  supportRegion.SetSize( supportSize );
  supportRegion.SetIndex( supportIndex );
  unsigned long counter = 0;

  typedef ImageRegionIterator<ImageType> IteratorType;

  IteratorType coeffIterator = IteratorType(
      this->m_CoefficientImages[0], supportRegion );
  const ParametersValueType *basePointer =
    this->m_CoefficientImages[0]->GetBufferPointer();
  while( !coeffIterator.IsAtEnd() )
    {
    indexes[counter] = &( coeffIterator.Value() ) - basePointer;

    // go to next coefficient in the support region
    ++counter;
    ++coeffIterator;
    }
}

template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
unsigned int
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::GetNumberOfAffectedWeights() const
{
  return this->m_WeightsFunction->GetNumberOfWeights();
}

// This helper class is used to work around a race condition where the dynamically
// generated images must exist before the references to the sub-sections are created.
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
typename BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>::CoefficientImageArray
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::ArrayOfImagePointerGeneratorHelper(void) const
{
  CoefficientImageArray tempArrayOfPointers;

  for( unsigned int j = 0; j < SpaceDimension; j++ )
    {
    tempArrayOfPointers[j] = ImageType::New();
    }
  return tempArrayOfPointers;
}

// Transform a point
template <typename TScalar, unsigned int NDimensions, unsigned int VSplineOrder>
typename BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::OutputPointType
BSplineBaseTransform<TScalar, NDimensions, VSplineOrder>
::TransformPoint(const InputPointType & point) const
{
  WeightsType             weights( this->m_WeightsFunction->GetNumberOfWeights() );
  ParameterIndexArrayType indices( this->m_WeightsFunction->GetNumberOfWeights() );
  OutputPointType         outputPoint;
  bool                    inside;

  this->TransformPoint( point, outputPoint, weights, indices, inside );

  return outputPoint;
}

} // namespace
#endif
<|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

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

#include "QmitkAbstractNodeSelectionWidget.h"
#include "QmitkModelViewSelectionConnector.h"

QmitkAbstractNodeSelectionWidget::QmitkAbstractNodeSelectionWidget(QWidget* parent) : QWidget(parent), m_InvalidInfo("Error. Select data."),
m_EmptyInfo("Empty. Make a selection."), m_PopUpTitel("Select a data node"), m_PopUpHint(""),
m_IsOptional(false), m_SelectOnlyVisibleNodes(true), m_DataStorageDeletedTag(0), m_LastEmissionAllowance(true), m_RecursionGuard(false)
{
}

QmitkAbstractNodeSelectionWidget::~QmitkAbstractNodeSelectionWidget()
{
  auto dataStorage = m_DataStorage.Lock();
  if (dataStorage.IsNotNull())
  {
    // remove Listener for the data storage itself
    dataStorage->RemoveObserver(m_DataStorageDeletedTag);

    // remove "add node listener" from data storage
    dataStorage->AddNodeEvent.RemoveListener(
      mitk::MessageDelegate1<QmitkAbstractNodeSelectionWidget, const mitk::DataNode*>(this, &QmitkAbstractNodeSelectionWidget::NodeAddedToStorage));

    // remove "remove node listener" from data storage
    dataStorage->RemoveNodeEvent.RemoveListener(
      mitk::MessageDelegate1<QmitkAbstractNodeSelectionWidget, const mitk::DataNode*>(this, &QmitkAbstractNodeSelectionWidget::NodeRemovedFromStorage));
  }

  for (auto& node : m_CurrentInternalSelection)
  {
    this->RemoveNodeObserver(node);
  }
}

QmitkAbstractNodeSelectionWidget::NodeList QmitkAbstractNodeSelectionWidget::GetSelectedNodes() const
{
  return this->CompileEmitSelection();
}

QmitkAbstractNodeSelectionWidget::ConstNodeStdVector QmitkAbstractNodeSelectionWidget::GetSelectedNodesStdVector() const
{
  auto result = this->GetSelectedNodes();
  return ConstNodeStdVector(result.begin(), result.end());
}

void QmitkAbstractNodeSelectionWidget::SetDataStorage(mitk::DataStorage* dataStorage)
{
  if (m_DataStorage == dataStorage)
  {
    return;
  }

  auto oldStorage = m_DataStorage.Lock();
  if (oldStorage.IsNotNull())
  {
    // remove Listener for the data storage itself
    oldStorage->RemoveObserver(m_DataStorageDeletedTag);

    // remove "add node listener" from old data storage
    oldStorage->AddNodeEvent.RemoveListener(
      mitk::MessageDelegate1<QmitkAbstractNodeSelectionWidget, const mitk::DataNode*>(this, &QmitkAbstractNodeSelectionWidget::NodeAddedToStorage));

    // remove "remove node listener" from old data storage
    oldStorage->RemoveNodeEvent.RemoveListener(
      mitk::MessageDelegate1<QmitkAbstractNodeSelectionWidget, const mitk::DataNode*>(this, &QmitkAbstractNodeSelectionWidget::NodeRemovedFromStorage));
  }

  m_DataStorage = dataStorage;

  auto newStorage = m_DataStorage.Lock();

  if (newStorage.IsNotNull())
  {
    // add Listener for the data storage itself
    auto command = itk::SimpleMemberCommand<QmitkAbstractNodeSelectionWidget>::New();
    command->SetCallbackFunction(this, &QmitkAbstractNodeSelectionWidget::SetDataStorageDeleted);
    m_DataStorageDeletedTag = newStorage->AddObserver(itk::DeleteEvent(), command);

    // add "add node listener" for new data storage
    newStorage->AddNodeEvent.AddListener(
      mitk::MessageDelegate1<QmitkAbstractNodeSelectionWidget, const mitk::DataNode*>(this, &QmitkAbstractNodeSelectionWidget::NodeAddedToStorage));

    // add remove node listener for new data storage
    newStorage->RemoveNodeEvent.AddListener(
      mitk::MessageDelegate1<QmitkAbstractNodeSelectionWidget, const mitk::DataNode*>(this, &QmitkAbstractNodeSelectionWidget::NodeRemovedFromStorage));
  }

  this->OnDataStorageChanged();

  this->HandleChangeOfInternalSelection({});
}

void QmitkAbstractNodeSelectionWidget::SetNodePredicate(const mitk::NodePredicateBase* nodePredicate)
{
  if (m_NodePredicate != nodePredicate)
  {
    m_NodePredicate = nodePredicate;

    this->OnNodePredicateChanged();

    NodeList newInternalNodes;

    for (auto& node : m_CurrentInternalSelection)
    {
      if (m_NodePredicate.IsNull() || m_NodePredicate->CheckNode(node))
      {
        newInternalNodes.append(node);
      }
    }

    if (!m_SelectOnlyVisibleNodes)
    {
      for (auto& node : m_CurrentExternalSelection)
      {
        if (!newInternalNodes.contains(node) && (m_NodePredicate.IsNull() || m_NodePredicate->CheckNode(node)))
        {
          newInternalNodes.append(node);
        }
      }
    }

    this->HandleChangeOfInternalSelection(newInternalNodes);
  }
}

void QmitkAbstractNodeSelectionWidget::HandleChangeOfInternalSelection(NodeList newInternalSelection)
{
  this->ReviseSelectionChanged(m_CurrentInternalSelection, newInternalSelection);

  this->SetCurrentInternalSelection(newInternalSelection);

  this->OnInternalSelectionChanged();

  auto newEmission = this->CompileEmitSelection();

  this->EmitSelection(newEmission);

  this->UpdateInfo();
}

void QmitkAbstractNodeSelectionWidget::SetCurrentSelection(NodeList selectedNodes)
{
  if (!m_RecursionGuard)
  {
    m_CurrentExternalSelection = selectedNodes;

    auto dataStorage = m_DataStorage.Lock();
    NodeList newInternalSelection;
    for (auto node : selectedNodes)
    {
      if (dataStorage.IsNotNull() && dataStorage->Exists(node) && (m_NodePredicate.IsNull() || m_NodePredicate->CheckNode(node)))
      {
        newInternalSelection.append(node);
      }
    }

    this->HandleChangeOfInternalSelection(newInternalSelection);
  }
}

const mitk::NodePredicateBase* QmitkAbstractNodeSelectionWidget::GetNodePredicate() const
{
  return m_NodePredicate;
}

QString QmitkAbstractNodeSelectionWidget::GetInvalidInfo() const
{
  return m_InvalidInfo;
}

QString QmitkAbstractNodeSelectionWidget::GetEmptyInfo() const
{
  return m_EmptyInfo;
}

QString QmitkAbstractNodeSelectionWidget::GetPopUpTitel() const
{
  return m_PopUpTitel;
}

QString QmitkAbstractNodeSelectionWidget::GetPopUpHint() const
{
  return m_PopUpHint;
}

bool QmitkAbstractNodeSelectionWidget::GetSelectionIsOptional() const
{
  return m_IsOptional;
}

bool QmitkAbstractNodeSelectionWidget::GetSelectOnlyVisibleNodes() const
{
  return m_SelectOnlyVisibleNodes;
}

void QmitkAbstractNodeSelectionWidget::SetSelectOnlyVisibleNodes(bool selectOnlyVisibleNodes)
{
  if (m_SelectOnlyVisibleNodes != selectOnlyVisibleNodes)
  {
    m_SelectOnlyVisibleNodes = selectOnlyVisibleNodes;

    auto newEmission = this->CompileEmitSelection();

    this->EmitSelection(newEmission);
  }
}

void QmitkAbstractNodeSelectionWidget::SetInvalidInfo(QString info)
{
  m_InvalidInfo = info;
  this->UpdateInfo();
}

void QmitkAbstractNodeSelectionWidget::SetEmptyInfo(QString info)
{
  m_EmptyInfo = info;
  this->UpdateInfo();
}

void QmitkAbstractNodeSelectionWidget::SetPopUpTitel(QString info)
{
  m_PopUpTitel = info;
}

void QmitkAbstractNodeSelectionWidget::SetPopUpHint(QString info)
{
  m_PopUpHint = info;
}

void QmitkAbstractNodeSelectionWidget::SetSelectionIsOptional(bool isOptional)
{
  m_IsOptional = isOptional;
  this->UpdateInfo();
}

void QmitkAbstractNodeSelectionWidget::SetDataStorageDeleted()
{
  this->OnDataStorageChanged();
  this->HandleChangeOfInternalSelection({});
}

void QmitkAbstractNodeSelectionWidget::ReviseSelectionChanged(const NodeList& /*oldInternalSelection*/, NodeList& /*newInternalSelection*/)
{
}

bool QmitkAbstractNodeSelectionWidget::AllowEmissionOfSelection(const NodeList& /*emissionCandidates*/) const
{
  return true;
}

void QmitkAbstractNodeSelectionWidget::EmitSelection(const NodeList& emissionCandidates)
{
  m_LastEmissionAllowance = this->AllowEmissionOfSelection(emissionCandidates);
  if (m_LastEmissionAllowance && !EqualNodeSelections(m_LastEmission, emissionCandidates))
  {
    m_RecursionGuard = true;
    emit CurrentSelectionChanged(emissionCandidates);
    m_RecursionGuard = false;
    m_LastEmission = emissionCandidates;
  }
}

void QmitkAbstractNodeSelectionWidget::SetCurrentInternalSelection(NodeList selectedNodes)
{
  for (auto& node : m_CurrentInternalSelection)
  {
    this->RemoveNodeObserver(node);
  }

  m_CurrentInternalSelection = selectedNodes;

  for (auto& node : m_CurrentInternalSelection)
  {
    this->AddNodeObserver(node);
  }
}

const QmitkAbstractNodeSelectionWidget::NodeList& QmitkAbstractNodeSelectionWidget::GetCurrentInternalSelection() const
{
  return m_CurrentInternalSelection;
}

const QmitkAbstractNodeSelectionWidget::NodeList& QmitkAbstractNodeSelectionWidget::GetCurrentExternalSelection() const
{
  return m_CurrentExternalSelection;
}

void QmitkAbstractNodeSelectionWidget::OnNodePredicateChanged()
{
}

void QmitkAbstractNodeSelectionWidget::OnDataStorageChanged()
{
}

void QmitkAbstractNodeSelectionWidget::OnInternalSelectionChanged()
{
}

void QmitkAbstractNodeSelectionWidget::NodeAddedToStorage(const mitk::DataNode* node)
{
  this->OnNodeAddedToStorage(node);
}

void QmitkAbstractNodeSelectionWidget::OnNodeAddedToStorage(const mitk::DataNode* /*node*/)
{
}

void QmitkAbstractNodeSelectionWidget::NodeRemovedFromStorage(const mitk::DataNode* node)
{
  this->OnNodeRemovedFromStorage(node);
  this->RemoveNodeFromSelection(node);
}

void QmitkAbstractNodeSelectionWidget::OnNodeRemovedFromStorage(const mitk::DataNode* /*node*/)
{
}

QmitkAbstractNodeSelectionWidget::NodeList QmitkAbstractNodeSelectionWidget::CompileEmitSelection() const
{
  NodeList result = m_CurrentInternalSelection;

  if (!m_SelectOnlyVisibleNodes)
  {
    for (auto node : m_CurrentExternalSelection)
    {
      if (!result.contains(node) && m_NodePredicate.IsNotNull() && !m_NodePredicate->CheckNode(node))
      {
        result.append(node);
      }
    }
  }

  return result;
}

void QmitkAbstractNodeSelectionWidget::RemoveNodeFromSelection(const mitk::DataNode* node)
{
  auto newSelection = m_CurrentInternalSelection;

  auto finding = std::find(std::begin(newSelection), std::end(newSelection), node);

  if (finding != std::end(newSelection))
  {
    newSelection.erase(finding);
    this->HandleChangeOfInternalSelection(newSelection);
  }
}

void QmitkAbstractNodeSelectionWidget::OnNodeModified(const itk::Object * caller, const itk::EventObject & event)
{
  if (itk::ModifiedEvent().CheckEvent(&event))
  {
    auto node = dynamic_cast<const mitk::DataNode*>(caller);

    if (node)
    {
      if (m_NodePredicate.IsNotNull() && !m_NodePredicate->CheckNode(node))
      {
        this->RemoveNodeFromSelection(node);
      }
      else
      {
        auto oldAllowance = m_LastEmissionAllowance;
        auto newEmission = this->CompileEmitSelection();
        auto nonConstNode = const_cast<mitk::DataNode*>(node);
        if (newEmission.contains(nonConstNode) && (oldAllowance != this->AllowEmissionOfSelection(newEmission)))
        {
          this->EmitSelection(newEmission);
          this->UpdateInfo();
        }
      }
    }
  }
}

void QmitkAbstractNodeSelectionWidget::AddNodeObserver(mitk::DataNode* node)
{
  if (node)
  {
    auto modifiedCommand = itk::MemberCommand<QmitkAbstractNodeSelectionWidget>::New();
    modifiedCommand->SetCallbackFunction(this, &QmitkAbstractNodeSelectionWidget::OnNodeModified);

    auto nodeModifiedObserverTag = node->AddObserver(itk::ModifiedEvent(), modifiedCommand);

    m_NodeObserverTags.insert(std::make_pair(node, nodeModifiedObserverTag));
  }
}

void QmitkAbstractNodeSelectionWidget::RemoveNodeObserver(mitk::DataNode* node)
{
  if (node)
  {
    auto finding = m_NodeObserverTags.find(node);
    if (finding != std::end(m_NodeObserverTags))
    {
      node->RemoveObserver(finding->second);
    }
    else
    {
      MITK_ERROR << "Selection widget is in a wrong state. A node should be removed from the internal selection but seems to have no observer. Node:" << node;
    }
    m_NodeObserverTags.erase(node);
  }
}
<commit_msg>Fixed T27200<commit_after>/*============================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

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

#include "QmitkAbstractNodeSelectionWidget.h"
#include "QmitkModelViewSelectionConnector.h"

QmitkAbstractNodeSelectionWidget::QmitkAbstractNodeSelectionWidget(QWidget* parent) : QWidget(parent), m_InvalidInfo("Error. Select data."),
m_EmptyInfo("Empty. Make a selection."), m_PopUpTitel("Select a data node"), m_PopUpHint(""),
m_IsOptional(false), m_SelectOnlyVisibleNodes(true), m_DataStorageDeletedTag(0), m_LastEmissionAllowance(true), m_RecursionGuard(false)
{
}

QmitkAbstractNodeSelectionWidget::~QmitkAbstractNodeSelectionWidget()
{
  auto dataStorage = m_DataStorage.Lock();
  if (dataStorage.IsNotNull())
  {
    // remove Listener for the data storage itself
    dataStorage->RemoveObserver(m_DataStorageDeletedTag);

    // remove "add node listener" from data storage
    dataStorage->AddNodeEvent.RemoveListener(
      mitk::MessageDelegate1<QmitkAbstractNodeSelectionWidget, const mitk::DataNode*>(this, &QmitkAbstractNodeSelectionWidget::NodeAddedToStorage));

    // remove "remove node listener" from data storage
    dataStorage->RemoveNodeEvent.RemoveListener(
      mitk::MessageDelegate1<QmitkAbstractNodeSelectionWidget, const mitk::DataNode*>(this, &QmitkAbstractNodeSelectionWidget::NodeRemovedFromStorage));
  }

  for (auto& node : m_CurrentInternalSelection)
  {
    this->RemoveNodeObserver(node);
  }
}

QmitkAbstractNodeSelectionWidget::NodeList QmitkAbstractNodeSelectionWidget::GetSelectedNodes() const
{
  return this->CompileEmitSelection();
}

QmitkAbstractNodeSelectionWidget::ConstNodeStdVector QmitkAbstractNodeSelectionWidget::GetSelectedNodesStdVector() const
{
  auto result = this->GetSelectedNodes();
  return ConstNodeStdVector(result.begin(), result.end());
}

void QmitkAbstractNodeSelectionWidget::SetDataStorage(mitk::DataStorage* dataStorage)
{
  if (m_DataStorage == dataStorage)
  {
    return;
  }

  auto oldStorage = m_DataStorage.Lock();
  if (oldStorage.IsNotNull())
  {
    // remove Listener for the data storage itself
    oldStorage->RemoveObserver(m_DataStorageDeletedTag);

    // remove "add node listener" from old data storage
    oldStorage->AddNodeEvent.RemoveListener(
      mitk::MessageDelegate1<QmitkAbstractNodeSelectionWidget, const mitk::DataNode*>(this, &QmitkAbstractNodeSelectionWidget::NodeAddedToStorage));

    // remove "remove node listener" from old data storage
    oldStorage->RemoveNodeEvent.RemoveListener(
      mitk::MessageDelegate1<QmitkAbstractNodeSelectionWidget, const mitk::DataNode*>(this, &QmitkAbstractNodeSelectionWidget::NodeRemovedFromStorage));
  }

  m_DataStorage = dataStorage;

  auto newStorage = m_DataStorage.Lock();

  if (newStorage.IsNotNull())
  {
    // add Listener for the data storage itself
    auto command = itk::SimpleMemberCommand<QmitkAbstractNodeSelectionWidget>::New();
    command->SetCallbackFunction(this, &QmitkAbstractNodeSelectionWidget::SetDataStorageDeleted);
    m_DataStorageDeletedTag = newStorage->AddObserver(itk::DeleteEvent(), command);

    // add "add node listener" for new data storage
    newStorage->AddNodeEvent.AddListener(
      mitk::MessageDelegate1<QmitkAbstractNodeSelectionWidget, const mitk::DataNode*>(this, &QmitkAbstractNodeSelectionWidget::NodeAddedToStorage));

    // add remove node listener for new data storage
    newStorage->RemoveNodeEvent.AddListener(
      mitk::MessageDelegate1<QmitkAbstractNodeSelectionWidget, const mitk::DataNode*>(this, &QmitkAbstractNodeSelectionWidget::NodeRemovedFromStorage));
  }

  this->OnDataStorageChanged();

  this->HandleChangeOfInternalSelection({});
}

void QmitkAbstractNodeSelectionWidget::SetNodePredicate(const mitk::NodePredicateBase* nodePredicate)
{
  if (m_NodePredicate != nodePredicate)
  {
    m_NodePredicate = nodePredicate;

    this->OnNodePredicateChanged();

    NodeList newInternalNodes;

    for (auto& node : m_CurrentInternalSelection)
    {
      if (m_NodePredicate.IsNull() || m_NodePredicate->CheckNode(node))
      {
        newInternalNodes.append(node);
      }
    }

    if (!m_SelectOnlyVisibleNodes)
    {
      for (auto& node : m_CurrentExternalSelection)
      {
        if (!newInternalNodes.contains(node) && (m_NodePredicate.IsNull() || m_NodePredicate->CheckNode(node)))
        {
          newInternalNodes.append(node);
        }
      }
    }

    this->HandleChangeOfInternalSelection(newInternalNodes);
  }
}

void QmitkAbstractNodeSelectionWidget::HandleChangeOfInternalSelection(NodeList newInternalSelection)
{
  if (!EqualNodeSelections(m_CurrentInternalSelection, newInternalSelection))
  {
    this->ReviseSelectionChanged(m_CurrentInternalSelection, newInternalSelection);

    this->SetCurrentInternalSelection(newInternalSelection);

    this->OnInternalSelectionChanged();

    auto newEmission = this->CompileEmitSelection();

    this->EmitSelection(newEmission);

    this->UpdateInfo();
  }
}

void QmitkAbstractNodeSelectionWidget::SetCurrentSelection(NodeList selectedNodes)
{
  if (!m_RecursionGuard)
  {
    m_CurrentExternalSelection = selectedNodes;

    auto dataStorage = m_DataStorage.Lock();
    NodeList newInternalSelection;
    for (auto node : selectedNodes)
    {
      if (dataStorage.IsNotNull() && dataStorage->Exists(node) && (m_NodePredicate.IsNull() || m_NodePredicate->CheckNode(node)))
      {
        newInternalSelection.append(node);
      }
    }

    this->HandleChangeOfInternalSelection(newInternalSelection);
  }
}

const mitk::NodePredicateBase* QmitkAbstractNodeSelectionWidget::GetNodePredicate() const
{
  return m_NodePredicate;
}

QString QmitkAbstractNodeSelectionWidget::GetInvalidInfo() const
{
  return m_InvalidInfo;
}

QString QmitkAbstractNodeSelectionWidget::GetEmptyInfo() const
{
  return m_EmptyInfo;
}

QString QmitkAbstractNodeSelectionWidget::GetPopUpTitel() const
{
  return m_PopUpTitel;
}

QString QmitkAbstractNodeSelectionWidget::GetPopUpHint() const
{
  return m_PopUpHint;
}

bool QmitkAbstractNodeSelectionWidget::GetSelectionIsOptional() const
{
  return m_IsOptional;
}

bool QmitkAbstractNodeSelectionWidget::GetSelectOnlyVisibleNodes() const
{
  return m_SelectOnlyVisibleNodes;
}

void QmitkAbstractNodeSelectionWidget::SetSelectOnlyVisibleNodes(bool selectOnlyVisibleNodes)
{
  if (m_SelectOnlyVisibleNodes != selectOnlyVisibleNodes)
  {
    m_SelectOnlyVisibleNodes = selectOnlyVisibleNodes;

    auto newEmission = this->CompileEmitSelection();

    this->EmitSelection(newEmission);
  }
}

void QmitkAbstractNodeSelectionWidget::SetInvalidInfo(QString info)
{
  m_InvalidInfo = info;
  this->UpdateInfo();
}

void QmitkAbstractNodeSelectionWidget::SetEmptyInfo(QString info)
{
  m_EmptyInfo = info;
  this->UpdateInfo();
}

void QmitkAbstractNodeSelectionWidget::SetPopUpTitel(QString info)
{
  m_PopUpTitel = info;
}

void QmitkAbstractNodeSelectionWidget::SetPopUpHint(QString info)
{
  m_PopUpHint = info;
}

void QmitkAbstractNodeSelectionWidget::SetSelectionIsOptional(bool isOptional)
{
  m_IsOptional = isOptional;
  this->UpdateInfo();
}

void QmitkAbstractNodeSelectionWidget::SetDataStorageDeleted()
{
  this->OnDataStorageChanged();
  this->HandleChangeOfInternalSelection({});
}

void QmitkAbstractNodeSelectionWidget::ReviseSelectionChanged(const NodeList& /*oldInternalSelection*/, NodeList& /*newInternalSelection*/)
{
}

bool QmitkAbstractNodeSelectionWidget::AllowEmissionOfSelection(const NodeList& /*emissionCandidates*/) const
{
  return true;
}

void QmitkAbstractNodeSelectionWidget::EmitSelection(const NodeList& emissionCandidates)
{
  m_LastEmissionAllowance = this->AllowEmissionOfSelection(emissionCandidates);
  if (m_LastEmissionAllowance && !EqualNodeSelections(m_LastEmission, emissionCandidates))
  {
    m_RecursionGuard = true;
    emit CurrentSelectionChanged(emissionCandidates);
    m_RecursionGuard = false;
    m_LastEmission = emissionCandidates;
  }
}

void QmitkAbstractNodeSelectionWidget::SetCurrentInternalSelection(NodeList selectedNodes)
{
  for (auto& node : m_CurrentInternalSelection)
  {
    this->RemoveNodeObserver(node);
  }

  m_CurrentInternalSelection = selectedNodes;

  for (auto& node : m_CurrentInternalSelection)
  {
    this->AddNodeObserver(node);
  }
}

const QmitkAbstractNodeSelectionWidget::NodeList& QmitkAbstractNodeSelectionWidget::GetCurrentInternalSelection() const
{
  return m_CurrentInternalSelection;
}

const QmitkAbstractNodeSelectionWidget::NodeList& QmitkAbstractNodeSelectionWidget::GetCurrentExternalSelection() const
{
  return m_CurrentExternalSelection;
}

void QmitkAbstractNodeSelectionWidget::OnNodePredicateChanged()
{
}

void QmitkAbstractNodeSelectionWidget::OnDataStorageChanged()
{
}

void QmitkAbstractNodeSelectionWidget::OnInternalSelectionChanged()
{
}

void QmitkAbstractNodeSelectionWidget::NodeAddedToStorage(const mitk::DataNode* node)
{
  this->OnNodeAddedToStorage(node);
}

void QmitkAbstractNodeSelectionWidget::OnNodeAddedToStorage(const mitk::DataNode* /*node*/)
{
}

void QmitkAbstractNodeSelectionWidget::NodeRemovedFromStorage(const mitk::DataNode* node)
{
  this->OnNodeRemovedFromStorage(node);
  this->RemoveNodeFromSelection(node);
}

void QmitkAbstractNodeSelectionWidget::OnNodeRemovedFromStorage(const mitk::DataNode* /*node*/)
{
}

QmitkAbstractNodeSelectionWidget::NodeList QmitkAbstractNodeSelectionWidget::CompileEmitSelection() const
{
  NodeList result = m_CurrentInternalSelection;

  if (!m_SelectOnlyVisibleNodes)
  {
    for (auto node : m_CurrentExternalSelection)
    {
      if (!result.contains(node) && m_NodePredicate.IsNotNull() && !m_NodePredicate->CheckNode(node))
      {
        result.append(node);
      }
    }
  }

  return result;
}

void QmitkAbstractNodeSelectionWidget::RemoveNodeFromSelection(const mitk::DataNode* node)
{
  auto newSelection = m_CurrentInternalSelection;

  auto finding = std::find(std::begin(newSelection), std::end(newSelection), node);

  if (finding != std::end(newSelection))
  {
    newSelection.erase(finding);
    this->HandleChangeOfInternalSelection(newSelection);
  }
}

void QmitkAbstractNodeSelectionWidget::OnNodeModified(const itk::Object * caller, const itk::EventObject & event)
{
  if (itk::ModifiedEvent().CheckEvent(&event))
  {
    auto node = dynamic_cast<const mitk::DataNode*>(caller);

    if (node)
    {
      if (m_NodePredicate.IsNotNull() && !m_NodePredicate->CheckNode(node))
      {
        this->RemoveNodeFromSelection(node);
      }
      else
      {
        auto oldAllowance = m_LastEmissionAllowance;
        auto newEmission = this->CompileEmitSelection();
        auto nonConstNode = const_cast<mitk::DataNode*>(node);
        if (newEmission.contains(nonConstNode) && (oldAllowance != this->AllowEmissionOfSelection(newEmission)))
        {
          this->EmitSelection(newEmission);
          this->UpdateInfo();
        }
      }
    }
  }
}

void QmitkAbstractNodeSelectionWidget::AddNodeObserver(mitk::DataNode* node)
{
  if (node)
  {
    auto modifiedCommand = itk::MemberCommand<QmitkAbstractNodeSelectionWidget>::New();
    modifiedCommand->SetCallbackFunction(this, &QmitkAbstractNodeSelectionWidget::OnNodeModified);

    auto nodeModifiedObserverTag = node->AddObserver(itk::ModifiedEvent(), modifiedCommand);

    m_NodeObserverTags.insert(std::make_pair(node, nodeModifiedObserverTag));
  }
}

void QmitkAbstractNodeSelectionWidget::RemoveNodeObserver(mitk::DataNode* node)
{
  if (node)
  {
    auto finding = m_NodeObserverTags.find(node);
    if (finding != std::end(m_NodeObserverTags))
    {
      node->RemoveObserver(finding->second);
    }
    else
    {
      MITK_ERROR << "Selection widget is in a wrong state. A node should be removed from the internal selection but seems to have no observer. Node:" << node;
    }
    m_NodeObserverTags.erase(node);
  }
}
<|endoftext|>


<commit_before>#include "../ClipperUtils.hpp"
#include "../PolylineCollection.hpp"
#include "../Surface.hpp"
#include <cmath>
#include <algorithm>
#include <iostream>

#include "FillGyroid.hpp"

namespace Slic3r {

static inline double f(double x, double z_sin, double z_cos, bool vertical, bool flip)
{
    if (vertical) {
        double phase_offset = (z_cos < 0 ? M_PI : 0) + M_PI;
        double a   = sin(x + phase_offset);
        double b   = - z_cos;
        double res = z_sin * cos(x + phase_offset + (flip ? M_PI : 0.));
        double r   = sqrt(sqr(a) + sqr(b));
        return asin(a/r) + asin(res/r) + M_PI;
    }
    else {
        double phase_offset = z_sin < 0 ? M_PI : 0.;
        double a   = cos(x + phase_offset);
        double b   = - z_sin;
        double res = z_cos * sin(x + phase_offset + (flip ? 0 : M_PI));
        double r   = sqrt(sqr(a) + sqr(b));
        return (asin(a/r) + asin(res/r) + 0.5 * M_PI);
    }
}

static inline Polyline make_wave(
    const std::vector<Vec2d>& one_period, double width, double height, double offset, double scaleFactor,
    double z_cos, double z_sin, bool vertical, bool flip)
{
    std::vector<Vec2d> points = one_period;
    double period = points.back()(0);
    if (width != period) // do not extend if already truncated
    {
        points.reserve(one_period.size() * floor(width / period));
        points.pop_back();

        int n = points.size();
        do {
            points.emplace_back(Vec2d(points[points.size()-n](0) + period, points[points.size()-n](1)));
        } while (points.back()(0) < width - EPSILON);

        points.emplace_back(Vec2d(width, f(width, z_sin, z_cos, vertical, flip)));
    }

    // and construct the final polyline to return:
    Polyline polyline;
    polyline.points.reserve(points.size());
    for (auto& point : points) {
        point(1) += offset;
        point(1) = clamp(0., height, double(point(1)));
        if (vertical)
            std::swap(point(0), point(1));
        polyline.points.emplace_back((point * scaleFactor).cast<coord_t>());
    }

    return polyline;
}

static std::vector<Vec2d> make_one_period(double width, double scaleFactor, double z_cos, double z_sin, bool vertical, bool flip, double tolerance)
{
    std::vector<Vec2d> points;
    double dx = M_PI_2; // exact coordinates on main inflexion lobes
    double limit = std::min(2*M_PI, width);
    points.reserve(ceil(limit / tolerance / 3));

    for (double x = 0.; x < limit - EPSILON; x += dx) {
        points.emplace_back(Vec2d(x, f(x, z_sin, z_cos, vertical, flip)));
    }
    points.emplace_back(Vec2d(limit, f(limit, z_sin, z_cos, vertical, flip)));

    // piecewise increase in resolution up to requested tolerance
    for(;;)
    {
        size_t size = points.size();
        for (unsigned int i = 1;i < size; ++i) {
            auto& lp = points[i-1]; // left point
            auto& rp = points[i];   // right point
            double x = lp(0) + (rp(0) - lp(0)) / 2;
            double y = f(x, z_sin, z_cos, vertical, flip);
            Vec2d ip = {x, y};
            if (std::abs(cross2(Vec2d(ip - lp), Vec2d(ip - rp))) > sqr(tolerance)) {
                points.emplace_back(std::move(ip));
            }
        }

        if (size == points.size())
            break;
        else
        {
            // insert new points in order
            std::sort(points.begin(), points.end(),
                      [](const Vec2d &lhs, const Vec2d &rhs) { return lhs(0) < rhs(0); });
        }
    }

    return points;
}

static Polylines make_gyroid_waves(double gridZ, double density_adjusted, double line_spacing, double width, double height)
{
    const double scaleFactor = scale_(line_spacing) / density_adjusted;

    // tolerance (in scaled units)
    // TODO: should consider layer thickness
    const double tolerance = line_spacing / 2 / unscale<double>(scaleFactor);

 //scale factor for 5% : 8 712 388
 // 1z = 10^-6 mm ?
    const double z     = gridZ / scaleFactor;
    const double z_sin = sin(z);
    const double z_cos = cos(z);

    bool vertical = (std::abs(z_sin) <= std::abs(z_cos));
    double lower_bound = 0.;
    double upper_bound = height;
    bool flip = true;
    if (vertical) {
        flip = false;
        lower_bound = -M_PI;
        upper_bound = width - M_PI_2;
        std::swap(width,height);
    }

    std::vector<Vec2d> one_period_odd = make_one_period(width, scaleFactor, z_cos, z_sin, vertical, flip, tolerance); // creates one period of the waves, so it doesn't have to be recalculated all the time
    flip = !flip;                                                                   // even polylines are a bit shifted
    std::vector<Vec2d> one_period_even = make_one_period(width, scaleFactor, z_cos, z_sin, vertical, flip, tolerance);
    Polylines result;

    for (double y0 = lower_bound; y0 < upper_bound + EPSILON; y0 += M_PI) {
        // creates odd polylines
        result.emplace_back(make_wave(one_period_odd, width, height, y0, scaleFactor, z_cos, z_sin, vertical, flip));
        // creates even polylines
        y0 += M_PI;
        if (y0 < upper_bound + EPSILON) {
            result.emplace_back(make_wave(one_period_even, width, height, y0, scaleFactor, z_cos, z_sin, vertical, flip));
        }
    }

    return result;
}

void FillGyroid::_fill_surface_single(
    const FillParams                &params,
    unsigned int                     thickness_layers,
    const std::pair<float, Point>   &direction,
    ExPolygon                       &expolygon,
    Polylines                       &polylines_out)
{
    // no rotation is supported for this infill pattern (yet)
    BoundingBox bb = expolygon.contour.bounding_box();
    // Density adjusted to have a good %of weight.
    double      density_adjusted = std::max(0., params.density * 2.44);
    // Distance between the gyroid waves in scaled coordinates.
    coord_t     distance = coord_t(scale_(this->spacing) / density_adjusted);

    // align bounding box to a multiple of our grid module
    bb.merge(_align_to_grid(bb.min, Point(2.*M_PI*distance, 2.*M_PI*distance)));

    // generate pattern
    Polylines polylines_square = make_gyroid_waves(
        scale_(this->z),
        density_adjusted,
        this->spacing,
        ceil(bb.size()(0) / distance) + 1.,
        ceil(bb.size()(1) / distance) + 1.);

    // move pattern in place
    for (Polyline &polyline : polylines_square)
        polyline.translate(bb.min(0), bb.min(1));

    // clip pattern to boundaries, keeping the polyline order & ordering the fragment to be able to join them easily
    //Polylines polylines = intersection_pl(polylines_square, (Polygons)expolygon);
    Polylines polylines_chained;
    for (size_t idx_polyline = 0; idx_polyline < polylines_square.size(); ++idx_polyline) {
        Polyline &poly_to_cut = polylines_square[idx_polyline];
        Polylines polylines_to_sort = intersection_pl(Polylines() = { poly_to_cut }, (Polygons)expolygon);
        for (Polyline &polyline : polylines_to_sort) {
            //TODO: replace by closest_index_point()
            if (idx_polyline % 2 == 0) {
                if (poly_to_cut.points.front().distance_to_square(polyline.points.front()) > poly_to_cut.points.front().distance_to_square(polyline.points.back())) {
                    polyline.reverse();
                }
            } else {
                if (poly_to_cut.points.back().distance_to_square(polyline.points.front()) > poly_to_cut.points.back().distance_to_square(polyline.points.back())) {
                    polyline.reverse();
                }
            }
        }
        if (polylines_to_sort.size() > 1) {
            Point nearest = poly_to_cut.points.front();
            if (idx_polyline % 2 != 0) {
                nearest = poly_to_cut.points.back();
            }
            //Bubble sort
            for (size_t idx_sort = polylines_to_sort.size() - 1; idx_sort > 0; idx_sort--) {
                for (size_t idx_bubble = 0; idx_bubble < idx_sort; idx_bubble++) {
                    if (polylines_to_sort[idx_bubble + 1].points.front().distance_to_square(nearest) < polylines_to_sort[idx_bubble].points.front().distance_to_square(nearest)) {
                        iter_swap(polylines_to_sort.begin() + idx_bubble, polylines_to_sort.begin() + idx_bubble + 1);
                    }
                }
            }
        }
        polylines_chained.insert(polylines_chained.end(), polylines_to_sort.begin(), polylines_to_sort.end());
    }

    size_t polylines_out_first_idx = polylines_out.size();
    if (!polylines_chained.empty()) {
        // connect lines
        if (params.dont_connect) {
            polylines_out.insert(polylines_out.end(), polylines_chained.begin(), polylines_chained.end());
        } else {
            this->connect_infill(polylines_chained, expolygon, polylines_out, params);
        }
    }

    //remove too small bits (larger than longer);
    for (size_t idx = polylines_out_first_idx; idx < polylines_out.size(); idx++) {
        if (polylines_out[idx].length() < scale_(this->spacing * 3)) {
            polylines_out.erase(polylines_out.begin() + idx);
            idx--;
        }
    }
}

} // namespace Slic3r
<commit_msg>Allow gyroid pattern rotation over Z<commit_after>#include "../ClipperUtils.hpp"
#include "../PolylineCollection.hpp"
#include "../Surface.hpp"
#include <cmath>
#include <algorithm>
#include <iostream>

#include "FillGyroid.hpp"

namespace Slic3r {

static inline double f(double x, double z_sin, double z_cos, bool vertical, bool flip)
{
    if (vertical) {
        double phase_offset = (z_cos < 0 ? M_PI : 0) + M_PI;
        double a   = sin(x + phase_offset);
        double b   = - z_cos;
        double res = z_sin * cos(x + phase_offset + (flip ? M_PI : 0.));
        double r   = sqrt(sqr(a) + sqr(b));
        return asin(a/r) + asin(res/r) + M_PI;
    }
    else {
        double phase_offset = z_sin < 0 ? M_PI : 0.;
        double a   = cos(x + phase_offset);
        double b   = - z_sin;
        double res = z_cos * sin(x + phase_offset + (flip ? 0 : M_PI));
        double r   = sqrt(sqr(a) + sqr(b));
        return (asin(a/r) + asin(res/r) + 0.5 * M_PI);
    }
}

static inline Polyline make_wave(
    const std::vector<Vec2d>& one_period, double width, double height, double offset, double scaleFactor,
    double z_cos, double z_sin, bool vertical, bool flip)
{
    std::vector<Vec2d> points = one_period;
    double period = points.back()(0);
    if (width != period) // do not extend if already truncated
    {
        points.reserve(one_period.size() * floor(width / period));
        points.pop_back();

        int n = points.size();
        do {
            points.emplace_back(Vec2d(points[points.size()-n](0) + period, points[points.size()-n](1)));
        } while (points.back()(0) < width - EPSILON);

        points.emplace_back(Vec2d(width, f(width, z_sin, z_cos, vertical, flip)));
    }

    // and construct the final polyline to return:
    Polyline polyline;
    polyline.points.reserve(points.size());
    for (auto& point : points) {
        point(1) += offset;
        point(1) = clamp(0., height, double(point(1)));
        if (vertical)
            std::swap(point(0), point(1));
        polyline.points.emplace_back((point * scaleFactor).cast<coord_t>());
    }

    return polyline;
}

static std::vector<Vec2d> make_one_period(double width, double scaleFactor, double z_cos, double z_sin, bool vertical, bool flip, double tolerance)
{
    std::vector<Vec2d> points;
    double dx = M_PI_2; // exact coordinates on main inflexion lobes
    double limit = std::min(2*M_PI, width);
    points.reserve(ceil(limit / tolerance / 3));

    for (double x = 0.; x < limit - EPSILON; x += dx) {
        points.emplace_back(Vec2d(x, f(x, z_sin, z_cos, vertical, flip)));
    }
    points.emplace_back(Vec2d(limit, f(limit, z_sin, z_cos, vertical, flip)));

    // piecewise increase in resolution up to requested tolerance
    for(;;)
    {
        size_t size = points.size();
        for (unsigned int i = 1;i < size; ++i) {
            auto& lp = points[i-1]; // left point
            auto& rp = points[i];   // right point
            double x = lp(0) + (rp(0) - lp(0)) / 2;
            double y = f(x, z_sin, z_cos, vertical, flip);
            Vec2d ip = {x, y};
            if (std::abs(cross2(Vec2d(ip - lp), Vec2d(ip - rp))) > sqr(tolerance)) {
                points.emplace_back(std::move(ip));
            }
        }

        if (size == points.size())
            break;
        else
        {
            // insert new points in order
            std::sort(points.begin(), points.end(),
                      [](const Vec2d &lhs, const Vec2d &rhs) { return lhs(0) < rhs(0); });
        }
    }

    return points;
}

static Polylines make_gyroid_waves(double gridZ, double density_adjusted, double line_spacing, double width, double height)
{
    const double scaleFactor = scale_(line_spacing) / density_adjusted;

    // tolerance (in scaled units)
    // TODO: should consider layer thickness
    const double tolerance = line_spacing / 2 / unscale<double>(scaleFactor);

 //scale factor for 5% : 8 712 388
 // 1z = 10^-6 mm ?
    const double z     = gridZ / scaleFactor;
    const double z_sin = sin(z);
    const double z_cos = cos(z);

    bool vertical = (std::abs(z_sin) <= std::abs(z_cos));
    double lower_bound = 0.;
    double upper_bound = height;
    bool flip = true;
    if (vertical) {
        flip = false;
        lower_bound = -M_PI;
        upper_bound = width - M_PI_2;
        std::swap(width,height);
    }

    std::vector<Vec2d> one_period_odd = make_one_period(width, scaleFactor, z_cos, z_sin, vertical, flip, tolerance); // creates one period of the waves, so it doesn't have to be recalculated all the time
    flip = !flip;                                                                   // even polylines are a bit shifted
    std::vector<Vec2d> one_period_even = make_one_period(width, scaleFactor, z_cos, z_sin, vertical, flip, tolerance);
    Polylines result;

    for (double y0 = lower_bound; y0 < upper_bound + EPSILON; y0 += M_PI) {
        // creates odd polylines
        result.emplace_back(make_wave(one_period_odd, width, height, y0, scaleFactor, z_cos, z_sin, vertical, flip));
        // creates even polylines
        y0 += M_PI;
        if (y0 < upper_bound + EPSILON) {
            result.emplace_back(make_wave(one_period_even, width, height, y0, scaleFactor, z_cos, z_sin, vertical, flip));
        }
    }

    return result;
}

void FillGyroid::_fill_surface_single(
    const FillParams                &params,
    unsigned int                     thickness_layers,
    const std::pair<float, Point>   &direction,
    ExPolygon                       &expolygon,
    Polylines                       &polylines_out)
{
    expolygon.rotate(-this->angle);

    BoundingBox bb = expolygon.contour.bounding_box();
    // Density adjusted to have a good %of weight.
    double      density_adjusted = std::max(0., params.density * 2.44);
    // Distance between the gyroid waves in scaled coordinates.
    coord_t     distance = coord_t(scale_(this->spacing) / density_adjusted);

    // align bounding box to a multiple of our grid module
    bb.merge(_align_to_grid(bb.min, Point(2*M_PI*distance, 2*M_PI*distance)));

    // generate pattern
    Polylines polylines_square = make_gyroid_waves(
        scale_(this->z),
        density_adjusted,
        this->spacing,
        ceil(bb.size()(0) / distance) + 1.,
        ceil(bb.size()(1) / distance) + 1.);

    // clip pattern to boundaries, keeping the polyline order & ordering the fragment to be able to join them easily
    Polylines polylines_chained;
    for (size_t idx_polyline = 0; idx_polyline < polylines_square.size(); ++idx_polyline) {
        // shift the polyline to the grid origin
        Polyline &poly_to_cut = polylines_square[idx_polyline];
        poly_to_cut.translate(bb.min);

        // intersect
        Polylines polylines_to_sort = intersection_pl(Polylines() = { poly_to_cut }, (Polygons)expolygon);
        for (Polyline &polyline : polylines_to_sort) {
            //TODO: replace by closest_index_point()
            if (idx_polyline % 2 == 0) {
                if (poly_to_cut.points.front().distance_to_square(polyline.points.front()) > poly_to_cut.points.front().distance_to_square(polyline.points.back())) {
                    polyline.reverse();
                }
            } else {
                if (poly_to_cut.points.back().distance_to_square(polyline.points.front()) > poly_to_cut.points.back().distance_to_square(polyline.points.back())) {
                    polyline.reverse();
                }
            }
        }
        if (polylines_to_sort.size() > 1) {
            Point nearest = poly_to_cut.points.front();
            if (idx_polyline % 2 != 0) {
                nearest = poly_to_cut.points.back();
            }
            //Bubble sort
            for (size_t idx_sort = polylines_to_sort.size() - 1; idx_sort > 0; idx_sort--) {
                for (size_t idx_bubble = 0; idx_bubble < idx_sort; idx_bubble++) {
                    if (polylines_to_sort[idx_bubble + 1].points.front().distance_to_square(nearest) < polylines_to_sort[idx_bubble].points.front().distance_to_square(nearest)) {
                        iter_swap(polylines_to_sort.begin() + idx_bubble, polylines_to_sort.begin() + idx_bubble + 1);
                    }
                }
            }
        }
        polylines_chained.insert(polylines_chained.end(), polylines_to_sort.begin(), polylines_to_sort.end());
    }

    size_t polylines_out_first_idx = polylines_out.size();
    if (!polylines_chained.empty()) {
        // connect lines
        if (params.dont_connect) {
            polylines_out.insert(polylines_out.end(), polylines_chained.begin(), polylines_chained.end());
        } else {
            this->connect_infill(polylines_chained, expolygon, polylines_out, params);
        }
    }

    //remove too small bits (larger than longer);
    for (size_t idx = polylines_out_first_idx; idx < polylines_out.size(); idx++) {
        if (polylines_out[idx].length() < scale_(this->spacing * 3)) {
            polylines_out.erase(polylines_out.begin() + idx);
            idx--;
        }
    }

    // new paths must be rotated back
    for (Polylines::iterator it = polylines_out.begin() + polylines_out_first_idx;
         it != polylines_out.end(); ++it) {
        it->rotate(this->angle);
    }
}

} // namespace Slic3r
<|endoftext|>


<commit_before>/***********************************************************************
    filename:   CEGuiOgreBaseApplication.cpp
    created:    9/3/2004
    author:     Paul D Turner
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#   include "config.h"
#endif

// this controls conditional compile of file for Apple
#include "CEGUISamplesConfig.h"
#ifdef CEGUI_SAMPLES_USE_OGRE

#include "CEGuiOgreBaseApplication.h"
#include "CEGuiSample.h"

#include <OgreKeyEvent.h>

CEGuiOgreBaseApplication::CEGuiOgreBaseApplication() :
        d_ogreRoot(0),
        d_renderer(0),
        d_initialised(false),
        d_frameListener(0)
{
    using namespace Ogre;

    d_ogreRoot = new Root();

    initialiseResources();

    if (d_ogreRoot->showConfigDialog())
    {
        // initialise system according to user options.
        d_window = d_ogreRoot->initialise(true);

        // Create and initialise the camera
        d_camera = d_ogreRoot->getSceneManagerIterator().getNext()->createCamera("PlayerCam");
        d_camera->setPosition(Vector3(0,0,500));
        d_camera->lookAt(Vector3(0,0,-300));
        d_camera->setNearClipDistance(5);

        // Create a viewport covering whole window
        Viewport* vp = d_window->addViewport(d_camera);
        vp->setBackgroundColour(ColourValue(0,0,0));

        // Update the camera aspect ratio to that of the viewport
        d_camera->setAspectRatio(Real(vp->getActualWidth()) / Real(vp->getActualHeight()));

        // initialise resources
        ResourceGroupManager::getSingleton().initialiseAllResourceGroups();

        // initialise GUI system
        d_renderer = new CEGUI::OgreCEGUIRenderer(d_window);
        new CEGUI::System(d_renderer);

        // create frame listener
        d_frameListener= new CEGuiDemoFrameListener(this, d_window, d_camera);
        d_ogreRoot->addFrameListener(d_frameListener);

        d_initialised = true;
    }
    else
    {
        // aborted.  Clean up and set root to 0 so when app attempts to run it knows what happened here.
        delete d_ogreRoot;
        d_ogreRoot = 0;
    }
}

CEGuiOgreBaseApplication::~CEGuiOgreBaseApplication()
{
    delete d_frameListener;
    delete CEGUI::System::getSingletonPtr();
    delete d_renderer;
    delete d_ogreRoot;
}

bool CEGuiOgreBaseApplication::execute(CEGuiSample* sampleApp)
{
    // if initialisation failed or was cancelled by user, bail out now.
    if (d_ogreRoot && d_initialised)
    {
        // perform sample initialisation
        sampleApp->initialiseSample();

        // start rendering via Ogre3D engine.
        try
        {
            d_ogreRoot->startRendering();
        }
        catch(Ogre::Exception&)
        {
            return false;
        }
        catch(CEGUI::Exception&)
        {
            return false;
        }

        return true;
    }
    else
    {
        return false;
    }
}

void CEGuiOgreBaseApplication::cleanup()
{
    // nothing to do here.
}

void CEGuiOgreBaseApplication::initialiseResources(void)
{
    using namespace Ogre;
    ResourceGroupManager& rgm = ResourceGroupManager::getSingleton();

    // add resource groups that we use
    rgm.createResourceGroup("imagesets");
    rgm.createResourceGroup("fonts");
    rgm.createResourceGroup("layouts");
    rgm.createResourceGroup("schemes");
    rgm.createResourceGroup("looknfeels");

    // add CEGUI sample framework datafile dirs as resource locations
    ResourceGroupManager::getSingleton().addResourceLocation("./", "FileSystem");
#ifndef __APPLE__
    ResourceGroupManager::getSingleton().addResourceLocation("../datafiles/fonts", "FileSystem", "fonts");
    ResourceGroupManager::getSingleton().addResourceLocation("../datafiles/imagesets", "FileSystem", "imagesets");
    ResourceGroupManager::getSingleton().addResourceLocation("../datafiles/layouts", "FileSystem", "layouts");
    ResourceGroupManager::getSingleton().addResourceLocation("../datafiles/looknfeel", "FileSystem", "looknfeels");
    ResourceGroupManager::getSingleton().addResourceLocation("../datafiles/schemes", "FileSystem", "schemes");
    ResourceGroupManager::getSingleton().addResourceLocation("../datafiles/configs", "FileSystem");
    ResourceGroupManager::getSingleton().addResourceLocation("../datafiles/lua_scripts", "FileSystem");
#else
    // Because Ogre/Mac looks in the bundle's Resources folder by default...
    ResourceGroupManager::getSingleton().addResourceLocation("datafiles/fonts", "FileSystem", "fonts");
    ResourceGroupManager::getSingleton().addResourceLocation("datafiles/imagesets", "FileSystem", "imagesets");
    ResourceGroupManager::getSingleton().addResourceLocation("datafiles/layouts", "FileSystem", "layouts");
    ResourceGroupManager::getSingleton().addResourceLocation("datafiles/looknfeel", "FileSystem", "looknfeels");
    ResourceGroupManager::getSingleton().addResourceLocation("datafiles/schemes", "FileSystem", "schemes");
    ResourceGroupManager::getSingleton().addResourceLocation("datafiles/configs", "FileSystem");
    ResourceGroupManager::getSingleton().addResourceLocation("datafiles/lua_scripts", "FileSystem");
#endif
}

////////////////////////////////////////////////////////////////////////////////
/*******************************************************************************
    Start of CEGuiDemoFrameListener mehods
*******************************************************************************/
////////////////////////////////////////////////////////////////////////////////
CEGuiDemoFrameListener::CEGuiDemoFrameListener(CEGuiBaseApplication* baseApp, Ogre::RenderWindow* window, Ogre::Camera* camera, bool useBufferedInputKeys, bool useBufferedInputMouse)
{
    // create and initialise events processor
    d_eventProcessor = new Ogre::EventProcessor();
    d_eventProcessor->initialise(window);
    d_eventProcessor->addKeyListener(this);
    d_eventProcessor->addMouseMotionListener(this);
    d_eventProcessor->addMouseListener(this);
    d_eventProcessor->startProcessingEvents();

    // store inputs we want to make use of
    d_camera = camera;
    d_window = window;

    // we've not quit yet.
    d_quit = false;

    // setup base app ptr
    d_baseApp = baseApp;
}

CEGuiDemoFrameListener::~CEGuiDemoFrameListener()
{
    delete d_eventProcessor;
}

bool CEGuiDemoFrameListener::frameStarted(const Ogre::FrameEvent& evt)
{
    if(d_window->isClosed() || d_quit || d_baseApp->isQuitting())
    {
        return false;
    }
    else
    {
        // always inject a time pulse to enable widget automation
        CEGUI::System::getSingleton().injectTimePulse(static_cast<float>(evt.timeSinceLastFrame));
        return true;
    }
}

bool CEGuiDemoFrameListener::frameEnded(const Ogre::FrameEvent& evt)
{
    return true;
}

void CEGuiDemoFrameListener::mouseMoved(Ogre::MouseEvent *e)
{
    CEGUI::Renderer* rend = CEGUI::System::getSingleton().getRenderer();
    CEGUI::System::getSingleton().injectMouseMove(e->getRelX() * rend->getWidth(), e->getRelY() * rend->getHeight());

    float wheel = e->getRelZ();

    if (wheel != 0)
    {
        CEGUI::System::getSingleton().injectMouseWheelChange(wheel * 10);
    }

    e->consume();
}

void CEGuiDemoFrameListener::mouseDragged(Ogre::MouseEvent *e)
{
    mouseMoved(e);
}

void CEGuiDemoFrameListener::keyPressed(Ogre::KeyEvent *e)
{
    // give 'quitting' priority
    if (e->getKey() == Ogre::KC_ESCAPE)
    {
        d_quit = true;
        e->consume();
        return;
    }

    // do event injection
    CEGUI::System& cegui = CEGUI::System::getSingleton();

    // key down
    cegui.injectKeyDown(e->getKey());

    // now character
    cegui.injectChar(e->getKeyChar());

    e->consume();
}

void CEGuiDemoFrameListener::keyReleased(Ogre::KeyEvent *e)
{
    CEGUI::System::getSingleton().injectKeyUp(e->getKey());
}

void CEGuiDemoFrameListener::mousePressed(Ogre::MouseEvent *e)
{
    CEGUI::System::getSingleton().injectMouseButtonDown(convertOgreButtonToCegui(e->getButtonID()));
    e->consume();
}

void CEGuiDemoFrameListener::mouseReleased(Ogre::MouseEvent *e)
{
    CEGUI::System::getSingleton().injectMouseButtonUp(convertOgreButtonToCegui(e->getButtonID()));
    e->consume();
}

void CEGuiDemoFrameListener::keyClicked(Ogre::KeyEvent *e)
{}

void CEGuiDemoFrameListener::mouseClicked(Ogre::MouseEvent *e)
{}

void CEGuiDemoFrameListener::mouseEntered(Ogre::MouseEvent *e)
{}

void CEGuiDemoFrameListener::mouseExited(Ogre::MouseEvent *e)
{}

CEGUI::MouseButton CEGuiDemoFrameListener::convertOgreButtonToCegui(int ogre_button_id)
{
    switch (ogre_button_id)
    {
    case Ogre::MouseEvent::BUTTON0_MASK:
        return CEGUI::LeftButton;
        break;

    case Ogre::MouseEvent::BUTTON1_MASK:
        return CEGUI::RightButton;
        break;

    case Ogre::MouseEvent::BUTTON2_MASK:
        return CEGUI::MiddleButton;
        break;

    case Ogre::MouseEvent::BUTTON3_MASK:
        return CEGUI::X1Button;
        break;

    default:
        return CEGUI::LeftButton;
        break;
    }

}

#endif

<commit_msg>Bug Fix: Support was broken in the Samples framework for newer versions of Ogre.<commit_after>/***********************************************************************
    filename:   CEGuiOgreBaseApplication.cpp
    created:    9/3/2004
    author:     Paul D Turner
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#   include "config.h"
#endif

// this controls conditional compile of file for Apple
#include "CEGUISamplesConfig.h"
#ifdef CEGUI_SAMPLES_USE_OGRE

#include "CEGuiOgreBaseApplication.h"
#include "CEGuiSample.h"

#include <OgreKeyEvent.h>

CEGuiOgreBaseApplication::CEGuiOgreBaseApplication() :
        d_ogreRoot(0),
        d_renderer(0),
        d_initialised(false),
        d_frameListener(0)
{
    using namespace Ogre;

    d_ogreRoot = new Root();

    initialiseResources();

    if (d_ogreRoot->showConfigDialog())
    {
        // initialise system according to user options.
        d_window = d_ogreRoot->initialise(true);

        // Create the scene manager
        SceneManager* sm = d_ogreRoot->
            createSceneManager(ST_GENERIC, "SampleSceneMgr");
        // Create and initialise the camera
        d_camera = sm->createCamera("SampleCam");
        d_camera->setPosition(Vector3(0,0,500));
        d_camera->lookAt(Vector3(0,0,-300));
        d_camera->setNearClipDistance(5);

        // Create a viewport covering whole window
        Viewport* vp = d_window->addViewport(d_camera);
        vp->setBackgroundColour(ColourValue(0,0,0));

        // Update the camera aspect ratio to that of the viewport
        d_camera->setAspectRatio(Real(vp->getActualWidth()) / Real(vp->getActualHeight()));

        // initialise resources
        ResourceGroupManager::getSingleton().initialiseAllResourceGroups();

        // initialise GUI system
        d_renderer = new CEGUI::OgreCEGUIRenderer(d_window, RENDER_QUEUE_OVERLAY, false, 0, sm);
        new CEGUI::System(d_renderer);

        // create frame listener
        d_frameListener= new CEGuiDemoFrameListener(this, d_window, d_camera);
        d_ogreRoot->addFrameListener(d_frameListener);

        d_initialised = true;
    }
    else
    {
        // aborted.  Clean up and set root to 0 so when app attempts to run it knows what happened here.
        delete d_ogreRoot;
        d_ogreRoot = 0;
    }
}

CEGuiOgreBaseApplication::~CEGuiOgreBaseApplication()
{
    delete d_frameListener;
    delete CEGUI::System::getSingletonPtr();
    delete d_renderer;
    delete d_ogreRoot;
}

bool CEGuiOgreBaseApplication::execute(CEGuiSample* sampleApp)
{
    // if initialisation failed or was cancelled by user, bail out now.
    if (d_ogreRoot && d_initialised)
    {
        // perform sample initialisation
        sampleApp->initialiseSample();

        // start rendering via Ogre3D engine.
        try
        {
            d_ogreRoot->startRendering();
        }
        catch(Ogre::Exception&)
        {
            return false;
        }
        catch(CEGUI::Exception&)
        {
            return false;
        }

        return true;
    }
    else
    {
        return false;
    }
}

void CEGuiOgreBaseApplication::cleanup()
{
    // nothing to do here.
}

void CEGuiOgreBaseApplication::initialiseResources(void)
{
    using namespace Ogre;
    ResourceGroupManager& rgm = ResourceGroupManager::getSingleton();

    // add resource groups that we use
    rgm.createResourceGroup("imagesets");
    rgm.createResourceGroup("fonts");
    rgm.createResourceGroup("layouts");
    rgm.createResourceGroup("schemes");
    rgm.createResourceGroup("looknfeels");

    // add CEGUI sample framework datafile dirs as resource locations
    ResourceGroupManager::getSingleton().addResourceLocation("./", "FileSystem");
#ifndef __APPLE__
    ResourceGroupManager::getSingleton().addResourceLocation("../datafiles/fonts", "FileSystem", "fonts");
    ResourceGroupManager::getSingleton().addResourceLocation("../datafiles/imagesets", "FileSystem", "imagesets");
    ResourceGroupManager::getSingleton().addResourceLocation("../datafiles/layouts", "FileSystem", "layouts");
    ResourceGroupManager::getSingleton().addResourceLocation("../datafiles/looknfeel", "FileSystem", "looknfeels");
    ResourceGroupManager::getSingleton().addResourceLocation("../datafiles/schemes", "FileSystem", "schemes");
    ResourceGroupManager::getSingleton().addResourceLocation("../datafiles/configs", "FileSystem");
    ResourceGroupManager::getSingleton().addResourceLocation("../datafiles/lua_scripts", "FileSystem");
#else
    // Because Ogre/Mac looks in the bundle's Resources folder by default...
    ResourceGroupManager::getSingleton().addResourceLocation("datafiles/fonts", "FileSystem", "fonts");
    ResourceGroupManager::getSingleton().addResourceLocation("datafiles/imagesets", "FileSystem", "imagesets");
    ResourceGroupManager::getSingleton().addResourceLocation("datafiles/layouts", "FileSystem", "layouts");
    ResourceGroupManager::getSingleton().addResourceLocation("datafiles/looknfeel", "FileSystem", "looknfeels");
    ResourceGroupManager::getSingleton().addResourceLocation("datafiles/schemes", "FileSystem", "schemes");
    ResourceGroupManager::getSingleton().addResourceLocation("datafiles/configs", "FileSystem");
    ResourceGroupManager::getSingleton().addResourceLocation("datafiles/lua_scripts", "FileSystem");
#endif
}

////////////////////////////////////////////////////////////////////////////////
/*******************************************************************************
    Start of CEGuiDemoFrameListener mehods
*******************************************************************************/
////////////////////////////////////////////////////////////////////////////////
CEGuiDemoFrameListener::CEGuiDemoFrameListener(CEGuiBaseApplication* baseApp, Ogre::RenderWindow* window, Ogre::Camera* camera, bool useBufferedInputKeys, bool useBufferedInputMouse)
{
    // create and initialise events processor
    d_eventProcessor = new Ogre::EventProcessor();
    d_eventProcessor->initialise(window);
    d_eventProcessor->addKeyListener(this);
    d_eventProcessor->addMouseMotionListener(this);
    d_eventProcessor->addMouseListener(this);
    d_eventProcessor->startProcessingEvents();

    // store inputs we want to make use of
    d_camera = camera;
    d_window = window;

    // we've not quit yet.
    d_quit = false;

    // setup base app ptr
    d_baseApp = baseApp;
}

CEGuiDemoFrameListener::~CEGuiDemoFrameListener()
{
    delete d_eventProcessor;
}

bool CEGuiDemoFrameListener::frameStarted(const Ogre::FrameEvent& evt)
{
    if(d_window->isClosed() || d_quit || d_baseApp->isQuitting())
    {
        return false;
    }
    else
    {
        // always inject a time pulse to enable widget automation
        CEGUI::System::getSingleton().injectTimePulse(static_cast<float>(evt.timeSinceLastFrame));
        return true;
    }
}

bool CEGuiDemoFrameListener::frameEnded(const Ogre::FrameEvent& evt)
{
    return true;
}

void CEGuiDemoFrameListener::mouseMoved(Ogre::MouseEvent *e)
{
    CEGUI::Renderer* rend = CEGUI::System::getSingleton().getRenderer();
    CEGUI::System::getSingleton().injectMouseMove(e->getRelX() * rend->getWidth(), e->getRelY() * rend->getHeight());

    float wheel = e->getRelZ();

    if (wheel != 0)
    {
        CEGUI::System::getSingleton().injectMouseWheelChange(wheel * 10);
    }

    e->consume();
}

void CEGuiDemoFrameListener::mouseDragged(Ogre::MouseEvent *e)
{
    mouseMoved(e);
}

void CEGuiDemoFrameListener::keyPressed(Ogre::KeyEvent *e)
{
    // give 'quitting' priority
    if (e->getKey() == Ogre::KC_ESCAPE)
    {
        d_quit = true;
        e->consume();
        return;
    }

    // do event injection
    CEGUI::System& cegui = CEGUI::System::getSingleton();

    // key down
    cegui.injectKeyDown(e->getKey());

    // now character
    cegui.injectChar(e->getKeyChar());

    e->consume();
}

void CEGuiDemoFrameListener::keyReleased(Ogre::KeyEvent *e)
{
    CEGUI::System::getSingleton().injectKeyUp(e->getKey());
}

void CEGuiDemoFrameListener::mousePressed(Ogre::MouseEvent *e)
{
    CEGUI::System::getSingleton().injectMouseButtonDown(convertOgreButtonToCegui(e->getButtonID()));
    e->consume();
}

void CEGuiDemoFrameListener::mouseReleased(Ogre::MouseEvent *e)
{
    CEGUI::System::getSingleton().injectMouseButtonUp(convertOgreButtonToCegui(e->getButtonID()));
    e->consume();
}

void CEGuiDemoFrameListener::keyClicked(Ogre::KeyEvent *e)
{}

void CEGuiDemoFrameListener::mouseClicked(Ogre::MouseEvent *e)
{}

void CEGuiDemoFrameListener::mouseEntered(Ogre::MouseEvent *e)
{}

void CEGuiDemoFrameListener::mouseExited(Ogre::MouseEvent *e)
{}

CEGUI::MouseButton CEGuiDemoFrameListener::convertOgreButtonToCegui(int ogre_button_id)
{
    switch (ogre_button_id)
    {
    case Ogre::MouseEvent::BUTTON0_MASK:
        return CEGUI::LeftButton;
        break;

    case Ogre::MouseEvent::BUTTON1_MASK:
        return CEGUI::RightButton;
        break;

    case Ogre::MouseEvent::BUTTON2_MASK:
        return CEGUI::MiddleButton;
        break;

    case Ogre::MouseEvent::BUTTON3_MASK:
        return CEGUI::X1Button;
        break;

    default:
        return CEGUI::LeftButton;
        break;
    }

}

#endif

<|endoftext|>