<commit_before>/************************************************************/
/* print_board_functions.cpp: some functions to plot boards */
/************************************************************/

#include "fctsys.h"
#include "gr_basic.h"
#include "common.h"
#include "class_drawpanel.h"

#include "pcbnew.h"
#include "class_board_design_settings.h"
#include "pcbplot.h"
#include "printout_controler.h"
#include "colors_selection.h"
#include "protos.h"

static void Print_Module( WinEDA_DrawPanel* aPanel, wxDC* aDC, MODULE* aModule,
                          int aDraw_mode, int aMasklayer,
                          PRINT_PARAMETERS::DrillShapeOptT aDrillShapeOpt );

/** Function PrintPage
 * Used to print the board (on printer, or when creating SVF files).
 * Print the board, but only layers allowed by aPrintMaskLayer
 * @param aDC = the print device context
 * @param aPrint_Sheet_Ref = true to print frame references
 * @param aPrint_Sheet_Ref = a 32 bits mask: bit n = 1 -> layer n is printed
 * @param aPrintMirrorMode = true to plot mirrored
 * @param aData = a pointer to an optional data (NULL if not used)
 */
void WinEDA_DrawPanel::PrintPage( wxDC* aDC,
                                  bool  aPrint_Sheet_Ref,
                                  int   aPrintMaskLayer,
                                  bool  aPrintMirrorMode,
                                  void * aData)
{
    MODULE* Module;
    int drawmode = GR_COPY;
    DISPLAY_OPTIONS      save_opt;
    TRACK*               pt_piste;
    WinEDA_BasePcbFrame* frame = (WinEDA_BasePcbFrame*) m_Parent;
    BOARD*               Pcb   = frame->GetBoard();
    PRINT_PARAMETERS * printParameters = (PRINT_PARAMETERS*) aData; // can be null

    PRINT_PARAMETERS::DrillShapeOptT drillShapeOpt = PRINT_PARAMETERS::FULL_DRILL_SHAPE;
    if( printParameters )
        drillShapeOpt = printParameters->m_DrillShapeOpt;

    save_opt = DisplayOpt;
    if( aPrintMaskLayer & ALL_CU_LAYERS )
    {
        DisplayOpt.DisplayPadFill = true;
        DisplayOpt.DisplayViaFill = true;
    }
    else
    {
        DisplayOpt.DisplayPadFill = false;
        DisplayOpt.DisplayViaFill = false;
    }

    frame->m_DisplayPadFill = DisplayOpt.DisplayPadFill;
    frame->m_DisplayViaFill = DisplayOpt.DisplayViaFill;
    frame->m_DisplayPadNum = DisplayOpt.DisplayPadNum = false;
    bool nctmp = frame->GetBoard()->IsElementVisible(NO_CONNECTS_VISIBLE);
    DisplayOpt.DisplayPadIsol    = false;
    DisplayOpt.DisplayModEdge    = FILLED;
    DisplayOpt.DisplayModText    = FILLED;
    frame->m_DisplayPcbTrackFill = DisplayOpt.DisplayPcbTrackFill = FILLED;
    DisplayOpt.ShowTrackClearanceMode = DO_NOT_SHOW_CLEARANCE;
    DisplayOpt.DisplayDrawItems    = FILLED;
    DisplayOpt.DisplayZonesMode    = 0;
    DisplayOpt.DisplayNetNamesMode = 0;

    m_PrintIsMirrored = aPrintMirrorMode;

    // The OR mode is used in color mode, but be aware the backgroud *must be
    // BLACK.  In the print page dialog, we first plrint in BLACK, and after
    // reprint in color, on the black "local" backgroud, in OR mode the black
    // print is not made before, only a white page is printed
    if( GetGRForceBlackPenState() == false )
        drawmode = GR_OR;

    /* Print the pcb graphic items (texts, ...) */
    GRSetDrawMode( aDC, drawmode );
    for( BOARD_ITEM* item = Pcb->m_Drawings; item; item = item->Next() )
    {
        switch( item->Type() )
        {
        case TYPE_DRAWSEGMENT:
        case TYPE_COTATION:
        case TYPE_TEXTE:
        case TYPE_MIRE:
            if( ( ( 1 << item->GetLayer() ) & aPrintMaskLayer ) == 0 )
                break;

            item->Draw( this, aDC, drawmode );
            break;

        case TYPE_MARKER_PCB:
        default:
            break;
        }
    }

    /* Print tracks */
    pt_piste = Pcb->m_Track;
    for( ; pt_piste != NULL; pt_piste = pt_piste->Next() )
    {
        if( ( aPrintMaskLayer & pt_piste->ReturnMaskLayer() ) == 0 )
            continue;
        if( pt_piste->Type() == TYPE_VIA ) /* VIA encountered. */
        {
            int rayon = pt_piste->m_Width >> 1;
            int color = g_ColorsSettings.GetItemColor(VIAS_VISIBLE+pt_piste->m_Shape);
            GRSetDrawMode( aDC, drawmode );
            GRFilledCircle( &m_ClipBox, aDC,
                            pt_piste->m_Start.x,
                            pt_piste->m_Start.y,
                            rayon,
                            0, color, color );
        }
        else
            pt_piste->Draw( this, aDC, drawmode );
    }

    pt_piste = Pcb->m_Zone;
    for( ; pt_piste != NULL; pt_piste = pt_piste->Next() )
    {
        if( ( aPrintMaskLayer & pt_piste->ReturnMaskLayer() ) == 0 )
            continue;
        pt_piste->Draw( this, aDC, drawmode );
    }

    /* Draw filled areas (i.e. zones) */
    for( int ii = 0; ii < Pcb->GetAreaCount(); ii++ )
    {
        ZONE_CONTAINER* zone = Pcb->GetArea( ii );
        if( ( aPrintMaskLayer & ( 1 << zone->GetLayer() ) ) == 0 )
            continue;

        zone->DrawFilledArea( this, aDC, drawmode );
    }

    // Draw footprints, this is done at last in order to print the pad holes in
    // white (or g_DrawBgColor) after the tracks and zones
    Module = (MODULE*) Pcb->m_Modules;
    for( ; Module != NULL; Module = Module->Next() )
    {
        Print_Module( this, aDC, Module, drawmode, aPrintMaskLayer, drillShapeOpt );
    }

    /* Print via holes in bg color: Not sure it is good for buried or blind
     * vias */
    if( drillShapeOpt != PRINT_PARAMETERS::NO_DRILL_SHAPE )
    {
        pt_piste = Pcb->m_Track;
        int  color = g_DrawBgColor;
        bool blackpenstate = GetGRForceBlackPenState();
        GRForceBlackPen( false );
        GRSetDrawMode( aDC, GR_COPY );
        for( ; pt_piste != NULL; pt_piste = pt_piste->Next() )
        {
            if( ( aPrintMaskLayer & pt_piste->ReturnMaskLayer() ) == 0 )
                continue;
            if( pt_piste->Type() == TYPE_VIA ) /* VIA encountered. */
            {
                int diameter;
                if( drillShapeOpt == PRINT_PARAMETERS::SMALL_DRILL_SHAPE )
                    diameter = min( SMALL_DRILL, pt_piste->GetDrillValue());
                else
                    diameter = pt_piste->GetDrillValue();
                GRFilledCircle( &m_ClipBox, aDC,
                                pt_piste->m_Start.x, pt_piste->m_Start.y,
                                diameter/2,
                                0, color, color );
            }
        }
        GRForceBlackPen( blackpenstate );
    }

    if( aPrint_Sheet_Ref )
        m_Parent->TraceWorkSheet( aDC, GetScreen(), 10 );

    m_PrintIsMirrored = false;

    DisplayOpt = save_opt;
    frame->m_DisplayPcbTrackFill = DisplayOpt.DisplayPcbTrackFill;
    frame->m_DisplayPadFill = DisplayOpt.DisplayPadFill;
    frame->m_DisplayViaFill = DisplayOpt.DisplayViaFill;
    frame->m_DisplayPadNum  = DisplayOpt.DisplayPadNum;
    frame->GetBoard()->SetElementVisibility(NO_CONNECTS_VISIBLE, nctmp);
}

