<commit_before>/////////////////////////////////////////////////////////////////////////////
// Name:        sch_sheet_pin.cpp
// Purpose:     member functions SCH_SHEET_PIN
//              header = sch_sheet.h
// Author:      jean-pierre Charras
// Modified by:
// Created:     08/02/2006 18:37:02
// RCS-ID:
// Copyright:   License GNU
// License:
/////////////////////////////////////////////////////////////////////////////

#include "fctsys.h"
#include "gr_basic.h"
#include "common.h"
#include "class_drawpanel.h"
#include "drawtxt.h"
#include "plot_common.h"
#include "trigo.h"
#include "richio.h"
#include "class_sch_screen.h"

#include "general.h"
#include "protos.h"
#include "sch_sheet.h"

/* m_Edge define on which edge the pin is positionned:
 *
 *        0: pin on left side
 *        1: pin on right side
 *        2: pin on top side
 *        3: pin on bottom side
 *  for compatibility reasons, this does not follow same values as text
 *  ortientation.
 */

SCH_SHEET_PIN::SCH_SHEET_PIN( SCH_SHEET* parent, const wxPoint& pos, const wxString& text ) :
    SCH_HIERLABEL( pos, text, SCH_SHEET_LABEL_T )
{
    SetParent( parent );
    wxASSERT( parent );
    m_Layer = LAYER_SHEETLABEL;
    m_Pos   = pos;
    if( parent->IsVerticalOrientation() )
        SetEdge( 2 );
    else
        SetEdge( 0 );
    m_Shape = NET_INPUT;
    m_IsDangling = TRUE;
    m_Number     = 2;
}

SCH_SHEET_PIN::SCH_SHEET_PIN( const SCH_SHEET_PIN& aSheetLabel ) :
    SCH_HIERLABEL( aSheetLabel )
{
    m_Number = aSheetLabel.m_Number;
    m_Edge = aSheetLabel.m_Edge;
}

EDA_ITEM* SCH_SHEET_PIN::doClone() const
{
    return new SCH_SHEET_PIN( *this );
}

void SCH_SHEET_PIN::Draw( EDA_DRAW_PANEL* aPanel,
                          wxDC*           aDC,
                          const wxPoint&  aOffset,
                          int             aDraw_mode,
                          int             aColor )
{
    // The icon selection is handle by the virtual method CreateGraphicShape
    // called by ::Draw
    SCH_HIERLABEL::Draw( aPanel, aDC, aOffset, aDraw_mode, aColor );
}

void SCH_SHEET_PIN::SwapData( SCH_SHEET_PIN* copyitem )
{
    SCH_TEXT::SwapData( (SCH_TEXT*) copyitem );
    int tmp;
    tmp = copyitem->GetNumber();
    copyitem->SetNumber( GetNumber() );
    SetNumber( tmp );
    tmp = copyitem->GetEdge();
    copyitem->SetEdge( GetEdge() );
    SetEdge( tmp );
}

bool SCH_SHEET_PIN::operator==( const SCH_SHEET_PIN* aPin ) const
{
    return aPin == this;
}

int SCH_SHEET_PIN::GetPenSize() const
{
    return g_DrawDefaultLineThickness;
}

void SCH_SHEET_PIN::SetNumber( int aNumber )
{
    wxASSERT( aNumber >= 2 );

    m_Number = aNumber;
}

void SCH_SHEET_PIN::SetEdge( int aEdge )
{
    SCH_SHEET* Sheet = (SCH_SHEET*) GetParent();

    /* use -1 to adjust text orientation without changing edge*/
    if( aEdge > -1 )
        m_Edge = aEdge;

    switch( m_Edge )
    {
    case 0:        /* pin on left side*/
        m_Pos.x = Sheet->m_Pos.x;
        SetOrientation( 2 ); /* Orientation horiz inverse */
        break;

    case 1:        /* pin on right side*/
        m_Pos.x = Sheet->m_Pos.x + Sheet->m_Size.x;
        SetOrientation( 0 ); /* Orientation horiz normal */
        break;

    case 2:        /* pin on top side*/
        m_Pos.y = Sheet->m_Pos.y;
        SetOrientation( 3 ); /* Orientation vert BOTTOM  */
        break;

    case 3:        /* pin on bottom side*/
        m_Pos.y = Sheet->m_Pos.y + Sheet->m_Size.y;
        SetOrientation( 1 ); /* Orientation vert UP  */
        break;
    }
}

int SCH_SHEET_PIN::GetEdge()
{
    return m_Edge;
}

void SCH_SHEET_PIN::ConstraintOnEdge( wxPoint Pos )
{
    SCH_SHEET* Sheet = (SCH_SHEET*) GetParent();

    if( Sheet == NULL )
        return;

    if( m_Edge<2 ) /*horizontal sheetpin*/
    {
        if( Pos.x > ( Sheet->m_Pos.x + ( Sheet->m_Size.x / 2 ) ) )
        {
            SetEdge( 1 );
        }
        else
        {
            SetEdge( 0 );
        }

        m_Pos.y = Pos.y;
        if( m_Pos.y < Sheet->m_Pos.y )
            m_Pos.y = Sheet->m_Pos.y;
        if( m_Pos.y > (Sheet->m_Pos.y + Sheet->m_Size.y) )
            m_Pos.y = Sheet->m_Pos.y + Sheet->m_Size.y;
    }
    else /* vertical sheetpin*/
    {
        if( Pos.y > ( Sheet->m_Pos.y + ( Sheet->m_Size.y / 2 ) ) )
        {
            SetEdge( 3 ); //bottom
        }
        else
        {
            SetEdge( 2 ); //top
        }

        m_Pos.x = Pos.x;

        if( m_Pos.x < Sheet->m_Pos.x )
            m_Pos.x = Sheet->m_Pos.x;

        if( m_Pos.x > (Sheet->m_Pos.x + Sheet->m_Size.x) )
            m_Pos.x = Sheet->m_Pos.x + Sheet->m_Size.x;
    }
}

bool SCH_SHEET_PIN::Save( FILE* aFile ) const
{
    int type = 'U', side = 'L';

    if( m_Text.IsEmpty() )
        return true;

    switch( m_Edge )
    {
    case 0:     //pin on left side
        side = 'L';
        break;

    case 1:     //pin on right side
        side = 'R';
        break;

    case 2:      //pin on top side
        side = 'T';
        break;

    case 3:     //pin on bottom side
        side = 'B';
        break;
    }

    switch( m_Shape )
    {
    case NET_INPUT:
        type = 'I'; break;

    case NET_OUTPUT:
        type = 'O'; break;

    case NET_BIDI:
        type = 'B'; break;

    case NET_TRISTATE:
        type = 'T'; break;

    case NET_UNSPECIFIED:
        type = 'U'; break;
    }

    if( fprintf( aFile, "F%d \"%s\" %c %c %-3d %-3d %-3d\n", m_Number,
                 TO_UTF8( m_Text ), type, side, m_Pos.x, m_Pos.y,
                 m_Size.x ) == EOF )
    {
        return false;
    }

    return true;
}

bool SCH_SHEET_PIN::Load( LINE_READER& aLine, wxString& aErrorMsg )
{
    int  size;
    char number[256];
    char name[256];
    char connectType[256];
    char sheetSide[256];

    /* Read coordinates. */
    if( sscanf( ((char*)aLine), "%s %s %s %s %d %d %d",
                number, name, connectType, sheetSide, &m_Pos.x, &m_Pos.y, &size ) != 7 )
    {
        aErrorMsg.Printf( wxT( "EESchema file sheet hierarchical label error at line %d.\n" ),
                          aLine.LineNumber() );
        aErrorMsg << FROM_UTF8( ((char*)aLine) );
        return false;
    }

    m_Text = FROM_UTF8( name );

    m_Text = m_Text.AfterFirst( wxChar( '"' ) );
    m_Text = m_Text.BeforeLast( wxChar( '"' ) );

    if( size == 0 )
        size = DEFAULT_SIZE_TEXT;

    m_Size.x = m_Size.y = size;

    switch( connectType[0] )
    {
    case 'I':
        m_Shape = NET_INPUT;
        break;
    case 'O':
        m_Shape = NET_OUTPUT;
        break;
    case 'B':
        m_Shape = NET_BIDI;
        break;
    case 'T':
        m_Shape = NET_TRISTATE;
        break;
    case 'U':
        m_Shape = NET_UNSPECIFIED;
        break;
    }

    switch( sheetSide[0] )
    {
    case 'R' : /* pin on right side */
        SetEdge( 1 );
        break;
    case 'T' : /* pin on top side */
        SetEdge( 2 );
        break;
    case 'B' : /* pin on bottom side */
        SetEdge( 3 );
        break;
    case 'L' : /* pin on left side */
    default  :
        SetEdge( 0 );
        break;
    }

    return true;
}

bool SCH_SHEET_PIN::Matches( wxFindReplaceData& aSearchData,
                             void* aAuxData, wxPoint * aFindLocation )
{
    if( SCH_ITEM::Matches( m_Text, aSearchData ) )
    {
        if( aFindLocation )
            *aFindLocation = m_Pos;

        return true;
    }

    return false;
}

void SCH_SHEET_PIN::Mirror_X( int aXaxis_position )
{
    int p = m_Pos.y - aXaxis_position;

    m_Pos.y = aXaxis_position - p;

    switch( m_Edge )
    {
    case 2:
        SetEdge( 3 );
        break;

    case 3:
        SetEdge( 2 );
        break;
    }
}

void SCH_SHEET_PIN::Mirror_Y( int aYaxis_position )
{
    int p = m_Pos.x - aYaxis_position;

    m_Pos.x = aYaxis_position - p;

    switch( m_Edge )
    {
    case 0:
        SetEdge( 1 );
        break;

    case 1:
        SetEdge( 0 );
        break;
    }
}

void SCH_SHEET_PIN::Rotate( wxPoint rotationPoint )
{
    RotatePoint( &m_Pos, rotationPoint, 900 );

    switch( m_Edge )
    {
    case 0:     //pin on left side
        SetEdge( 3 );
        break;

    case 1:     //pin on right side
        SetEdge( 2 );
        break;

    case 2:      //pin on top side
        SetEdge( 0 );
        break;

    case 3:     //pin on bottom side
        SetEdge( 1 );
        break;
    }
}

void SCH_SHEET_PIN::CreateGraphicShape( std::vector <wxPoint>& aCorner_list,
                                        const wxPoint&         aPos )
{
     /* This is the same icon shapes as SCH_HIERLABEL
     * but the graphic icon is slightly different in 2 cases:
     * for INPUT type the icon is the OUTPUT shape of SCH_HIERLABEL
     * for OUTPUT type the icon is the INPUT shape of SCH_HIERLABEL
     */
    int tmp = m_Shape;

    switch( m_Shape )
    {
    case NET_INPUT:
        m_Shape = NET_OUTPUT;
        break;

    case NET_OUTPUT:
        m_Shape = NET_INPUT;
        break;

    default:
        break;
    }

    SCH_HIERLABEL::CreateGraphicShape( aCorner_list, aPos );
    m_Shape = tmp;
}

void SCH_SHEET_PIN::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
{
    DANGLING_END_ITEM item( SHEET_LABEL_END, this );
    item.m_Pos  = m_Pos;
    aItemList.push_back( item );
}

#if defined(DEBUG)

void SCH_SHEET_PIN::Show( int nestLevel, std::ostream& os )
{
    // XML output:
    wxString s = GetClass();

    NestedSpace( nestLevel, os ) << '<' << s.Lower().mb_str() << ">"
                                 << " pin_name=\"" << TO_UTF8( m_Text )
                                 << '"' << "/>\n" << std::flush;

//    NestedSpace( nestLevel, os ) << "</" << s.Lower().mb_str() << ">\n";
}

#endif
<commit_msg>bugfix<commit_after>/////////////////////////////////////////////////////////////////////////////
// Name:        sch_sheet_pin.cpp
// Purpose:     member functions SCH_SHEET_PIN
//              header = sch_sheet.h
// Author:      jean-pierre Charras
// Modified by:
// Created:     08/02/2006 18:37:02
// RCS-ID:
// Copyright:   License GNU
// License:
/////////////////////////////////////////////////////////////////////////////

