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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

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

#include "mitkContourModelWriter.h"
#include <iostream>
#include <fstream>
#include <locale>

/*
 * The xml file will look like:
 *
 *   <?xml version="1.0" encoding="utf-8"?>
 *   <contourModel>
 *      <head>
 *        <geometryInfo>
 *        </geometryInfo>
 *      </head>
 *      <data>
 *        <timestep n="0">
 *          <controlPoints>
 *            <point>
 *              <x></x>
 *              <y></y>
 *              <z></z>
 *            </point>
 *          </controlPoint>
 *        </timestep>
 *      </data>
 *    </contourModel>
 */

//
// Initialization of the xml tags.
//

const char* mitk::ContourModelWriter::XML_CONTOURMODEL = "contourModel" ;

const char* mitk::ContourModelWriter::XML_HEAD = "head" ;

const char* mitk::ContourModelWriter::XML_GEOMETRY_INFO = "geometryInfo" ;

const char* mitk::ContourModelWriter::XML_DATA = "data";

const char* mitk::ContourModelWriter::XML_TIME_STEP = "timestep";

const char* mitk::ContourModelWriter::XML_CONTROL_POINTS = "controlPoints" ;

const char* mitk::ContourModelWriter::XML_POINT = "point" ;

const char* mitk::ContourModelWriter::XML_X = "x" ;

const char* mitk::ContourModelWriter::XML_Y = "y" ;

const char* mitk::ContourModelWriter::XML_Z = "z" ;

mitk::ContourModelWriter::ContourModelWriter()
    : m_FileName(""), m_FilePrefix(""), m_FilePattern("")
{
    this->SetNumberOfRequiredInputs( 1 );
    this->SetNumberOfOutputs( 1 );
    this->SetNthOutput( 0, mitk::ContourModel::New().GetPointer() );
    m_Indent = 2;
    m_IndentDepth = 0;
    m_Success = false;
}

mitk::ContourModelWriter::~ContourModelWriter()
{}

void mitk::ContourModelWriter::GenerateData()
{
    m_Success = false;
    m_IndentDepth = 0;

    //
    // Opening the file to write to
    //
    if ( m_FileName == "" )
    {
        itkWarningMacro( << "Sorry, filename has not been set!" );
        return ;
    }
    std::ofstream out( m_FileName.c_str() );
    if ( !out.good() )
    {
      itkExceptionMacro(<< "File " << m_FileName << " could not be opened!");
      itkWarningMacro( << "Sorry, file " << m_FileName << " could not be opened!" );
      out.close();
        return ;
    }

    std::locale previousLocale(out.getloc());
    std::locale I("C");
    out.imbue(I);

/*+++++++++++ Here the actual xml writing begins +++++++++*/

    /*++++ <?xml version="1.0" encoding="utf-8"?> ++++*/
    WriteXMLHeader( out );
    /*++++ <contourModel> ++++*/
    WriteStartElement( XML_CONTOURMODEL, out );

    /*++++ <head> ++++*/
    WriteStartElement( XML_HEAD, out);

    /*++++ <geometryInfo> ++++*/
    WriteStartElement( XML_GEOMETRY_INFO, out);

    //write the geometry informations to the stream
      InputType::Pointer contourModel = this->GetInput();
      assert( contourModel.IsNotNull() );
      WriteGeometryInformation( contourModel->GetTimeSlicedGeometry(), out);;

    /*++++ </geometryInfo> ++++*/
    WriteEndElement( XML_GEOMETRY_INFO, out);

    /*++++ </head> ++++*/
    WriteEndElement( XML_HEAD, out);

    //
    // for each input object write its xml representation to
    // the stream
    //
    for ( unsigned int i = 0 ; i < this->GetNumberOfInputs(); ++i )
    {
        InputType::Pointer contourModel = this->GetInput( i );
        assert( contourModel.IsNotNull() );
        WriteXML( contourModel.GetPointer(), out );
    }

    /*++++ </contourModel> ++++*/
    WriteEndElement( XML_CONTOURMODEL, out );

    out.imbue(previousLocale);

    if ( !out.good() ) // some error during output
    {
      out.close();
      throw std::ios_base::failure("Some error during point set writing.");
    }

    out.close();
    m_Success = true;
    m_MimeType = "application/MITK.ContourModel";
}

void mitk::ContourModelWriter::WriteXML( mitk::ContourModel* contourModel, std::ofstream& out )
{
  /*++++ <data> ++++*/
  WriteStartElement( XML_DATA, out);

  unsigned int timecount = contourModel->GetTimeSteps();

  for(unsigned int i=0; i< timecount; i++)
  {
    /*++++ <timestep> ++++*/
    WriteStartElement( XML_TIME_STEP, out );

    mitk::ContourModel::VertexIterator it = contourModel->IteratorBegin();
    mitk::ContourModel::VertexIterator end = contourModel->IteratorEnd();

    while(it != end)
    {
      /*++++ <point> ++++*/
      WriteStartElement( XML_POINT, out );

      mitk::ContourModel::VertexType* v = *it;

      /*++++ <x> ++++*/
      WriteStartElement( XML_X, out );
      WriteCharacterData( ConvertToString(v->Coordinates[0] ).c_str(), out );
      /*++++ </x> ++++*/
      WriteEndElement( XML_X, out, false );

      /*++++ <y> ++++*/
      WriteStartElement( XML_Y, out );
      WriteCharacterData( ConvertToString( v->Coordinates[ 1 ] ).c_str(), out );
      /*++++ </y> ++++*/
      WriteEndElement( XML_Y, out, false );

      /*++++ <z> ++++*/
      WriteStartElement( XML_Z, out );
      WriteCharacterData( ConvertToString( v->Coordinates[ 2 ] ).c_str(), out );
      /*++++ </z> ++++*/
      WriteEndElement( XML_Z, out, false );

      /*++++ </point> ++++*/
      WriteEndElement( XML_POINT, out );
    }

    /*++++ </timestep> ++++*/
    WriteEndElement( XML_TIME_STEP, out );
  }

  /*++++ </data> ++++*/
  WriteEndElement( XML_DATA, out );
}

void mitk::ContourModelWriter::WriteGeometryInformation( mitk::TimeSlicedGeometry* geometry, std::ofstream& out )
{
  WriteCharacterData("<!-- geometry information -->", out);
}

void mitk::ContourModelWriter::ResizeInputs( const unsigned int& num )
{
    unsigned int prevNum = this->GetNumberOfInputs();
    this->SetNumberOfInputs( num );
    for ( unsigned int i = prevNum; i < num; ++i )
    {
        this->SetNthInput( i, mitk::ContourModel::New().GetPointer() );
    }
}

void mitk::ContourModelWriter::SetInput( InputType* contourModel )
{
    this->ProcessObject::SetNthInput( 0, contourModel );
}

void mitk::ContourModelWriter::SetInput( const unsigned int& id, InputType* contourModel )
{
    if ( id >= this->GetNumberOfInputs() )
        this->ResizeInputs( id + 1 );
    this->ProcessObject::SetNthInput( id, contourModel );
}

mitk::ContourModel* mitk::ContourModelWriter::GetInput()
{
    if ( this->GetNumberOfInputs() < 1 )
    {
        return 0;
    }
    else
    {
        return dynamic_cast<InputType*> ( this->GetInput( 0 ) );
    }
}

mitk::ContourModel* mitk::ContourModelWriter::GetInput( const unsigned int& num )
{
    return dynamic_cast<InputType*> ( this->ProcessObject::GetInput( num ) );
}

template < typename T>
std::string mitk::ContourModelWriter::ConvertToString( T value )
{
    std::ostringstream o;
    std::locale I("C");
    o.imbue(I);

    if ( o << value )
    {
        return o.str();
     }
    else
        return "conversion error";
}

void mitk::ContourModelWriter::WriteXMLHeader( std::ofstream &file )
{
    file << "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
}

void mitk::ContourModelWriter::WriteStartElement( const char *const tag, std::ofstream &file )
{
    file << std::endl;
    WriteIndent( file );
    file << '<' << tag << '>';
    m_IndentDepth++;
}

void mitk::ContourModelWriter::WriteEndElement( const char *const tag, std::ofstream &file, const bool& indent )
{
    m_IndentDepth--;
    if ( indent )
    {
        file << std::endl;
        WriteIndent( file );
    }
    file << '<' << '/' << tag << '>';
}

void mitk::ContourModelWriter::WriteCharacterData( const char *const data, std::ofstream &file )
{
    file << data;
}

void mitk::ContourModelWriter::WriteStartElement( std::string &tag, std::ofstream &file )
{
    WriteStartElement( tag.c_str(), file );
}

void mitk::ContourModelWriter::WriteEndElement( std::string &tag, std::ofstream &file, const bool& indent )
{
    WriteEndElement( tag.c_str(), file, indent );
}

void mitk::ContourModelWriter::WriteCharacterData( std::string &data, std::ofstream &file )
{
    WriteCharacterData( data.c_str(), file );
}

void mitk::ContourModelWriter::WriteIndent( std::ofstream& file )
{
    std::string spaces( m_IndentDepth * m_Indent, ' ' );
    file << spaces.c_str();
}

bool mitk::ContourModelWriter::GetSuccess() const
{
    return m_Success;
}

bool mitk::ContourModelWriter::CanWriteDataType( DataNode* input )
{
  if ( input )
  {
    mitk::BaseData* data = input->GetData();
    if ( data )
    {
       mitk::ContourModel::Pointer contourModel = dynamic_cast<mitk::ContourModel*>( data );
       if( contourModel.IsNotNull() )
       {
         //this writer has no "SetDefaultExtension()" - function
         m_Extension = ".cnt";
         return true;
       }
    }
  }
  return false;
}

void mitk::ContourModelWriter::SetInput( DataNode* input )
{
  if( input && CanWriteDataType( input ) )
    this->ProcessObject::SetNthInput( 0, dynamic_cast<mitk::ContourModel*>( input->GetData() ) );
}

std::string mitk::ContourModelWriter::GetWritenMIMEType()
{
  return m_MimeType;
}

std::vector<std::string> mitk::ContourModelWriter::GetPossibleFileExtensions()
{
  std::vector<std::string> possibleFileExtensions;
  possibleFileExtensions.push_back(m_Extension);
  return possibleFileExtensions;
}

std::string mitk::ContourModelWriter::GetFileExtension()
{
  return m_Extension;
}
<commit_msg>writer is now working<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

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

#include "mitkContourModelWriter.h"
#include <iostream>
#include <fstream>
#include <locale>

/*
 * The xml file will look like:
 *
 *   <?xml version="1.0" encoding="utf-8"?>
 *   <contourModel>
 *      <head>
 *        <geometryInfo>
 *        </geometryInfo>
 *      </head>
 *      <data>
 *        <timestep n="0">
 *          <controlPoints>
 *            <point>
 *              <x></x>
 *              <y></y>
 *              <z></z>
 *            </point>
 *          </controlPoint>
 *        </timestep>
 *      </data>
 *    </contourModel>
 */

//
// Initialization of the xml tags.
//

const char* mitk::ContourModelWriter::XML_CONTOURMODEL = "contourModel" ;

const char* mitk::ContourModelWriter::XML_HEAD = "head" ;

const char* mitk::ContourModelWriter::XML_GEOMETRY_INFO = "geometryInfo" ;

const char* mitk::ContourModelWriter::XML_DATA = "data";

const char* mitk::ContourModelWriter::XML_TIME_STEP = "timestep";

const char* mitk::ContourModelWriter::XML_CONTROL_POINTS = "controlPoints" ;

const char* mitk::ContourModelWriter::XML_POINT = "point" ;

const char* mitk::ContourModelWriter::XML_X = "x" ;

const char* mitk::ContourModelWriter::XML_Y = "y" ;

const char* mitk::ContourModelWriter::XML_Z = "z" ;

mitk::ContourModelWriter::ContourModelWriter()
    : m_FileName(""), m_FilePrefix(""), m_FilePattern("")
{
    this->SetNumberOfRequiredInputs( 1 );
    this->SetNumberOfOutputs( 1 );
    this->SetNthOutput( 0, mitk::ContourModel::New().GetPointer() );
    m_Indent = 2;
    m_IndentDepth = 0;
    m_Success = false;
}