static void Print_Module( WinEDA_DrawPanel* aPanel, wxDC* aDC, MODULE* aModule,
                          int aDraw_mode, int aMasklayer,
                          PRINT_PARAMETERS::DrillShapeOptT aDrillShapeOpt )
{
    D_PAD*          pt_pad;
    EDA_BaseStruct* PtStruct;
    TEXTE_MODULE*   TextMod;
    int             mlayer;

    /* Print pads */
    pt_pad = aModule->m_Pads;
    for( ; pt_pad != NULL; pt_pad = pt_pad->Next() )
    {
        if( (pt_pad->m_Masque_Layer & aMasklayer ) == 0 )
            continue;

        // Usually we draw pads in sketch mode on non copper layers:
        if( (aMasklayer & ALL_CU_LAYERS) == 0 )
        {
            int tmp_fill =
                ( (WinEDA_BasePcbFrame*) aPanel->GetParent() )->m_DisplayPadFill;

            // Switch in sketch mode
            ( (WinEDA_BasePcbFrame*) aPanel->GetParent() )->m_DisplayPadFill = 0;
            pt_pad->Draw( aPanel, aDC, aDraw_mode );
            ( (WinEDA_BasePcbFrame*) aPanel->GetParent() )->m_DisplayPadFill =
                tmp_fill;
        }
        else    // on copper layer, draw pads according to current options
        {
            // Manage hole according to the print drill option
            wxSize drill_tmp = pt_pad->m_Drill;
            switch ( aDrillShapeOpt )
            {
                case PRINT_PARAMETERS::NO_DRILL_SHAPE:
                    pt_pad->m_Drill = wxSize(0,0);
                    break;
                case PRINT_PARAMETERS::SMALL_DRILL_SHAPE:
                    pt_pad->m_Drill.x = MIN(SMALL_DRILL,pt_pad->m_Drill.x);
                    pt_pad->m_Drill.y = MIN(SMALL_DRILL,pt_pad->m_Drill.y);
                    break;
                case PRINT_PARAMETERS::FULL_DRILL_SHAPE:
                    // Do nothing
                    break;
            }
            pt_pad->Draw( aPanel, aDC, aDraw_mode );
            pt_pad->m_Drill = drill_tmp;
        }
    }

    /* Print footprint graphic shapes */
    PtStruct = aModule->m_Drawings;
    mlayer   = g_TabOneLayerMask[aModule->GetLayer()];
    if( aModule->GetLayer() == LAYER_N_BACK )
        mlayer = SILKSCREEN_LAYER_BACK;
    else if( aModule->GetLayer() == LAYER_N_FRONT )
        mlayer = SILKSCREEN_LAYER_FRONT;

    if( mlayer & aMasklayer )
    {
        if( !aModule->m_Reference->m_NoShow )
            aModule->m_Reference->Draw( aPanel, aDC, aDraw_mode );
        if( !aModule->m_Value->m_NoShow )
            aModule->m_Value->Draw( aPanel, aDC, aDraw_mode );
    }

    for( ; PtStruct != NULL; PtStruct = PtStruct->Next() )
    {
        switch( PtStruct->Type() )
        {
        case TYPE_TEXTE_MODULE:
            if( (mlayer & aMasklayer ) == 0 )
                break;

            TextMod = (TEXTE_MODULE*) PtStruct;
            TextMod->Draw( aPanel, aDC, aDraw_mode );
            break;

        case TYPE_EDGE_MODULE:
        {
            EDGE_MODULE* edge = (EDGE_MODULE*) PtStruct;
            if( ( g_TabOneLayerMask[edge->GetLayer()] & aMasklayer ) == 0 )
                break;
            edge->Draw( aPanel, aDC, aDraw_mode );
            break;
        }

        default:
            break;
        }
    }
}
<commit_msg>Pcbnew: removed the "no connect" mark when printing a board.<commit_after>/************************************************************/
/* print_board_functions.cpp: some functions to plot boards */
/************************************************************/

#include "fctsys.h"
#include "gr_basic.h"
#include "common.h"
#include "class_drawpanel.h"

#include "pcbnew.h"
#include "class_board_design_settings.h"
#include "pcbplot.h"
#include "printout_controler.h"
#include "colors_selection.h"
#include "protos.h"

static void Print_Module( WinEDA_DrawPanel* aPanel, wxDC* aDC, MODULE* aModule,
                          int aDraw_mode, int aMasklayer,
                          PRINT_PARAMETERS::DrillShapeOptT aDrillShapeOpt );

/** Function PrintPage
 * Used to print the board (on printer, or when creating SVF files).
 * Print the board, but only layers allowed by aPrintMaskLayer
 * @param aDC = the print device context
 * @param aPrint_Sheet_Ref = true to print frame references
 * @param aPrint_Sheet_Ref = a 32 bits mask: bit n = 1 -> layer n is printed
 * @param aPrintMirrorMode = true to plot mirrored
 * @param aData = a pointer to an optional data (NULL if not used)
 */
void WinEDA_DrawPanel::PrintPage( wxDC* aDC,
                                  bool  aPrint_Sheet_Ref,
                                  int   aPrintMaskLayer,
                                  bool  aPrintMirrorMode,
                                  void * aData)
{
    MODULE* Module;
    int drawmode = GR_COPY;
    DISPLAY_OPTIONS      save_opt;
    TRACK*               pt_piste;
    WinEDA_BasePcbFrame* frame = (WinEDA_BasePcbFrame*) m_Parent;
    BOARD*               Pcb   = frame->GetBoard();
    PRINT_PARAMETERS * printParameters = (PRINT_PARAMETERS*) aData; // can be null

    PRINT_PARAMETERS::DrillShapeOptT drillShapeOpt = PRINT_PARAMETERS::FULL_DRILL_SHAPE;
    if( printParameters )
        drillShapeOpt = printParameters->m_DrillShapeOpt;

    save_opt = DisplayOpt;
    if( aPrintMaskLayer & ALL_CU_LAYERS )
    {
        DisplayOpt.DisplayPadFill = true;
        DisplayOpt.DisplayViaFill = true;
    }
    else
    {
        DisplayOpt.DisplayPadFill = false;
        DisplayOpt.DisplayViaFill = false;
    }

    frame->m_DisplayPadFill = DisplayOpt.DisplayPadFill;
    frame->m_DisplayViaFill = DisplayOpt.DisplayViaFill;
    frame->m_DisplayPadNum = DisplayOpt.DisplayPadNum = false;
    bool nctmp = frame->GetBoard()->IsElementVisible(NO_CONNECTS_VISIBLE);
    frame->GetBoard()->SetElementVisibility(NO_CONNECTS_VISIBLE, false);
    DisplayOpt.DisplayPadIsol    = false;
    DisplayOpt.DisplayModEdge    = FILLED;
    DisplayOpt.DisplayModText    = FILLED;
    frame->m_DisplayPcbTrackFill = DisplayOpt.DisplayPcbTrackFill = FILLED;
    DisplayOpt.ShowTrackClearanceMode = DO_NOT_SHOW_CLEARANCE;
    DisplayOpt.DisplayDrawItems    = FILLED;
    DisplayOpt.DisplayZonesMode    = 0;
    DisplayOpt.DisplayNetNamesMode = 0;

    m_PrintIsMirrored = aPrintMirrorMode;

    // The OR mode is used in color mode, but be aware the backgroud *must be
    // BLACK.  In the print page dialog, we first plrint in BLACK, and after
    // reprint in color, on the black "local" backgroud, in OR mode the black
    // print is not made before, only a white page is printed
    if( GetGRForceBlackPenState() == false )
        drawmode = GR_OR;

    /* Print the pcb graphic items (texts, ...) */
    GRSetDrawMode( aDC, drawmode );
    for( BOARD_ITEM* item = Pcb->m_Drawings; item; item = item->Next() )
    {
        switch( item->Type() )
        {
        case TYPE_DRAWSEGMENT:
        case TYPE_COTATION:
        case TYPE_TEXTE:
        case TYPE_MIRE:
            if( ( ( 1 << item->GetLayer() ) & aPrintMaskLayer ) == 0 )
                break;

            item->Draw( this, aDC, drawmode );
            break;

        case TYPE_MARKER_PCB:
        default:
            break;
        }
    }

    /* Print tracks */
    pt_piste = Pcb->m_Track;
    for( ; pt_piste != NULL; pt_piste = pt_piste->Next() )
    {
        if( ( aPrintMaskLayer & pt_piste->ReturnMaskLayer() ) == 0 )
            continue;
        if( pt_piste->Type() == TYPE_VIA ) /* VIA encountered. */
        {
            int rayon = pt_piste->m_Width >> 1;
            int color = g_ColorsSettings.GetItemColor(VIAS_VISIBLE+pt_piste->m_Shape);
            GRSetDrawMode( aDC, drawmode );
            GRFilledCircle( &m_ClipBox, aDC,
                            pt_piste->m_Start.x,
                            pt_piste->m_Start.y,
                            rayon,
                            0, color, color );
        }
        else
            pt_piste->Draw( this, aDC, drawmode );
    }

    pt_piste = Pcb->m_Zone;
    for( ; pt_piste != NULL; pt_piste = pt_piste->Next() )
    {
        if( ( aPrintMaskLayer & pt_piste->ReturnMaskLayer() ) == 0 )
            continue;
        pt_piste->Draw( this, aDC, drawmode );
    }

    /* Draw filled areas (i.e. zones) */
    for( int ii = 0; ii < Pcb->GetAreaCount(); ii++ )
    {
        ZONE_CONTAINER* zone = Pcb->GetArea( ii );
        if( ( aPrintMaskLayer & ( 1 << zone->GetLayer() ) ) == 0 )
            continue;

        zone->DrawFilledArea( this, aDC, drawmode );
    }

    // Draw footprints, this is done at last in order to print the pad holes in
    // white (or g_DrawBgColor) after the tracks and zones
    Module = (MODULE*) Pcb->m_Modules;
    for( ; Module != NULL; Module = Module->Next() )
    {
        Print_Module( this, aDC, Module, drawmode, aPrintMaskLayer, drillShapeOpt );
    }

    /* Print via holes in bg color: Not sure it is good for buried or blind
     * vias */
    if( drillShapeOpt != PRINT_PARAMETERS::NO_DRILL_SHAPE )
    {
        pt_piste = Pcb->m_Track;
        int  color = g_DrawBgColor;
        bool blackpenstate = GetGRForceBlackPenState();
        GRForceBlackPen( false );
        GRSetDrawMode( aDC, GR_COPY );
        for( ; pt_piste != NULL; pt_piste = pt_piste->Next() )
        {
            if( ( aPrintMaskLayer & pt_piste->ReturnMaskLayer() ) == 0 )
                continue;
            if( pt_piste->Type() == TYPE_VIA ) /* VIA encountered. */
            {
                int diameter;
                if( drillShapeOpt == PRINT_PARAMETERS::SMALL_DRILL_SHAPE )
                    diameter = min( SMALL_DRILL, pt_piste->GetDrillValue());
                else
                    diameter = pt_piste->GetDrillValue();
                GRFilledCircle( &m_ClipBox, aDC,
                                pt_piste->m_Start.x, pt_piste->m_Start.y,
                                diameter/2,
                                0, color, color );
            }
        }
        GRForceBlackPen( blackpenstate );
    }

    if( aPrint_Sheet_Ref )
        m_Parent->TraceWorkSheet( aDC, GetScreen(), 10 );

    m_PrintIsMirrored = false;

    DisplayOpt = save_opt;
    frame->m_DisplayPcbTrackFill = DisplayOpt.DisplayPcbTrackFill;
    frame->m_DisplayPadFill = DisplayOpt.DisplayPadFill;
    frame->m_DisplayViaFill = DisplayOpt.DisplayViaFill;
    frame->m_DisplayPadNum  = DisplayOpt.DisplayPadNum;
    frame->GetBoard()->SetElementVisibility(NO_CONNECTS_VISIBLE, nctmp);
}