#include "fctsys.h"
#include "gr_basic.h"
#include "common.h"
#include "class_drawpanel.h"
#include "drawtxt.h"
#include "plot_common.h"
#include "trigo.h"
#include "richio.h"
#include "class_sch_screen.h"

#include "general.h"
#include "protos.h"
#include "sch_sheet.h"
#include "kicad_string.h"

/* m_Edge define on which edge the pin is positionned:
 *
 *        0: pin on left side
 *        1: pin on right side
 *        2: pin on top side
 *        3: pin on bottom side
 *  for compatibility reasons, this does not follow same values as text
 *  ortientation.
 */

SCH_SHEET_PIN::SCH_SHEET_PIN( SCH_SHEET* parent, const wxPoint& pos, const wxString& text ) :
    SCH_HIERLABEL( pos, text, SCH_SHEET_LABEL_T )
{
    SetParent( parent );
    wxASSERT( parent );
    m_Layer = LAYER_SHEETLABEL;
    m_Pos   = pos;
    if( parent->IsVerticalOrientation() )
        SetEdge( 2 );
    else
        SetEdge( 0 );
    m_Shape = NET_INPUT;
    m_IsDangling = TRUE;
    m_Number     = 2;
}

SCH_SHEET_PIN::SCH_SHEET_PIN( const SCH_SHEET_PIN& aSheetLabel ) :
    SCH_HIERLABEL( aSheetLabel )
{
    m_Number = aSheetLabel.m_Number;
    m_Edge = aSheetLabel.m_Edge;
}

EDA_ITEM* SCH_SHEET_PIN::doClone() const
{
    return new SCH_SHEET_PIN( *this );
}

void SCH_SHEET_PIN::Draw( EDA_DRAW_PANEL* aPanel,
                          wxDC*           aDC,
                          const wxPoint&  aOffset,
                          int             aDraw_mode,
                          int             aColor )
{
    // The icon selection is handle by the virtual method CreateGraphicShape
    // called by ::Draw
    SCH_HIERLABEL::Draw( aPanel, aDC, aOffset, aDraw_mode, aColor );
}

void SCH_SHEET_PIN::SwapData( SCH_SHEET_PIN* copyitem )
{
    SCH_TEXT::SwapData( (SCH_TEXT*) copyitem );
    int tmp;
    tmp = copyitem->GetNumber();
    copyitem->SetNumber( GetNumber() );
    SetNumber( tmp );
    tmp = copyitem->GetEdge();
    copyitem->SetEdge( GetEdge() );
    SetEdge( tmp );
}

bool SCH_SHEET_PIN::operator==( const SCH_SHEET_PIN* aPin ) const
{
    return aPin == this;
}

int SCH_SHEET_PIN::GetPenSize() const
{
    return g_DrawDefaultLineThickness;
}

void SCH_SHEET_PIN::SetNumber( int aNumber )
{
    wxASSERT( aNumber >= 2 );

    m_Number = aNumber;
}

void SCH_SHEET_PIN::SetEdge( int aEdge )
{
    SCH_SHEET* Sheet = (SCH_SHEET*) GetParent();

    /* use -1 to adjust text orientation without changing edge*/
    if( aEdge > -1 )
        m_Edge = aEdge;

    switch( m_Edge )
    {
    case 0:        /* pin on left side*/
        m_Pos.x = Sheet->m_Pos.x;
        SetOrientation( 2 ); /* Orientation horiz inverse */
        break;

    case 1:        /* pin on right side*/
        m_Pos.x = Sheet->m_Pos.x + Sheet->m_Size.x;
        SetOrientation( 0 ); /* Orientation horiz normal */
        break;

    case 2:        /* pin on top side*/
        m_Pos.y = Sheet->m_Pos.y;
        SetOrientation( 3 ); /* Orientation vert BOTTOM  */
        break;

    case 3:        /* pin on bottom side*/
        m_Pos.y = Sheet->m_Pos.y + Sheet->m_Size.y;
        SetOrientation( 1 ); /* Orientation vert UP  */
        break;
    }
}

int SCH_SHEET_PIN::GetEdge()
{
    return m_Edge;
}

void SCH_SHEET_PIN::ConstraintOnEdge( wxPoint Pos )
{
    SCH_SHEET* Sheet = (SCH_SHEET*) GetParent();

    if( Sheet == NULL )
        return;

    if( m_Edge<2 ) /*horizontal sheetpin*/
    {
        if( Pos.x > ( Sheet->m_Pos.x + ( Sheet->m_Size.x / 2 ) ) )
        {
            SetEdge( 1 );
        }
        else
        {
            SetEdge( 0 );
        }

        m_Pos.y = Pos.y;
        if( m_Pos.y < Sheet->m_Pos.y )
            m_Pos.y = Sheet->m_Pos.y;
        if( m_Pos.y > (Sheet->m_Pos.y + Sheet->m_Size.y) )
            m_Pos.y = Sheet->m_Pos.y + Sheet->m_Size.y;
    }
    else /* vertical sheetpin*/
    {
        if( Pos.y > ( Sheet->m_Pos.y + ( Sheet->m_Size.y / 2 ) ) )
        {
            SetEdge( 3 ); //bottom
        }
        else
        {
            SetEdge( 2 ); //top
        }

        m_Pos.x = Pos.x;

        if( m_Pos.x < Sheet->m_Pos.x )
            m_Pos.x = Sheet->m_Pos.x;

        if( m_Pos.x > (Sheet->m_Pos.x + Sheet->m_Size.x) )
            m_Pos.x = Sheet->m_Pos.x + Sheet->m_Size.x;
    }
}

bool SCH_SHEET_PIN::Save( FILE* aFile ) const
{
    int type = 'U', side = 'L';

    if( m_Text.IsEmpty() )
        return true;

    switch( m_Edge )
    {
    case 0:     //pin on left side
        side = 'L';
        break;

    case 1:     //pin on right side
        side = 'R';
        break;

    case 2:      //pin on top side
        side = 'T';
        break;

    case 3:     //pin on bottom side
        side = 'B';
        break;
    }

    switch( m_Shape )
    {
    case NET_INPUT:
        type = 'I'; break;

    case NET_OUTPUT:
        type = 'O'; break;

    case NET_BIDI:
        type = 'B'; break;

    case NET_TRISTATE:
        type = 'T'; break;

    case NET_UNSPECIFIED:
        type = 'U'; break;
    }

    if( fprintf( aFile, "F%d \"%s\" %c %c %-3d %-3d %-3d\n", m_Number,
                 TO_UTF8( m_Text ), type, side, m_Pos.x, m_Pos.y,
                 m_Size.x ) == EOF )
    {
        return false;
    }

    return true;
}

bool SCH_SHEET_PIN::Load( LINE_READER& aLine, wxString& aErrorMsg )
{
    int     size;
    char    number[256];
    char    name[256];
    char    connectType[256];
    char    sheetSide[256];
    char*   line = aLine.Line();
    char*   cp;

    static const char delims[] = " \t";

    // Read coordinates.
    D( printf( "line: \"%s\"\n", line );)

    cp = strtok( line, delims );

    strncpy( number, cp, sizeof(number) );
    number[sizeof(number)-1] = 0;

    cp += strlen( number ) + 1;

    cp += ReadDelimitedText( name, cp, sizeof(name) );

    cp = strtok( cp, delims );
    strncpy( connectType, cp, sizeof(connectType) );
    connectType[sizeof(connectType)-1] = 0;

    cp = strtok( NULL, delims );
    strncpy( sheetSide, cp, sizeof(sheetSide) );
    sheetSide[sizeof(sheetSide)-1] = 0;

    cp += strlen( sheetSide ) + 1;

    int r = sscanf( cp, "%d %d %d", &m_Pos.x, &m_Pos.y, &size );
    if( r != 3 )
    {
        aErrorMsg.Printf( wxT( "EESchema file sheet hierarchical label error at line %d.\n" ),
                          aLine.LineNumber() );

        aErrorMsg << FROM_UTF8( line );
        return false;
    }

    m_Text = FROM_UTF8( name );

    m_Text = m_Text.AfterFirst( wxChar( '"' ) );
    m_Text = m_Text.BeforeLast( wxChar( '"' ) );

    if( size == 0 )
        size = DEFAULT_SIZE_TEXT;

    m_Size.x = m_Size.y = size;

    switch( connectType[0] )
    {
    case 'I':
        m_Shape = NET_INPUT;
        break;
    case 'O':
        m_Shape = NET_OUTPUT;
        break;
    case 'B':
        m_Shape = NET_BIDI;
        break;
    case 'T':
        m_Shape = NET_TRISTATE;
        break;
    case 'U':
        m_Shape = NET_UNSPECIFIED;
        break;
    }

    switch( sheetSide[0] )
    {
    case 'R' : /* pin on right side */
        SetEdge( 1 );
        break;
    case 'T' : /* pin on top side */
        SetEdge( 2 );
        break;
    case 'B' : /* pin on bottom side */
        SetEdge( 3 );
        break;
    case 'L' : /* pin on left side */
    default  :
        SetEdge( 0 );
        break;
    }

    return true;
}

bool SCH_SHEET_PIN::Matches( wxFindReplaceData& aSearchData,
                             void* aAuxData, wxPoint * aFindLocation )
{
    if( SCH_ITEM::Matches( m_Text, aSearchData ) )
    {
        if( aFindLocation )
            *aFindLocation = m_Pos;

        return true;
    }

    return false;
}

void SCH_SHEET_PIN::Mirror_X( int aXaxis_position )
{
    int p = m_Pos.y - aXaxis_position;

    m_Pos.y = aXaxis_position - p;

    switch( m_Edge )
    {
    case 2:
        SetEdge( 3 );
        break;

    case 3:
        SetEdge( 2 );
        break;
    }
}

void SCH_SHEET_PIN::Mirror_Y( int aYaxis_position )
{
    int p = m_Pos.x - aYaxis_position;

    m_Pos.x = aYaxis_position - p;

    switch( m_Edge )
    {
    case 0:
        SetEdge( 1 );
        break;

    case 1:
        SetEdge( 0 );
        break;
    }
}

void SCH_SHEET_PIN::Rotate( wxPoint rotationPoint )
{
    RotatePoint( &m_Pos, rotationPoint, 900 );

    switch( m_Edge )
    {
    case 0:     //pin on left side
        SetEdge( 3 );
        break;

    case 1:     //pin on right side
        SetEdge( 2 );
        break;

    case 2:      //pin on top side
        SetEdge( 0 );
        break;

    case 3:     //pin on bottom side
        SetEdge( 1 );
        break;
    }
}

void SCH_SHEET_PIN::CreateGraphicShape( std::vector <wxPoint>& aCorner_list,
                                        const wxPoint&         aPos )
{
     /* This is the same icon shapes as SCH_HIERLABEL
     * but the graphic icon is slightly different in 2 cases:
     * for INPUT type the icon is the OUTPUT shape of SCH_HIERLABEL
     * for OUTPUT type the icon is the INPUT shape of SCH_HIERLABEL
     */
    int tmp = m_Shape;

    switch( m_Shape )
    {
    case NET_INPUT:
        m_Shape = NET_OUTPUT;
        break;

    case NET_OUTPUT:
        m_Shape = NET_INPUT;
        break;

    default:
        break;
    }

    SCH_HIERLABEL::CreateGraphicShape( aCorner_list, aPos );
    m_Shape = tmp;
}

void SCH_SHEET_PIN::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
{
    DANGLING_END_ITEM item( SHEET_LABEL_END, this );
    item.m_Pos  = m_Pos;
    aItemList.push_back( item );
}

#if defined(DEBUG)

void SCH_SHEET_PIN::Show( int nestLevel, std::ostream& os )
{
    // XML output:
    wxString s = GetClass();

    NestedSpace( nestLevel, os ) << '<' << s.Lower().mb_str() << ">"
                                 << " pin_name=\"" << TO_UTF8( m_Text )
                                 << '"' << "/>\n" << std::flush;

//    NestedSpace( nestLevel, os ) << "</" << s.Lower().mb_str() << ">\n";
}

#endif
<|endoftext|>