mitk::ContourModelWriter::~ContourModelWriter()
{}

void mitk::ContourModelWriter::GenerateData()
{
    m_Success = false;
    m_IndentDepth = 0;

    //
    // Opening the file to write to
    //
    if ( m_FileName == "" )
    {
        itkWarningMacro( << "Sorry, filename has not been set!" );
        return ;
    }
    std::ofstream out( m_FileName.c_str() );
    if ( !out.good() )
    {
      itkExceptionMacro(<< "File " << m_FileName << " could not be opened!");
      itkWarningMacro( << "Sorry, file " << m_FileName << " could not be opened!" );
      out.close();
        return ;
    }

    std::locale previousLocale(out.getloc());
    std::locale I("C");
    out.imbue(I);

/*+++++++++++ Here the actual xml writing begins +++++++++*/

    /*++++ <?xml version="1.0" encoding="utf-8"?> ++++*/
    WriteXMLHeader( out );
    /*++++ <contourModel> ++++*/
    WriteStartElement( XML_CONTOURMODEL, out );

    /*++++ <head> ++++*/
    WriteStartElement( XML_HEAD, out);

    /*++++ <geometryInfo> ++++*/
    WriteStartElement( XML_GEOMETRY_INFO, out);

    //write the geometry informations to the stream
      InputType::Pointer contourModel = this->GetInput();
      assert( contourModel.IsNotNull() );
      WriteGeometryInformation( contourModel->GetTimeSlicedGeometry(), out);;

    /*++++ </geometryInfo> ++++*/
    WriteEndElement( XML_GEOMETRY_INFO, out);

    /*++++ </head> ++++*/
    WriteEndElement( XML_HEAD, out);

    //
    // for each input object write its xml representation to
    // the stream
    //
    for ( unsigned int i = 0 ; i < this->GetNumberOfInputs(); ++i )
    {
        InputType::Pointer contourModel = this->GetInput( i );
        assert( contourModel.IsNotNull() );
        WriteXML( contourModel.GetPointer(), out );
    }

    /*++++ </contourModel> ++++*/
    WriteEndElement( XML_CONTOURMODEL, out );

    out.imbue(previousLocale);

    if ( !out.good() ) // some error during output
    {
      out.close();
      throw std::ios_base::failure("Some error during point set writing.");
    }

    out.close();
    m_Success = true;
    m_MimeType = "application/MITK.ContourModel";
}

void mitk::ContourModelWriter::WriteXML( mitk::ContourModel* contourModel, std::ofstream& out )
{
  /*++++ <data> ++++*/
  WriteStartElement( XML_DATA, out);

  unsigned int timecount = contourModel->GetTimeSteps();

  for(unsigned int i=0; i< timecount; i++)
  {
    /*++++ <timestep> ++++*/
    WriteStartElement( XML_TIME_STEP, out );

    mitk::ContourModel::VertexIterator it = contourModel->IteratorBegin();
    mitk::ContourModel::VertexIterator end = contourModel->IteratorEnd();

    while(it != end)
    {
      /*++++ <point> ++++*/
      WriteStartElement( XML_POINT, out );

      mitk::ContourModel::VertexType* v = *it;

      /*++++ <x> ++++*/
      WriteStartElement( XML_X, out );
      WriteCharacterData( ConvertToString(v->Coordinates[0] ).c_str(), out );
      /*++++ </x> ++++*/
      WriteEndElement( XML_X, out, false );

      /*++++ <y> ++++*/
      WriteStartElement( XML_Y, out );
      WriteCharacterData( ConvertToString( v->Coordinates[ 1 ] ).c_str(), out );
      /*++++ </y> ++++*/
      WriteEndElement( XML_Y, out, false );

      /*++++ <z> ++++*/
      WriteStartElement( XML_Z, out );
      WriteCharacterData( ConvertToString( v->Coordinates[ 2 ] ).c_str(), out );
      /*++++ </z> ++++*/
      WriteEndElement( XML_Z, out, false );

      /*++++ </point> ++++*/
      WriteEndElement( XML_POINT, out );

      it++;
    }

    /*++++ </timestep> ++++*/
    WriteEndElement( XML_TIME_STEP, out );

  }

  /*++++ </data> ++++*/
  WriteEndElement( XML_DATA, out );
}

void mitk::ContourModelWriter::WriteGeometryInformation( mitk::TimeSlicedGeometry* geometry, std::ofstream& out )
{
  WriteCharacterData("<!-- geometry information -->", out);
}

void mitk::ContourModelWriter::ResizeInputs( const unsigned int& num )
{
    unsigned int prevNum = this->GetNumberOfInputs();
    this->SetNumberOfInputs( num );
    for ( unsigned int i = prevNum; i < num; ++i )
    {
        this->SetNthInput( i, mitk::ContourModel::New().GetPointer() );
    }
}

void mitk::ContourModelWriter::SetInput( InputType* contourModel )
{
    this->ProcessObject::SetNthInput( 0, contourModel );
}

void mitk::ContourModelWriter::SetInput( const unsigned int& id, InputType* contourModel )
{
    if ( id >= this->GetNumberOfInputs() )
        this->ResizeInputs( id + 1 );
    this->ProcessObject::SetNthInput( id, contourModel );
}

mitk::ContourModel* mitk::ContourModelWriter::GetInput()
{
    if ( this->GetNumberOfInputs() < 1 )
    {
        return 0;
    }
    else
    {
        return dynamic_cast<InputType*> ( this->GetInput( 0 ) );
    }
}

mitk::ContourModel* mitk::ContourModelWriter::GetInput( const unsigned int& num )
{
    return dynamic_cast<InputType*> ( this->ProcessObject::GetInput( num ) );
}

template < typename T>
std::string mitk::ContourModelWriter::ConvertToString( T value )
{
    std::ostringstream o;
    std::locale I("C");
    o.imbue(I);

    if ( o << value )
    {
        return o.str();
     }
    else
        return "conversion error";
}

void mitk::ContourModelWriter::WriteXMLHeader( std::ofstream &file )
{
    file << "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
}

void mitk::ContourModelWriter::WriteStartElement( const char *const tag, std::ofstream &file )
{
    file << std::endl;
    WriteIndent( file );
    file << '<' << tag << '>';
    m_IndentDepth++;
}

void mitk::ContourModelWriter::WriteEndElement( const char *const tag, std::ofstream &file, const bool& indent )
{
    m_IndentDepth--;
    if ( indent )
    {
        file << std::endl;
        WriteIndent( file );
    }
    file << '<' << '/' << tag << '>';
}

void mitk::ContourModelWriter::WriteCharacterData( const char *const data, std::ofstream &file )
{
    file << data;
}

void mitk::ContourModelWriter::WriteStartElement( std::string &tag, std::ofstream &file )
{
    WriteStartElement( tag.c_str(), file );
}

void mitk::ContourModelWriter::WriteEndElement( std::string &tag, std::ofstream &file, const bool& indent )
{
    WriteEndElement( tag.c_str(), file, indent );
}

void mitk::ContourModelWriter::WriteCharacterData( std::string &data, std::ofstream &file )
{
    WriteCharacterData( data.c_str(), file );
}

void mitk::ContourModelWriter::WriteIndent( std::ofstream& file )
{
    std::string spaces( m_IndentDepth * m_Indent, ' ' );
    file << spaces.c_str();
}

bool mitk::ContourModelWriter::GetSuccess() const
{
    return m_Success;
}

bool mitk::ContourModelWriter::CanWriteDataType( DataNode* input )
{
  if ( input )
  {
    mitk::BaseData* data = input->GetData();
    if ( data )
    {
       mitk::ContourModel::Pointer contourModel = dynamic_cast<mitk::ContourModel*>( data );
       if( contourModel.IsNotNull() )
       {
         //this writer has no "SetDefaultExtension()" - function
         m_Extension = ".cnt";
         return true;
       }
    }
  }
  return false;
}

void mitk::ContourModelWriter::SetInput( DataNode* input )
{
  if( input && CanWriteDataType( input ) )
    this->ProcessObject::SetNthInput( 0, dynamic_cast<mitk::ContourModel*>( input->GetData() ) );
}

std::string mitk::ContourModelWriter::GetWritenMIMEType()
{
  return m_MimeType;
}

std::vector<std::string> mitk::ContourModelWriter::GetPossibleFileExtensions()
{
  std::vector<std::string> possibleFileExtensions;
  possibleFileExtensions.push_back(".cnt");
  return possibleFileExtensions;
}

std::string mitk::ContourModelWriter::GetFileExtension()
{
  return m_Extension;
}
<|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

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

#include "mitkUSCombinedModality.h"
#include "mitkUSDevice.h"
#include "mitkNavigationDataSource.h"
#include "mitkImageReadAccessor.h"

//TempIncludes
#include <tinyxml.h>

const std::string mitk::USCombinedModality::DeviceClassIdentifier = "org.mitk.modules.us.USCombinedModality";

mitk::USCombinedModality::USCombinedModality(USDevice::Pointer usDevice, NavigationDataSource::Pointer trackingDevice, std::string manufacturer, std::string model)
  : mitk::USDevice(manufacturer, model), m_UltrasoundDevice(usDevice), m_TrackingDevice(trackingDevice),
  m_SmoothingFilter(mitk::NavigationDataSmoothingFilter::New()), m_DelayFilter(mitk::NavigationDataDelayFilter::New(0))
{
  // build tracking filter pipeline
  for (int i = 0; i < m_TrackingDevice->GetNumberOfOutputs(); i++)
  {
    m_SmoothingFilter->SetInput(i, m_TrackingDevice->GetOutput(i));
    mitk::NavigationData::Pointer nd1 = m_TrackingDevice->GetOutput(i);
    m_DelayFilter->SetInput(i, m_SmoothingFilter->GetOutput(i));
    mitk::NavigationData::Pointer nd2 = m_SmoothingFilter->GetOutput(i);
  }
  m_SmoothingFilter->SetNumerOfValues(10);

  //create a new output (for the image data)
  mitk::Image::Pointer newOutput = mitk::Image::New();
  this->SetNthOutput(0,newOutput);
}

mitk::USCombinedModality::~USCombinedModality()
{
}

std::string mitk::USCombinedModality::GetDeviceClass()
{
  return DeviceClassIdentifier;
}

mitk::USImageSource::Pointer mitk::USCombinedModality::GetUSImageSource()
{
  if (m_UltrasoundDevice.IsNull())
  {
    MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null.";
    mitkThrow() << "UltrasoundDevice must not be null.";
  }

  return m_UltrasoundDevice->GetUSImageSource();
}

mitk::USControlInterfaceBMode::Pointer mitk::USCombinedModality::GetControlInterfaceBMode()
{
  if (m_UltrasoundDevice.IsNull())
  {
    MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null.";
    mitkThrow() << "UltrasoundDevice must not be null.";
  }

  return m_UltrasoundDevice->GetControlInterfaceBMode();
}

mitk::USControlInterfaceProbes::Pointer mitk::USCombinedModality::GetControlInterfaceProbes()
{
  if (m_UltrasoundDevice.IsNull())
  {
    MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null.";
    mitkThrow() << "UltrasoundDevice must not be null.";
  }

  return m_UltrasoundDevice->GetControlInterfaceProbes();
}

mitk::USControlInterfaceDoppler::Pointer mitk::USCombinedModality::GetControlInterfaceDoppler()
{
  if (m_UltrasoundDevice.IsNull())
  {
    MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null.";
    mitkThrow() << "UltrasoundDevice must not be null.";
  }

  return m_UltrasoundDevice->GetControlInterfaceDoppler();
}

void mitk::USCombinedModality::UnregisterOnService()
{
  if (m_DeviceState == State_Activated) { this->Deactivate(); }
  if (m_DeviceState == State_Connected) { this->Disconnect(); }

  mitk::USDevice::UnregisterOnService();
}