static void Print_Module( WinEDA_DrawPanel* aPanel, wxDC* aDC, MODULE* aModule,
                          int aDraw_mode, int aMasklayer,
                          PRINT_PARAMETERS::DrillShapeOptT aDrillShapeOpt )
{
    D_PAD*          pt_pad;
    EDA_BaseStruct* PtStruct;
    TEXTE_MODULE*   TextMod;
    int             mlayer;

    /* Print pads */
    pt_pad = aModule->m_Pads;
    for( ; pt_pad != NULL; pt_pad = pt_pad->Next() )
    {
        if( (pt_pad->m_Masque_Layer & aMasklayer ) == 0 )
            continue;

        // Usually we draw pads in sketch mode on non copper layers:
        if( (aMasklayer & ALL_CU_LAYERS) == 0 )
        {
            int tmp_fill =
                ( (WinEDA_BasePcbFrame*) aPanel->GetParent() )->m_DisplayPadFill;

            // Switch in sketch mode
            ( (WinEDA_BasePcbFrame*) aPanel->GetParent() )->m_DisplayPadFill = 0;
            pt_pad->Draw( aPanel, aDC, aDraw_mode );
            ( (WinEDA_BasePcbFrame*) aPanel->GetParent() )->m_DisplayPadFill =
                tmp_fill;
        }
        else    // on copper layer, draw pads according to current options
        {
            // Manage hole according to the print drill option
            wxSize drill_tmp = pt_pad->m_Drill;
            switch ( aDrillShapeOpt )
            {
                case PRINT_PARAMETERS::NO_DRILL_SHAPE:
                    pt_pad->m_Drill = wxSize(0,0);
                    break;
                case PRINT_PARAMETERS::SMALL_DRILL_SHAPE:
                    pt_pad->m_Drill.x = MIN(SMALL_DRILL,pt_pad->m_Drill.x);
                    pt_pad->m_Drill.y = MIN(SMALL_DRILL,pt_pad->m_Drill.y);
                    break;
                case PRINT_PARAMETERS::FULL_DRILL_SHAPE:
                    // Do nothing
                    break;
            }
            pt_pad->Draw( aPanel, aDC, aDraw_mode );
            pt_pad->m_Drill = drill_tmp;
        }
    }

    /* Print footprint graphic shapes */
    PtStruct = aModule->m_Drawings;
    mlayer   = g_TabOneLayerMask[aModule->GetLayer()];
    if( aModule->GetLayer() == LAYER_N_BACK )
        mlayer = SILKSCREEN_LAYER_BACK;
    else if( aModule->GetLayer() == LAYER_N_FRONT )
        mlayer = SILKSCREEN_LAYER_FRONT;

    if( mlayer & aMasklayer )
    {
        if( !aModule->m_Reference->m_NoShow )
            aModule->m_Reference->Draw( aPanel, aDC, aDraw_mode );
        if( !aModule->m_Value->m_NoShow )
            aModule->m_Value->Draw( aPanel, aDC, aDraw_mode );
    }

    for( ; PtStruct != NULL; PtStruct = PtStruct->Next() )
    {
        switch( PtStruct->Type() )
        {
        case TYPE_TEXTE_MODULE:
            if( (mlayer & aMasklayer ) == 0 )
                break;

            TextMod = (TEXTE_MODULE*) PtStruct;
            TextMod->Draw( aPanel, aDC, aDraw_mode );
            break;

        case TYPE_EDGE_MODULE:
        {
            EDGE_MODULE* edge = (EDGE_MODULE*) PtStruct;
            if( ( g_TabOneLayerMask[edge->GetLayer()] & aMasklayer ) == 0 )
                break;
            edge->Draw( aPanel, aDC, aDraw_mode );
            break;
        }

        default:
            break;
        }
    }
}
<|endoftext|>


<commit_before>//
//  ofxFBXSkeleton.cpp
//  ofxFBX-Example-Importer
//
//  Created by Nick Hardeman on 11/5/13.
//
//

#include "ofxFBXSkeleton.h"
ofxFBXBone dummyBone;

//--------------------------------------------------------------
ofxFBXSkeleton::ofxFBXSkeleton() {
    numBones = 0;
}

//--------------------------------------------------------------
ofxFBXSkeleton::~ofxFBXSkeleton() {

}

//--------------------------------------------------------------
void ofxFBXSkeleton::setup( FbxNode *pNode ) {
    ofxFBXNode::setup( pNode );
}

//--------------------------------------------------------------
void ofxFBXSkeleton::reconstructNodeParenting() {

    map<string, ofxFBXBone >::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        ofxFBXBone* bone    = &it->second;
        if( bone->parentBoneName == "" ) continue;
//        ofxFBXBone* pbone   = getBone( bone->parentBoneName );
//        if( bone->parentBoneName == "Armature|FootIK.L" || bone->parentBoneName == "Armature|FootIK.R" ) {
//            cout << "removing parent with name " << bone->parentBoneName << endl;
//            bone->clearParent( false );
//        }
//
//        if( pbone == NULL ) continue;
//
//        cout << "reconstructNodeParenting :: " << bone->getName() << " parent: " << bone->parentBoneName << endl;
//
//        if( bone->getParent() != NULL ) {
//            bone->clearParent( false );
//        }
//
//        bone->setParent( *pbone, false );
//        bone->setGlobalPosition( bone->origNode.getGlobalPosition() );
//        bone->setGlobalOrientation( bone->origNode.getGlobalOrientation() );
    }
}

//--------------------------------------------------------------
void ofxFBXSkeleton::update( FbxTime& pTime, FbxPose* pPose ) {

    updateBoneProperties();
//    map<string, ofxFBXBone >::iterator it;
//    for(it = bones.begin(); it != bones.end(); ++it ) {
//        ofxFBXBone* bone    = &it->second;
//        ofxFBXBone* sbone   = getSourceBone( it->first );
//        if( sbone != NULL ) {
//            if( bone->isExternalControlEnabled() ) {
//                sbone->enableExternalControl();
//            } else {
//                sbone->disableExternalControl();
//            }
//
//            if( bone->isAnimationEnabled() ) {
//                sbone->enableAnimation();
//            } else {
//                sbone->disableAnimation();
//            }
//        }
//    }

    map<string, ofxFBXBone >::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        ofxFBXBone* bone    = &it->second;
        ofxFBXBone* sbone   = getSourceBone( it->first );
        if( sbone != NULL ) {
            sbone->update( pTime, pPose );
        }
    }
    for(it = bones.begin(); it != bones.end(); ++it ) {
        ofxFBXBone* bone    = &it->second;
        ofxFBXBone* sbone   = getSourceBone( it->first );
        if( sbone != NULL ) {
            bone->setTransformMatrix( sbone->getLocalTransformMatrix() );
        }
    }
}

//--------------------------------------------------------------
void ofxFBXSkeleton::lateUpdate() {
    map<string, ofxFBXBone >::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        ofxFBXBone* bone    = &it->second;
        ofxFBXBone* sbone   = getSourceBone( it->first );
        if( sbone != NULL ) {
            sbone->setGlobalOrientation( bone->getGlobalOrientation() );
            sbone->setGlobalPosition( bone->getGlobalPosition() );
        }
    }

    for(it = bones.begin(); it != bones.end(); ++it ) {
        ofxFBXBone* bone    = &it->second;
        ofxFBXBone* sbone   = getSourceBone( it->first );
        if( sbone != NULL ) {
            sbone->updateFbxTransform();
        }
    }
}

//--------------------------------------------------------------
void ofxFBXSkeleton::updateWithAnimation( FbxTime& pTime, FbxPose* pPose ) {

    updateBoneProperties();
//    map<string, ofxFBXBone >::iterator it;
//    for(it = bones.begin(); it != bones.end(); ++it ) {
//        ofxFBXBone* bone    = &it->second;
//        ofxFBXBone* sbone   = getSourceBone( it->first );
//        if( sbone != NULL ) {
//            if( bone->isExternalControlEnabled() ) {
//                sbone->enableExternalControl();
//            } else {
//                sbone->disableExternalControl();
//            }
//
//            if( bone->isAnimationEnabled() ) {
//                sbone->enableAnimation();
//            } else {
//                sbone->disableAnimation();
//            }
//        }
//    }

    map<string, ofxFBXBone >::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        ofxFBXBone* bone    = &it->second;
        ofxFBXBone* sbone   = getSourceBone( it->first );
        if( sbone != NULL ) {
            sbone->update( pTime, pPose );
            bone->setTransformMatrix( sbone->getLocalTransformMatrix() );
        }
    }
}

//--------------------------------------------------------------
void ofxFBXSkeleton::lateUpdateWithAnimation() {
    map<string, ofxFBXBone >::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        ofxFBXBone* bone    = &it->second;
        ofxFBXBone* sbone   = getSourceBone( it->first );
        if( sbone != NULL ) {
//            sbone->setTransformMatrix( bone->getLocalTransformMatrix() );
            sbone->localTransformMatrix = bone->localTransformMatrix;
            sbone->setPosition( bone->getPosition() );
            sbone->setOrientation( bone->getOrientationQuat() );
            sbone->setScale( bone->getScale() );
        }
    }

    for(it = bones.begin(); it != bones.end(); ++it ) {
        ofxFBXBone* bone    = &it->second;
        ofxFBXBone* sbone   = getSourceBone( it->first );
        if( sbone != NULL ) {
            sbone->updateFbxTransform();
        }
    }
}