<commit_before>#include <mitkLabeledImageToSurfaceFilter.h>

#include <vtkImageChangeInformation.h>
#include <vtkImageThreshold.h>
#include <vtkImageGaussianSmooth.h>
#include <vtkImageMarchingCubes.h>
#include <vtkPolyData.h>
#include <vtkSmoothPolyDataFilter.h>
#include <vtkDecimatePro.h>
#if (VTK_MAJOR_VERSION < 5)
#include <vtkDecimate.h>
#endif
#include <vtkLinearTransform.h>
#include <vtkMatrix4x4.h>

#include <mitkImageAccessByItk.h>
#include <itkImageRegionIterator.h>
#include <itkNumericTraits.h>

mitk::LabeledImageToSurfaceFilter::LabeledImageToSurfaceFilter()
{
  m_GaussianStandardDeviation = 1.5;
  m_GenerateAllLabels = true;
  m_Label = 1;
  m_BackgroundLabel = 0;
}

mitk::LabeledImageToSurfaceFilter::~LabeledImageToSurfaceFilter()
{
}

void mitk::LabeledImageToSurfaceFilter::GenerateOutputInformation()
{
  Superclass::GenerateOutputInformation();
  //
  // check which labels are available in the image
  //
  m_AvailableLabels = this->GetAvailableLabels();
  m_IdxToLabels.clear();

  //
  // if we don't want to generate surfaces for all labels
  // we have to remove all labales except m_Label and m_BackgroundLabel
  // from the list of available labels
  //
  if ( ! m_GenerateAllLabels )
  {
    LabelMapType tmp;
    LabelMapType::iterator it;
    it = m_AvailableLabels.find( m_Label );
    if ( it != m_AvailableLabels.end() )
      tmp[m_Label] = it->second;
    else
      tmp[m_Label] = 0;

    it = m_AvailableLabels.find( m_BackgroundLabel );
    if ( it != m_AvailableLabels.end() )
      tmp[m_BackgroundLabel] = it->second;
    else
      tmp[m_BackgroundLabel] = 0;

    m_AvailableLabels = tmp;
  }

  //
  // check for the number of labels: if the whole image is filled, no
  // background is available and thus the numberOfOutpus is equal to the
  // number of available labels in the image (which is a special case).
  // If we have background voxels, the number of ouputs is one less than
  // then number of available labels.
  //
  unsigned int numberOfOutputs = 0;
  if ( m_AvailableLabels.find( m_BackgroundLabel ) == m_AvailableLabels.end() )
    numberOfOutputs = m_AvailableLabels.size();
  else
    numberOfOutputs = m_AvailableLabels.size() - 1;
  if ( numberOfOutputs == 0 )
  {
    itkWarningMacro("Number of outputs == 0");
  }

  //
  // determine the number of timesteps of the input image
  //
  mitk::Image* image =  ( mitk::Image* )GetInput();
  unsigned int numberOfTimeSteps = image->GetTimeSlicedGeometry()->GetTimeSteps();

  //
  // set the number of outputs to the number of labels used.
  // initialize the output surfaces accordingly (incl. timesteps)
  //
  this->SetNumberOfOutputs( numberOfOutputs );
  this->SetNumberOfRequiredOutputs( numberOfOutputs );
  for ( unsigned int i = 0 ; i < numberOfOutputs; ++i )
  {
    if ( ! this->GetOutput( i ) )
    {
      mitk::Surface::Pointer output = static_cast<mitk::Surface*>( this->MakeOutput(0).GetPointer() );
      assert ( output.IsNotNull() );
      output->Resize( numberOfTimeSteps );
      this->SetNthOutput( i, output.GetPointer() );
    }
  }
}

void mitk::LabeledImageToSurfaceFilter::GenerateData()
{
  mitk::Image* image =  ( mitk::Image* )GetInput();
  if ( image == NULL )
  {
    itkWarningMacro("Image is NULL");
    return;
  }

  mitk::Image::RegionType outputRegion = image->GetRequestedRegion();

  m_IdxToLabels.clear();

  if ( this->GetNumberOfOutputs() == 0 )
    return;

  //
  // traverse the known labels and create surfaces for them.
  //
  unsigned int currentOutputIndex = 0;
  for ( LabelMapType::iterator it = m_AvailableLabels.begin() ; it != m_AvailableLabels.end() ; ++it )
  {
    if ( it->first == m_BackgroundLabel )
      continue;
    if ( ( it->second == 0 ) && m_GenerateAllLabels )
      continue;

    assert ( currentOutputIndex < this->GetNumberOfOutputs() );
    mitk::Surface::Pointer surface = this->GetOutput( currentOutputIndex );
    assert( surface.IsNotNull() );

    int tstart=outputRegion.GetIndex(3);
    int tmax=tstart+outputRegion.GetSize(3); //GetSize()==1 - will aber 0 haben, wenn nicht zeitaufgeloet
    int t;
    for( t=tstart; t < tmax; ++t)
    {
      vtkImageData *vtkimagedata =  image->GetVtkImageData( t );
      CreateSurface( t,vtkimagedata,surface.GetPointer(), it->first );
    }
    m_IdxToLabels[ currentOutputIndex ] = it->first;
    currentOutputIndex++;
  }
}

void mitk::LabeledImageToSurfaceFilter::CreateSurface( int time, vtkImageData *vtkimage, mitk::Surface * surface, mitk::LabeledImageToSurfaceFilter::LabelType label )
{
  vtkImageChangeInformation *indexCoordinatesImageFilter = vtkImageChangeInformation::New();
  indexCoordinatesImageFilter->SetInput(vtkimage);
  indexCoordinatesImageFilter->SetOutputOrigin(0.0,0.0,0.0);

    vtkImageThreshold* threshold = vtkImageThreshold::New();
    threshold->SetInput( indexCoordinatesImageFilter->GetOutput() );
    //indexCoordinatesImageFilter->Delete();
    threshold->SetInValue( 100 );
    threshold->SetOutValue( 0 );
    threshold->ThresholdBetween( label, label );
    threshold->SetOutputScalarTypeToUnsignedChar();
    threshold->ReleaseDataFlagOn();

    vtkImageGaussianSmooth *gaussian = vtkImageGaussianSmooth::New();
    gaussian->SetInput( threshold->GetOutput() );
    //threshold->Delete();
    gaussian->SetDimensionality( 3  );
    gaussian->SetRadiusFactor( 0.49 );
    gaussian->SetStandardDeviation( 1.5 );
    gaussian->ReleaseDataFlagOn();
    gaussian->UpdateInformation();
    gaussian->Update();

  //MarchingCube -->create Surface
  vtkMarchingCubes *skinExtractor = vtkMarchingCubes::New();
  skinExtractor->ReleaseDataFlagOn();
  skinExtractor->SetInput(gaussian->GetOutput());//RC++
  indexCoordinatesImageFilter->Delete();
  skinExtractor->SetValue(0, 50);

  vtkPolyData *polydata;
  polydata = skinExtractor->GetOutput();
  polydata->Register(NULL);//RC++
  skinExtractor->Delete();

  if (m_Smooth)
  {
    vtkSmoothPolyDataFilter *smoother = vtkSmoothPolyDataFilter::New();
    //read poly1 (poly1 can be the original polygon, or the decimated polygon)
    smoother->SetInput(polydata);//RC++
    smoother->SetNumberOfIterations( m_SmoothIteration );
    smoother->SetRelaxationFactor( m_SmoothRelaxation );
    smoother->SetFeatureAngle( 60 );
    smoother->FeatureEdgeSmoothingOff();
    smoother->BoundarySmoothingOff();
    smoother->SetConvergence( 0 );

    polydata->Delete();//RC--
    polydata = smoother->GetOutput();
    polydata->Register(NULL);//RC++
    smoother->Delete();
  }

#if (VTK_MAJOR_VERSION >= 5)
  if (m_Decimate == Decimate )
  {
    std::cerr << "vtkDecimate not available for VTK 5.0 and above.";
    std::cerr << " Using vtkDecimatePro instead." << std::endl;
    m_Decimate = DecimatePro;
  }
#endif

  //decimate = to reduce number of polygons
  if(m_Decimate==DecimatePro)
  {
    vtkDecimatePro *decimate = vtkDecimatePro::New();
    decimate->SplittingOff();
    decimate->SetErrorIsAbsolute(5);
    decimate->SetFeatureAngle(30);
    decimate->PreserveTopologyOn();
    decimate->BoundaryVertexDeletionOff();
    decimate->SetDegree(10); //std-value is 25!

    decimate->SetInput(polydata);//RC++
    decimate->SetTargetReduction(m_TargetReduction);
    decimate->SetMaximumError(0.002);

    polydata->Delete();//RC--
    polydata = decimate->GetOutput();
    polydata->Register(NULL);//RC++
    decimate->Delete();
  }
#if (VTK_MAJOR_VERSION < 5)
  else if (m_Decimate==Decimate)
  {
    vtkDecimate *decimate = vtkDecimate::New();
    decimate->SetInput( polydata );
    decimate->PreserveTopologyOn();
    decimate->BoundaryVertexDeletionOff();
    decimate->SetTargetReduction( m_TargetReduction );
    polydata->Delete();//RC--
    polydata = decimate->GetOutput();
    polydata->Register(NULL);//RC++
    decimate->Delete();
  }
#endif

  polydata->Update();

  polydata->SetSource(NULL);

  if(polydata->GetNumberOfPoints() > 0)
  {
    mitk::Vector3D spacing = GetInput()->GetGeometry(time)->GetSpacing();

    vtkPoints * points = polydata->GetPoints();
    vtkMatrix4x4 *vtkmatrix = vtkMatrix4x4::New();
    GetInput()->GetGeometry(time)->GetVtkTransform()->GetMatrix(vtkmatrix);
    double (*matrix)[4] = vtkmatrix->Element;

    unsigned int i,j;
    for(i=0;i<3;++i)
      for(j=0;j<3;++j)
        matrix[i][j]/=spacing[j];

    unsigned int n = points->GetNumberOfPoints();
    vtkFloatingPointType point[3];

    for (i = 0; i < n; i++)
    {
      points->GetPoint(i, point);
      mitkVtkLinearTransformPoint(matrix,point,point);
      points->SetPoint(i, point);
    }
    vtkmatrix->Delete();
  }

  surface->SetVtkPolyData(polydata, time);
  polydata->UnRegister(NULL);

  gaussian->Delete();
  threshold->Delete();
}

template < typename TPixel, unsigned int VImageDimension >
    void GetAvailableLabelsInternal( itk::Image<TPixel, VImageDimension>* image, mitk::LabeledImageToSurfaceFilter::LabelMapType& availableLabels )
{
  typedef itk::Image<TPixel, VImageDimension> ImageType;
  typedef itk::ImageRegionIterator< ImageType > ImageRegionIteratorType;
  availableLabels.clear();
  ImageRegionIteratorType it( image, image->GetRequestedRegion() );
  it.GoToBegin();
  mitk::LabeledImageToSurfaceFilter::LabelMapType::iterator labelIt;
  while( ! it.IsAtEnd() )
  {
    labelIt = availableLabels.find( ( mitk::LabeledImageToSurfaceFilter::LabelType ) ( it.Get() ) );
    if ( labelIt == availableLabels.end() )
      availableLabels[ ( mitk::LabeledImageToSurfaceFilter::LabelType ) ( it.Get() ) ] = 1;
    else
      ( labelIt->second )++;
    ++it;
  }
}

InstantiateAccessFunctionForFixedDimension_1(GetAvailableLabelsInternal, 3, mitk::LabeledImageToSurfaceFilter::LabelMapType&);

mitk::LabeledImageToSurfaceFilter::LabelMapType mitk::LabeledImageToSurfaceFilter::GetAvailableLabels()
{
  mitk::Image::Pointer image =  ( mitk::Image* )GetInput();
  LabelMapType availableLabels;
  AccessFixedDimensionByItk_1( image, GetAvailableLabelsInternal, 3, availableLabels );
  return availableLabels;
}

void mitk::LabeledImageToSurfaceFilter::CreateSurface(int, vtkImageData*, mitk::Surface*, const ScalarType)
{
  itkWarningMacro( "This function should never be called!" );
  assert(false);
}