mitk::AffineTransform3D::Pointer mitk::USCombinedModality::GetCalibration()
{
  std::string calibrationKey = this->GetIdentifierForCurrentCalibration();
  if (calibrationKey.empty())
  {
    MITK_WARN("USCombinedModality")("USDevice")
        << "Could not get a key for the calibration.";
    return 0;
  }

  // find calibration for combination of probe identifier and depth
  std::map<std::string, mitk::AffineTransform3D::Pointer>::iterator calibrationIterator
    = m_Calibrations.find(calibrationKey);

  if (calibrationIterator == m_Calibrations.end())
  {
    MITK_WARN("USCombinedModality")("USDevice")
        << "No calibration found for selected probe and depth.";
    return 0;
  }

  return calibrationIterator->second;
}

void mitk::USCombinedModality::SetCalibration (mitk::AffineTransform3D::Pointer calibration)
{
  if (calibration.IsNull())
  {
    MITK_WARN << "Null pointer passed to SetCalibration of mitk::USDevice. Ignoring call.";
    return;
  }

  std::string calibrationKey = this->GetIdentifierForCurrentCalibration();
  if (calibrationKey.empty())
  {
    MITK_WARN << "Could not get a key for the calibration -> Calibration cannot be set.";
    return;
  }

  m_Calibrations[calibrationKey] = calibration;

  m_Metadata->SetDeviceIsCalibrated(true);

  if (m_ServiceRegistration != 0)
  {
    this->UpdateServiceProperty(mitk::USImageMetadata::PROP_DEV_ISCALIBRATED, true);
  }
}

bool mitk::USCombinedModality::OnInitialization()
{
  if (m_UltrasoundDevice.IsNull())
  {
    MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null.";
    mitkThrow() << "UltrasoundDevice must not be null.";
  }

  if ( m_UltrasoundDevice->GetDeviceState() < mitk::USDevice::State_Initialized )
  {
    return m_UltrasoundDevice->Initialize();
  }
  else
  {
    return true;
  }
}

bool mitk::USCombinedModality::OnConnection()
{
  if (m_UltrasoundDevice.IsNull())
  {
    MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null.";
    mitkThrow() << "UltrasoundDevice must not be null.";
  }

  return m_UltrasoundDevice->Connect();
}

bool mitk::USCombinedModality::OnDisconnection()
{
  if (m_UltrasoundDevice.IsNull())
  {
    MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null.";
    mitkThrow() << "UltrasoundDevice must not be null.";
  }

  return m_UltrasoundDevice->Disconnect();
}

bool mitk::USCombinedModality::OnActivation()
{
  if (m_UltrasoundDevice.IsNull())
  {
    MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null.";
    mitkThrow() << "UltrasoundDevice must not be null.";
  }

  return m_UltrasoundDevice->Activate();
}

bool mitk::USCombinedModality::OnDeactivation()
{
  if (m_UltrasoundDevice.IsNull())
  {
    MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null.";
    mitkThrow() << "UltrasoundDevice must not be null.";
  }

  m_UltrasoundDevice->Deactivate();

  return m_UltrasoundDevice->GetIsInitialized();
}

mitk::NavigationDataSource::Pointer mitk::USCombinedModality::GetNavigationDataSource()
{
  return m_DelayFilter.GetPointer();
}

void mitk::USCombinedModality::GenerateData()
{
  // update ultrasound image source and get current output then
  m_UltrasoundDevice->Modified();
  m_UltrasoundDevice->Update();
  mitk::Image::Pointer image = m_UltrasoundDevice->GetOutput();
  if ( image.IsNull() || ! image->IsInitialized() ) {
    return;
  }

  // get output and initialize it if it wasn't initialized before
  mitk::Image::Pointer output = this->GetOutput();
  if ( ! output->IsInitialized() ) { output->Initialize(image); }

  std::string calibrationKey = this->GetIdentifierForCurrentCalibration();
  if ( ! calibrationKey.empty() )
  {
    std::map<std::string, mitk::AffineTransform3D::Pointer>::iterator calibrationIterator
      = m_Calibrations.find(calibrationKey);
    if ( calibrationIterator != m_Calibrations.end())
    {
      // transform image according to callibration if one is set
      // for current configuration of probe and depth
      image->GetGeometry()->SetIndexToWorldTransform(calibrationIterator->second);
    }
  }

  // TODO: do processing here

  mitk::ImageReadAccessor inputReadAccessor(image, image->GetSliceData(0,0,0));
  output->SetSlice(inputReadAccessor.GetData());
}

std::string mitk::USCombinedModality::SerializeCalibration()
{
  std::stringstream result;
  result << "<calibrations>" << std::endl;
  // For each calibration in the set
  for (std::map<std::string, mitk::AffineTransform3D::Pointer>::iterator it = m_Calibrations.begin(); it != m_Calibrations.end(); it++)
  {
    mitk::AffineTransform3D::MatrixType matrix = it->second->GetMatrix();
    mitk::AffineTransform3D::OffsetType offset = it->second->GetOffset();
    TiXmlElement elem(it->first);
    // Serialize Matrix
    elem.SetDoubleAttribute("M00", matrix[0][0]);
    elem.SetDoubleAttribute("M01", matrix[0][1]);
    elem.SetDoubleAttribute("M02", matrix[0][2]);
    elem.SetDoubleAttribute("M10", matrix[1][0]);
    elem.SetDoubleAttribute("M11", matrix[1][1]);
    elem.SetDoubleAttribute("M12", matrix[1][2]);
    elem.SetDoubleAttribute("M20", matrix[2][0]);
    elem.SetDoubleAttribute("M21", matrix[2][1]);
    elem.SetDoubleAttribute("M22", matrix[2][2]);
    // Serialize Offset
    elem.SetDoubleAttribute("O0", offset[0]);
    elem.SetDoubleAttribute("O1", offset[1]);
    elem.SetDoubleAttribute("O2", offset[2]);

    result << elem << std::endl;
  }
  result << "</calibrations>" << std::endl;

  return result.str();
}

void mitk::USCombinedModality::DeserializeCalibration(const std::string& xmlString, bool clearPreviousCalibrations)
{
  // Sanitize Input
  if (xmlString == "")
  {
    MITK_WARN << "Empty string passed to Deserialize() method of CombinedModality. Aborting...";
    return;
  }
  // Clear previous calibrations if necessary
  if (clearPreviousCalibrations) m_Calibrations.clear();

  // Parse Input
  TiXmlDocument doc;
  if(!doc.Parse(xmlString.c_str()))
  {
    MITK_WARN << "Unable to deserialize calibrations in CombinedModality. Error was: " << doc.ErrorDesc();
    return;
  }
  TiXmlElement* root = doc.FirstChildElement();
  if(root == NULL)
  {
    MITK_WARN << "Unable to deserialize calibrations in CombinedModality. String contained no root element.";
    return;
  }
  // Read Calibrations
  for(TiXmlElement* elem = root->FirstChildElement(); elem != NULL; elem = elem->NextSiblingElement())
  {
    mitk::AffineTransform3D::MatrixType matrix;
    mitk::AffineTransform3D::OffsetType offset;

    std::string calibName = elem->Value();

    // Deserialize Matrix
    elem->QueryFloatAttribute("M00", &matrix[0][0]);
    elem->QueryFloatAttribute("M01", &matrix[0][1]);
    elem->QueryFloatAttribute("M02", &matrix[0][2]);
    elem->QueryFloatAttribute("M10", &matrix[1][0]);
    elem->QueryFloatAttribute("M11", &matrix[1][1]);
    elem->QueryFloatAttribute("M12", &matrix[1][2]);
    elem->QueryFloatAttribute("M20", &matrix[2][0]);
    elem->QueryFloatAttribute("M21", &matrix[2][1]);
    elem->QueryFloatAttribute("M22", &matrix[2][2]);

    // Deserialize Offset
    elem->QueryFloatAttribute("O0", &offset[0]);
    elem->QueryFloatAttribute("O1", &offset[1]);
    elem->QueryFloatAttribute("O2", &offset[2]);

    mitk::AffineTransform3D::Pointer calibration = mitk::AffineTransform3D::New();
    calibration->SetMatrix(matrix);
    calibration->SetOffset(offset);
    m_Calibrations[calibName] = calibration;
  }
}

std::string mitk::USCombinedModality::GetIdentifierForCurrentCalibration()
{
  us::ServiceProperties::const_iterator probeIt = m_ServiceProperties.find(US_PROPKEY_PROBES_SELECTED);

  // get probe identifier from control interface for probes
  std::string probeName = "default";
  if (probeIt != m_ServiceProperties.end())
  {
    probeName = (probeIt->second).ToString();
  }

  // get string for depth value from the micro service properties
  std::string depth;
  us::ServiceProperties::iterator depthIterator = m_ServiceProperties.find(US_PROPKEY_BMODE_DEPTH);
  if (depthIterator != m_ServiceProperties.end())
  {
    depth = depthIterator->second.ToString();
  }
  else
  {
    depth = "0";
  }

  return probeName + depth;
}
<commit_msg>Transformation is done on output now in GenerateData method.<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

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

#include "mitkUSCombinedModality.h"
#include "mitkUSDevice.h"
#include "mitkNavigationDataSource.h"
#include "mitkImageReadAccessor.h"

//TempIncludes
#include <tinyxml.h>

const std::string mitk::USCombinedModality::DeviceClassIdentifier = "org.mitk.modules.us.USCombinedModality";

mitk::USCombinedModality::USCombinedModality(USDevice::Pointer usDevice, NavigationDataSource::Pointer trackingDevice, std::string manufacturer, std::string model)
  : mitk::USDevice(manufacturer, model), m_UltrasoundDevice(usDevice), m_TrackingDevice(trackingDevice),
  m_SmoothingFilter(mitk::NavigationDataSmoothingFilter::New()), m_DelayFilter(mitk::NavigationDataDelayFilter::New(0))
{
  // build tracking filter pipeline
  for (int i = 0; i < m_TrackingDevice->GetNumberOfOutputs(); i++)
  {
    m_SmoothingFilter->SetInput(i, m_TrackingDevice->GetOutput(i));
    mitk::NavigationData::Pointer nd1 = m_TrackingDevice->GetOutput(i);
    m_DelayFilter->SetInput(i, m_SmoothingFilter->GetOutput(i));
    mitk::NavigationData::Pointer nd2 = m_SmoothingFilter->GetOutput(i);
  }
  m_SmoothingFilter->SetNumerOfValues(10);

  //create a new output (for the image data)
  mitk::Image::Pointer newOutput = mitk::Image::New();
  this->SetNthOutput(0,newOutput);
}

mitk::USCombinedModality::~USCombinedModality()
{
}

std::string mitk::USCombinedModality::GetDeviceClass()
{
  return DeviceClassIdentifier;
}

mitk::USImageSource::Pointer mitk::USCombinedModality::GetUSImageSource()
{
  if (m_UltrasoundDevice.IsNull())
  {
    MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null.";
    mitkThrow() << "UltrasoundDevice must not be null.";
  }

  return m_UltrasoundDevice->GetUSImageSource();
}

mitk::USControlInterfaceBMode::Pointer mitk::USCombinedModality::GetControlInterfaceBMode()
{
  if (m_UltrasoundDevice.IsNull())
  {
    MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null.";
    mitkThrow() << "UltrasoundDevice must not be null.";
  }

  return m_UltrasoundDevice->GetControlInterfaceBMode();
}

mitk::USControlInterfaceProbes::Pointer mitk::USCombinedModality::GetControlInterfaceProbes()
{
  if (m_UltrasoundDevice.IsNull())
  {
    MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null.";
    mitkThrow() << "UltrasoundDevice must not be null.";
  }

  return m_UltrasoundDevice->GetControlInterfaceProbes();
}

mitk::USControlInterfaceDoppler::Pointer mitk::USCombinedModality::GetControlInterfaceDoppler()
{
  if (m_UltrasoundDevice.IsNull())
  {
    MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null.";
    mitkThrow() << "UltrasoundDevice must not be null.";
  }

  return m_UltrasoundDevice->GetControlInterfaceDoppler();
}

void mitk::USCombinedModality::UnregisterOnService()
{
  if (m_DeviceState == State_Activated) { this->Deactivate(); }
  if (m_DeviceState == State_Connected) { this->Disconnect(); }

  mitk::USDevice::UnregisterOnService();
}