//--------------------------------------------------------------
void ofxFBXSkeleton::updateFromCachedSkeleton( shared_ptr< ofxFBXSkeleton> aSkeleton ) {

//    updateBoneProperties();
    map<string, ofxFBXBone >::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        ofxFBXBone* bone    = &it->second;
//        ofxFBXBone* sbone   = getSourceBone( it->first );
//        ofxFBXBone* sbone = aSkeleton->getSourceBone( it->first );
        ofxFBXBone* obone = aSkeleton->getBone( it->first );
        if( obone != NULL ) {
//
//            localTransformMatrix = m44;
//
//            ofQuaternion so;
//            localTransformMatrix.decompose(position, orientation, scale, so);
//
//            onPositionChanged();
//            onOrientationChanged();
//            onScaleChanged();

//            sbone->update( pTime, NULL );
//            bone->setTransformMatrix( obone->getLocalTransformMatrix() );
            bone->localTransformMatrix = obone->localTransformMatrix;
            bone->setPosition( obone->getPosition() );
            bone->setOrientation( obone->getOrientationQuat() );
            bone->setScale( obone->getScale() );

        } else {
            ofLogWarning() << "updateFromCachedSkeleton: " << it->first << " is null !!" << endl;
        }
    }
}

//--------------------------------------------------------------
void ofxFBXSkeleton::updateBoneProperties() {
    map<string, ofxFBXBone >::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        ofxFBXBone* bone    = &it->second;
        ofxFBXBone* sbone   = getSourceBone( it->first );
        if( sbone != NULL ) {
            if( bone->isExternalControlEnabled() ) {
                sbone->enableExternalControl();
            } else {
                sbone->disableExternalControl();
            }

            if( bone->isAnimationEnabled() ) {
                sbone->enableAnimation();
            } else {
                sbone->disableAnimation();
            }
        }
    }
}

//--------------------------------------------------------------
void ofxFBXSkeleton::draw( float aLen ) {
    map<string, ofxFBXBone>::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        it->second.draw(aLen);
    }
}

//--------------------------------------------------------------
void ofxFBXSkeleton::addBone( string aName, ofxFBXBone* aBone ) {
    if(aName == "") {
        ofLogWarning("ofxFBXSkeleton :: addBone : name is empty, not adding bone");
        return;
    }
    if(bones.find(aName) != bones.end()) {
        // the bone has a duplicate name, try to make a unique key //
        aName += ofToString(numBones,0);
    }

    vector <string> strs;// = ofSplitString(aName, ":");

    ofxFBXBone tbone = *aBone;
    string newBoneName = aName;
    if(strs.size() > 1) {
        newBoneName = strs[1];
    }

//    cout << "adding a bone with name -" << newBoneName << "- parent name -" << getName() <<"-" << endl;

    sourceBones[ newBoneName ]    = aBone;
    bones[ newBoneName ]          = tbone;

//    cout << "ofxFBXSkeleton :: addBone : name: " << aName << " ptr parent = " << aBone->getParent() << " other: " << tbone.getParent() << endl;

    numBones++;
}

//--------------------------------------------------------------
ofxFBXBone* ofxFBXSkeleton::getBone( string aName ) {
    if(bones.find(aName) != bones.end()) {
        return &bones[ aName ];
    }
    cout << "did not find the bone with name: " << aName << " | " << ofGetElapsedTimef() << endl;
    return NULL;
}

//--------------------------------------------------------------
ofxFBXBone* ofxFBXSkeleton::getSourceBone( string aName ) {
    if(bones.find(aName) != bones.end()) {
        return sourceBones[ aName ];
    }
    return NULL;
}

//--------------------------------------------------------------
void ofxFBXSkeleton::enableExternalControl( string aName ) {
    // loop through hierarchy to make children also controlled externally
    ofxFBXBone* bone = getBone( aName );
    if(bone == NULL) {
        ofLogWarning("ofxFBXSkeleton :: enableExternalControl : can not find bone with name ") << aName;
        return;
    }
    bone->enableExternalControl();

    enableExternalControlRecursive( getSourceBone(aName) );

}

//--------------------------------------------------------------
void ofxFBXSkeleton::enableExternalControlRecursive( ofxFBXBone* aBone ) {
    if( aBone == NULL ) return;
    map<string, ofxFBXBone* >::iterator it;
    for(it = sourceBones.begin(); it != sourceBones.end(); ++it ) {
        if( it->second->fbxNode->GetParent() == aBone->fbxNode ) {
//            it->second->enableExternalControl();
            getBone( it->first )->enableExternalControl();
            enableExternalControlRecursive( it->second );
        }
    }
}

//--------------------------------------------------------------
void ofxFBXSkeleton::enableAnimation() {
    map<string, ofxFBXBone >::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        it->second.enableAnimation();
    }
}

//--------------------------------------------------------------
void ofxFBXSkeleton::disableAnimation() {
    map<string, ofxFBXBone >::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        it->second.disableAnimation();
    }
}

//--------------------------------------------------------------
int ofxFBXSkeleton::getNumBones() {
    return (int)bones.size();
}

//--------------------------------------------------------------
void ofxFBXSkeleton::reset() {
    map<string, ofxFBXBone >::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        it->second.reset();
    }
}

//--------------------------------------------------------------
string ofxFBXSkeleton::toString() {
    map<string, ofxFBXBone >::iterator it;
    map< string, bool > printMap;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        printMap[ it->first ] = false;
    }

    stringstream ss;
    ss << "Skeleton: " << getName() << " - Number of bones: " << bones.size() << endl;

    if( bones.size() ) {
        printOutBoneRecursive(ss, sourceBones.begin()->first, printMap, "" );
    } else {
        ss << "NO BONES" << endl;
    }

    return ss.str().c_str();
}

//--------------------------------------------------------------
void ofxFBXSkeleton::printOutBoneRecursive( stringstream& aSS, string aBoneName, map< string, bool >& aPrintMap, string aSpacer ) {
    if( aPrintMap[ aBoneName ] ) return;

    aPrintMap[ aBoneName ] = true;
    ofxFBXBone* bone = getSourceBone( aBoneName );
    if( bone == NULL ) return;

    aSS << aSpacer << " bone: " << aBoneName << " parent: " << bone->parentBoneName << endl;
    aSpacer += "---";

    map<string, ofxFBXBone*>::iterator it;
    for(it = sourceBones.begin(); it != sourceBones.end(); ++it ) {
        if( it->second->fbxNode->GetParent() == bone->fbxNode ) {
            printOutBoneRecursive( aSS, it->first, aPrintMap, aSpacer );
        }
    }
}

<commit_msg>fix for node private member<commit_after>//
//  ofxFBXSkeleton.cpp
//  ofxFBX-Example-Importer
//
//  Created by Nick Hardeman on 11/5/13.
//
//

#include "ofxFBXSkeleton.h"
ofxFBXBone dummyBone;

//--------------------------------------------------------------
ofxFBXSkeleton::ofxFBXSkeleton() {
    numBones = 0;
}

//--------------------------------------------------------------
ofxFBXSkeleton::~ofxFBXSkeleton() {

}

//--------------------------------------------------------------
void ofxFBXSkeleton::setup( FbxNode *pNode ) {
    ofxFBXNode::setup( pNode );
}

//--------------------------------------------------------------
void ofxFBXSkeleton::reconstructNodeParenting() {

    map<string, ofxFBXBone >::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        ofxFBXBone* bone    = &it->second;
        if( bone->parentBoneName == "" ) continue;
//        ofxFBXBone* pbone   = getBone( bone->parentBoneName );
//        if( bone->parentBoneName == "Armature|FootIK.L" || bone->parentBoneName == "Armature|FootIK.R" ) {
//            cout << "removing parent with name " << bone->parentBoneName << endl;
//            bone->clearParent( false );
//        }
//
//        if( pbone == NULL ) continue;
//
//        cout << "reconstructNodeParenting :: " << bone->getName() << " parent: " << bone->parentBoneName << endl;
//
//        if( bone->getParent() != NULL ) {
//            bone->clearParent( false );
//        }
//
//        bone->setParent( *pbone, false );
//        bone->setGlobalPosition( bone->origNode.getGlobalPosition() );
//        bone->setGlobalOrientation( bone->origNode.getGlobalOrientation() );
    }
}

//--------------------------------------------------------------
void ofxFBXSkeleton::update( FbxTime& pTime, FbxPose* pPose ) {

    updateBoneProperties();
//    map<string, ofxFBXBone >::iterator it;
//    for(it = bones.begin(); it != bones.end(); ++it ) {
//        ofxFBXBone* bone    = &it->second;
//        ofxFBXBone* sbone   = getSourceBone( it->first );
//        if( sbone != NULL ) {
//            if( bone->isExternalControlEnabled() ) {
//                sbone->enableExternalControl();
//            } else {
//                sbone->disableExternalControl();
//            }
//
//            if( bone->isAnimationEnabled() ) {
//                sbone->enableAnimation();
//            } else {
//                sbone->disableAnimation();
//            }
//        }
//    }

    map<string, ofxFBXBone >::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        ofxFBXBone* bone    = &it->second;
        ofxFBXBone* sbone   = getSourceBone( it->first );
        if( sbone != NULL ) {
            sbone->update( pTime, pPose );
        }
    }
    for(it = bones.begin(); it != bones.end(); ++it ) {
        ofxFBXBone* bone    = &it->second;
        ofxFBXBone* sbone   = getSourceBone( it->first );
        if( sbone != NULL ) {
            bone->setTransformMatrix( sbone->getLocalTransformMatrix() );
        }
    }
}

//--------------------------------------------------------------
void ofxFBXSkeleton::lateUpdate() {
    map<string, ofxFBXBone >::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        ofxFBXBone* bone    = &it->second;
        ofxFBXBone* sbone   = getSourceBone( it->first );
        if( sbone != NULL ) {
            sbone->setGlobalOrientation( bone->getGlobalOrientation() );
            sbone->setGlobalPosition( bone->getGlobalPosition() );
        }
    }

    for(it = bones.begin(); it != bones.end(); ++it ) {
        ofxFBXBone* bone    = &it->second;
        ofxFBXBone* sbone   = getSourceBone( it->first );
        if( sbone != NULL ) {
            sbone->updateFbxTransform();
        }
    }
}