mitk::LabeledImageToSurfaceFilter::LabelType mitk::LabeledImageToSurfaceFilter::GetLabelForNthOutput( const unsigned int& idx )
{
  IdxToLabelMapType::iterator it = m_IdxToLabels.find( idx );
  if ( it != m_IdxToLabels.end() )
  {
    return it->second;
  }
  else
  {
    itkWarningMacro( "Unknown index encountered: " << idx << ". There are " << this->GetNumberOfOutputs() << " outputs available." );
    return itk::NumericTraits<LabelType>::max();
  }
}

mitk::ScalarType mitk::LabeledImageToSurfaceFilter::GetVolumeForNthOutput( const unsigned int& i )
{
  return GetVolumeForLabel( GetLabelForNthOutput( i ) );
}

mitk::ScalarType mitk::LabeledImageToSurfaceFilter::GetVolumeForLabel( const mitk::LabeledImageToSurfaceFilter::LabelType& label )
{
  // get the image spacing
  mitk::Image* image =  ( mitk::Image* )GetInput();
  const float* spacing = image->GetSlicedGeometry()->GetFloatSpacing();

  // get the number of voxels encountered for the given label,
  // calculate the volume and return it.
  LabelMapType::iterator it = m_AvailableLabels.find( label );
  if ( it != m_AvailableLabels.end() )
  {
    return it->second * ( spacing[0] * spacing[1] * spacing[2] / 1000.0 );
  }
  else
  {
    itkWarningMacro( "Unknown label encountered: " << label );
    return 0.0;
  }
}

<commit_msg>FIX: now the user supplied value for gaussian standard deviation is used.<commit_after>#include <mitkLabeledImageToSurfaceFilter.h>

#include <vtkImageChangeInformation.h>
#include <vtkImageThreshold.h>
#include <vtkImageGaussianSmooth.h>
#include <vtkImageMarchingCubes.h>
#include <vtkPolyData.h>
#include <vtkSmoothPolyDataFilter.h>
#include <vtkDecimatePro.h>
#if (VTK_MAJOR_VERSION < 5)
#include <vtkDecimate.h>
#endif
#include <vtkLinearTransform.h>
#include <vtkMatrix4x4.h>

#include <mitkImageAccessByItk.h>
#include <itkImageRegionIterator.h>
#include <itkNumericTraits.h>

mitk::LabeledImageToSurfaceFilter::LabeledImageToSurfaceFilter()
{
  m_GaussianStandardDeviation = 1.5;
  m_GenerateAllLabels = true;
  m_Label = 1;
  m_BackgroundLabel = 0;
}

mitk::LabeledImageToSurfaceFilter::~LabeledImageToSurfaceFilter()
{
}

void mitk::LabeledImageToSurfaceFilter::GenerateOutputInformation()
{
  Superclass::GenerateOutputInformation();
  //
  // check which labels are available in the image
  //
  m_AvailableLabels = this->GetAvailableLabels();
  m_IdxToLabels.clear();

  //
  // if we don't want to generate surfaces for all labels
  // we have to remove all labales except m_Label and m_BackgroundLabel
  // from the list of available labels
  //
  if ( ! m_GenerateAllLabels )
  {
    LabelMapType tmp;
    LabelMapType::iterator it;
    it = m_AvailableLabels.find( m_Label );
    if ( it != m_AvailableLabels.end() )
      tmp[m_Label] = it->second;
    else
      tmp[m_Label] = 0;

    it = m_AvailableLabels.find( m_BackgroundLabel );
    if ( it != m_AvailableLabels.end() )
      tmp[m_BackgroundLabel] = it->second;
    else
      tmp[m_BackgroundLabel] = 0;

    m_AvailableLabels = tmp;
  }

  //
  // check for the number of labels: if the whole image is filled, no
  // background is available and thus the numberOfOutpus is equal to the
  // number of available labels in the image (which is a special case).
  // If we have background voxels, the number of ouputs is one less than
  // then number of available labels.
  //
  unsigned int numberOfOutputs = 0;
  if ( m_AvailableLabels.find( m_BackgroundLabel ) == m_AvailableLabels.end() )
    numberOfOutputs = m_AvailableLabels.size();
  else
    numberOfOutputs = m_AvailableLabels.size() - 1;
  if ( numberOfOutputs == 0 )
  {
    itkWarningMacro("Number of outputs == 0");
  }

  //
  // determine the number of timesteps of the input image
  //
  mitk::Image* image =  ( mitk::Image* )GetInput();
  unsigned int numberOfTimeSteps = image->GetTimeSlicedGeometry()->GetTimeSteps();

  //
  // set the number of outputs to the number of labels used.
  // initialize the output surfaces accordingly (incl. timesteps)
  //
  this->SetNumberOfOutputs( numberOfOutputs );
  this->SetNumberOfRequiredOutputs( numberOfOutputs );
  for ( unsigned int i = 0 ; i < numberOfOutputs; ++i )
  {
    if ( ! this->GetOutput( i ) )
    {
      mitk::Surface::Pointer output = static_cast<mitk::Surface*>( this->MakeOutput(0).GetPointer() );
      assert ( output.IsNotNull() );
      output->Resize( numberOfTimeSteps );
      this->SetNthOutput( i, output.GetPointer() );
    }
  }
}

void mitk::LabeledImageToSurfaceFilter::GenerateData()
{
  mitk::Image* image =  ( mitk::Image* )GetInput();
  if ( image == NULL )
  {
    itkWarningMacro("Image is NULL");
    return;
  }

  mitk::Image::RegionType outputRegion = image->GetRequestedRegion();

  m_IdxToLabels.clear();

  if ( this->GetNumberOfOutputs() == 0 )
    return;

  //
  // traverse the known labels and create surfaces for them.
  //
  unsigned int currentOutputIndex = 0;
  for ( LabelMapType::iterator it = m_AvailableLabels.begin() ; it != m_AvailableLabels.end() ; ++it )
  {
    if ( it->first == m_BackgroundLabel )
      continue;
    if ( ( it->second == 0 ) && m_GenerateAllLabels )
      continue;

    assert ( currentOutputIndex < this->GetNumberOfOutputs() );
    mitk::Surface::Pointer surface = this->GetOutput( currentOutputIndex );
    assert( surface.IsNotNull() );

    int tstart=outputRegion.GetIndex(3);
    int tmax=tstart+outputRegion.GetSize(3); //GetSize()==1 - will aber 0 haben, wenn nicht zeitaufgeloet
    int t;
    for( t=tstart; t < tmax; ++t)
    {
      vtkImageData *vtkimagedata =  image->GetVtkImageData( t );
      CreateSurface( t,vtkimagedata,surface.GetPointer(), it->first );
    }
    m_IdxToLabels[ currentOutputIndex ] = it->first;
    currentOutputIndex++;
  }
}

void mitk::LabeledImageToSurfaceFilter::CreateSurface( int time, vtkImageData *vtkimage, mitk::Surface * surface, mitk::LabeledImageToSurfaceFilter::LabelType label )
{
  vtkImageChangeInformation *indexCoordinatesImageFilter = vtkImageChangeInformation::New();
  indexCoordinatesImageFilter->SetInput(vtkimage);
  indexCoordinatesImageFilter->SetOutputOrigin(0.0,0.0,0.0);

    vtkImageThreshold* threshold = vtkImageThreshold::New();
    threshold->SetInput( indexCoordinatesImageFilter->GetOutput() );
    //indexCoordinatesImageFilter->Delete();
    threshold->SetInValue( 100 );
    threshold->SetOutValue( 0 );
    threshold->ThresholdBetween( label, label );
    threshold->SetOutputScalarTypeToUnsignedChar();
    threshold->ReleaseDataFlagOn();

    vtkImageGaussianSmooth *gaussian = vtkImageGaussianSmooth::New();
    gaussian->SetInput( threshold->GetOutput() );
    //threshold->Delete();
    gaussian->SetDimensionality( 3  );
    gaussian->SetRadiusFactor( 0.49 );
    gaussian->SetStandardDeviation( GetGaussianStandardDeviation() );
    gaussian->ReleaseDataFlagOn();
    gaussian->UpdateInformation();
    gaussian->Update();

  //MarchingCube -->create Surface
  vtkMarchingCubes *skinExtractor = vtkMarchingCubes::New();
  skinExtractor->ReleaseDataFlagOn();
  skinExtractor->SetInput(gaussian->GetOutput());//RC++
  indexCoordinatesImageFilter->Delete();
  skinExtractor->SetValue(0, 50);

  vtkPolyData *polydata;
  polydata = skinExtractor->GetOutput();
  polydata->Register(NULL);//RC++
  skinExtractor->Delete();

  if (m_Smooth)
  {
    vtkSmoothPolyDataFilter *smoother = vtkSmoothPolyDataFilter::New();
    //read poly1 (poly1 can be the original polygon, or the decimated polygon)
    smoother->SetInput(polydata);//RC++
    smoother->SetNumberOfIterations( m_SmoothIteration );
    smoother->SetRelaxationFactor( m_SmoothRelaxation );
    smoother->SetFeatureAngle( 60 );
    smoother->FeatureEdgeSmoothingOff();
    smoother->BoundarySmoothingOff();
    smoother->SetConvergence( 0 );

    polydata->Delete();//RC--
    polydata = smoother->GetOutput();
    polydata->Register(NULL);//RC++
    smoother->Delete();
  }

#if (VTK_MAJOR_VERSION >= 5)
  if (m_Decimate == Decimate )
  {
    std::cerr << "vtkDecimate not available for VTK 5.0 and above.";
    std::cerr << " Using vtkDecimatePro instead." << std::endl;
    m_Decimate = DecimatePro;
  }
#endif

  //decimate = to reduce number of polygons
  if(m_Decimate==DecimatePro)
  {
    vtkDecimatePro *decimate = vtkDecimatePro::New();
    decimate->SplittingOff();
    decimate->SetErrorIsAbsolute(5);
    decimate->SetFeatureAngle(30);
    decimate->PreserveTopologyOn();
    decimate->BoundaryVertexDeletionOff();
    decimate->SetDegree(10); //std-value is 25!

    decimate->SetInput(polydata);//RC++
    decimate->SetTargetReduction(m_TargetReduction);
    decimate->SetMaximumError(0.002);

    polydata->Delete();//RC--
    polydata = decimate->GetOutput();
    polydata->Register(NULL);//RC++
    decimate->Delete();
  }
#if (VTK_MAJOR_VERSION < 5)
  else if (m_Decimate==Decimate)
  {
    vtkDecimate *decimate = vtkDecimate::New();
    decimate->SetInput( polydata );
    decimate->PreserveTopologyOn();
    decimate->BoundaryVertexDeletionOff();
    decimate->SetTargetReduction( m_TargetReduction );
    polydata->Delete();//RC--
    polydata = decimate->GetOutput();
    polydata->Register(NULL);//RC++
    decimate->Delete();
  }
#endif

  polydata->Update();

  polydata->SetSource(NULL);

  if(polydata->GetNumberOfPoints() > 0)
  {
    mitk::Vector3D spacing = GetInput()->GetGeometry(time)->GetSpacing();

    vtkPoints * points = polydata->GetPoints();
    vtkMatrix4x4 *vtkmatrix = vtkMatrix4x4::New();
    GetInput()->GetGeometry(time)->GetVtkTransform()->GetMatrix(vtkmatrix);
    double (*matrix)[4] = vtkmatrix->Element;

    unsigned int i,j;
    for(i=0;i<3;++i)
      for(j=0;j<3;++j)
        matrix[i][j]/=spacing[j];

    unsigned int n = points->GetNumberOfPoints();
    vtkFloatingPointType point[3];

    for (i = 0; i < n; i++)
    {
      points->GetPoint(i, point);
      mitkVtkLinearTransformPoint(matrix,point,point);
      points->SetPoint(i, point);
    }
    vtkmatrix->Delete();
  }

  surface->SetVtkPolyData(polydata, time);
  polydata->UnRegister(NULL);

  gaussian->Delete();
  threshold->Delete();
}