mitk::AffineTransform3D::Pointer mitk::USCombinedModality::GetCalibration()
{
  std::string calibrationKey = this->GetIdentifierForCurrentCalibration();
  if (calibrationKey.empty())
  {
    MITK_WARN("USCombinedModality")("USDevice")
        << "Could not get a key for the calibration.";
    return 0;
  }

  // find calibration for combination of probe identifier and depth
  std::map<std::string, mitk::AffineTransform3D::Pointer>::iterator calibrationIterator
    = m_Calibrations.find(calibrationKey);

  if (calibrationIterator == m_Calibrations.end())
  {
    MITK_WARN("USCombinedModality")("USDevice")
        << "No calibration found for selected probe and depth.";
    return 0;
  }

  return calibrationIterator->second;
}

void mitk::USCombinedModality::SetCalibration (mitk::AffineTransform3D::Pointer calibration)
{
  if (calibration.IsNull())
  {
    MITK_WARN << "Null pointer passed to SetCalibration of mitk::USDevice. Ignoring call.";
    return;
  }

  std::string calibrationKey = this->GetIdentifierForCurrentCalibration();
  if (calibrationKey.empty())
  {
    MITK_WARN << "Could not get a key for the calibration -> Calibration cannot be set.";
    return;
  }

  m_Calibrations[calibrationKey] = calibration;

  m_Metadata->SetDeviceIsCalibrated(true);

  if (m_ServiceRegistration != 0)
  {
    this->UpdateServiceProperty(mitk::USImageMetadata::PROP_DEV_ISCALIBRATED, true);
  }
}

bool mitk::USCombinedModality::OnInitialization()
{
  if (m_UltrasoundDevice.IsNull())
  {
    MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null.";
    mitkThrow() << "UltrasoundDevice must not be null.";
  }

  if ( m_UltrasoundDevice->GetDeviceState() < mitk::USDevice::State_Initialized )
  {
    return m_UltrasoundDevice->Initialize();
  }
  else
  {
    return true;
  }
}

bool mitk::USCombinedModality::OnConnection()
{
  if (m_UltrasoundDevice.IsNull())
  {
    MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null.";
    mitkThrow() << "UltrasoundDevice must not be null.";
  }

  return m_UltrasoundDevice->Connect();
}

bool mitk::USCombinedModality::OnDisconnection()
{
  if (m_UltrasoundDevice.IsNull())
  {
    MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null.";
    mitkThrow() << "UltrasoundDevice must not be null.";
  }

  return m_UltrasoundDevice->Disconnect();
}

bool mitk::USCombinedModality::OnActivation()
{
  if (m_UltrasoundDevice.IsNull())
  {
    MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null.";
    mitkThrow() << "UltrasoundDevice must not be null.";
  }

  return m_UltrasoundDevice->Activate();
}

bool mitk::USCombinedModality::OnDeactivation()
{
  if (m_UltrasoundDevice.IsNull())
  {
    MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null.";
    mitkThrow() << "UltrasoundDevice must not be null.";
  }

  m_UltrasoundDevice->Deactivate();

  return m_UltrasoundDevice->GetIsInitialized();
}

mitk::NavigationDataSource::Pointer mitk::USCombinedModality::GetNavigationDataSource()
{
  return m_DelayFilter.GetPointer();
}

void mitk::USCombinedModality::GenerateData()
{
  // update ultrasound image source and get current output then
  m_UltrasoundDevice->Modified();
  m_UltrasoundDevice->Update();
  mitk::Image::Pointer image = m_UltrasoundDevice->GetOutput();
  if ( image.IsNull() || ! image->IsInitialized() ) {
    return;
  }

  // get output and initialize it if it wasn't initialized before
  mitk::Image::Pointer output = this->GetOutput();
  if ( ! output->IsInitialized() ) { output->Initialize(image); }

  mitk::ImageReadAccessor inputReadAccessor(image, image->GetSliceData(0,0,0));
  output->SetSlice(inputReadAccessor.GetData());

  std::string calibrationKey = this->GetIdentifierForCurrentCalibration();
  if ( ! calibrationKey.empty() )
  {
    std::map<std::string, mitk::AffineTransform3D::Pointer>::iterator calibrationIterator
      = m_Calibrations.find(calibrationKey);
    if ( calibrationIterator != m_Calibrations.end())
    {
      // transform image according to callibration if one is set
      // for current configuration of probe and depth
      output->GetGeometry()->SetIndexToWorldTransform(calibrationIterator->second);
    }
  }

  // TODO: do processing here
}

std::string mitk::USCombinedModality::SerializeCalibration()
{
  std::stringstream result;
  result << "<calibrations>" << std::endl;
  // For each calibration in the set
  for (std::map<std::string, mitk::AffineTransform3D::Pointer>::iterator it = m_Calibrations.begin(); it != m_Calibrations.end(); it++)
  {
    mitk::AffineTransform3D::MatrixType matrix = it->second->GetMatrix();
    mitk::AffineTransform3D::OffsetType offset = it->second->GetOffset();
    TiXmlElement elem(it->first);
    // Serialize Matrix
    elem.SetDoubleAttribute("M00", matrix[0][0]);
    elem.SetDoubleAttribute("M01", matrix[0][1]);
    elem.SetDoubleAttribute("M02", matrix[0][2]);
    elem.SetDoubleAttribute("M10", matrix[1][0]);
    elem.SetDoubleAttribute("M11", matrix[1][1]);
    elem.SetDoubleAttribute("M12", matrix[1][2]);
    elem.SetDoubleAttribute("M20", matrix[2][0]);
    elem.SetDoubleAttribute("M21", matrix[2][1]);
    elem.SetDoubleAttribute("M22", matrix[2][2]);
    // Serialize Offset
    elem.SetDoubleAttribute("O0", offset[0]);
    elem.SetDoubleAttribute("O1", offset[1]);
    elem.SetDoubleAttribute("O2", offset[2]);

    result << elem << std::endl;
  }
  result << "</calibrations>" << std::endl;

  return result.str();
}

void mitk::USCombinedModality::DeserializeCalibration(const std::string& xmlString, bool clearPreviousCalibrations)
{
  // Sanitize Input
  if (xmlString == "")
  {
    MITK_WARN << "Empty string passed to Deserialize() method of CombinedModality. Aborting...";
    return;
  }
  // Clear previous calibrations if necessary
  if (clearPreviousCalibrations) m_Calibrations.clear();

  // Parse Input
  TiXmlDocument doc;
  if(!doc.Parse(xmlString.c_str()))
  {
    MITK_WARN << "Unable to deserialize calibrations in CombinedModality. Error was: " << doc.ErrorDesc();
    return;
  }
  TiXmlElement* root = doc.FirstChildElement();
  if(root == NULL)
  {
    MITK_WARN << "Unable to deserialize calibrations in CombinedModality. String contained no root element.";
    return;
  }
  // Read Calibrations
  for(TiXmlElement* elem = root->FirstChildElement(); elem != NULL; elem = elem->NextSiblingElement())
  {
    mitk::AffineTransform3D::MatrixType matrix;
    mitk::AffineTransform3D::OffsetType offset;

    std::string calibName = elem->Value();

    // Deserialize Matrix
    elem->QueryFloatAttribute("M00", &matrix[0][0]);
    elem->QueryFloatAttribute("M01", &matrix[0][1]);
    elem->QueryFloatAttribute("M02", &matrix[0][2]);
    elem->QueryFloatAttribute("M10", &matrix[1][0]);
    elem->QueryFloatAttribute("M11", &matrix[1][1]);
    elem->QueryFloatAttribute("M12", &matrix[1][2]);
    elem->QueryFloatAttribute("M20", &matrix[2][0]);
    elem->QueryFloatAttribute("M21", &matrix[2][1]);
    elem->QueryFloatAttribute("M22", &matrix[2][2]);

    // Deserialize Offset
    elem->QueryFloatAttribute("O0", &offset[0]);
    elem->QueryFloatAttribute("O1", &offset[1]);
    elem->QueryFloatAttribute("O2", &offset[2]);

    mitk::AffineTransform3D::Pointer calibration = mitk::AffineTransform3D::New();
    calibration->SetMatrix(matrix);
    calibration->SetOffset(offset);
    m_Calibrations[calibName] = calibration;
  }
}

std::string mitk::USCombinedModality::GetIdentifierForCurrentCalibration()
{
  us::ServiceProperties::const_iterator probeIt = m_ServiceProperties.find(US_PROPKEY_PROBES_SELECTED);

  // get probe identifier from control interface for probes
  std::string probeName = "default";
  if (probeIt != m_ServiceProperties.end())
  {
    probeName = (probeIt->second).ToString();
  }

  // get string for depth value from the micro service properties
  std::string depth;
  us::ServiceProperties::iterator depthIterator = m_ServiceProperties.find(US_PROPKEY_BMODE_DEPTH);
  if (depthIterator != m_ServiceProperties.end())
  {
    depth = depthIterator->second.ToString();
  }
  else
  {
    depth = "0";
  }

  return probeName + depth;
}
<|endoftext|>


<commit_before><commit_msg>Revert unintentional part of previous change<commit_after><|endoftext|>


<commit_before><commit_msg>Patch from <yuzo@google.com>:<commit_after><|endoftext|>


<commit_before>/*!
	@file
	@author		Albert Semenov
	@date		02/2010
	@module
*/
#include "BerkeliumWidget.h"
#include "MyGUI.h"
#include "../../Common/Input/InputConverter.h"

namespace MyGUI
{

	BerkeliumWidget::BerkeliumWidget() :
		mWindow(nullptr),
		mOldWidth(0),
		mOldHeight(0)
	{
	}

	BerkeliumWidget::~BerkeliumWidget()
	{
		requestUpdateCanvas = nullptr;

		shutdownWidgetSkin();
	}

	void BerkeliumWidget::updateSize()
	{
		mOldWidth = std::max(1, getWidth());
		mOldHeight = std::max(1, getHeight());
	}