//--------------------------------------------------------------
void ofxFBXSkeleton::updateWithAnimation( FbxTime& pTime, FbxPose* pPose ) {

    updateBoneProperties();
//    map<string, ofxFBXBone >::iterator it;
//    for(it = bones.begin(); it != bones.end(); ++it ) {
//        ofxFBXBone* bone    = &it->second;
//        ofxFBXBone* sbone   = getSourceBone( it->first );
//        if( sbone != NULL ) {
//            if( bone->isExternalControlEnabled() ) {
//                sbone->enableExternalControl();
//            } else {
//                sbone->disableExternalControl();
//            }
//
//            if( bone->isAnimationEnabled() ) {
//                sbone->enableAnimation();
//            } else {
//                sbone->disableAnimation();
//            }
//        }
//    }

    map<string, ofxFBXBone >::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        ofxFBXBone* bone    = &it->second;
        ofxFBXBone* sbone   = getSourceBone( it->first );
        if( sbone != NULL ) {
            sbone->update( pTime, pPose );
            bone->setTransformMatrix( sbone->getLocalTransformMatrix() );
        }
    }
}

//--------------------------------------------------------------
void ofxFBXSkeleton::lateUpdateWithAnimation() {
    map<string, ofxFBXBone >::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        ofxFBXBone* bone    = &it->second;
        ofxFBXBone* sbone   = getSourceBone( it->first );
        if( sbone != NULL ) {
            sbone->setTransformMatrix( bone->getLocalTransformMatrix() );
//            sbone->localTransformMatrix = bone->localTransformMatrix;
            sbone->setPosition( bone->getPosition() );
            sbone->setOrientation( bone->getOrientationQuat() );
            sbone->setScale( bone->getScale() );
        }
    }

    for(it = bones.begin(); it != bones.end(); ++it ) {
        ofxFBXBone* bone    = &it->second;
        ofxFBXBone* sbone   = getSourceBone( it->first );
        if( sbone != NULL ) {
            sbone->updateFbxTransform();
        }
    }
}

//--------------------------------------------------------------
void ofxFBXSkeleton::updateFromCachedSkeleton( shared_ptr< ofxFBXSkeleton> aSkeleton ) {

//    updateBoneProperties();
    map<string, ofxFBXBone >::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        ofxFBXBone* bone    = &it->second;
//        ofxFBXBone* sbone   = getSourceBone( it->first );
//        ofxFBXBone* sbone = aSkeleton->getSourceBone( it->first );
        ofxFBXBone* obone = aSkeleton->getBone( it->first );
        if( obone != NULL ) {
//
//            localTransformMatrix = m44;
//
//            ofQuaternion so;
//            localTransformMatrix.decompose(position, orientation, scale, so);
//
//            onPositionChanged();
//            onOrientationChanged();
//            onScaleChanged();

//            sbone->update( pTime, NULL );
            bone->setTransformMatrix( obone->getLocalTransformMatrix() );
//            bone->localTransformMatrix = obone->localTransformMatrix;
            bone->setPosition( obone->getPosition() );
            bone->setOrientation( obone->getOrientationQuat() );
            bone->setScale( obone->getScale() );

        } else {
            ofLogWarning() << "updateFromCachedSkeleton: " << it->first << " is null !!" << endl;
        }
    }
}

//--------------------------------------------------------------
void ofxFBXSkeleton::updateBoneProperties() {
    map<string, ofxFBXBone >::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        ofxFBXBone* bone    = &it->second;
        ofxFBXBone* sbone   = getSourceBone( it->first );
        if( sbone != NULL ) {
            if( bone->isExternalControlEnabled() ) {
                sbone->enableExternalControl();
            } else {
                sbone->disableExternalControl();
            }

            if( bone->isAnimationEnabled() ) {
                sbone->enableAnimation();
            } else {
                sbone->disableAnimation();
            }
        }
    }
}

//--------------------------------------------------------------
void ofxFBXSkeleton::draw( float aLen ) {
    map<string, ofxFBXBone>::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        it->second.draw(aLen);
    }
}

//--------------------------------------------------------------
void ofxFBXSkeleton::addBone( string aName, ofxFBXBone* aBone ) {
    if(aName == "") {
        ofLogWarning("ofxFBXSkeleton :: addBone : name is empty, not adding bone");
        return;
    }
    if(bones.find(aName) != bones.end()) {
        // the bone has a duplicate name, try to make a unique key //
        aName += ofToString(numBones,0);
    }

    vector <string> strs;// = ofSplitString(aName, ":");

    ofxFBXBone tbone = *aBone;
    string newBoneName = aName;
    if(strs.size() > 1) {
        newBoneName = strs[1];
    }

//    cout << "adding a bone with name -" << newBoneName << "- parent name -" << getName() <<"-" << endl;

    sourceBones[ newBoneName ]    = aBone;
    bones[ newBoneName ]          = tbone;

//    cout << "ofxFBXSkeleton :: addBone : name: " << aName << " ptr parent = " << aBone->getParent() << " other: " << tbone.getParent() << endl;

    numBones++;
}

//--------------------------------------------------------------
ofxFBXBone* ofxFBXSkeleton::getBone( string aName ) {
    if(bones.find(aName) != bones.end()) {
        return &bones[ aName ];
    }
    cout << "did not find the bone with name: " << aName << " | " << ofGetElapsedTimef() << endl;
    return NULL;
}

//--------------------------------------------------------------
ofxFBXBone* ofxFBXSkeleton::getSourceBone( string aName ) {
    if(bones.find(aName) != bones.end()) {
        return sourceBones[ aName ];
    }
    return NULL;
}

//--------------------------------------------------------------
void ofxFBXSkeleton::enableExternalControl( string aName ) {
    // loop through hierarchy to make children also controlled externally
    ofxFBXBone* bone = getBone( aName );
    if(bone == NULL) {
        ofLogWarning("ofxFBXSkeleton :: enableExternalControl : can not find bone with name ") << aName;
        return;
    }
    bone->enableExternalControl();

    enableExternalControlRecursive( getSourceBone(aName) );

}

//--------------------------------------------------------------
void ofxFBXSkeleton::enableExternalControlRecursive( ofxFBXBone* aBone ) {
    if( aBone == NULL ) return;
    map<string, ofxFBXBone* >::iterator it;
    for(it = sourceBones.begin(); it != sourceBones.end(); ++it ) {
        if( it->second->fbxNode->GetParent() == aBone->fbxNode ) {
//            it->second->enableExternalControl();
            getBone( it->first )->enableExternalControl();
            enableExternalControlRecursive( it->second );
        }
    }
}

//--------------------------------------------------------------
void ofxFBXSkeleton::enableAnimation() {
    map<string, ofxFBXBone >::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        it->second.enableAnimation();
    }
}

//--------------------------------------------------------------
void ofxFBXSkeleton::disableAnimation() {
    map<string, ofxFBXBone >::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        it->second.disableAnimation();
    }
}

//--------------------------------------------------------------
int ofxFBXSkeleton::getNumBones() {
    return (int)bones.size();
}

//--------------------------------------------------------------
void ofxFBXSkeleton::reset() {
    map<string, ofxFBXBone >::iterator it;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        it->second.reset();
    }
}

//--------------------------------------------------------------
string ofxFBXSkeleton::toString() {
    map<string, ofxFBXBone >::iterator it;
    map< string, bool > printMap;
    for(it = bones.begin(); it != bones.end(); ++it ) {
        printMap[ it->first ] = false;
    }

    stringstream ss;
    ss << "Skeleton: " << getName() << " - Number of bones: " << bones.size() << endl;

    if( bones.size() ) {
        printOutBoneRecursive(ss, sourceBones.begin()->first, printMap, "" );
    } else {
        ss << "NO BONES" << endl;
    }

    return ss.str().c_str();
}

//--------------------------------------------------------------
void ofxFBXSkeleton::printOutBoneRecursive( stringstream& aSS, string aBoneName, map< string, bool >& aPrintMap, string aSpacer ) {
    if( aPrintMap[ aBoneName ] ) return;

    aPrintMap[ aBoneName ] = true;
    ofxFBXBone* bone = getSourceBone( aBoneName );
    if( bone == NULL ) return;

    aSS << aSpacer << " bone: " << aBoneName << " parent: " << bone->parentBoneName << endl;
    aSpacer += "---";

    map<string, ofxFBXBone*>::iterator it;
    for(it = sourceBones.begin(); it != sourceBones.end(); ++it ) {
        if( it->second->fbxNode->GetParent() == bone->fbxNode ) {
            printOutBoneRecursive( aSS, it->first, aPrintMap, aSpacer );
        }
    }
}

<|endoftext|>


<commit_before>#include "MazeFileUtilities.h"

#include <fstream>
#include <iostream>
#include <iterator>
#include <sstream>
#include <vector>

#ifdef _WIN32
    #include <windows.h>
#elif __linux
    #include <limits.h>
    #include <unistd.h>
#endif