template < typename TPixel, unsigned int VImageDimension >
    void GetAvailableLabelsInternal( itk::Image<TPixel, VImageDimension>* image, mitk::LabeledImageToSurfaceFilter::LabelMapType& availableLabels )
{
  typedef itk::Image<TPixel, VImageDimension> ImageType;
  typedef itk::ImageRegionIterator< ImageType > ImageRegionIteratorType;
  availableLabels.clear();
  ImageRegionIteratorType it( image, image->GetRequestedRegion() );
  it.GoToBegin();
  mitk::LabeledImageToSurfaceFilter::LabelMapType::iterator labelIt;
  while( ! it.IsAtEnd() )
  {
    labelIt = availableLabels.find( ( mitk::LabeledImageToSurfaceFilter::LabelType ) ( it.Get() ) );
    if ( labelIt == availableLabels.end() )
      availableLabels[ ( mitk::LabeledImageToSurfaceFilter::LabelType ) ( it.Get() ) ] = 1;
    else
      ( labelIt->second )++;
    ++it;
  }
}

InstantiateAccessFunctionForFixedDimension_1(GetAvailableLabelsInternal, 3, mitk::LabeledImageToSurfaceFilter::LabelMapType&);

mitk::LabeledImageToSurfaceFilter::LabelMapType mitk::LabeledImageToSurfaceFilter::GetAvailableLabels()
{
  mitk::Image::Pointer image =  ( mitk::Image* )GetInput();
  LabelMapType availableLabels;
  AccessFixedDimensionByItk_1( image, GetAvailableLabelsInternal, 3, availableLabels );
  return availableLabels;
}

void mitk::LabeledImageToSurfaceFilter::CreateSurface(int, vtkImageData*, mitk::Surface*, const ScalarType)
{
  itkWarningMacro( "This function should never be called!" );
  assert(false);
}

mitk::LabeledImageToSurfaceFilter::LabelType mitk::LabeledImageToSurfaceFilter::GetLabelForNthOutput( const unsigned int& idx )
{
  IdxToLabelMapType::iterator it = m_IdxToLabels.find( idx );
  if ( it != m_IdxToLabels.end() )
  {
    return it->second;
  }
  else
  {
    itkWarningMacro( "Unknown index encountered: " << idx << ". There are " << this->GetNumberOfOutputs() << " outputs available." );
    return itk::NumericTraits<LabelType>::max();
  }
}

mitk::ScalarType mitk::LabeledImageToSurfaceFilter::GetVolumeForNthOutput( const unsigned int& i )
{
  return GetVolumeForLabel( GetLabelForNthOutput( i ) );
}

mitk::ScalarType mitk::LabeledImageToSurfaceFilter::GetVolumeForLabel( const mitk::LabeledImageToSurfaceFilter::LabelType& label )
{
  // get the image spacing
  mitk::Image* image =  ( mitk::Image* )GetInput();
  const float* spacing = image->GetSlicedGeometry()->GetFloatSpacing();

  // get the number of voxels encountered for the given label,
  // calculate the volume and return it.
  LabelMapType::iterator it = m_AvailableLabels.find( label );
  if ( it != m_AvailableLabels.end() )
  {
    return it->second * ( spacing[0] * spacing[1] * spacing[2] / 1000.0 );
  }
  else
  {
    itkWarningMacro( "Unknown label encountered: " << label );
    return 0.0;
  }
}

<|endoftext|>


<commit_before>#include "util/log.h"
#include <stdio.h>
#include <stdarg.h>

void openxc::util::log::debugUart(const char* message) {
    printf(message);
}

void openxc::util::log::initialize() { }
<commit_msg>Use a format string for debug logging.<commit_after>#include "util/log.h"
#include <stdio.h>
#include <stdarg.h>

void openxc::util::log::debugUart(const char* message) {
    printf("%s", message);
}

void openxc::util::log::initialize() { }
<|endoftext|>


<commit_before>#include <memory>
#include <mutex>
#include <fstream>
#include <chrono>

#include "test_manager.h"
#include "FileManager.h"
#include "p2pnode.h"

using namespace std;

pair<bool, string> filesEqual(const std::string & left, const std::string & right) {
	ifstream l(left, ios::in | ios::binary);
	if (!l) {
		return pair<bool, string>{false, "Failed to open " + left};
	}
	ifstream r(right, ios::in | ios::binary);

	if (!r) {
		return pair<bool, string>{false, "Failed to open " + right};
	}

	l.seekg(ios::end, 0);
	r.seekg(ios::end, 0);

	if (l.tellg() != r.tellg()) {
		return pair<bool, string>{false, "File sizes differ " + to_string(l.tellg()) + " " + to_string(r.tellg())};
	}

	const int sz = 8192;
	unique_ptr<char> buffer[2] = {
		unique_ptr<char>(new char[sz]),
		unique_ptr<char>(new char[sz])
	};

	while (true) {
		// both files should have equal states after read
		if (!!l.read(buffer[0].get(), sz) != !!r.read(buffer[1].get(), sz)) {
			return pair<bool, string>{false, "Error states differ in file read"};
		}

		if (r.gcount() != l.gcount()) {
			return pair<bool, string>{false, "Failed to read same sizes from both files"};
		}

		if (!memcmp(buffer[0].get(), buffer[1].get(), r.gcount())) {
			return pair<bool, string>{false, "Data missmatch in files!"};
		}
	}

	return pair<bool, string>{true, ""};
}

shared_ptr<App> createApp(int fileMgrPort, int p2pPort, int msPort, string savePath) {
	auto fileMgr = unique_ptr<FileManagerInterface>(new FileManager(fileMgrPort, savePath));
	auto node = unique_ptr<P2PNetworkInterface>(new P2PNode(msPort, p2pPort, fileMgrPort));
	App::Settings st;
	return shared_ptr<App>(new App(st, move(fileMgr), move(node)));
}

int InstanceManager::startPort = InstanceManager::msPort + 1;
int InstanceManager::startSavePath = 1;

shared_ptr<App> InstanceManager::nextNonColidingApp() {
	unique_lock<mutex> l(this->mx);
	auto app = createApp(++startPort, ++startPort, msPort, to_string(++startSavePath) + ".dat");
	this->apps.push_back(app);
	return app;
}

void InstanceManager::startMs() {
	if (!ms) {
		ms = unique_ptr<P2PMainServer>(new P2PMainServer());
	}
	this->worker = thread(&P2PMainServer::start, &*ms, msPort);
	this_thread::sleep_for(chrono::milliseconds(500));
}

void InstanceManager::stopMs() {
	ms->stop();
	this->worker.join();
	this->worker = thread();
}

void InstanceManager::clear() {
	this->apps.clear();
}

InstanceManager & InstanceManager::getInstance() {
	static InstanceManager imgr;
	return imgr;
}
<commit_msg>Fix bug in fire compare<commit_after>#include <memory>
#include <mutex>
#include <fstream>
#include <chrono>

#include "test_manager.h"
#include "FileManager.h"
#include "p2pnode.h"

using namespace std;

pair<bool, string> filesEqual(const std::string & left, const std::string & right) {
	ifstream l(left, ios::in | ios::binary);
	if (!l) {
		return pair<bool, string>{false, "Failed to open " + left};
	}
	ifstream r(right, ios::in | ios::binary);

	if (!r) {
		return pair<bool, string>{false, "Failed to open " + right};
	}

	l.seekg(ios::end, 0);
	r.seekg(ios::end, 0);

	if (l.tellg() != r.tellg()) {
		return pair<bool, string>{false, "File sizes differ " + to_string(l.tellg()) + " " + to_string(r.tellg())};
	}

	const int sz = 8192;
	unique_ptr<char> buffer[2] = {
		unique_ptr<char>(new char[sz]),
		unique_ptr<char>(new char[sz])
	};

	while (true) {
		// both files should have equal states after read
		if (!!l.read(buffer[0].get(), sz) != !!r.read(buffer[1].get(), sz)) {
			return pair<bool, string>{false, "Error states differ in file read"};
		}

		if (r.gcount() != l.gcount()) {
			return pair<bool, string>{false, "Failed to read same sizes from both files"};
		}

		if (memcmp(buffer[0].get(), buffer[1].get(), r.gcount()) != 0) {
			return pair<bool, string>{false, "Data missmatch in files!"};
		}
	}

	return pair<bool, string>{true, ""};
}

shared_ptr<App> createApp(int fileMgrPort, int p2pPort, int msPort, string savePath) {
	auto fileMgr = unique_ptr<FileManagerInterface>(new FileManager(fileMgrPort, savePath));
	auto node = unique_ptr<P2PNetworkInterface>(new P2PNode(msPort, p2pPort, fileMgrPort));
	App::Settings st;
	return shared_ptr<App>(new App(st, move(fileMgr), move(node)));
}

int InstanceManager::startPort = InstanceManager::msPort + 1;
int InstanceManager::startSavePath = 1;

shared_ptr<App> InstanceManager::nextNonColidingApp() {
	unique_lock<mutex> l(this->mx);
	auto app = createApp(++startPort, ++startPort, msPort, to_string(++startSavePath) + ".dat");
	this->apps.push_back(app);
	return app;
}

void InstanceManager::startMs() {
	if (!ms) {
		ms = unique_ptr<P2PMainServer>(new P2PMainServer());
	}
	this->worker = thread(&P2PMainServer::start, &*ms, msPort);
	this_thread::sleep_for(chrono::milliseconds(500));
}

void InstanceManager::stopMs() {
	ms->stop();
	this->worker.join();
	this->worker = thread();
}

void InstanceManager::clear() {
	this->apps.clear();
}

InstanceManager & InstanceManager::getInstance() {
	static InstanceManager imgr;
	return imgr;
}
<|endoftext|>


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

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

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

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

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

// Software Guide : BeginLatex
//
// The \doxygen{ImageLinearIteratorWithIndex} is designed for line-by-line
// processing of an image.  It walks a linear path along a selected image
// direction parallel to one of the coordinate axes of the image. This
// iterator conceptually breaks an image into a set of parallel lines
// that span the selected image dimension.
//
// \index{Iterators!and image lines}
//
// Like all image iterators, movement of the
// ImageLinearIteratorWithIndex is constrained within an
// image region $R$.  The line $\ell$ through which the iterator moves is
// defined by selecting a direction and an origin.   The line $\ell$
// extends from the origin to the upper boundary of $R$. The origin can be
// moved to any position along the lower boundary of $R$.
//
// Several additional methods are defined for this iterator to control movement
// of the iterator along the line $\ell$ and movement of the origin of $\ell$.
//
// %Might need a figure here to describe this iterator.
//
// \begin{itemize}
//
// \index{itk::ImageLinearIteratorWithIndex!NextLine()}
//
// \item \textbf{\code{NextLine()}} Moves the iterator to the beginning pixel
// location of the next line in the image.  The origin of the next line is
// determined by incrementing the current origin along the fastest increasing
// dimension of the subspace of the image that excludes the selected dimension.
//
//
// \index{itk::ImageLinearIteratorWithIndex!PreviousLine()}
//
// \item \textbf{\code{PreviousLine()}} Moves the iterator to the \emph{last valid
// pixel location} in the previous line. The origin of the previous line is
// determined by decrementing the current origin along the fastest increasing
// dimension of the subspace of the image that excludes the selected dimension.
//
// \index{itk::ImageLinearIteratorWithIndex!GoToBeginOfLine()}
//
// \item \textbf{\code{GoToBeginOfLine()}} Moves the iterator to the beginning
// pixel of the current line.
//
// \index{itk::ImageLinearIteratorWithIndex!GoToEndOfLine()}
//
// \item \textbf{\code{GoToEndOfLine()}}  Move the iterator to
// \emph{one past} the last valid pixel of the current line.
//
// \index{itk::ImageLinearIteratorWithIndex!GoToReverseBeginOfLine()}
//
// \item \textbf{\code{GoToReverseBeginOfLine()}}  Move the iterator
// to \emph{the last valid pixel} of the current line.
//
// \index{itk::ImageLinearIteratorWithIndex!IsAtReverseEndOfLine()}
//
// \item \textbf{\code{IsAtReverseEndOfLine()}}
// Returns true if the iterator points
// to \emph{one position before} the beginning pixel of the current line.
//
// \index{itk::ImageLinearIteratorWithIndex!IsAtEndOfLine()}
//
// \item \textbf{\code{IsAtEndOfLine()}}
// Returns true if the iterator points to
// \emph{one position past} the last valid pixel of the current line.
// \end{itemize}
//
// The following code example shows how to use the
// ImageLinearIteratorWithIndex.  It implements the same algorithm as
// in the previous example, flipping an image across its $x$-axis.  Two line
// iterators are iterated in opposite directions across the $x$-axis.
// After each line is traversed, the iterator origins are stepped along
// the $y$-axis to the
// next line.
//
// \index{itk::ImageLinearIteratorWithIndex!example of using|(}
//
// Headers for both the const and non-const versions are needed.
//
// Software Guide : EndLatex