	void BerkeliumWidget::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name)
	{
		Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name);

		updateSize();

		createTexture(mOldWidth, mOldHeight, TRM_PT_VIEW_REQUESTED);
		requestUpdateCanvas = newDelegate(this, &BerkeliumWidget::notifyUpdateCanvas);

		initialiseWidgetSkin(_info);
	}

	void BerkeliumWidget::baseChangeWidgetSkin(ResourceSkin* _info)
	{
		shutdownWidgetSkin();
		Base::baseChangeWidgetSkin(_info);
		initialiseWidgetSkin(_info);
	}

	void BerkeliumWidget::initialiseWidgetSkin(ResourceSkin* _info)
	{
		mWindow = Berkelium::Window::create();

		updateSize();

		mBuffer.resize(mOldWidth, mOldHeight);
		mWindow->resize(mOldWidth, mOldHeight);
		mWindow->setDelegate(this);

		MyGUI::Gui::getInstance().eventFrameStart += MyGUI::newDelegate(this, &BerkeliumWidget::notifyFrameStart);
	}

	void BerkeliumWidget::shutdownWidgetSkin()
	{
		MyGUI::Gui::getInstance().eventFrameStart -= MyGUI::newDelegate(this, &BerkeliumWidget::notifyFrameStart);

		if (mWindow != nullptr)
		{
			delete mWindow;
			mWindow = nullptr;
		}
	}

	void BerkeliumWidget::notifyUpdateCanvas(Canvas* _canvas, Canvas::Event _event)
	{
		if (mWindow == nullptr)
			return;

		if (_event.widgetResized)
		{
			if (mOldWidth != getWidth() || mOldHeight != getHeight())
			{
				updateSize();

				mBuffer.resize(mOldWidth, mOldHeight);
				mWindow->resize(mOldWidth, mOldHeight);

				update(true);
			}
			else if (_event.requested || _event.textureChanged)
			{
				update(true);
			}
		}
		else if (_event.requested || _event.textureChanged)
		{
			update(true);
		}
	}

	void BerkeliumWidget::loadURL(const std::string& _url)
	{
		if (mWindow != nullptr)
			mWindow->navigateTo(_url.data(), _url.length());
	}

	void BerkeliumWidget::setProperty(const std::string& _key, const std::string& _value)
	{
		if (_key == "Berkelium_SourceURL") loadURL(_value);
		else Base::setProperty(_key, _value);
	}

	void BerkeliumWidget::onPaint(Berkelium::Window *win, const unsigned char *sourceBuffer, const Berkelium::Rect &rect, int dx, int dy, const Berkelium::Rect &scrollRect)
	{
		if (mWindow == nullptr)
			return;

		mBuffer.scroll(dx, dy, scrollRect.left(), scrollRect.top(), scrollRect.width(), scrollRect.height());
		mBuffer.update((void*)sourceBuffer, rect.left(), rect.top(), rect.width(), rect.height());
	}

	void BerkeliumWidget::notifyFrameStart(float _time)
	{
		if (mWindow == nullptr)
			return;

		update(false);
	}

	void BerkeliumWidget::update(bool _invalidate)
	{
		if (!mBuffer.isDirty() && !_invalidate)
			return;

		void* data = lock();

		mBuffer.draw(data, getTextureRealWidth());

		unlock();
	}

	void BerkeliumWidget::onMouseDrag(int _left, int _top)
	{
		if (mWindow != nullptr)
			mWindow->mouseMoved(_left - getLeft(), _top - getTop());

		Base::onMouseDrag(_left, _top);
	}

	void BerkeliumWidget::onMouseMove(int _left, int _top)
	{
		if (mWindow != nullptr)
			mWindow->mouseMoved(_left - getLeft(), _top - getTop());

		Base::onMouseMove(_left, _top);
	}

	void BerkeliumWidget::onMouseWheel(int _rel)
	{
		if (mWindow != nullptr)
			mWindow->mouseWheel(0, _rel);

		Base::onMouseWheel(_rel);
	}

	void BerkeliumWidget::onMouseButtonPressed(int _left, int _top, MouseButton _id)
	{
		if (mWindow != nullptr)
			mWindow->mouseButton(_id.toValue(), true);

		Base::onMouseButtonPressed(_left, _top, _id);
	}

	void BerkeliumWidget::onMouseButtonReleased(int _left, int _top, MouseButton _id)
	{
		if (mWindow != nullptr)
			mWindow->mouseButton(_id.toValue(), false);

		Base::onMouseButtonReleased(_left, _top, _id);
	}

	void BerkeliumWidget::onKeyLostFocus(Widget* _new)
	{
		if (mWindow != nullptr)
			mWindow->unfocus();

		Base::onKeyLostFocus(_new);
	}

	void BerkeliumWidget::onKeySetFocus(Widget* _old)
	{
		if (mWindow != nullptr)
			mWindow->focus();

		Base::onKeySetFocus(_old);
	}

	void BerkeliumWidget::onKeyButtonPressed(KeyCode _key, Char _char)
	{
		if (mWindow != nullptr)
		{
			InputManager& manager = InputManager::getInstance();
			int mod = 0;
			if (manager.isControlPressed())
				mod |= Berkelium::CONTROL_MOD;
			if (manager.isShiftPressed())
				mod |= Berkelium::SHIFT_MOD;

			mWindow->keyEvent(true, mod, input::ScanCodeToVirtualKey(_key.toValue()), 0);

			if (_char != 0)
			{
				wchar_t text = (wchar_t)_char;
				mWindow->textEvent(&text, 1);
			}
		}

		Base::onKeyButtonPressed(_key, _char);
	}

	void BerkeliumWidget::onKeyButtonReleased(KeyCode _key)
	{
		if (mWindow != nullptr)
		{
			InputManager& manager = InputManager::getInstance();
			int mod = 0;
			if (manager.isControlPressed())
				mod |= Berkelium::CONTROL_MOD;
			if (manager.isShiftPressed())
				mod |= Berkelium::SHIFT_MOD;

			mWindow->keyEvent(false, mod, input::ScanCodeToVirtualKey(_key.toValue()), 0);
		}

		Base::onKeyButtonReleased(_key);
	}
}
<commit_msg>fix Berkelium mouse input in hierarchy<commit_after>/*!
	@file
	@author		Albert Semenov
	@date		02/2010
	@module
*/
#include "BerkeliumWidget.h"
#include "MyGUI.h"
#include "../../Common/Input/InputConverter.h"

namespace MyGUI
{

	BerkeliumWidget::BerkeliumWidget() :
		mWindow(nullptr),
		mOldWidth(0),
		mOldHeight(0)
	{
	}

	BerkeliumWidget::~BerkeliumWidget()
	{
		requestUpdateCanvas = nullptr;

		shutdownWidgetSkin();
	}

	void BerkeliumWidget::updateSize()
	{
		mOldWidth = std::max(1, getWidth());
		mOldHeight = std::max(1, getHeight());
	}

	void BerkeliumWidget::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name)
	{
		Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name);

		updateSize();

		createTexture(mOldWidth, mOldHeight, TRM_PT_VIEW_REQUESTED);
		requestUpdateCanvas = newDelegate(this, &BerkeliumWidget::notifyUpdateCanvas);

		initialiseWidgetSkin(_info);
	}

	void BerkeliumWidget::baseChangeWidgetSkin(ResourceSkin* _info)
	{
		shutdownWidgetSkin();
		Base::baseChangeWidgetSkin(_info);
		initialiseWidgetSkin(_info);
	}

	void BerkeliumWidget::initialiseWidgetSkin(ResourceSkin* _info)
	{
		mWindow = Berkelium::Window::create();

		updateSize();

		mBuffer.resize(mOldWidth, mOldHeight);
		mWindow->resize(mOldWidth, mOldHeight);
		mWindow->setDelegate(this);

		MyGUI::Gui::getInstance().eventFrameStart += MyGUI::newDelegate(this, &BerkeliumWidget::notifyFrameStart);
	}

	void BerkeliumWidget::shutdownWidgetSkin()
	{
		MyGUI::Gui::getInstance().eventFrameStart -= MyGUI::newDelegate(this, &BerkeliumWidget::notifyFrameStart);

		if (mWindow != nullptr)
		{
			delete mWindow;
			mWindow = nullptr;
		}
	}

	void BerkeliumWidget::notifyUpdateCanvas(Canvas* _canvas, Canvas::Event _event)
	{
		if (mWindow == nullptr)
			return;

		if (_event.widgetResized)
		{
			if (mOldWidth != getWidth() || mOldHeight != getHeight())
			{
				updateSize();

				mBuffer.resize(mOldWidth, mOldHeight);
				mWindow->resize(mOldWidth, mOldHeight);

				update(true);
			}
			else if (_event.requested || _event.textureChanged)
			{
				update(true);
			}
		}
		else if (_event.requested || _event.textureChanged)
		{
			update(true);
		}
	}

	void BerkeliumWidget::loadURL(const std::string& _url)
	{
		if (mWindow != nullptr)
			mWindow->navigateTo(_url.data(), _url.length());
	}

	void BerkeliumWidget::setProperty(const std::string& _key, const std::string& _value)
	{
		if (_key == "Berkelium_SourceURL") loadURL(_value);
		else Base::setProperty(_key, _value);
	}

	void BerkeliumWidget::onPaint(Berkelium::Window *win, const unsigned char *sourceBuffer, const Berkelium::Rect &rect, int dx, int dy, const Berkelium::Rect &scrollRect)
	{
		if (mWindow == nullptr)
			return;

		mBuffer.scroll(dx, dy, scrollRect.left(), scrollRect.top(), scrollRect.width(), scrollRect.height());
		mBuffer.update((void*)sourceBuffer, rect.left(), rect.top(), rect.width(), rect.height());
	}

	void BerkeliumWidget::notifyFrameStart(float _time)
	{
		if (mWindow == nullptr)
			return;

		update(false);
	}

	void BerkeliumWidget::update(bool _invalidate)
	{
		if (!mBuffer.isDirty() && !_invalidate)
			return;

		void* data = lock();

		mBuffer.draw(data, getTextureRealWidth());

		unlock();
	}

	void BerkeliumWidget::onMouseDrag(int _left, int _top)
	{
		if (mWindow != nullptr)
			mWindow->mouseMoved(_left - getAbsoluteLeft(), _top - getAbsoluteTop());

		Base::onMouseDrag(_left, _top);
	}

	void BerkeliumWidget::onMouseMove(int _left, int _top)
	{
		if (mWindow != nullptr)
			mWindow->mouseMoved(_left - getAbsoluteLeft(), _top - getAbsoluteTop());

		Base::onMouseMove(_left, _top);
	}

	void BerkeliumWidget::onMouseWheel(int _rel)
	{
		if (mWindow != nullptr)
			mWindow->mouseWheel(0, _rel);

		Base::onMouseWheel(_rel);
	}

	void BerkeliumWidget::onMouseButtonPressed(int _left, int _top, MouseButton _id)
	{
		if (mWindow != nullptr)
			mWindow->mouseButton(_id.toValue(), true);

		Base::onMouseButtonPressed(_left, _top, _id);
	}

	void BerkeliumWidget::onMouseButtonReleased(int _left, int _top, MouseButton _id)
	{
		if (mWindow != nullptr)
			mWindow->mouseButton(_id.toValue(), false);

		Base::onMouseButtonReleased(_left, _top, _id);
	}

	void BerkeliumWidget::onKeyLostFocus(Widget* _new)
	{
		if (mWindow != nullptr)
			mWindow->unfocus();

		Base::onKeyLostFocus(_new);
	}

	void BerkeliumWidget::onKeySetFocus(Widget* _old)
	{
		if (mWindow != nullptr)
			mWindow->focus();

		Base::onKeySetFocus(_old);
	}

	void BerkeliumWidget::onKeyButtonPressed(KeyCode _key, Char _char)
	{
		if (mWindow != nullptr)
		{
			InputManager& manager = InputManager::getInstance();
			int mod = 0;
			if (manager.isControlPressed())
				mod |= Berkelium::CONTROL_MOD;
			if (manager.isShiftPressed())
				mod |= Berkelium::SHIFT_MOD;

			mWindow->keyEvent(true, mod, input::ScanCodeToVirtualKey(_key.toValue()), 0);

			if (_char != 0)
			{
				wchar_t text = (wchar_t)_char;
				mWindow->textEvent(&text, 1);
			}
		}

		Base::onKeyButtonPressed(_key, _char);
	}

	void BerkeliumWidget::onKeyButtonReleased(KeyCode _key)
	{
		if (mWindow != nullptr)
		{
			InputManager& manager = InputManager::getInstance();
			int mod = 0;
			if (manager.isControlPressed())
				mod |= Berkelium::CONTROL_MOD;
			if (manager.isShiftPressed())
				mod |= Berkelium::SHIFT_MOD;

			mWindow->keyEvent(false, mod, input::ScanCodeToVirtualKey(_key.toValue()), 0);
		}

		Base::onKeyButtonReleased(_key);
	}
}
<|endoftext|>


<commit_before>/*!
	@file
	@author		Albert Semenov
	@date		02/2010
	@module
*/
#include "BerkeliumWidget.h"
#include "MyGUI.h"
#include "../../Common/Input/InputConverter.h"

namespace MyGUI
{

	BerkeliumWidget::BerkeliumWidget() :
		mWindow(nullptr),
		mOldWidth(0),
		mOldHeight(0)
	{
	}

	BerkeliumWidget::~BerkeliumWidget()
	{
		requestUpdateCanvas = nullptr;

		shutdownWidgetSkin();
	}

	void BerkeliumWidget::updateSize()
	{
		mOldWidth = std::max(1, getWidth());
		mOldHeight = std::max(1, getHeight());
	}