namespace sim {

std::string getProjectDirectory(){

    // This approach is claimed to be more reliable than argv[0] on windows
    // and linux.  On Windows GetModuleFileName is the directory to the executable
    // which is located in /mms/src/Debug/.  On linux /proc/self/exe is a path to exe.
    // This aproach does not work for all flavors to Linux, should on the common.
    // executable on Linux is located at /mms/bin/

    std::string path;

#ifdef _WIN32
    char result[MAX_PATH];
    path = std::string(result, GetModuleFileName(NULL, result, MAX_PATH));
    path = path.substr(0, path.find_last_of("\\/"));; // Remove the executable name as it is part of path
    path += "\\..\\..\\"; // Point to /mms/
    // Windows uses \ in directory
#elif __linux
    char result[PATH_MAX];
    ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
    path = std::string(result, (count > 0) ? count : 0);
    path = path.substr(0, path.find_last_of("\\/"));; // Remove the executable name as it is part of path
    path += "/../"; // Point to /mms/
#endif

    return path;
}

std::string getMazeFileDirPath(){

    std::string path;

    path = getProjectDirectory();

    // Append mazeFile directory path from the root of the project
    path += "src/maze_files/";

    return path;
}

/*int mazeFileWidth(std::string mazeFilePath){

}

int mazeFileHeight(std::string mazeFilePath){

}
*/

bool checkValidMazeFile(std::string mazeFilePath){

    // TODO: Ensure that you have unique y values for all x values
    // TODO: Ensure that the walls line up
    // TODO: Make a mazeFileValidator - gets height, width, valid, etc

    // This function validates following:
    // 1.) There are an equal number of y values for each x value
    // 2.) All the x and y values are unique
    // 3.) The walls are valid

    // Create the file object
    std::ifstream file(mazeFilePath.c_str());

    // Initialize a string variable
    std::string line("");

    if (file.is_open()){

        // Vector that counts the number of y values colums for each x value // TODO
        std::vector<int> counts;
        counts.push_back(0);
        int xValue = 0;

        while (getline(file, line)){
            std::istringstream iss(line);
            std::vector<std::string> tokens;
            copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(),
                 std::back_inserter<std::vector<std::string> >(tokens));

            // Counting logic // TODO
            /*if (tokens.at(0) == xValue){
                counts.at(xValue) += 1;
            }
            else{
                xValue = tokens.at(0);
                counts.push_back(1);
            }*/
        }

        file.close();

        /*int numberOfYValues = counts.at(0);
        for (int i = 1; i < counts.size(); i += 1){
            if (counts.at(i) != numberOfYValues){
                return 0;
            }
        }*/

    }

    // false indicates invalid file
    return false;
}

bool checkValidMazeFileTom(std::string mazeFilePath, int height, int width){

    // Create the file object
    std::ifstream file(mazeFilePath.c_str());

    // Error opening file
    if (!file.is_open()) {
        return false;
    }

    // Initialize a string variable
    std::string line("");

    int expected_x_pos = 0;
    int expected_y_pos = 0;

    int current_int = 0;

    while (std::getline(file, line)) {

        if (!hasOnlyDigits(line)){ // The line has some non digit characters
            return false;
        }

        for (int i = 0; i < 6; i += 1) {

            if (line.at(0) == ' '){ //Check that the first character is not a space
                                    //This would only occur if two spaces apear in a row
                return false;
            }

            current_int = std::strtol(line.c_str(), nullptr, 10);  //Get the next int an integer which is followed by a space

            if (i == 0 && current_int != expected_x_pos){ // X Pos on line does not match the expected X Position
                return false;
            }
            if (i == 1){ // Y Pos Handliing
                if (current_int != expected_y_pos){ // Y Pos on line does not match the expected Y Position
                    return false;
                }

                expected_y_pos += 1; // Add one to the expected Y_position

                if (expected_y_pos == height) { // Wrap Around
                    expected_y_pos = 0;
                    expected_x_pos += 1; // X-Pos will increase
                }
            }
            if (i > 1 && !(current_int == 0 || current_int == 1)) { // Wall Values - check if 1 or 0
                return false;
            }

            std::size_t found = line.find_first_of(" ");
            if (found != std::string::npos) { // extra space exists in the string
                line = line.substr(line.find_first_of(" ") + 1, line.length());
                if (i == 5) {
                    return false; // return false if more spaces after last digit remain
                }
            }
            else if (i != 5) {
                return false; // If no more spaces before the last digit that means the line
                                  // does not have enough digits
            }
        }
    }

    if (expected_x_pos != width && expected_y_pos != 0) {
        return false; // Not all lines present in the last group
    }

    // TODO: Maze validation - has a path to the center, no wall following robot, etc.

    // TODO: Make sure the neighboring tiles have corresponding walls (if a tile has
    // a wall to the right, the tile to its right should have a wall to the left, etc.)

    return true; //should be fine
}

bool hasOnlyDigits(const std::string &str) {
    return str.find_first_not_of("0123456789 ") == std::string::npos;
}

} // namespace sim
<commit_msg>Maze valid fix<commit_after>#include "MazeFileUtilities.h"

#include <fstream>
#include <iostream>
#include <iterator>
#include <sstream>
#include <vector>

#ifdef _WIN32
    #include <windows.h>
#elif __linux
    #include <limits.h>
    #include <unistd.h>
#endif

namespace sim {

std::string getProjectDirectory(){

    // This approach is claimed to be more reliable than argv[0] on windows
    // and linux.  On Windows GetModuleFileName is the directory to the executable
    // which is located in /mms/src/Debug/.  On linux /proc/self/exe is a path to exe.
    // This aproach does not work for all flavors to Linux, should on the common.
    // executable on Linux is located at /mms/bin/

    std::string path;

#ifdef _WIN32
    char result[MAX_PATH];
    path = std::string(result, GetModuleFileName(NULL, result, MAX_PATH));
    path = path.substr(0, path.find_last_of("\\/"));; // Remove the executable name as it is part of path
    path += "\\..\\..\\"; // Point to /mms/
    // Windows uses \ in directory
#elif __linux
    char result[PATH_MAX];
    ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
    path = std::string(result, (count > 0) ? count : 0);
    path = path.substr(0, path.find_last_of("\\/"));; // Remove the executable name as it is part of path
    path += "/../"; // Point to /mms/
#endif

    return path;
}

std::string getMazeFileDirPath(){

    std::string path;

    path = getProjectDirectory();

    // Append mazeFile directory path from the root of the project
    path += "src/maze_files/";

    return path;
}

/*int mazeFileWidth(std::string mazeFilePath){

}

int mazeFileHeight(std::string mazeFilePath){

}
*/

bool checkValidMazeFile(std::string mazeFilePath){

    // TODO: Ensure that you have unique y values for all x values
    // TODO: Ensure that the walls line up
    // TODO: Make a mazeFileValidator - gets height, width, valid, etc

    // This function validates following:
    // 1.) There are an equal number of y values for each x value
    // 2.) All the x and y values are unique
    // 3.) The walls are valid

    // Create the file object
    std::ifstream file(mazeFilePath.c_str());

    // Initialize a string variable
    std::string line("");

    if (file.is_open()){

        // Vector that counts the number of y values colums for each x value // TODO
        std::vector<int> counts;
        counts.push_back(0);
        int xValue = 0;

        while (getline(file, line)){
            std::istringstream iss(line);
            std::vector<std::string> tokens;
            copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(),
                 std::back_inserter<std::vector<std::string> >(tokens));

            // Counting logic // TODO
            /*if (tokens.at(0) == xValue){
                counts.at(xValue) += 1;
            }
            else{
                xValue = tokens.at(0);
                counts.push_back(1);
            }*/
        }

        file.close();

        /*int numberOfYValues = counts.at(0);
        for (int i = 1; i < counts.size(); i += 1){
            if (counts.at(i) != numberOfYValues){
                return 0;
            }
        }*/

    }

    // false indicates invalid file
    return false;
}

bool checkValidMazeFileTom(std::string mazeFilePath, int height, int width){

    // Create the file object
    std::ifstream file(mazeFilePath.c_str());

    // Error opening file
    if (!file.is_open()) {
        return false;
    }

    // Initialize a string variable
    std::string line("");

    int expected_x_pos = 0;
    int expected_y_pos = -1;

    int current_int = 0;

    while (std::getline(file, line)) {

        if (!hasOnlyDigits(line)){ // The line has some non digit characters
            return false;
        }

        expected_y_pos += 1; // Add one to the expected Y_position

        if (expected_y_pos == height) { // Wrap Around
            expected_y_pos = 0;
            expected_x_pos += 1; // X-Pos will increase
        }

        if (expected_x_pos == width) {
            return false; // Too many lines, RUN
        }

        for (int i = 0; i < 6; i += 1) {

            if (line.at(0) == ' '){ //Check that the first character is not a space
                                    //This would only occur if two spaces apear in a row
                return false;
            }

            current_int = std::strtol(line.c_str(), nullptr, 10);  //Get the next int an integer which is followed by a space

            if (i == 0 && current_int != expected_x_pos){ // X Pos on line does not match the expected X Position
                return false;
            }
            if (i == 1){ // Y Pos Handliing
                if (current_int != expected_y_pos){ // Y Pos on line does not match the expected Y Position
                    return false;
                }
            }

            if (i > 1 && !(current_int == 0 || current_int == 1)) { // Wall Values - check if 1 or 0
                return false;
            }

            std::size_t found = line.find_first_of(" ");
            if (found != std::string::npos) { // extra space exists in the string
                line = line.substr(line.find_first_of(" ") + 1, line.length());
                if (i == 5) {
                    return false; // return false if more spaces after last digit remain
                }
            }
            else if (i != 5) {
                return false; // If no more spaces before the last digit that means the line
                                  // does not have enough digits
            }
        }
    }

    if (expected_x_pos != width - 1 && expected_y_pos != 0) {
        return false; // Not all lines present in the last group
    }

    // TODO: Maze validation - has a path to the center, no wall following robot, etc.

    // TODO: Make sure the neighboring tiles have corresponding walls (if a tile has
    // a wall to the right, the tile to its right should have a wall to the left, etc.)

    return true; //should be fine
}

bool hasOnlyDigits(const std::string &str) {
    return str.find_first_not_of("0123456789 ") == std::string::npos;
}

} // namespace sim
<|endoftext|>


<commit_before>#include <cmath>
#include <array>
#include <chrono>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <algorithm>

#include <sys/stat.h>

#include "simulation.h"
#include "codes/codes.h"

namespace detail {
inline bool file_exists(const std::string &fname) {
  struct stat buf;
  return (stat(fname.c_str(), &buf) != -1);
}
}