#include "itkImage.h"
#include "itkRGBPixel.h"
// Software Guide : BeginCodeSnippet
#include "itkImageLinearConstIteratorWithIndex.h"
#include "itkImageLinearIteratorWithIndex.h"
// Software Guide : EndCodeSnippet
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

int main( int argc, char *argv[] )
{
  // Verify the number of parameters on the command line.
  if ( argc < 3 )
    {
    std::cerr << "Missing parameters. " << std::endl;
    std::cerr << "Usage: " << std::endl;
    std::cerr << argv[0]
              << " inputImageFile outputImageFile"
              << std::endl;
    return -1;
    }

// Software Guide : BeginLatex
//
// The RGB image and pixel types are defined as in the previous example.  The
// ImageLinearIteratorWithIndex class and its const version each have
// single template parameters, the image type.
//
// Software Guide : EndLatex

  const unsigned int Dimension = 2;

  typedef itk::RGBPixel< unsigned char > RGBPixelType;
  typedef itk::Image< RGBPixelType, Dimension >  ImageType;

// Software Guide : BeginCodeSnippet
  typedef itk::ImageLinearIteratorWithIndex< ImageType >       IteratorType;
  typedef itk::ImageLinearConstIteratorWithIndex< ImageType >  ConstIteratorType;
// Software Guide : EndCodeSnippet

  typedef itk::ImageFileReader< ImageType > ReaderType;
  typedef itk::ImageFileWriter< ImageType > WriterType;

  ImageType::ConstPointer inputImage;
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName( argv[1] );
  try
    {
    reader->Update();
    inputImage = reader->GetOutput();
    }
  catch ( itk::ExceptionObject &err)
    {
    std::cout << "ExceptionObject caught a !" << std::endl;
    std::cout << err << std::endl;
    return -1;
    }

// Software Guide : BeginLatex
//
// After reading the input image, we allocate an output image that of the same
// size, spacing, and origin.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
  ImageType::Pointer outputImage = ImageType::New();
  outputImage->SetRegions( inputImage->GetRequestedRegion() );
  outputImage->CopyInformation( inputImage );
  outputImage->Allocate();
// Software Guide : EndCodeSnippet

// Software Guide : BeginLatex
//
// Next we create the two iterators.  The const iterator walks the input image,
// and the non-const iterator walks the output image.  The iterators are
// initialized over the same region.  The direction of iteration is set to 0,
// the $x$ dimension.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
  ConstIteratorType inputIt( inputImage, inputImage->GetRequestedRegion() );
  IteratorType outputIt( outputImage, inputImage->GetRequestedRegion() );

  inputIt.SetDirection(0);
  outputIt.SetDirection(0);
// Software Guide : EndCodeSnippet

// Software Guide: BeginLatex
//
// Each line in the input is copied to the output.  The input iterator moves
// forward across columns while the output iterator moves backwards.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
  for ( inputIt.GoToBegin(),  outputIt.GoToBegin(); ! inputIt.IsAtEnd();
        outputIt.NextLine(),  inputIt.NextLine())
    {
    inputIt.GoToBeginOfLine();
    outputIt.GoToEndOfLine();
    --outputIt;
    while ( ! inputIt.IsAtEndOfLine() )
      {
      outputIt.Set( inputIt.Get() );
      ++inputIt;
      --outputIt;
      }
    }
// Software Guide : EndCodeSnippet

  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName( argv[2] );
  writer->SetInput(outputImage);
  try
    {
    writer->Update();
    }
  catch ( itk::ExceptionObject &err)
    {
    std::cout << "ExceptionObject caught !" << std::endl;
    std::cout << err << std::endl;
    return -1;
    }

// Software Guide : BeginLatex
//
// Running this example on \code{VisibleWomanEyeSlice.png} produces
// the same output image shown in
// Figure~\ref{fig:ImageRegionIteratorWithIndexExample}.
//
// \index{itk::ImageLinearIteratorWithIndex!example of using|)}
// Software Guide : EndLatex

  return 0;
}
<commit_msg>BUG: crasinh on 64 bit vista system. Try rearranging output iterator --.<commit_after>/*=========================================================================

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

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

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

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

// Software Guide : BeginLatex
//
// The \doxygen{ImageLinearIteratorWithIndex} is designed for line-by-line
// processing of an image.  It walks a linear path along a selected image
// direction parallel to one of the coordinate axes of the image. This
// iterator conceptually breaks an image into a set of parallel lines
// that span the selected image dimension.
//
// \index{Iterators!and image lines}
//
// Like all image iterators, movement of the
// ImageLinearIteratorWithIndex is constrained within an
// image region $R$.  The line $\ell$ through which the iterator moves is
// defined by selecting a direction and an origin.   The line $\ell$
// extends from the origin to the upper boundary of $R$. The origin can be
// moved to any position along the lower boundary of $R$.
//
// Several additional methods are defined for this iterator to control movement
// of the iterator along the line $\ell$ and movement of the origin of $\ell$.
//
// %Might need a figure here to describe this iterator.
//
// \begin{itemize}
//
// \index{itk::ImageLinearIteratorWithIndex!NextLine()}
//
// \item \textbf{\code{NextLine()}} Moves the iterator to the beginning pixel
// location of the next line in the image.  The origin of the next line is
// determined by incrementing the current origin along the fastest increasing
// dimension of the subspace of the image that excludes the selected dimension.
//
//
// \index{itk::ImageLinearIteratorWithIndex!PreviousLine()}
//
// \item \textbf{\code{PreviousLine()}} Moves the iterator to the \emph{last valid
// pixel location} in the previous line. The origin of the previous line is
// determined by decrementing the current origin along the fastest increasing
// dimension of the subspace of the image that excludes the selected dimension.
//
// \index{itk::ImageLinearIteratorWithIndex!GoToBeginOfLine()}
//
// \item \textbf{\code{GoToBeginOfLine()}} Moves the iterator to the beginning
// pixel of the current line.
//
// \index{itk::ImageLinearIteratorWithIndex!GoToEndOfLine()}
//
// \item \textbf{\code{GoToEndOfLine()}}  Move the iterator to
// \emph{one past} the last valid pixel of the current line.
//
// \index{itk::ImageLinearIteratorWithIndex!GoToReverseBeginOfLine()}
//
// \item \textbf{\code{GoToReverseBeginOfLine()}}  Move the iterator
// to \emph{the last valid pixel} of the current line.
//
// \index{itk::ImageLinearIteratorWithIndex!IsAtReverseEndOfLine()}
//
// \item \textbf{\code{IsAtReverseEndOfLine()}}
// Returns true if the iterator points
// to \emph{one position before} the beginning pixel of the current line.
//
// \index{itk::ImageLinearIteratorWithIndex!IsAtEndOfLine()}
//
// \item \textbf{\code{IsAtEndOfLine()}}
// Returns true if the iterator points to
// \emph{one position past} the last valid pixel of the current line.
// \end{itemize}
//
// The following code example shows how to use the
// ImageLinearIteratorWithIndex.  It implements the same algorithm as
// in the previous example, flipping an image across its $x$-axis.  Two line
// iterators are iterated in opposite directions across the $x$-axis.
// After each line is traversed, the iterator origins are stepped along
// the $y$-axis to the
// next line.
//
// \index{itk::ImageLinearIteratorWithIndex!example of using|(}
//
// Headers for both the const and non-const versions are needed.
//
// Software Guide : EndLatex

#include "itkImage.h"
#include "itkRGBPixel.h"
// Software Guide : BeginCodeSnippet
#include "itkImageLinearConstIteratorWithIndex.h"
#include "itkImageLinearIteratorWithIndex.h"
// Software Guide : EndCodeSnippet
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

int main( int argc, char *argv[] )
{
  // Verify the number of parameters on the command line.
  if ( argc < 3 )
    {
    std::cerr << "Missing parameters. " << std::endl;
    std::cerr << "Usage: " << std::endl;
    std::cerr << argv[0]
              << " inputImageFile outputImageFile"
              << std::endl;
    return -1;
    }

// Software Guide : BeginLatex
//
// The RGB image and pixel types are defined as in the previous example.  The
// ImageLinearIteratorWithIndex class and its const version each have
// single template parameters, the image type.
//
// Software Guide : EndLatex

  const unsigned int Dimension = 2;

  typedef itk::RGBPixel< unsigned char > RGBPixelType;
  typedef itk::Image< RGBPixelType, Dimension >  ImageType;

// Software Guide : BeginCodeSnippet
  typedef itk::ImageLinearIteratorWithIndex< ImageType >       IteratorType;
  typedef itk::ImageLinearConstIteratorWithIndex< ImageType >  ConstIteratorType;
// Software Guide : EndCodeSnippet

  typedef itk::ImageFileReader< ImageType > ReaderType;
  typedef itk::ImageFileWriter< ImageType > WriterType;

  ImageType::ConstPointer inputImage;
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName( argv[1] );
  try
    {
    reader->Update();
    inputImage = reader->GetOutput();
    }
  catch ( itk::ExceptionObject &err)
    {
    std::cout << "ExceptionObject caught a !" << std::endl;
    std::cout << err << std::endl;
    return -1;
    }

// Software Guide : BeginLatex
//
// After reading the input image, we allocate an output image that of the same
// size, spacing, and origin.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
  ImageType::Pointer outputImage = ImageType::New();
  outputImage->SetRegions( inputImage->GetRequestedRegion() );
  outputImage->CopyInformation( inputImage );
  outputImage->Allocate();
// Software Guide : EndCodeSnippet

// Software Guide : BeginLatex
//
// Next we create the two iterators.  The const iterator walks the input image,
// and the non-const iterator walks the output image.  The iterators are
// initialized over the same region.  The direction of iteration is set to 0,
// the $x$ dimension.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
  ConstIteratorType inputIt( inputImage, inputImage->GetRequestedRegion() );
  IteratorType outputIt( outputImage, inputImage->GetRequestedRegion() );

  inputIt.SetDirection(0);
  outputIt.SetDirection(0);
// Software Guide : EndCodeSnippet

// Software Guide: BeginLatex
//
// Each line in the input is copied to the output.  The input iterator moves
// forward across columns while the output iterator moves backwards.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
  for ( inputIt.GoToBegin(),  outputIt.GoToBegin(); ! inputIt.IsAtEnd();
        outputIt.NextLine(),  inputIt.NextLine())
    {
    inputIt.GoToBeginOfLine();
    outputIt.GoToEndOfLine();
    while ( ! inputIt.IsAtEndOfLine() )
      {
      --outputIt;
      outputIt.Set( inputIt.Get() );
      ++inputIt;
      }
    }
// Software Guide : EndCodeSnippet

  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName( argv[2] );
  writer->SetInput(outputImage);
  try
    {
    writer->Update();
    }
  catch ( itk::ExceptionObject &err)
    {
    std::cout << "ExceptionObject caught !" << std::endl;
    std::cout << err << std::endl;
    return -1;
    }

// Software Guide : BeginLatex
//
// Running this example on \code{VisibleWomanEyeSlice.png} produces
// the same output image shown in
// Figure~\ref{fig:ImageRegionIteratorWithIndexExample}.
//
// \index{itk::ImageLinearIteratorWithIndex!example of using|)}
// Software Guide : EndLatex

  return 0;
}
<|endoftext|>


<commit_before>#ifndef AMGCL_MPI_PASTIX_HPP
#define AMGCL_MPI_PASTIX_HPP

/*
The MIT License

Copyright (c) 2012-2014 Denis Demidov <dennis.demidov@gmail.com>

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

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

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

/**
\file   amgcl/mpi/pastix.hpp
\author Denis Demidov <dennis.demidov@gmail.com>
\brief  Wrapper for PaStiX distributed sparse solver.

See http://pastix.gforge.inria.fr
*/