	void BerkeliumWidget::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name)
	{
		Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name);

		updateSize();

		createTexture(mOldWidth, mOldHeight, TRM_PT_VIEW_REQUESTED);
		requestUpdateCanvas = newDelegate(this, &BerkeliumWidget::notifyUpdateCanvas);

		initialiseWidgetSkin(_info);
	}

	void BerkeliumWidget::baseChangeWidgetSkin(ResourceSkin* _info)
	{
		shutdownWidgetSkin();
		Base::baseChangeWidgetSkin(_info);
		initialiseWidgetSkin(_info);
	}

	void BerkeliumWidget::initialiseWidgetSkin(ResourceSkin* _info)
	{
		mWindow = Berkelium::Window::create();

		updateSize();

		mBuffer.resize(mOldWidth, mOldHeight);
		mWindow->resize(mOldWidth, mOldHeight);
		mWindow->setDelegate(this);

		std::string url = "http://ru.msn.com/?ocid=iehp";
		mWindow->navigateTo(url.data(), url.length());

		MyGUI::Gui::getInstance().eventFrameStart += MyGUI::newDelegate(this, &BerkeliumWidget::notifyFrameStart);
	}

	void BerkeliumWidget::shutdownWidgetSkin()
	{
		MyGUI::Gui::getInstance().eventFrameStart -= MyGUI::newDelegate(this, &BerkeliumWidget::notifyFrameStart);

		if (mWindow != nullptr)
		{
			delete mWindow;
			mWindow = nullptr;
		}
	}

	void BerkeliumWidget::notifyUpdateCanvas(Canvas* _canvas, Canvas::Event _event)
	{
		if (mWindow == nullptr)
			return;

		if (_event.widgetResized)
		{
			if (mOldWidth != getWidth() || mOldHeight != getHeight())
			{
				updateSize();

				mBuffer.resize(mOldWidth, mOldHeight);
				mWindow->resize(mOldWidth, mOldHeight);

				update(true);
			}
			else if (_event.requested || _event.textureChanged)
			{
				update(true);
			}
		}
		else if (_event.requested || _event.textureChanged)
		{
			update(true);
		}
	}

	void BerkeliumWidget::loadURL(const std::string& _url)
	{
		if (mWindow != nullptr)
			mWindow->navigateTo(_url.data(), _url.length());
	}

	void BerkeliumWidget::setProperty(const std::string& _key, const std::string& _value)
	{
		if (_key == "Berkelium_SourceURL") loadURL(_value);
		else Base::setProperty(_key, _value);
	}

	void BerkeliumWidget::onPaint(Berkelium::Window *win, const unsigned char *sourceBuffer, const Berkelium::Rect &rect, int dx, int dy, const Berkelium::Rect &scrollRect)
	{
		if (mWindow == nullptr)
			return;

		mBuffer.scroll(dx, dy, scrollRect.left(), scrollRect.top(), scrollRect.width(), scrollRect.height());
		mBuffer.update((void*)sourceBuffer, rect.left(), rect.top(), rect.width(), rect.height());
	}

	void BerkeliumWidget::notifyFrameStart(float _time)
	{
		if (mWindow == nullptr)
			return;

		update(false);
	}

	void BerkeliumWidget::update(bool _invalidate)
	{
		if (!mBuffer.isDirty() && !_invalidate)
			return;

		void* data = lock();

		mBuffer.draw(data, getTextureRealWidth());

		unlock();
	}

	void BerkeliumWidget::onMouseDrag(int _left, int _top)
	{
		if (mWindow != nullptr)
			mWindow->mouseMoved(_left - getLeft(), _top - getTop());

		Base::onMouseDrag(_left, _top);
	}

	void BerkeliumWidget::onMouseMove(int _left, int _top)
	{
		if (mWindow != nullptr)
			mWindow->mouseMoved(_left - getLeft(), _top - getTop());

		Base::onMouseMove(_left, _top);
	}

	void BerkeliumWidget::onMouseWheel(int _rel)
	{
		if (mWindow != nullptr)
			mWindow->mouseWheel(0, _rel);

		Base::onMouseWheel(_rel);
	}

	void BerkeliumWidget::onMouseButtonPressed(int _left, int _top, MouseButton _id)
	{
		if (mWindow != nullptr)
			mWindow->mouseButton(_id.toValue(), true);

		Base::onMouseButtonPressed(_left, _top, _id);
	}

	void BerkeliumWidget::onMouseButtonReleased(int _left, int _top, MouseButton _id)
	{
		if (mWindow != nullptr)
			mWindow->mouseButton(_id.toValue(), false);

		Base::onMouseButtonReleased(_left, _top, _id);
	}

	void BerkeliumWidget::onKeyLostFocus(Widget* _new)
	{
		if (mWindow != nullptr)
			mWindow->unfocus();

		Base::onKeyLostFocus(_new);
	}

	void BerkeliumWidget::onKeySetFocus(Widget* _old)
	{
		if (mWindow != nullptr)
			mWindow->focus();

		Base::onKeySetFocus(_old);
	}

	void BerkeliumWidget::onKeyButtonPressed(KeyCode _key, Char _char)
	{
		if (mWindow != nullptr)
		{
			InputManager& manager = InputManager::getInstance();
			int mod = 0;
			if (manager.isControlPressed())
				mod |= Berkelium::CONTROL_MOD;
			if (manager.isShiftPressed())
				mod |= Berkelium::SHIFT_MOD;

			mWindow->keyEvent(true, mod, input::ScanCodeToVirtualKey(_key.toValue()), 0);

			if (_char != 0)
			{
				wchar_t text = (wchar_t)_char;
				mWindow->textEvent(&text, 1);
			}
		}

		Base::onKeyButtonPressed(_key, _char);
	}

	void BerkeliumWidget::onKeyButtonReleased(KeyCode _key)
	{
		if (mWindow != nullptr)
		{
			InputManager& manager = InputManager::getInstance();
			int mod = 0;
			if (manager.isControlPressed())
				mod |= Berkelium::CONTROL_MOD;
			if (manager.isShiftPressed())
				mod |= Berkelium::SHIFT_MOD;

			mWindow->keyEvent(false, mod, input::ScanCodeToVirtualKey(_key.toValue()), 0);
		}

		Base::onKeyButtonReleased(_key);
	}
}
<commit_msg>remove test data<commit_after>/*!
	@file
	@author		Albert Semenov
	@date		02/2010
	@module
*/
#include "BerkeliumWidget.h"
#include "MyGUI.h"
#include "../../Common/Input/InputConverter.h"

namespace MyGUI
{

	BerkeliumWidget::BerkeliumWidget() :
		mWindow(nullptr),
		mOldWidth(0),
		mOldHeight(0)
	{
	}

	BerkeliumWidget::~BerkeliumWidget()
	{
		requestUpdateCanvas = nullptr;

		shutdownWidgetSkin();
	}

	void BerkeliumWidget::updateSize()
	{
		mOldWidth = std::max(1, getWidth());
		mOldHeight = std::max(1, getHeight());
	}

	void BerkeliumWidget::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name)
	{
		Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name);

		updateSize();

		createTexture(mOldWidth, mOldHeight, TRM_PT_VIEW_REQUESTED);
		requestUpdateCanvas = newDelegate(this, &BerkeliumWidget::notifyUpdateCanvas);

		initialiseWidgetSkin(_info);
	}

	void BerkeliumWidget::baseChangeWidgetSkin(ResourceSkin* _info)
	{
		shutdownWidgetSkin();
		Base::baseChangeWidgetSkin(_info);
		initialiseWidgetSkin(_info);
	}

	void BerkeliumWidget::initialiseWidgetSkin(ResourceSkin* _info)
	{
		mWindow = Berkelium::Window::create();

		updateSize();

		mBuffer.resize(mOldWidth, mOldHeight);
		mWindow->resize(mOldWidth, mOldHeight);
		mWindow->setDelegate(this);

		MyGUI::Gui::getInstance().eventFrameStart += MyGUI::newDelegate(this, &BerkeliumWidget::notifyFrameStart);
	}

	void BerkeliumWidget::shutdownWidgetSkin()
	{
		MyGUI::Gui::getInstance().eventFrameStart -= MyGUI::newDelegate(this, &BerkeliumWidget::notifyFrameStart);

		if (mWindow != nullptr)
		{
			delete mWindow;
			mWindow = nullptr;
		}
	}

	void BerkeliumWidget::notifyUpdateCanvas(Canvas* _canvas, Canvas::Event _event)
	{
		if (mWindow == nullptr)
			return;

		if (_event.widgetResized)
		{
			if (mOldWidth != getWidth() || mOldHeight != getHeight())
			{
				updateSize();

				mBuffer.resize(mOldWidth, mOldHeight);
				mWindow->resize(mOldWidth, mOldHeight);

				update(true);
			}
			else if (_event.requested || _event.textureChanged)
			{
				update(true);
			}
		}
		else if (_event.requested || _event.textureChanged)
		{
			update(true);
		}
	}

	void BerkeliumWidget::loadURL(const std::string& _url)
	{
		if (mWindow != nullptr)
			mWindow->navigateTo(_url.data(), _url.length());
	}

	void BerkeliumWidget::setProperty(const std::string& _key, const std::string& _value)
	{
		if (_key == "Berkelium_SourceURL") loadURL(_value);
		else Base::setProperty(_key, _value);
	}

	void BerkeliumWidget::onPaint(Berkelium::Window *win, const unsigned char *sourceBuffer, const Berkelium::Rect &rect, int dx, int dy, const Berkelium::Rect &scrollRect)
	{
		if (mWindow == nullptr)
			return;

		mBuffer.scroll(dx, dy, scrollRect.left(), scrollRect.top(), scrollRect.width(), scrollRect.height());
		mBuffer.update((void*)sourceBuffer, rect.left(), rect.top(), rect.width(), rect.height());
	}

	void BerkeliumWidget::notifyFrameStart(float _time)
	{
		if (mWindow == nullptr)
			return;

		update(false);
	}

	void BerkeliumWidget::update(bool _invalidate)
	{
		if (!mBuffer.isDirty() && !_invalidate)
			return;

		void* data = lock();

		mBuffer.draw(data, getTextureRealWidth());

		unlock();
	}

	void BerkeliumWidget::onMouseDrag(int _left, int _top)
	{
		if (mWindow != nullptr)
			mWindow->mouseMoved(_left - getLeft(), _top - getTop());

		Base::onMouseDrag(_left, _top);
	}

	void BerkeliumWidget::onMouseMove(int _left, int _top)
	{
		if (mWindow != nullptr)
			mWindow->mouseMoved(_left - getLeft(), _top - getTop());

		Base::onMouseMove(_left, _top);
	}

	void BerkeliumWidget::onMouseWheel(int _rel)
	{
		if (mWindow != nullptr)
			mWindow->mouseWheel(0, _rel);

		Base::onMouseWheel(_rel);
	}

	void BerkeliumWidget::onMouseButtonPressed(int _left, int _top, MouseButton _id)
	{
		if (mWindow != nullptr)
			mWindow->mouseButton(_id.toValue(), true);

		Base::onMouseButtonPressed(_left, _top, _id);
	}

	void BerkeliumWidget::onMouseButtonReleased(int _left, int _top, MouseButton _id)
	{
		if (mWindow != nullptr)
			mWindow->mouseButton(_id.toValue(), false);

		Base::onMouseButtonReleased(_left, _top, _id);
	}

	void BerkeliumWidget::onKeyLostFocus(Widget* _new)
	{
		if (mWindow != nullptr)
			mWindow->unfocus();

		Base::onKeyLostFocus(_new);
	}

	void BerkeliumWidget::onKeySetFocus(Widget* _old)
	{
		if (mWindow != nullptr)
			mWindow->focus();

		Base::onKeySetFocus(_old);
	}

	void BerkeliumWidget::onKeyButtonPressed(KeyCode _key, Char _char)
	{
		if (mWindow != nullptr)
		{
			InputManager& manager = InputManager::getInstance();
			int mod = 0;
			if (manager.isControlPressed())
				mod |= Berkelium::CONTROL_MOD;
			if (manager.isShiftPressed())
				mod |= Berkelium::SHIFT_MOD;

			mWindow->keyEvent(true, mod, input::ScanCodeToVirtualKey(_key.toValue()), 0);

			if (_char != 0)
			{
				wchar_t text = (wchar_t)_char;
				mWindow->textEvent(&text, 1);
			}
		}

		Base::onKeyButtonPressed(_key, _char);
	}

	void BerkeliumWidget::onKeyButtonReleased(KeyCode _key)
	{
		if (mWindow != nullptr)
		{
			InputManager& manager = InputManager::getInstance();
			int mod = 0;
			if (manager.isControlPressed())
				mod |= Berkelium::CONTROL_MOD;
			if (manager.isShiftPressed())
				mod |= Berkelium::SHIFT_MOD;

			mWindow->keyEvent(false, mod, input::ScanCodeToVirtualKey(_key.toValue()), 0);
		}

		Base::onKeyButtonReleased(_key);
	}
}
<|endoftext|>