static std::array<double, 131> rates{
  { 0.01,  0.02,  0.03,  0.04,  0.05,  0.06,  0.07,  0.08,  0.09,  0.10,  0.11,
    0.12,  0.13,  0.14,  0.15,  0.16,  0.17,  0.18,  0.19,  0.20,  0.21,  0.22,
    0.23,  0.24,  0.25,  0.26,  0.27,  0.28,  0.29,  0.30,  0.31,  0.32,  0.33,
    0.34,  0.35,  0.36,  0.37,  0.38,  0.39,  0.40,  0.41,  0.42,  0.43,  0.44,
    0.45,  0.46,  0.47,  0.48,  0.49,  0.50,  0.51,  0.52,  0.53,  0.54,  0.55,
    0.56,  0.57,  0.58,  0.59,  0.60,  0.61,  0.62,  0.63,  0.64,  0.65,  0.66,
    0.67,  0.68,  0.69,  0.70,  0.71,  0.72,  0.73,  0.74,  0.75,  0.76,  0.77,
    0.78,  0.79,  0.800, 0.807, 0.817, 0.827, 0.837, 0.846, 0.855, 0.864, 0.872,
    0.880, 0.887, 0.894, 0.900, 0.907, 0.913, 0.918, 0.924, 0.929, 0.934, 0.938,
    0.943, 0.947, 0.951, 0.954, 0.958, 0.961, 0.964, 0.967, 0.970, 0.972, 0.974,
    0.976, 0.978, 0.980, 0.982, 0.983, 0.984, 0.985, 0.986, 0.987, 0.988, 0.989,
    0.990, 0.991, 0.992, 0.993, 0.994, 0.995, 0.996, 0.997, 0.998, 0.999 }
};

static std::array<double, 131> limits = {
  { -1.548, -1.531, -1.500, -1.470, -1.440, -1.409, -1.378, -1.347, -1.316,
    -1.285, -1.254, -1.222, -1.190, -1.158, -1.126, -1.094, -1.061, -1.028,
    -0.995, -0.963, -0.928, -0.896, -0.861, -0.827, -0.793, -0.757, -0.724,
    -0.687, -0.651, -0.616, -0.579, -0.544, -0.507, -0.469, -0.432, -0.394,
    -0.355, -0.314, -0.276, -0.236, -0.198, -0.156, -0.118, -0.074, -0.032,
    0.010,  0.055,  0.097,  0.144,  0.188,  0.233,  0.279,  0.326,  0.374,
    0.424,  0.474,  0.526,  0.574,  0.628,  0.682,  0.734,  0.791,  0.844,
    0.904,  0.960,  1.021,  1.084,  1.143,  1.208,  1.275,  1.343,  1.412,
    1.483,  1.554,  1.628,  1.708,  1.784,  1.867,  1.952,  2.045,  2.108,
    2.204,  2.302,  2.402,  2.503,  2.600,  2.712,  2.812,  2.913,  3.009,
    3.114,  3.205,  3.312,  3.414,  3.500,  3.612,  3.709,  3.815,  3.906,
    4.014,  4.115,  4.218,  4.304,  4.425,  4.521,  4.618,  4.725,  4.841,
    4.922,  5.004,  5.104,  5.196,  5.307,  5.418,  5.484,  5.549,  5.615,
    5.681,  5.756,  5.842,  5.927,  6.023,  6.119,  6.234,  6.360,  6.495,
    6.651,  6.837,  7.072,  7.378,  7.864 }
};

static constexpr double ebno(const double rate) {
  if (rate <= 0.800) {
    const size_t index = static_cast<size_t>(rate * 100);
    return limits.at(index);
  } else if (rate >= 0.999) {
    return limits.back();
  } else {
    const size_t offset = 80;
    const size_t index = static_cast<size_t>(std::distance(
        std::cbegin(rates),
        std::find_if(std::cbegin(rates) + offset, std::cend(rates) - 1,
                     [=](const double r) { return r >= rate; })));
    return limits.at(index);
  }
}

static std::ofstream open_file(const std::string &fname) {
  if (detail::file_exists(fname)) {
    std::ostringstream os;
    os << "File " << fname << " already exists.";
    throw std::runtime_error(os.str());
  }

  std::ofstream log_file(fname.c_str(), std::ofstream::out);
  return log_file;
}

double awgn_simulation::sigma(const double eb_no) const {
  return 1.0f / sqrt((2 * decoder.rate() * pow(10, eb_no / 10.0)));
}

awgn_simulation::awgn_simulation(const class decoder &decoder_,
                                 const double step_, const uint64_t seed_)
    : decoder(decoder_), step(step_), seed(seed_) {}

void awgn_simulation::operator()() {
  const size_t wer_width = std::numeric_limits<double>::digits10;
  const size_t ebno_width = 6;
  std::ofstream log_file(open_file(decoder.to_string() + ".log"));
  std::vector<float> b(decoder.n());

  log_file << std::setw(ebno_width + 1) << "ebno"
           << " ";
  log_file << std::setw(wer_width + 6) << "wer" << std::endl;

  const size_t factor = static_cast<size_t>(1.0 / step);
  const size_t tmp = static_cast<size_t>(ebno(decoder.rate()) / step);
  const double start = (tmp + (1.0 / step)) * step;
  const double max = std::max(8.0, start) + step / 2;

  /* TODO round ebno() up to next step */
  for (double eb_no = start; eb_no < max; eb_no += step) {
    std::normal_distribution<float> distribution(
        1.0, static_cast<float>(sigma(eb_no)));
    auto noise = std::bind(std::ref(distribution), std::ref(generator));
    size_t word_errors = 0;
    size_t samples = 10000;

    std::cout << std::this_thread::get_id() << " " << decoder.to_string()
              << ": E_b/N_0 = " << eb_no << " with " << samples << " … ";
    std::cout.flush();
    auto start_time = std::chrono::high_resolution_clock::now();

    for (size_t i = 0; i < samples; i++) {
      std::generate(std::begin(b), std::end(b), noise);
      try {
        auto result = decoder.correct(b);
        if (std::any_of(std::cbegin(result), std::cend(result),
                        [](const auto &bit) { return bool(bit); })) {
          word_errors++;
        }
      }
      catch (const decoding_failure &) {
        word_errors++;
      }
    }

    auto end_time = std::chrono::high_resolution_clock::now();
    auto seconds = std::chrono::duration_cast<std::chrono::seconds>(
        end_time - start_time).count();
    std::cout << seconds << " s" << std::endl;

    log_file << std::setw(ebno_width + 1) << std::setprecision(ebno_width)
             << std::defaultfloat << eb_no << " ";
    log_file << std::setw(wer_width + 1) << std::setprecision(wer_width)
             << std::scientific << (double)word_errors / samples << std::endl;
  }
}

bitflip_simulation::bitflip_simulation(const class decoder &decoder,
                                       const size_t errors)
    : decoder(decoder), errors(errors) {}

void bitflip_simulation::operator()() const {
  const size_t wer_width = std::numeric_limits<double>::digits10;
  const size_t ebno_width = 6;

  std::ofstream log_file(open_file(decoder.to_string() + ".log"));
  std::vector<float> b(decoder.n());

  log_file << std::setw(ebno_width + 1) << "errors"
           << " ";
  log_file << std::setw(wer_width + 6) << "wer" << std::endl;

  const size_t length = decoder.n();

  for (size_t error = 0; error <= errors; error++) {
    size_t patterns = 0;
    size_t word_errors = 0;
    std::vector<int> b;

    std::fill_n(std::back_inserter(b), length - error, 0);
    std::fill_n(std::back_inserter(b), error, 1);

    std::cout << std::this_thread::get_id() << " " << decoder.to_string()
              << ": errors = " << error << " … ";
    std::cout.flush();
    auto start = std::chrono::high_resolution_clock::now();

    do {
      std::vector<float> x;
      x.reserve(length);

      std::transform(std::cbegin(b), std::cend(b), std::back_inserter(x),
                     [](const auto &bit) { return -2 * bit + 1; });

      patterns++;
      try {
        auto result = decoder.correct(x);
        if (std::any_of(std::cbegin(result), std::cend(result),
                        [](const auto &bit) { return bool(bit); })) {
          word_errors++;
        }
      }
      catch (const decoding_failure &) {
        word_errors++;
      }
    } while (std::next_permutation(std::begin(b), std::end(b)));

    auto end = std::chrono::high_resolution_clock::now();
    auto seconds =
        std::chrono::duration_cast<std::chrono::seconds>(end - start).count();
    std::cout << seconds << " s " << word_errors << " " << patterns
              << std::endl;

    log_file << std::setw(ebno_width + 1) << std::setprecision(ebno_width)
             << std::defaultfloat << error << " ";
    log_file << std::setw(wer_width + 1) << std::setprecision(wer_width)
             << std::scientific << (double)word_errors / patterns << std::endl;
  }
}

std::atomic_bool thread_pool::running{ true };
std::mutex thread_pool::lock;
std::condition_variable thread_pool::cv;
std::list<std::function<void(void)> > thread_pool::queue;

thread_pool::thread_pool() {
  for (unsigned i = 0; i < std::thread::hardware_concurrency(); i++) {
    pool.emplace_back(std::bind(&thread_pool::thread_function, this));
  }
}

thread_pool::~thread_pool() {
  running = false;
  cv.notify_all();
  for (auto &&t : pool)
    t.join();
}

void thread_pool::thread_function() const {
  for (;;) {
    bool have_work = false;
    std::function<void(void)> work;
    {
      std::unique_lock<std::mutex> m(lock);

      /*
       * empty running wait
       * 0     0       0
       * 0     1       0
       * 1     0       0
       * 1     1       1
      */
      cv.wait(m, [&]() { return !(queue.empty() && running); });
      if (!queue.empty()) {
        work = queue.front();
        queue.pop_front();
        have_work = true;
      }
    }

    if (have_work) {
      try {
        work();
      }
      catch (const std::exception &e) {
        std::cerr << e.what() << std::endl;
      }
    } else if (!running) {
      return;
    }
  }
}

<commit_msg>Replace old-style cast with static_cast<commit_after>#include <cmath>
#include <array>
#include <chrono>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <algorithm>

#include <sys/stat.h>

#include "simulation.h"
#include "codes/codes.h"

namespace detail {
inline bool file_exists(const std::string &fname) {
  struct stat buf;
  return (stat(fname.c_str(), &buf) != -1);
}
}