#include <boost/static_assert.hpp>
#include <boost/type_traits.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/numeric.hpp>
#include <boost/range/irange.hpp>
#include <boost/foreach.hpp>

#include <amgcl/util.hpp>
#include <amgcl/mpi/util.hpp>

extern "C" {
#include <pastix.h>
}

namespace amgcl {
namespace mpi {

template <typename value_type>
class PaStiX {
    public:
        BOOST_STATIC_ASSERT_MSG(
                (boost::is_same<value_type, pastix_float_t>::value),
                "Unsupported value type for PaStiX solver"
                );
        struct params {};

        static int comm_size(int n_global_rows) {
            return std::max(1, n_global_rows / 5000);
        }

        template <class PRng, class CRng, class VRng>
        PaStiX(
                MPI_Comm mpi_comm,
                int n_local_rows,
                const PRng &p_ptr,
                const CRng &p_col,
                const VRng &p_val,
                const params &prm = params()
                )
            : comm(mpi_comm), nrows(n_local_rows), pastix_data(0),
              ptr(boost::begin(p_ptr), boost::end(p_ptr)),
              col(boost::begin(p_col), boost::end(p_col)),
              val(boost::begin(p_val), boost::end(p_val)),
              row(nrows), perm(nrows, 0), invp(nrows, 0)
        {
            std::vector<int> domain(comm.size + 1, 0);
            MPI_Allgather(&nrows, 1, MPI_INT, &domain[1], 1, MPI_INT, comm);
            boost::partial_sum(domain, domain.begin());

            boost::copy(
                    boost::irange(domain[comm.rank], domain[comm.rank + 1]),
                    row.begin()
                    );

            boost::copy(boost::irange(1, nrows + 1), perm.begin());
            boost::copy(boost::irange(1, nrows + 1), invp.begin());

            // PaStiX needs 1-based matrices:
            BOOST_FOREACH(pastix_int_t &p, ptr) ++p;
            BOOST_FOREACH(pastix_int_t &c, col) ++c;
            BOOST_FOREACH(pastix_int_t &r, row) ++r;

            // Initialize parameters with default values:
            iparm[IPARM_MODIFY_PARAMETER] = API_NO;
            call_pastix(API_TASK_INIT, API_TASK_INIT, NULL);

            // Factorize the matrix.
            iparm[IPARM_VERBOSE        ] = API_VERBOSE_NOT;
            iparm[IPARM_RHS_MAKING     ] = API_RHS_B;
            iparm[IPARM_SYM            ] = API_SYM_NO;
            iparm[IPARM_FACTORIZATION  ] = API_FACT_LU;
            iparm[IPARM_TRANSPOSE_SOLVE] = API_YES;
            call_pastix(API_TASK_ORDERING, API_TASK_NUMFACT, NULL);
        }

        ~PaStiX() {
            call_pastix(API_TASK_CLEAN, API_TASK_CLEAN, NULL);
        }

        template <class Vec1, class Vec2>
        void operator()(const Vec1 &rhs, Vec2 &x) const {
            boost::copy(rhs, &x[0]);
            call_pastix(API_TASK_SOLVE, API_TASK_SOLVE, &x[0]);
        }
    private:
        amgcl::mpi::communicator comm;

        int nrows;

        // Pastix internal data.
        mutable pastix_data_t *pastix_data;

        // Pastix parameters
        mutable pastix_int_t   iparm[IPARM_SIZE];
        mutable double         dparm[DPARM_SIZE];

        std::vector<pastix_int_t>   ptr;
        std::vector<pastix_int_t>   col;
        std::vector<pastix_float_t> val;

        // Local to global mapping
        std::vector<pastix_int_t> row;

        // Permutation arrays
        std::vector<pastix_int_t> perm, invp;

        void call_pastix(int beg, int end, pastix_float_t *x) const {
            iparm[IPARM_START_TASK] = beg;
            iparm[IPARM_END_TASK  ] = end;

            dpastix(&pastix_data, comm, nrows,
                    const_cast<pastix_int_t*  >(ptr.data()),
                    const_cast<pastix_int_t*  >(col.data()),
                    const_cast<pastix_float_t*>(val.data()),
                    const_cast<pastix_int_t*  >(row.data()),
                    const_cast<pastix_int_t*  >(perm.data()),
                    const_cast<pastix_int_t*  >(invp.data()),
                    x, 1, iparm, dparm
                   );
        }
};

}
}

#endif
<commit_msg>Fixed PaStiX::comm_size() implementation<commit_after>#ifndef AMGCL_MPI_PASTIX_HPP
#define AMGCL_MPI_PASTIX_HPP

/*
The MIT License

Copyright (c) 2012-2014 Denis Demidov <dennis.demidov@gmail.com>

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

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

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

/**
\file   amgcl/mpi/pastix.hpp
\author Denis Demidov <dennis.demidov@gmail.com>
\brief  Wrapper for PaStiX distributed sparse solver.

See http://pastix.gforge.inria.fr
*/

#include <boost/static_assert.hpp>
#include <boost/type_traits.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/numeric.hpp>
#include <boost/range/irange.hpp>
#include <boost/foreach.hpp>

#include <amgcl/util.hpp>
#include <amgcl/mpi/util.hpp>

extern "C" {
#include <pastix.h>
}

namespace amgcl {
namespace mpi {

template <typename value_type>
class PaStiX {
    public:
        BOOST_STATIC_ASSERT_MSG(
                (boost::is_same<value_type, pastix_float_t>::value),
                "Unsupported value type for PaStiX solver"
                );
        struct params {};

        static int comm_size(int n_global_rows) {
            const int dofs_per_process = 5000;
            return (n_global_rows + dofs_per_process - 1) / dofs_per_process;
        }

        template <class PRng, class CRng, class VRng>
        PaStiX(
                MPI_Comm mpi_comm,
                int n_local_rows,
                const PRng &p_ptr,
                const CRng &p_col,
                const VRng &p_val,
                const params &prm = params()
                )
            : comm(mpi_comm), nrows(n_local_rows), pastix_data(0),
              ptr(boost::begin(p_ptr), boost::end(p_ptr)),
              col(boost::begin(p_col), boost::end(p_col)),
              val(boost::begin(p_val), boost::end(p_val)),
              row(nrows), perm(nrows, 0), invp(nrows, 0)
        {
            std::vector<int> domain(comm.size + 1, 0);
            MPI_Allgather(&nrows, 1, MPI_INT, &domain[1], 1, MPI_INT, comm);
            boost::partial_sum(domain, domain.begin());

            boost::copy(
                    boost::irange(domain[comm.rank], domain[comm.rank + 1]),
                    row.begin()
                    );

            boost::copy(boost::irange(1, nrows + 1), perm.begin());
            boost::copy(boost::irange(1, nrows + 1), invp.begin());

            // PaStiX needs 1-based matrices:
            BOOST_FOREACH(pastix_int_t &p, ptr) ++p;
            BOOST_FOREACH(pastix_int_t &c, col) ++c;
            BOOST_FOREACH(pastix_int_t &r, row) ++r;

            // Initialize parameters with default values:
            iparm[IPARM_MODIFY_PARAMETER] = API_NO;
            call_pastix(API_TASK_INIT, API_TASK_INIT, NULL);

            // Factorize the matrix.
            iparm[IPARM_VERBOSE        ] = API_VERBOSE_NOT;
            iparm[IPARM_RHS_MAKING     ] = API_RHS_B;
            iparm[IPARM_SYM            ] = API_SYM_NO;
            iparm[IPARM_FACTORIZATION  ] = API_FACT_LU;
            iparm[IPARM_TRANSPOSE_SOLVE] = API_YES;
            call_pastix(API_TASK_ORDERING, API_TASK_NUMFACT, NULL);
        }

        ~PaStiX() {
            call_pastix(API_TASK_CLEAN, API_TASK_CLEAN, NULL);
        }

        template <class Vec1, class Vec2>
        void operator()(const Vec1 &rhs, Vec2 &x) const {
            boost::copy(rhs, &x[0]);
            call_pastix(API_TASK_SOLVE, API_TASK_SOLVE, &x[0]);
        }
    private:
        amgcl::mpi::communicator comm;

        int nrows;

        // Pastix internal data.
        mutable pastix_data_t *pastix_data;

        // Pastix parameters
        mutable pastix_int_t   iparm[IPARM_SIZE];
        mutable double         dparm[DPARM_SIZE];

        std::vector<pastix_int_t>   ptr;
        std::vector<pastix_int_t>   col;
        std::vector<pastix_float_t> val;

        // Local to global mapping
        std::vector<pastix_int_t> row;

        // Permutation arrays
        std::vector<pastix_int_t> perm, invp;

        void call_pastix(int beg, int end, pastix_float_t *x) const {
            iparm[IPARM_START_TASK] = beg;
            iparm[IPARM_END_TASK  ] = end;

            dpastix(&pastix_data, comm, nrows,
                    const_cast<pastix_int_t*  >(ptr.data()),
                    const_cast<pastix_int_t*  >(col.data()),
                    const_cast<pastix_float_t*>(val.data()),
                    const_cast<pastix_int_t*  >(row.data()),
                    const_cast<pastix_int_t*  >(perm.data()),
                    const_cast<pastix_int_t*  >(invp.data()),
                    x, 1, iparm, dparm
                   );
        }
};

}
}

#endif
<|endoftext|>


<commit_before>/*
 * Call the translation server.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "Client.hxx"
#include "Marshal.hxx"
#include "Parser.hxx"
#include "Request.hxx"
#include "Handler.hxx"
#include "buffered_socket.hxx"
#include "please.hxx"
#include "stopwatch.hxx"
#include "GException.hxx"
#include "gerrno.h"
#include "pool.hxx"
#include "system/Error.hxx"
#include "util/Cancellable.hxx"
#include "util/Exception.hxx"

#include <stdexcept>

#include <assert.h>
#include <string.h>
#include <errno.h>

static const uint8_t PROTOCOL_VERSION = 3;

struct TranslateClient final : Cancellable {
    struct pool &pool;

    Stopwatch *const stopwatch;

    BufferedSocket socket;
    struct lease_ref lease_ref;

    /** the marshalled translate request */
    GrowingBufferReader request_buffer;
    GrowingBufferReader request;

    const TranslateHandler &handler;
    void *handler_ctx;

    TranslateParser parser;

    TranslateClient(struct pool &p, EventLoop &event_loop,
                    int fd, Lease &lease,
                    const TranslateRequest &request2,
                    GrowingBuffer &&_request,
                    const TranslateHandler &_handler, void *_ctx,
                    CancellablePointer &cancel_ptr);

    void ReleaseSocket(bool reuse);
    void Release(bool reuse);

    void Fail(std::exception_ptr ep);
    void Fail(const std::exception &e);

    BufferedResult Feed(const uint8_t *data, size_t length);

    /* virtual methods from class Cancellable */
    void Cancel() override {
        stopwatch_event(stopwatch, "cancel");
        Release(false);
    }
};

static constexpr struct timeval translate_read_timeout = {
    .tv_sec = 60,
    .tv_usec = 0,
};

static constexpr struct timeval translate_write_timeout = {
    .tv_sec = 10,
    .tv_usec = 0,
};

void
TranslateClient::ReleaseSocket(bool reuse)
{
    assert(socket.IsConnected());

    stopwatch_dump(stopwatch);

    socket.Abandon();
    socket.Destroy();

    p_lease_release(lease_ref, reuse, pool);
}

/**
 * Release resources held by this object: the event object, the socket
 * lease, and the pool reference.
 */
void
TranslateClient::Release(bool reuse)
{
    ReleaseSocket(reuse);
    pool_unref(&pool);
}

void
TranslateClient::Fail(std::exception_ptr ep)
{
    stopwatch_event(stopwatch, "error");

    ReleaseSocket(false);

    handler.error(ep, handler_ctx);
    pool_unref(&pool);
}