<commit_before>// TRENTO: Reduced Thickness Event-by-event Nuclear Topology
// Copyright 2015 Jonah E. Bernhard, J. Scott Moreland
// MIT License

#include "nucleon.h"

#include <cmath>
#include <limits>
#include <random>
#include <stdexcept>

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <iomanip>

#include <boost/math/constants/constants.hpp>
#include <boost/math/special_functions/expint.hpp>
#include <boost/math/tools/roots.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/math/special_functions/erf.hpp>
#include <boost/filesystem.hpp>

#include "fwd_decl.h"

namespace trento {

namespace {

// These constants define distances in terms of the width of the nucleon profile
// Gaussian thickness function.

// Truncation radius of the thickness function.
constexpr double radius_widths = 5.;

// Maximum impact parameter for participation.
constexpr double max_impact_widths = 6.;
// Create ctor parameters for unit mean std::gamma_distribution.
//   mean = alpha*beta == 1  ->  beta = 1/alpha
// Used below in NucleonProfile ctor initializer list.

template <typename RealType> using param_type =
  typename std::gamma_distribution<RealType>::param_type;

template <typename RealType>
param_type<RealType> gamma_param_unit_mean(RealType alpha = 1.) {
  return param_type<RealType>{alpha, 1./alpha};
}

// Return appropriate path to temporary file directory.
// Used to store cross section parameter \sigma_partonic.
fs::path get_data_home() {
  const auto data_path = std::getenv("XDG_DATA_HOME");
  if(data_path == nullptr)
    return fs::path{std::getenv("HOME")} / ".local/share";
  return data_path;
}

// Test approximate cross section parameter equality
bool almost_equal(double a, double b) {
  return fabs(a - b) < 1e-6;
}

// Default parton width to nucleon width.
double infer_parton_width(const VarMap& var_map) {
  auto nucleon_width = var_map["nucleon-width"].as<double>();
  auto parton_width = var_map["parton-width"].as<double>();
  if (parton_width < 0)
    return nucleon_width;
  else
    return parton_width;
}

// Determine the effective parton-parton cross section for sampling participants.
// TODO: derive this
double analytic_partonic_cross_section(const VarMap& var_map) {
  // Read parameters from the configuration.
  auto sigma_nn = var_map["cross-section"].as<double>();
  auto width = var_map["nucleon-width"].as<double>();

  // TODO: automatically set from beam energy
  // if (sigma_nn < 0.) {
  //   auto sqrt_s = var_map["beam-energy"].as<double>();
  // }

  // Initialize arguments for boost root finding function.

  // Bracket min and max.
  auto a = -10.;
  auto b = 20.;

  // Tolerance function.
  // Require 3/4 of double precision.
  math::tools::eps_tolerance<double> tol{
    (std::numeric_limits<double>::digits * 3) / 4};

  // Maximum iterations.
  // This is overkill -- in testing only 10-20 iterations were required
  // (but no harm in overestimating).
  boost::uintmax_t max_iter = 1000;

  // The right-hand side of the equation.
  auto rhs = sigma_nn / (4 * math::double_constants::pi * sqr(width));

  // This quantity appears a couple times in the equation.
  auto c = sqr(max_impact_widths) / 4;

  try {
    auto result = math::tools::toms748_solve(
      [&rhs, &c](double x) {
        using std::exp;
        using math::expint;
        return c - expint(-exp(x)) + expint(-exp(x-c)) - rhs;
      },
      a, b, tol, max_iter);

    auto cross_section_param = .5*(result.first + result.second);
    return std::exp(cross_section_param) * 4 * math::double_constants::pi * sqr(width);
  }
  catch (const std::domain_error&) {
    // Root finding fails for very small nucleon widths, w^2/sigma_nn < ~0.01.
    throw std::domain_error{
      "unable to fit cross section -- nucleon and/or parton width too small?"};
  }
}

// Use Monte Carlo methods to determine the partonic cross section
// \sigma_partonic. Solves MonteCarloCrossSection(sigma_partonic) = sigma_nn.
double numeric_partonic_cross_section(const VarMap& var_map) {
  MonteCarloCrossSection mc_cross_section(var_map);
  auto sigma_nn = var_map["cross-section"].as<double>();
  auto parton_width = infer_parton_width(var_map);

  // Bracket min and max.
  auto a = -10.;
  auto b = 20.;

  // Tolerance function.
  math::tools::eps_tolerance<double> tol{8};

  // Maximum iterations.
  boost::uintmax_t max_iter = 20;

  // Dimensional constant [fm^-1] used to rescale sigma_partonic
  auto c = 4 * math::double_constants::pi * sqr(parton_width);

  try {
    auto result = math::tools::toms748_solve(
      [&sigma_nn, &mc_cross_section, &c](double cross_section_param) {
        auto x = std::exp(cross_section_param) * c;
        return mc_cross_section(x) - sigma_nn;
      },
      a, b, tol, max_iter);

    auto cross_section_param = .5*(result.first + result.second);
    return std::exp(cross_section_param) * c;
  }
  catch (const std::domain_error&) {
    // Root finding fails for very small nucleon widths, w^2/sigma_nn < ~0.01.
    throw std::domain_error{
      "unable to fit cross section -- nucleon and/or parton width too small?"};
  }
}

// Determine the cross section parameter sigma_partonic, given the
// nucleon width, parton width, nucleon-nucleon cross section, and parton number.
double partonic_cross_section(const VarMap& var_map) {
  // Read parameters from the configuration.
  auto parton_width = infer_parton_width(var_map);
  auto nucleon_width = var_map["nucleon-width"].as<double>();
  auto sigma_nn = var_map["cross-section"].as<double>();
  auto nparton = var_map["parton-number"].as<int>();

  // Create trento cache directory
  auto cache_dir = get_data_home() / "trento";
  fs::create_directory(cache_dir);

  // Create dummy cross section file
  auto cache_path = cache_dir / "cross_section.dat";
  std::fstream cache_file(cache_path.string(),
      std::ios_base::out | std::ios_base::in | std::ios_base::app);

  int nparton_;
  double nucleon_width_;
  double parton_width_;
  double sigma_nn_;
  double sigma_partonic;

  // Check parameter configuration cache
  while(!cache_file.eof()) {
    cache_file >> nparton_ >> nucleon_width_ >>
      parton_width_ >> sigma_nn_ >> sigma_partonic;
    if (almost_equal(nucleon_width, nucleon_width_) &&
        almost_equal(parton_width, parton_width_) &&
        almost_equal(sigma_nn, sigma_nn_) &&
        (nparton == nparton_)) {
      return sigma_partonic;
    }
  }

  // Use a semi-analytic method to determine sigma_partonic
  // if there is no subnucleonic structure---otherwise use MC method.
  if (nucleon_width == parton_width)
    sigma_partonic = analytic_partonic_cross_section(var_map);
  else
    sigma_partonic = numeric_partonic_cross_section(var_map);

  // Save new cross section parameters to cache
  using std::fixed;
  using std::setprecision;
  using std::setw;
  using std::scientific;

  cache_file.clear();
  cache_file.seekg(0, std::ios::end);

  if (cache_file.tellg() != 0) {
    cache_file << std::endl;
  }

  cache_file.clear();

  cache_file << setprecision(6) << std::left
             << setw(8) << fixed << nparton
             << setw(10) << fixed << nucleon_width
             << setw(10) << fixed << parton_width
             << setw(10) << fixed << sigma_nn
             << setw(14) << scientific << sigma_partonic;

  return sigma_partonic;
}

// Determine the width of the normal distribution for sampling parton positions.
double compute_parton_sampling_width(const VarMap& var_map) {
  // Read parameters from the configuration.
  auto nucleon_width = var_map["nucleon-width"].as<double>();
  auto parton_width = var_map["parton-width"].as<double>();

  // Default parton width to nucleon width.
  if (parton_width < 0) return 0.;

  // Compute Gaussian sampling width by deconvolving the parton profile from the
  // nucleon profile.  The convolution of two Gaussians is a third Gaussian
  // with the variances simply added together.
  auto sampling_width_sq = sqr(nucleon_width) - sqr(parton_width);

  if (sampling_width_sq < 0.) {
    throw std::out_of_range{
      "the parton width cannot be larger than the nucleon width"};
  }

  return std::sqrt(sampling_width_sq);
}

}  // unnamed namespace

NucleonCommon::NucleonCommon(const VarMap& var_map)
    : fast_exp_(-.5*sqr(radius_widths), 0., 1000),
      max_impact_sq_(sqr(max_impact_widths*var_map["nucleon-width"].as<double>())),
      parton_width_sq_(sqr(infer_parton_width(var_map))),
      parton_radius_sq_(sqr(radius_widths)*parton_width_sq_),
      npartons_(std::size_t(var_map["parton-number"].as<int>())),
      sigma_partonic_(partonic_cross_section(var_map)),
      prefactor_(math::double_constants::one_div_two_pi/parton_width_sq_/npartons_),
      participant_fluctuation_dist_(gamma_param_unit_mean(var_map["fluctuation"].as<double>())),
      parton_position_dist_(0, compute_parton_sampling_width(var_map))
{}

MonteCarloCrossSection::MonteCarloCrossSection(const VarMap& var_map)
  : npartons(std::size_t(var_map["parton-number"].as<int>())),
    nucleon_width(var_map["nucleon-width"].as<double>()),
    parton_width(infer_parton_width(var_map)),
    parton_sampling_width(compute_parton_sampling_width(var_map)),
    parton_width_sq(sqr(parton_width)),
    prefactor(math::double_constants::one_div_two_pi/parton_width_sq/npartons)
{}

double MonteCarloCrossSection::operator() (const double sigma_partonic) const {

  random::CyclicNormal<> cyclic_normal{
    0., parton_sampling_width, cache_size, n_loops
  };

  struct Parton {
    double x, y;
  };

  std::vector<Parton> nucleonA(npartons);
  std::vector<Parton> nucleonB(npartons);

  auto bmax = max_impact_widths * nucleon_width;
  auto arg_max = 0.25*sqr(bmax)/parton_width_sq;
  const FastExp<double> fast_exp(-arg_max, 0., 1000);

  double ref_cross_section = 0.;
  double prob_miss = 0.;
  int pass_tolerance = 0;

  for (std::size_t n = 0; n < n_max; ++n) {
    // Sample b from P(b)db = 2*pi*b.
    auto b = bmax * std::sqrt(random::canonical<double>());

    for (auto&& p : nucleonA) {
      p.x = cyclic_normal(random::engine);
      p.y = cyclic_normal(random::engine);
    }

    for (auto&& p : nucleonB) {
      p.x = cyclic_normal(random::engine);
      p.y = cyclic_normal(random::engine);
    }

    auto overlap = 0.;
    for (auto&& pa : nucleonA) {
      for (auto&& pb : nucleonB) {
        auto distance_sq = sqr(pa.x - pb.x + b) + sqr(pa.y - pb.y);
        auto arg = .25*distance_sq/parton_width_sq;
        if (arg < arg_max) overlap += fast_exp(-arg);
      }
    }

    prob_miss +=
      std::exp(-sigma_partonic * prefactor/(2.*npartons) * overlap);

    auto fraction_hit = 1. - (prob_miss/n);
    auto sample_area = math::double_constants::pi * sqr(bmax);
    auto cross_section = fraction_hit * sample_area;

    auto update_difference =
      std::abs((cross_section - ref_cross_section)/cross_section);

    if (update_difference < tolerance) {
      ++pass_tolerance;
    } else {
      pass_tolerance = 0;
      ref_cross_section = cross_section;
    }

    if (pass_tolerance > n_pass){
      return cross_section;
    }
  }

  throw std::out_of_range{
    "Partonic cross section failed to converge \
      -- check nucleon-width, parton-width and npartons"};

  // Code throws an error before it ever gets here.
  return -1;
}

}  // namespace trento
<commit_msg>Fix bug with floating point precision where parton width and nucleon width are the same size.<commit_after>// TRENTO: Reduced Thickness Event-by-event Nuclear Topology
// Copyright 2015 Jonah E. Bernhard, J. Scott Moreland
// MIT License