static std::array<double, 131> rates{
  { 0.01,  0.02,  0.03,  0.04,  0.05,  0.06,  0.07,  0.08,  0.09,  0.10,  0.11,
    0.12,  0.13,  0.14,  0.15,  0.16,  0.17,  0.18,  0.19,  0.20,  0.21,  0.22,
    0.23,  0.24,  0.25,  0.26,  0.27,  0.28,  0.29,  0.30,  0.31,  0.32,  0.33,
    0.34,  0.35,  0.36,  0.37,  0.38,  0.39,  0.40,  0.41,  0.42,  0.43,  0.44,
    0.45,  0.46,  0.47,  0.48,  0.49,  0.50,  0.51,  0.52,  0.53,  0.54,  0.55,
    0.56,  0.57,  0.58,  0.59,  0.60,  0.61,  0.62,  0.63,  0.64,  0.65,  0.66,
    0.67,  0.68,  0.69,  0.70,  0.71,  0.72,  0.73,  0.74,  0.75,  0.76,  0.77,
    0.78,  0.79,  0.800, 0.807, 0.817, 0.827, 0.837, 0.846, 0.855, 0.864, 0.872,
    0.880, 0.887, 0.894, 0.900, 0.907, 0.913, 0.918, 0.924, 0.929, 0.934, 0.938,
    0.943, 0.947, 0.951, 0.954, 0.958, 0.961, 0.964, 0.967, 0.970, 0.972, 0.974,
    0.976, 0.978, 0.980, 0.982, 0.983, 0.984, 0.985, 0.986, 0.987, 0.988, 0.989,
    0.990, 0.991, 0.992, 0.993, 0.994, 0.995, 0.996, 0.997, 0.998, 0.999 }
};

static std::array<double, 131> limits = {
  { -1.548, -1.531, -1.500, -1.470, -1.440, -1.409, -1.378, -1.347, -1.316,
    -1.285, -1.254, -1.222, -1.190, -1.158, -1.126, -1.094, -1.061, -1.028,
    -0.995, -0.963, -0.928, -0.896, -0.861, -0.827, -0.793, -0.757, -0.724,
    -0.687, -0.651, -0.616, -0.579, -0.544, -0.507, -0.469, -0.432, -0.394,
    -0.355, -0.314, -0.276, -0.236, -0.198, -0.156, -0.118, -0.074, -0.032,
    0.010,  0.055,  0.097,  0.144,  0.188,  0.233,  0.279,  0.326,  0.374,
    0.424,  0.474,  0.526,  0.574,  0.628,  0.682,  0.734,  0.791,  0.844,
    0.904,  0.960,  1.021,  1.084,  1.143,  1.208,  1.275,  1.343,  1.412,
    1.483,  1.554,  1.628,  1.708,  1.784,  1.867,  1.952,  2.045,  2.108,
    2.204,  2.302,  2.402,  2.503,  2.600,  2.712,  2.812,  2.913,  3.009,
    3.114,  3.205,  3.312,  3.414,  3.500,  3.612,  3.709,  3.815,  3.906,
    4.014,  4.115,  4.218,  4.304,  4.425,  4.521,  4.618,  4.725,  4.841,
    4.922,  5.004,  5.104,  5.196,  5.307,  5.418,  5.484,  5.549,  5.615,
    5.681,  5.756,  5.842,  5.927,  6.023,  6.119,  6.234,  6.360,  6.495,
    6.651,  6.837,  7.072,  7.378,  7.864 }
};

static constexpr double ebno(const double rate) {
  if (rate <= 0.800) {
    const size_t index = static_cast<size_t>(rate * 100);
    return limits.at(index);
  } else if (rate >= 0.999) {
    return limits.back();
  } else {
    const size_t offset = 80;
    const size_t index = static_cast<size_t>(std::distance(
        std::cbegin(rates),
        std::find_if(std::cbegin(rates) + offset, std::cend(rates) - 1,
                     [=](const double r) { return r >= rate; })));
    return limits.at(index);
  }
}

static std::ofstream open_file(const std::string &fname) {
  if (detail::file_exists(fname)) {
    std::ostringstream os;
    os << "File " << fname << " already exists.";
    throw std::runtime_error(os.str());
  }

  std::ofstream log_file(fname.c_str(), std::ofstream::out);
  return log_file;
}

double awgn_simulation::sigma(const double eb_no) const {
  return 1.0f / sqrt((2 * decoder.rate() * pow(10, eb_no / 10.0)));
}

awgn_simulation::awgn_simulation(const class decoder &decoder_,
                                 const double step_, const uint64_t seed_)
    : decoder(decoder_), step(step_), seed(seed_) {}

void awgn_simulation::operator()() {
  const size_t wer_width = std::numeric_limits<double>::digits10;
  const size_t ebno_width = 6;
  std::ofstream log_file(open_file(decoder.to_string() + ".log"));
  std::vector<float> b(decoder.n());

  log_file << std::setw(ebno_width + 1) << "ebno"
           << " ";
  log_file << std::setw(wer_width + 6) << "wer" << std::endl;

  const size_t factor = static_cast<size_t>(1.0 / step);
  const size_t tmp = static_cast<size_t>(ebno(decoder.rate()) / step);
  const double start = (tmp + (1.0 / step)) * step;
  const double max = std::max(8.0, start) + step / 2;

  /* TODO round ebno() up to next step */
  for (double eb_no = start; eb_no < max; eb_no += step) {
    std::normal_distribution<float> distribution(
        1.0, static_cast<float>(sigma(eb_no)));
    auto noise = std::bind(std::ref(distribution), std::ref(generator));
    size_t word_errors = 0;
    size_t samples = 10000;

    std::cout << std::this_thread::get_id() << " " << decoder.to_string()
              << ": E_b/N_0 = " << eb_no << " with " << samples << " … ";
    std::cout.flush();
    auto start_time = std::chrono::high_resolution_clock::now();

    for (size_t i = 0; i < samples; i++) {
      std::generate(std::begin(b), std::end(b), noise);
      try {
        auto result = decoder.correct(b);
        if (std::any_of(std::cbegin(result), std::cend(result),
                        [](const auto &bit) { return bool(bit); })) {
          word_errors++;
        }
      }
      catch (const decoding_failure &) {
        word_errors++;
      }
    }

    auto end_time = std::chrono::high_resolution_clock::now();
    auto seconds = std::chrono::duration_cast<std::chrono::seconds>(
        end_time - start_time).count();
    std::cout << seconds << " s" << std::endl;

    log_file << std::setw(ebno_width + 1) << std::setprecision(ebno_width)
             << std::defaultfloat << eb_no << " ";
    log_file << std::setw(wer_width + 1) << std::setprecision(wer_width)
             << std::scientific << static_cast<double>(word_errors) / samples
             << std::endl;
  }
}

bitflip_simulation::bitflip_simulation(const class decoder &decoder,
                                       const size_t errors)
    : decoder(decoder), errors(errors) {}

void bitflip_simulation::operator()() const {
  const size_t wer_width = std::numeric_limits<double>::digits10;
  const size_t ebno_width = 6;

  std::ofstream log_file(open_file(decoder.to_string() + ".log"));
  std::vector<float> b(decoder.n());

  log_file << std::setw(ebno_width + 1) << "errors"
           << " ";
  log_file << std::setw(wer_width + 6) << "wer" << std::endl;

  const size_t length = decoder.n();

  for (size_t error = 0; error <= errors; error++) {
    size_t patterns = 0;
    size_t word_errors = 0;
    std::vector<int> b;

    std::fill_n(std::back_inserter(b), length - error, 0);
    std::fill_n(std::back_inserter(b), error, 1);

    std::cout << std::this_thread::get_id() << " " << decoder.to_string()
              << ": errors = " << error << " … ";
    std::cout.flush();
    auto start = std::chrono::high_resolution_clock::now();

    do {
      std::vector<float> x;
      x.reserve(length);

      std::transform(std::cbegin(b), std::cend(b), std::back_inserter(x),
                     [](const auto &bit) { return -2 * bit + 1; });

      patterns++;
      try {
        auto result = decoder.correct(x);
        if (std::any_of(std::cbegin(result), std::cend(result),
                        [](const auto &bit) { return bool(bit); })) {
          word_errors++;
        }
      }
      catch (const decoding_failure &) {
        word_errors++;
      }
    } while (std::next_permutation(std::begin(b), std::end(b)));

    auto end = std::chrono::high_resolution_clock::now();
    auto seconds =
        std::chrono::duration_cast<std::chrono::seconds>(end - start).count();
    std::cout << seconds << " s " << word_errors << " " << patterns
              << std::endl;

    log_file << std::setw(ebno_width + 1) << std::setprecision(ebno_width)
             << std::defaultfloat << error << " ";
    log_file << std::setw(wer_width + 1) << std::setprecision(wer_width)
             << std::scientific << (double)word_errors / patterns << std::endl;
  }
}

std::atomic_bool thread_pool::running{ true };
std::mutex thread_pool::lock;
std::condition_variable thread_pool::cv;
std::list<std::function<void(void)> > thread_pool::queue;

thread_pool::thread_pool() {
  for (unsigned i = 0; i < std::thread::hardware_concurrency(); i++) {
    pool.emplace_back(std::bind(&thread_pool::thread_function, this));
  }
}

thread_pool::~thread_pool() {
  running = false;
  cv.notify_all();
  for (auto &&t : pool)
    t.join();
}

void thread_pool::thread_function() const {
  for (;;) {
    bool have_work = false;
    std::function<void(void)> work;
    {
      std::unique_lock<std::mutex> m(lock);

      /*
       * empty running wait
       * 0     0       0
       * 0     1       0
       * 1     0       0
       * 1     1       1
      */
      cv.wait(m, [&]() { return !(queue.empty() && running); });
      if (!queue.empty()) {
        work = queue.front();
        queue.pop_front();
        have_work = true;
      }
    }

    if (have_work) {
      try {
        work();
      }
      catch (const std::exception &e) {
        std::cerr << e.what() << std::endl;
      }
    } else if (!running) {
      return;
    }
  }
}

<|endoftext|>