void
TranslateClient::Fail(const std::exception &e)
{
    Fail(std::make_exception_ptr(e));
}

/*
 * receive response
 *
 */

inline BufferedResult
TranslateClient::Feed(const uint8_t *data, size_t length)
try {
    size_t consumed = 0;
    while (consumed < length) {
        size_t nbytes = parser.Feed(data + consumed, length - consumed);
        if (nbytes == 0)
            /* need more data */
            break;

        consumed += nbytes;
        socket.Consumed(nbytes);

        auto result = parser.Process();
        switch (result) {
        case TranslateParser::Result::MORE:
            break;

        case TranslateParser::Result::DONE:
            ReleaseSocket(true);
            handler.response(parser.GetResponse(), handler_ctx);
            pool_unref(&pool);
            return BufferedResult::CLOSED;
        }
    }

    return BufferedResult::MORE;
} catch (const std::runtime_error &e) {
    Fail(e);
    return BufferedResult::CLOSED;
}

/*
 * send requests
 *
 */

static bool
translate_try_write(TranslateClient *client)
{
    auto src = client->request.Read();
    assert(!src.IsNull());

    ssize_t nbytes = client->socket.Write(src.data, src.size);
    if (gcc_unlikely(nbytes < 0)) {
        if (gcc_likely(nbytes == WRITE_BLOCKING))
            return true;

        client->Fail(MakeErrno("write error to translation server"));
        return false;
    }

    client->request.Consume(nbytes);
    if (client->request.IsEOF()) {
        /* the buffer is empty, i.e. the request has been sent */

        stopwatch_event(client->stopwatch, "request");

        client->socket.UnscheduleWrite();
        return client->socket.Read(true);
    }

    client->socket.ScheduleWrite();
    return true;
}

/*
 * buffered_socket handler
 *
 */

static BufferedResult
translate_client_socket_data(const void *buffer, size_t size, void *ctx)
{
    TranslateClient *client = (TranslateClient *)ctx;

    return client->Feed((const uint8_t *)buffer, size);
}

static bool
translate_client_socket_closed(void *ctx)
{
    TranslateClient *client = (TranslateClient *)ctx;

    client->ReleaseSocket(false);
    return true;
}

static bool
translate_client_socket_write(void *ctx)
{
    TranslateClient *client = (TranslateClient *)ctx;

    return translate_try_write(client);
}

static void
translate_client_socket_error(std::exception_ptr ep, void *ctx)
{
    TranslateClient *client = (TranslateClient *)ctx;

    client->Fail(NestException(ep,
                               std::runtime_error("Translation server connection failed")));
}

static constexpr BufferedSocketHandler translate_client_socket_handler = {
    .data = translate_client_socket_data,
    .direct = nullptr,
    .closed = translate_client_socket_closed,
    .remaining = nullptr,
    .end = nullptr,
    .write = translate_client_socket_write,
    .drained = nullptr,
    .timeout = nullptr,
    .broken = nullptr,
    .error = translate_client_socket_error,
};

/*
 * constructor
 *
 */

inline
TranslateClient::TranslateClient(struct pool &p, EventLoop &event_loop,
                                 int fd, Lease &lease,
                                 const TranslateRequest &request2,
                                 GrowingBuffer &&_request,
                                 const TranslateHandler &_handler, void *_ctx,
                                 CancellablePointer &cancel_ptr)
    :pool(p),
     stopwatch(stopwatch_fd_new(&p, fd, request2.GetDiagnosticName())),
     socket(event_loop),
     request_buffer(std::move(_request)),
     request(request_buffer),
     handler(_handler), handler_ctx(_ctx),
     parser(p, request2)
{
    socket.Init(fd, FdType::FD_SOCKET,
                &translate_read_timeout,
                &translate_write_timeout,
                translate_client_socket_handler, this);
    p_lease_ref_set(lease_ref, lease, p, "translate_lease");

    cancel_ptr = *this;
}

void
translate(struct pool &pool, EventLoop &event_loop,
          int fd, Lease &lease,
          const TranslateRequest &request,
          const TranslateHandler &handler, void *ctx,
          CancellablePointer &cancel_ptr)
try {
    assert(fd >= 0);
    assert(request.uri != nullptr || request.widget_type != nullptr ||
           (!request.content_type_lookup.IsNull() &&
            request.suffix != nullptr));
    assert(handler.response != nullptr);
    assert(handler.error != nullptr);

    GrowingBuffer gb = MarshalTranslateRequest(pool, PROTOCOL_VERSION,
                                               request);

    auto *client = NewFromPool<TranslateClient>(pool, pool, event_loop,
                                                fd, lease,
                                                request, std::move(gb),
                                                handler, ctx, cancel_ptr);

    pool_ref(&client->pool);
    translate_try_write(client);
} catch (...) {
    lease.ReleaseLease(true);

    handler.error(std::current_exception(), ctx);
}
<commit_msg>translation/Client: eliminate duplicate GrowingBufferReader attribute<commit_after>/*
 * Call the translation server.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "Client.hxx"
#include "Marshal.hxx"
#include "Parser.hxx"
#include "Request.hxx"
#include "Handler.hxx"
#include "buffered_socket.hxx"
#include "please.hxx"
#include "stopwatch.hxx"
#include "GException.hxx"
#include "gerrno.h"
#include "pool.hxx"
#include "system/Error.hxx"
#include "util/Cancellable.hxx"
#include "util/Exception.hxx"

#include <stdexcept>

#include <assert.h>
#include <string.h>
#include <errno.h>

static const uint8_t PROTOCOL_VERSION = 3;

struct TranslateClient final : Cancellable {
    struct pool &pool;

    Stopwatch *const stopwatch;

    BufferedSocket socket;
    struct lease_ref lease_ref;

    /** the marshalled translate request */
    GrowingBufferReader request;

    const TranslateHandler &handler;
    void *handler_ctx;

    TranslateParser parser;

    TranslateClient(struct pool &p, EventLoop &event_loop,
                    int fd, Lease &lease,
                    const TranslateRequest &request2,
                    GrowingBuffer &&_request,
                    const TranslateHandler &_handler, void *_ctx,
                    CancellablePointer &cancel_ptr);

    void ReleaseSocket(bool reuse);
    void Release(bool reuse);

    void Fail(std::exception_ptr ep);
    void Fail(const std::exception &e);

    BufferedResult Feed(const uint8_t *data, size_t length);

    /* virtual methods from class Cancellable */
    void Cancel() override {
        stopwatch_event(stopwatch, "cancel");
        Release(false);
    }
};

static constexpr struct timeval translate_read_timeout = {
    .tv_sec = 60,
    .tv_usec = 0,
};

static constexpr struct timeval translate_write_timeout = {
    .tv_sec = 10,
    .tv_usec = 0,
};

void
TranslateClient::ReleaseSocket(bool reuse)
{
    assert(socket.IsConnected());

    stopwatch_dump(stopwatch);

    socket.Abandon();
    socket.Destroy();

    p_lease_release(lease_ref, reuse, pool);
}

/**
 * Release resources held by this object: the event object, the socket
 * lease, and the pool reference.
 */
void
TranslateClient::Release(bool reuse)
{
    ReleaseSocket(reuse);
    pool_unref(&pool);
}

void
TranslateClient::Fail(std::exception_ptr ep)
{
    stopwatch_event(stopwatch, "error");

    ReleaseSocket(false);

    handler.error(ep, handler_ctx);
    pool_unref(&pool);
}

void
TranslateClient::Fail(const std::exception &e)
{
    Fail(std::make_exception_ptr(e));
}

/*
 * receive response
 *
 */

inline BufferedResult
TranslateClient::Feed(const uint8_t *data, size_t length)
try {
    size_t consumed = 0;
    while (consumed < length) {
        size_t nbytes = parser.Feed(data + consumed, length - consumed);
        if (nbytes == 0)
            /* need more data */
            break;

        consumed += nbytes;
        socket.Consumed(nbytes);

        auto result = parser.Process();
        switch (result) {
        case TranslateParser::Result::MORE:
            break;

        case TranslateParser::Result::DONE:
            ReleaseSocket(true);
            handler.response(parser.GetResponse(), handler_ctx);
            pool_unref(&pool);
            return BufferedResult::CLOSED;
        }
    }

    return BufferedResult::MORE;
} catch (const std::runtime_error &e) {
    Fail(e);
    return BufferedResult::CLOSED;
}

/*
 * send requests
 *
 */

static bool
translate_try_write(TranslateClient *client)
{
    auto src = client->request.Read();
    assert(!src.IsNull());

    ssize_t nbytes = client->socket.Write(src.data, src.size);
    if (gcc_unlikely(nbytes < 0)) {
        if (gcc_likely(nbytes == WRITE_BLOCKING))
            return true;

        client->Fail(MakeErrno("write error to translation server"));
        return false;
    }

    client->request.Consume(nbytes);
    if (client->request.IsEOF()) {
        /* the buffer is empty, i.e. the request has been sent */

        stopwatch_event(client->stopwatch, "request");

        client->socket.UnscheduleWrite();
        return client->socket.Read(true);
    }

    client->socket.ScheduleWrite();
    return true;
}

/*
 * buffered_socket handler
 *
 */

static BufferedResult
translate_client_socket_data(const void *buffer, size_t size, void *ctx)
{
    TranslateClient *client = (TranslateClient *)ctx;

    return client->Feed((const uint8_t *)buffer, size);
}

static bool
translate_client_socket_closed(void *ctx)
{
    TranslateClient *client = (TranslateClient *)ctx;

    client->ReleaseSocket(false);
    return true;
}

static bool
translate_client_socket_write(void *ctx)
{
    TranslateClient *client = (TranslateClient *)ctx;

    return translate_try_write(client);
}

static void
translate_client_socket_error(std::exception_ptr ep, void *ctx)
{
    TranslateClient *client = (TranslateClient *)ctx;

    client->Fail(NestException(ep,
                               std::runtime_error("Translation server connection failed")));
}

static constexpr BufferedSocketHandler translate_client_socket_handler = {
    .data = translate_client_socket_data,
    .direct = nullptr,
    .closed = translate_client_socket_closed,
    .remaining = nullptr,
    .end = nullptr,
    .write = translate_client_socket_write,
    .drained = nullptr,
    .timeout = nullptr,
    .broken = nullptr,
    .error = translate_client_socket_error,
};

/*
 * constructor
 *
 */

inline
TranslateClient::TranslateClient(struct pool &p, EventLoop &event_loop,
                                 int fd, Lease &lease,
                                 const TranslateRequest &request2,
                                 GrowingBuffer &&_request,
                                 const TranslateHandler &_handler, void *_ctx,
                                 CancellablePointer &cancel_ptr)
    :pool(p),
     stopwatch(stopwatch_fd_new(&p, fd, request2.GetDiagnosticName())),
     socket(event_loop),
     request(std::move(_request)),
     handler(_handler), handler_ctx(_ctx),
     parser(p, request2)
{
    socket.Init(fd, FdType::FD_SOCKET,
                &translate_read_timeout,
                &translate_write_timeout,
                translate_client_socket_handler, this);
    p_lease_ref_set(lease_ref, lease, p, "translate_lease");

    cancel_ptr = *this;
}

void
translate(struct pool &pool, EventLoop &event_loop,
          int fd, Lease &lease,
          const TranslateRequest &request,
          const TranslateHandler &handler, void *ctx,
          CancellablePointer &cancel_ptr)
try {
    assert(fd >= 0);
    assert(request.uri != nullptr || request.widget_type != nullptr ||
           (!request.content_type_lookup.IsNull() &&
            request.suffix != nullptr));
    assert(handler.response != nullptr);
    assert(handler.error != nullptr);

    GrowingBuffer gb = MarshalTranslateRequest(pool, PROTOCOL_VERSION,
                                               request);

    auto *client = NewFromPool<TranslateClient>(pool, pool, event_loop,
                                                fd, lease,
                                                request, std::move(gb),
                                                handler, ctx, cancel_ptr);

    pool_ref(&client->pool);
    translate_try_write(client);
} catch (...) {
    lease.ReleaseLease(true);

    handler.error(std::current_exception(), ctx);
}
<|endoftext|>