#include "nucleon.h"

#include <cmath>
#include <limits>
#include <random>
#include <stdexcept>

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <iomanip>

#include <boost/math/constants/constants.hpp>
#include <boost/math/special_functions/expint.hpp>
#include <boost/math/tools/roots.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/math/special_functions/erf.hpp>
#include <boost/filesystem.hpp>

#include "fwd_decl.h"

namespace trento {

namespace {

// These constants define distances in terms of the width of the nucleon profile
// Gaussian thickness function.

// Truncation radius of the thickness function.
constexpr double radius_widths = 5.;

// Maximum impact parameter for participation.
constexpr double max_impact_widths = 6.;
// Create ctor parameters for unit mean std::gamma_distribution.
//   mean = alpha*beta == 1  ->  beta = 1/alpha
// Used below in NucleonProfile ctor initializer list.

template <typename RealType> using param_type =
  typename std::gamma_distribution<RealType>::param_type;

template <typename RealType>
param_type<RealType> gamma_param_unit_mean(RealType alpha = 1.) {
  return param_type<RealType>{alpha, 1./alpha};
}

// Return appropriate path to temporary file directory.
// Used to store cross section parameter \sigma_partonic.
fs::path get_data_home() {
  const auto data_path = std::getenv("XDG_DATA_HOME");
  if(data_path == nullptr)
    return fs::path{std::getenv("HOME")} / ".local/share";
  return data_path;
}

// Test approximate cross section parameter equality
bool almost_equal(double a, double b) {
  return fabs(a - b) < 1e-6;
}

// Default parton width to nucleon width.
double infer_parton_width(const VarMap& var_map) {
  auto nucleon_width = var_map["nucleon-width"].as<double>();
  auto parton_width = var_map["parton-width"].as<double>();
  if (parton_width < 0)
    return nucleon_width;
  else
    return parton_width;
}

// Determine the effective parton-parton cross section for sampling participants.
// TODO: derive this
double analytic_partonic_cross_section(const VarMap& var_map) {
  // Read parameters from the configuration.
  auto sigma_nn = var_map["cross-section"].as<double>();
  auto width = var_map["nucleon-width"].as<double>();

  // TODO: automatically set from beam energy
  // if (sigma_nn < 0.) {
  //   auto sqrt_s = var_map["beam-energy"].as<double>();
  // }

  // Initialize arguments for boost root finding function.

  // Bracket min and max.
  auto a = -10.;
  auto b = 20.;

  // Tolerance function.
  // Require 3/4 of double precision.
  math::tools::eps_tolerance<double> tol{
    (std::numeric_limits<double>::digits * 3) / 4};

  // Maximum iterations.
  // This is overkill -- in testing only 10-20 iterations were required
  // (but no harm in overestimating).
  boost::uintmax_t max_iter = 1000;

  // The right-hand side of the equation.
  auto rhs = sigma_nn / (4 * math::double_constants::pi * sqr(width));

  // This quantity appears a couple times in the equation.
  auto c = sqr(max_impact_widths) / 4;

  try {
    auto result = math::tools::toms748_solve(
      [&rhs, &c](double x) {
        using std::exp;
        using math::expint;
        return c - expint(-exp(x)) + expint(-exp(x-c)) - rhs;
      },
      a, b, tol, max_iter);

    auto cross_section_param = .5*(result.first + result.second);
    return std::exp(cross_section_param) * 4 * math::double_constants::pi * sqr(width);
  }
  catch (const std::domain_error&) {
    // Root finding fails for very small nucleon widths, w^2/sigma_nn < ~0.01.
    throw std::domain_error{
      "unable to fit cross section -- nucleon and/or parton width too small?"};
  }
}

// Use Monte Carlo methods to determine the partonic cross section
// \sigma_partonic. Solves MonteCarloCrossSection(sigma_partonic) = sigma_nn.
double numeric_partonic_cross_section(const VarMap& var_map) {
  MonteCarloCrossSection mc_cross_section(var_map);
  auto sigma_nn = var_map["cross-section"].as<double>();
  auto parton_width = infer_parton_width(var_map);

  // Bracket min and max.
  auto a = -10.;
  auto b = 20.;

  // Tolerance function.
  math::tools::eps_tolerance<double> tol{8};

  // Maximum iterations.
  boost::uintmax_t max_iter = 20;

  // Dimensional constant [fm^-1] used to rescale sigma_partonic
  auto c = 4 * math::double_constants::pi * sqr(parton_width);

  try {
    auto result = math::tools::toms748_solve(
      [&sigma_nn, &mc_cross_section, &c](double cross_section_param) {
        auto x = std::exp(cross_section_param) * c;
        return mc_cross_section(x) - sigma_nn;
      },
      a, b, tol, max_iter);

    auto cross_section_param = .5*(result.first + result.second);
    return std::exp(cross_section_param) * c;
  }
  catch (const std::domain_error&) {
    // Root finding fails for very small nucleon widths, w^2/sigma_nn < ~0.01.
    throw std::domain_error{
      "unable to fit cross section -- nucleon and/or parton width too small?"};
  }
}

// Determine the cross section parameter sigma_partonic, given the
// nucleon width, parton width, nucleon-nucleon cross section, and parton number.
double partonic_cross_section(const VarMap& var_map) {
  // Read parameters from the configuration.
  auto parton_width = infer_parton_width(var_map);
  auto nucleon_width = var_map["nucleon-width"].as<double>();
  auto sigma_nn = var_map["cross-section"].as<double>();
  auto nparton = var_map["parton-number"].as<int>();

  // Create trento cache directory
  auto cache_dir = get_data_home() / "trento";
  fs::create_directory(cache_dir);

  // Create dummy cross section file
  auto cache_path = cache_dir / "cross_section.dat";
  std::fstream cache_file(cache_path.string(),
      std::ios_base::out | std::ios_base::in | std::ios_base::app);

  int nparton_;
  double nucleon_width_;
  double parton_width_;
  double sigma_nn_;
  double sigma_partonic;

  // Check parameter configuration cache
  while(!cache_file.eof()) {
    cache_file >> nparton_ >> nucleon_width_ >>
      parton_width_ >> sigma_nn_ >> sigma_partonic;
    if (almost_equal(nucleon_width, nucleon_width_) &&
        almost_equal(parton_width, parton_width_) &&
        almost_equal(sigma_nn, sigma_nn_) &&
        (nparton == nparton_)) {
      return sigma_partonic;
    }
  }

  // Use a semi-analytic method to determine sigma_partonic
  // if there is no subnucleonic structure---otherwise use MC method.
  if (nucleon_width == parton_width)
    sigma_partonic = analytic_partonic_cross_section(var_map);
  else
    sigma_partonic = numeric_partonic_cross_section(var_map);

  // Save new cross section parameters to cache
  using std::fixed;
  using std::setprecision;
  using std::setw;
  using std::scientific;

  cache_file.clear();
  cache_file.seekg(0, std::ios::end);

  if (cache_file.tellg() != 0) {
    cache_file << std::endl;
  }

  cache_file.clear();

  cache_file << setprecision(6) << std::left
             << setw(8) << fixed << nparton
             << setw(10) << fixed << nucleon_width
             << setw(10) << fixed << parton_width
             << setw(10) << fixed << sigma_nn
             << setw(14) << scientific << sigma_partonic;

  return sigma_partonic;
}

// Determine the width of the normal distribution for sampling parton positions.
double compute_parton_sampling_width(const VarMap& var_map) {
  // Read parameters from the configuration.
  auto nucleon_width = var_map["nucleon-width"].as<double>();
  auto parton_width = var_map["parton-width"].as<double>();

  // Default parton width to nucleon width.
  if (parton_width < 0) return 0.;

  // Compute Gaussian sampling width by deconvolving the parton profile from the
  // nucleon profile.  The convolution of two Gaussians is a third Gaussian
  // with the variances simply added together.
  auto sampling_width_sq = sqr(nucleon_width) - sqr(parton_width);
  auto TINY = 1e-8;

  if (sampling_width_sq < -TINY) {
    throw std::out_of_range{
      "the parton width cannot be larger than the nucleon width"};
  }

  return std::sqrt(std::max(sampling_width_sq, 0.));
}

}  // unnamed namespace

NucleonCommon::NucleonCommon(const VarMap& var_map)
    : fast_exp_(-.5*sqr(radius_widths), 0., 1000),
      max_impact_sq_(sqr(max_impact_widths*var_map["nucleon-width"].as<double>())),
      parton_width_sq_(sqr(infer_parton_width(var_map))),
      parton_radius_sq_(sqr(radius_widths)*parton_width_sq_),
      npartons_(std::size_t(var_map["parton-number"].as<int>())),
      sigma_partonic_(partonic_cross_section(var_map)),
      prefactor_(math::double_constants::one_div_two_pi/parton_width_sq_/npartons_),
      participant_fluctuation_dist_(gamma_param_unit_mean(var_map["fluctuation"].as<double>())),
      parton_position_dist_(0, compute_parton_sampling_width(var_map))
{}

MonteCarloCrossSection::MonteCarloCrossSection(const VarMap& var_map)
  : npartons(std::size_t(var_map["parton-number"].as<int>())),
    nucleon_width(var_map["nucleon-width"].as<double>()),
    parton_width(infer_parton_width(var_map)),
    parton_sampling_width(compute_parton_sampling_width(var_map)),
    parton_width_sq(sqr(parton_width)),
    prefactor(math::double_constants::one_div_two_pi/parton_width_sq/npartons)
{}

double MonteCarloCrossSection::operator() (const double sigma_partonic) const {

  random::CyclicNormal<> cyclic_normal{
    0., parton_sampling_width, cache_size, n_loops
  };

  struct Parton {
    double x, y;
  };

  std::vector<Parton> nucleonA(npartons);
  std::vector<Parton> nucleonB(npartons);

  auto bmax = max_impact_widths * nucleon_width;
  auto arg_max = 0.25*sqr(bmax)/parton_width_sq;
  const FastExp<double> fast_exp(-arg_max, 0., 1000);

  double ref_cross_section = 0.;
  double prob_miss = 0.;
  int pass_tolerance = 0;

  for (std::size_t n = 0; n < n_max; ++n) {
    // Sample b from P(b)db = 2*pi*b.
    auto b = bmax * std::sqrt(random::canonical<double>());

    for (auto&& p : nucleonA) {
      p.x = cyclic_normal(random::engine);
      p.y = cyclic_normal(random::engine);
    }

    for (auto&& p : nucleonB) {
      p.x = cyclic_normal(random::engine);
      p.y = cyclic_normal(random::engine);
    }

    auto overlap = 0.;
    for (auto&& pa : nucleonA) {
      for (auto&& pb : nucleonB) {
        auto distance_sq = sqr(pa.x - pb.x + b) + sqr(pa.y - pb.y);
        auto arg = .25*distance_sq/parton_width_sq;
        if (arg < arg_max) overlap += fast_exp(-arg);
      }
    }

    prob_miss +=
      std::exp(-sigma_partonic * prefactor/(2.*npartons) * overlap);

    auto fraction_hit = 1. - (prob_miss/n);
    auto sample_area = math::double_constants::pi * sqr(bmax);
    auto cross_section = fraction_hit * sample_area;

    auto update_difference =
      std::abs((cross_section - ref_cross_section)/cross_section);

    if (update_difference < tolerance) {
      ++pass_tolerance;
    } else {
      pass_tolerance = 0;
      ref_cross_section = cross_section;
    }

    if (pass_tolerance > n_pass){
      return cross_section;
    }
  }

  throw std::out_of_range{
    "Partonic cross section failed to converge \
      -- check nucleon-width, parton-width and npartons"};

  // Code throws an error before it ever gets here.
  return -1;
}

}  // namespace trento
<|endoftext|>