<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 RC 1        *
*                (c) 2006-2011 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include <sofa/simulation/common/Simulation.h>
#include <sofa/simulation/common/PrintVisitor.h>
#include <sofa/simulation/common/ExportGnuplotVisitor.h>
#include <sofa/simulation/common/InitVisitor.h>
#include <sofa/simulation/common/AnimateVisitor.h>
#include <sofa/simulation/common/MechanicalVisitor.h>
#include <sofa/simulation/common/CollisionVisitor.h>
#include <sofa/simulation/common/UpdateContextVisitor.h>
#include <sofa/simulation/common/UpdateMappingVisitor.h>
#include <sofa/simulation/common/ResetVisitor.h>
#include <sofa/simulation/common/VisualVisitor.h>
#include <sofa/simulation/common/ExportOBJVisitor.h>
#include <sofa/simulation/common/WriteStateVisitor.h>
#include <sofa/simulation/common/XMLPrintVisitor.h>
#include <sofa/simulation/common/PropagateEventVisitor.h>
#include <sofa/simulation/common/BehaviorUpdatePositionVisitor.h>
#include <sofa/simulation/common/AnimateBeginEvent.h>
#include <sofa/simulation/common/AnimateEndEvent.h>
#include <sofa/simulation/common/UpdateMappingEndEvent.h>
#include <sofa/simulation/common/CleanupVisitor.h>
#include <sofa/simulation/common/DeleteVisitor.h>
#include <sofa/simulation/common/UpdateBoundingBoxVisitor.h>
#include <sofa/simulation/common/UpdateLinksVisitor.h>

#include <sofa/helper/system/SetDirectory.h>
#include <sofa/helper/AdvancedTimer.h>

#include <sofa/core/ObjectFactory.h>
#include <sofa/core/visual/VisualParams.h>

#include <sofa/simulation/common/SceneLoaderFactory.h>

#include <fstream>
#include <string.h>

// #include <sofa/simulation/common/FindByTypeVisitor.h>

// #include <sofa/helper/system/FileRepository.h>

// #include <fstream>
// #include <string.h>
// #ifndef WIN32
// #include <locale.h>
// #endif

namespace sofa
{

namespace simulation
{

Node::SPtr Simulation::sRoot = NULL;

using namespace sofa::defaulttype;
Simulation::Simulation()
{
}

Simulation::~Simulation()
{
}
/// The (unique) simulation which controls the scene
Simulation::SPtr Simulation::theSimulation;

void setSimulation ( Simulation* s )
{
    Simulation::theSimulation.reset(s);

}

Simulation* getSimulation()
{
    return Simulation::theSimulation.get();
}

sofa::simulation::Node::SPtr Simulation::GetRoot()
{
    return sRoot;
}

/// Print all object in the graph
void Simulation::print ( Node* root )
{
    if ( !root ) return;
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();
    root->execute<PrintVisitor>(params);
}

/// Print all object in the graph
void Simulation::exportXML ( Node* root, const char* fileName )
{
    if ( !root ) return;
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();
    if ( fileName!=NULL )
    {
        std::ofstream out ( fileName );
        out << "<?xml version=\"1.0\"?>\n";

        XMLPrintVisitor print ( params, out );
        root->execute ( print );
    }
    else
    {
        XMLPrintVisitor print ( params, std::cout );
        root->execute ( print );
    }
}

/// Print all object in the graph
void Simulation::exportGraph ( Node* root, const char* filename )
{
    if ( !root ) return;

    SceneLoader *exporter = SceneLoaderFactory::getInstance()->getExporterEntryFileName(filename);

    if (exporter)
    {
        exporter->write(root,filename);
    }
    else
    {
        // unable to write the file
        std::cerr << "Simulation::exportGraph : Error : extension ("<<sofa::helper::system::SetDirectory::GetExtension(filename)<<") not handled for export" << std::endl;
    }
}

/// Initialize the scene.
void Simulation::init ( Node* root )
{
    //cerr<<"Simulation::init"<<endl;
    if ( !root ) return;
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();

    //setContext( root->getContext());

    if (!root->getAnimationLoop())
    {
        root->getContext()->sout
                <<"Default Animation Manager Loop will be used. Add DefaultAnimationLoop to the root node of scene file to remove this warning"
                        <<root->getContext()->sendl;

        DefaultAnimationLoop::SPtr aloop = sofa::core::objectmodel::New<DefaultAnimationLoop>(root);
        aloop->setName(core::objectmodel::BaseObject::shortName(aloop.get()));
        root->addObject(aloop);
    }

    if(!root->getVisualLoop())
    {
        root->getContext()->sout
                <<"Default Visual Manager Loop will be used. Add DefaultVisualManagerLoop to the root node of scene file to remove this warning"
                        <<root->getContext()->sendl;

        DefaultVisualManagerLoop::SPtr vloop = sofa::core::objectmodel::New<DefaultVisualManagerLoop>(root);
        vloop->setName(core::objectmodel::BaseObject::shortName(vloop.get()));
        root->addObject(vloop);
    }

    // all the objects have now been created, update the links
    root->execute<UpdateLinksVisitor>(params);

    // apply the init() and bwdInit() methods to all the components.
    // and put the VisualModels in a separate graph, rooted at getVisualRoot()
    root->execute<InitVisitor>(params);

    // Save reset state for later uses in reset()
    root->execute<StoreResetStateVisitor>(params);
    {
        // Why do we need  a copy of the params here ?
        sofa::core::MechanicalParams mparams(*params);
        root->execute<MechanicalPropagatePositionAndVelocityVisitor>(&mparams);
    }

    root->execute<UpdateBoundingBoxVisitor>(params);

    // propagate the visualization settings (showVisualModels, etc.) in the whole graph
    updateVisualContext(root);
}

void Simulation::initNode( Node* node)
{
    if(!node)
    {
        return;
    }
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();
    node->execute<InitVisitor>(params);

    //node->execute<MechanicalPropagatePositionAndVelocityVisitor>(params);
    //node->execute<MechanicalPropagateFreePositionVisitor>(params);
    {
        sofa::core::MechanicalParams mparams(*params);
        node->execute<MechanicalPropagatePositionAndVelocityVisitor>(&mparams);
        /*sofa::core::MultiVecCoordId xfree = sofa::core::VecCoordId::freePosition();
          mparams.x() = xfree;
          MechanicalPropagatePositionVisitor act(&mparams   // PARAMS FIRST //, 0, xfree, true);
          node->execute(act);*/
    }

    node->execute<StoreResetStateVisitor>(params);
}

/// Execute one timestep. If do is 0, the dt parameter in the graph will be used
void Simulation::animate ( Node* root, SReal dt )
{
    if ( !root ) {
        serr<<"Simulation::animate, no root found"<<sendl;
        return;
    }
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();

    sofa::core::behavior::BaseAnimationLoop* aloop = root->getAnimationLoop();
    if(aloop)
    {
        aloop->step(params,dt);
    }
    else
    {
        serr<<"ERROR in Simulation::animate(): AnimationLoop expected at the root node"<<sendl;
        return;
    }

}

void Simulation::updateVisual ( Node* root)
{
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();
    core::visual::VisualLoop* vloop = root->getVisualLoop();

    if(vloop)
    {
        vloop->updateStep(params);
    }
    else
    {
        serr<<"ERROR in updateVisual(): VisualLoop expected at the root node"<<sendl;
        return;
    }
}

/// Reset to initial state
void Simulation::reset ( Node* root )
{
    if ( !root ) return;
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();

    // start by resetting the time
    const core::behavior::BaseAnimationLoop *animLoop = root->getAnimationLoop();
    if (animLoop)
        root->setTime(animLoop->getResetTime());
    else
        root->setTime(0.);
    UpdateSimulationContextVisitor(sofa::core::ExecParams::defaultInstance()).execute(root);

    root->execute<CleanupVisitor>(params);
    root->execute<ResetVisitor>(params);
    sofa::core::MechanicalParams mparams(*params);
    root->execute<MechanicalPropagatePositionAndVelocityVisitor>(&mparams);
    root->execute<UpdateMappingVisitor>(params);
    root->execute<VisualUpdateVisitor>(params);
}

/// Initialize the textures
void Simulation::initTextures ( Node* root )
{

    if ( !root ) return;
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();
    core::visual::VisualLoop* vloop = root->getVisualLoop();

    if(vloop)
    {
        vloop->initStep(params);
    }
    else
    {
        serr<<"ERROR in initTextures() : VisualLoop expected at the root node"<<sendl;
        return;
    }
}

/// Compute the bounding box of the scene.
void Simulation::computeBBox ( Node* root, SReal* minBBox, SReal* maxBBox, bool init )
{
	if ( !root ) return;
    sofa::core::visual::VisualParams* vparams = sofa::core::visual::VisualParams::defaultInstance();
    core::visual::VisualLoop* vloop = root->getVisualLoop();
    if(vloop)
    {
        vloop->computeBBoxStep(vparams, minBBox, maxBBox, init);
    }
    else
    {
        serr<<"ERROR in computeBBox() : VisualLoop expected at the root node"<<sendl;
        return;
    }
}

/// Compute the bounding box of the scene.
void Simulation::computeTotalBBox ( Node* root, SReal* minBBox, SReal* maxBBox )
{
    assert ( root!=NULL );
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();
    root->execute<UpdateBoundingBoxVisitor>( params );
    defaulttype::BoundingBox bb = root->f_bbox.getValue();
    for(int i=0; i<3; i++){
        minBBox[i]= bb.minBBox()[i];
        maxBBox[i]= bb.maxBBox()[i];
    }
}

/// Update contexts. Required before drawing the scene if root flags are modified.
void Simulation::updateContext ( Node* root )
{
    if ( !root ) return;
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();
    root->execute<UpdateContextVisitor>(params);
}

/// Update only Visual contexts. Required before drawing the scene if root flags are modified.( can filter by specifying a specific element)
void Simulation::updateVisualContext (Node* root)
{
    if ( !root ) return;
    sofa::core::visual::VisualParams* vparams = sofa::core::visual::VisualParams::defaultInstance();
    core::visual::VisualLoop* vloop = root->getVisualLoop();

    if(vloop)
    {
        vloop->updateContextStep(vparams);
    }
    else
    {
        serr<<"ERROR in updateVisualContext() : VisualLoop expected at the root node"<<sendl;
        return;
    }

    /*
    UpdateVisualContextVisitor vis(vparams);
    vis.execute(root);*/
}
/// Render the scene
void Simulation::draw ( sofa::core::visual::VisualParams* vparams, Node* root )
{
    core::visual::VisualLoop* vloop = root->getVisualLoop();
    if(vloop)
    {
        if (!vparams) vparams = sofa::core::visual::VisualParams::defaultInstance();
        vparams->update();

        vloop->drawStep(vparams);
    }
    else
    {
        serr<<"ERROR in draw() : VisualLoop expected at the root node"<<sendl;
        return;
    }
}

/// Export a scene to an OBJ 3D Scene
void Simulation::exportOBJ ( Node* root, const char* filename, bool exportMTL )
{
    if ( !root ) return;
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();
    std::ofstream fout ( filename );

    fout << "# Generated from SOFA Simulation" << std::endl;

    if ( !exportMTL )
    {
        ExportOBJVisitor act ( params, &fout );
        root->execute ( &act );
    }
    else
    {
        const char *path1 = strrchr ( filename, '/' );
        const char *path2 = strrchr ( filename, '\\' );
        const char* path = ( path1==NULL ) ? ( ( path2==NULL ) ?filename : path2+1 ) : ( path2==NULL ) ? path1+1 : ( ( path1-filename ) > ( path2-filename ) ) ? path1+1 : path2+1;

        const char *ext = strrchr ( path, '.' );

        if ( !ext ) ext = path + strlen ( path );
        std::string mtlfilename ( path, ext );
        mtlfilename += ".mtl";
        std::string mtlpathname ( filename, ext );
        mtlpathname += ".mtl";
        std::ofstream mtl ( mtlpathname.c_str() );
        mtl << "# Generated from SOFA Simulation" << std::endl;
        fout << "mtllib "<<mtlfilename<<'\n';

        ExportOBJVisitor act ( params, &fout,&mtl );
        root->execute ( &act );
    }
}

void Simulation::dumpState ( Node* root, std::ofstream& out )
{
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();
    out<<root->getTime() <<" ";
    WriteStateVisitor ( params, out ).execute ( root );
    out<<endl;
}

/// Load a scene from a file
Node::SPtr Simulation::load ( const char *filename )
{
    SceneLoader *loader = SceneLoaderFactory::getInstance()->getEntryFileName(filename);

    if (loader)
    {
        sRoot = loader->load(filename);
        return sRoot;
    }

    // unable to load file
    std::cerr << "Simulation : Error : extension ("<<sofa::helper::system::SetDirectory::GetExtension(filename)<<") not handled" << std::endl;
    return NULL;
}

/// Delete a scene from memory. After this call the pointer is invalid
void Simulation::unload(Node::SPtr root)
{
    if ( !root ) return;
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();
    //if (dynamic_cast<Node*>(this->getContext()) == root)
    //{
    //    this->setContext(NULL);
    //}
    root->detachFromGraph();
    root->execute<CleanupVisitor>(params);
    root->execute<DeleteVisitor>(params);
}

} // namespace simulation

} // namespace sofa
<commit_msg>Simulation: improved messages<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 RC 1        *
*                (c) 2006-2011 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include <sofa/simulation/common/Simulation.h>
#include <sofa/simulation/common/PrintVisitor.h>
#include <sofa/simulation/common/ExportGnuplotVisitor.h>
#include <sofa/simulation/common/InitVisitor.h>
#include <sofa/simulation/common/AnimateVisitor.h>
#include <sofa/simulation/common/MechanicalVisitor.h>
#include <sofa/simulation/common/CollisionVisitor.h>
#include <sofa/simulation/common/UpdateContextVisitor.h>
#include <sofa/simulation/common/UpdateMappingVisitor.h>
#include <sofa/simulation/common/ResetVisitor.h>
#include <sofa/simulation/common/VisualVisitor.h>
#include <sofa/simulation/common/ExportOBJVisitor.h>
#include <sofa/simulation/common/WriteStateVisitor.h>
#include <sofa/simulation/common/XMLPrintVisitor.h>
#include <sofa/simulation/common/PropagateEventVisitor.h>
#include <sofa/simulation/common/BehaviorUpdatePositionVisitor.h>
#include <sofa/simulation/common/AnimateBeginEvent.h>
#include <sofa/simulation/common/AnimateEndEvent.h>
#include <sofa/simulation/common/UpdateMappingEndEvent.h>
#include <sofa/simulation/common/CleanupVisitor.h>
#include <sofa/simulation/common/DeleteVisitor.h>
#include <sofa/simulation/common/UpdateBoundingBoxVisitor.h>
#include <sofa/simulation/common/UpdateLinksVisitor.h>

#include <sofa/helper/system/SetDirectory.h>
#include <sofa/helper/AdvancedTimer.h>

#include <sofa/core/ObjectFactory.h>
#include <sofa/core/visual/VisualParams.h>

#include <sofa/simulation/common/SceneLoaderFactory.h>

#include <fstream>
#include <string.h>

// #include <sofa/simulation/common/FindByTypeVisitor.h>

// #include <sofa/helper/system/FileRepository.h>

// #include <fstream>
// #include <string.h>
// #ifndef WIN32
// #include <locale.h>
// #endif

namespace sofa
{

namespace simulation
{

Node::SPtr Simulation::sRoot = NULL;

using namespace sofa::defaulttype;
Simulation::Simulation()
{
    name.setValue("Simulation");
}

Simulation::~Simulation()
{
}
/// The (unique) simulation which controls the scene
Simulation::SPtr Simulation::theSimulation;

void setSimulation ( Simulation* s )
{
    Simulation::theSimulation.reset(s);

}

Simulation* getSimulation()
{
    return Simulation::theSimulation.get();
}

sofa::simulation::Node::SPtr Simulation::GetRoot()
{
    return sRoot;
}

/// Print all object in the graph
void Simulation::print ( Node* root )
{
    if ( !root ) return;
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();
    root->execute<PrintVisitor>(params);
}

/// Print all object in the graph
void Simulation::exportXML ( Node* root, const char* fileName )
{
    if ( !root ) return;
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();
    if ( fileName!=NULL )
    {
        std::ofstream out ( fileName );
        out << "<?xml version=\"1.0\"?>\n";

        XMLPrintVisitor print ( params, out );
        root->execute ( print );
    }
    else
    {
        XMLPrintVisitor print ( params, std::cout );
        root->execute ( print );
    }
}

/// Print all object in the graph
void Simulation::exportGraph ( Node* root, const char* filename )
{
    if ( !root ) return;

    SceneLoader *exporter = SceneLoaderFactory::getInstance()->getExporterEntryFileName(filename);

    if (exporter)
    {
        exporter->write(root,filename);
    }
    else
    {
        // unable to write the file
        serr << "exportGraph : Error : extension ("<<sofa::helper::system::SetDirectory::GetExtension(filename)<<") not handled for export" << sendl;
    }
}

/// Initialize the scene.
void Simulation::init ( Node* root )
{
    //cerr<<"Simulation::init"<<endl;
    if ( !root ) return;
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();

    //setContext( root->getContext());

    if (!root->getAnimationLoop())
    {
        root->getContext()->sout
                <<"Default Animation Manager Loop will be used. Add DefaultAnimationLoop to the root node of scene file to remove this warning"
                        <<root->getContext()->sendl;

        DefaultAnimationLoop::SPtr aloop = sofa::core::objectmodel::New<DefaultAnimationLoop>(root);
        aloop->setName(core::objectmodel::BaseObject::shortName(aloop.get()));
        root->addObject(aloop);
    }

    if(!root->getVisualLoop())
    {
        root->getContext()->sout
                <<"Default Visual Manager Loop will be used. Add DefaultVisualManagerLoop to the root node of scene file to remove this warning"
                        <<root->getContext()->sendl;

        DefaultVisualManagerLoop::SPtr vloop = sofa::core::objectmodel::New<DefaultVisualManagerLoop>(root);
        vloop->setName(core::objectmodel::BaseObject::shortName(vloop.get()));
        root->addObject(vloop);
    }

    // all the objects have now been created, update the links
    root->execute<UpdateLinksVisitor>(params);

    // apply the init() and bwdInit() methods to all the components.
    // and put the VisualModels in a separate graph, rooted at getVisualRoot()
    root->execute<InitVisitor>(params);

    // Save reset state for later uses in reset()
    root->execute<StoreResetStateVisitor>(params);
    {
        // Why do we need  a copy of the params here ?
        sofa::core::MechanicalParams mparams(*params);
        root->execute<MechanicalPropagatePositionAndVelocityVisitor>(&mparams);
    }

    root->execute<UpdateBoundingBoxVisitor>(params);

    // propagate the visualization settings (showVisualModels, etc.) in the whole graph
    updateVisualContext(root);
}

void Simulation::initNode( Node* node)
{
    if(!node)
    {
        return;
    }
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();
    node->execute<InitVisitor>(params);

    //node->execute<MechanicalPropagatePositionAndVelocityVisitor>(params);
    //node->execute<MechanicalPropagateFreePositionVisitor>(params);
    {
        sofa::core::MechanicalParams mparams(*params);
        node->execute<MechanicalPropagatePositionAndVelocityVisitor>(&mparams);
        /*sofa::core::MultiVecCoordId xfree = sofa::core::VecCoordId::freePosition();
          mparams.x() = xfree;
          MechanicalPropagatePositionVisitor act(&mparams   // PARAMS FIRST //, 0, xfree, true);
          node->execute(act);*/
    }

    node->execute<StoreResetStateVisitor>(params);
}

/// Execute one timestep. If do is 0, the dt parameter in the graph will be used
void Simulation::animate ( Node* root, SReal dt )
{
    if ( !root ) {
        serr<<"Simulation::animate, no root found"<<sendl;
        return;
    }
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();

    sofa::core::behavior::BaseAnimationLoop* aloop = root->getAnimationLoop();
    if(aloop)
    {
        aloop->step(params,dt);
    }
    else
    {
        serr<<"ERROR in Simulation::animate(): AnimationLoop expected at the root node"<<sendl;
        return;
    }

}

void Simulation::updateVisual ( Node* root)
{
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();
    core::visual::VisualLoop* vloop = root->getVisualLoop();

    if(vloop)
    {
        vloop->updateStep(params);
    }
    else
    {
        serr<<"ERROR in updateVisual(): VisualLoop expected at the root node"<<sendl;
        return;
    }
}

/// Reset to initial state
void Simulation::reset ( Node* root )
{
    if ( !root ) return;
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();

    // start by resetting the time
    const core::behavior::BaseAnimationLoop *animLoop = root->getAnimationLoop();
    if (animLoop)
        root->setTime(animLoop->getResetTime());
    else
        root->setTime(0.);
    UpdateSimulationContextVisitor(sofa::core::ExecParams::defaultInstance()).execute(root);

    root->execute<CleanupVisitor>(params);
    root->execute<ResetVisitor>(params);
    sofa::core::MechanicalParams mparams(*params);
    root->execute<MechanicalPropagatePositionAndVelocityVisitor>(&mparams);
    root->execute<UpdateMappingVisitor>(params);
    root->execute<VisualUpdateVisitor>(params);
}

/// Initialize the textures
void Simulation::initTextures ( Node* root )
{

    if ( !root ) return;
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();
    core::visual::VisualLoop* vloop = root->getVisualLoop();

    if(vloop)
    {
        vloop->initStep(params);
    }
    else
    {
        serr<<"ERROR in initTextures() : VisualLoop expected at the root node"<<sendl;
        return;
    }
}

/// Compute the bounding box of the scene.
void Simulation::computeBBox ( Node* root, SReal* minBBox, SReal* maxBBox, bool init )
{
	if ( !root ) return;
    sofa::core::visual::VisualParams* vparams = sofa::core::visual::VisualParams::defaultInstance();
    core::visual::VisualLoop* vloop = root->getVisualLoop();
    if(vloop)
    {
        vloop->computeBBoxStep(vparams, minBBox, maxBBox, init);
    }
    else
    {
        serr<<"ERROR in computeBBox() : VisualLoop expected at the root node"<<sendl;
        return;
    }
}

/// Compute the bounding box of the scene.
void Simulation::computeTotalBBox ( Node* root, SReal* minBBox, SReal* maxBBox )
{
    assert ( root!=NULL );
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();
    root->execute<UpdateBoundingBoxVisitor>( params );
    defaulttype::BoundingBox bb = root->f_bbox.getValue();
    for(int i=0; i<3; i++){
        minBBox[i]= bb.minBBox()[i];
        maxBBox[i]= bb.maxBBox()[i];
    }
}

/// Update contexts. Required before drawing the scene if root flags are modified.
void Simulation::updateContext ( Node* root )
{
    if ( !root ) return;
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();
    root->execute<UpdateContextVisitor>(params);
}

/// Update only Visual contexts. Required before drawing the scene if root flags are modified.( can filter by specifying a specific element)
void Simulation::updateVisualContext (Node* root)
{
    if ( !root ) return;
    sofa::core::visual::VisualParams* vparams = sofa::core::visual::VisualParams::defaultInstance();
    core::visual::VisualLoop* vloop = root->getVisualLoop();

    if(vloop)
    {
        vloop->updateContextStep(vparams);
    }
    else
    {
        serr<<"ERROR in updateVisualContext() : VisualLoop expected at the root node"<<sendl;
        return;
    }

    /*
    UpdateVisualContextVisitor vis(vparams);
    vis.execute(root);*/
}
/// Render the scene
void Simulation::draw ( sofa::core::visual::VisualParams* vparams, Node* root )
{
    core::visual::VisualLoop* vloop = root->getVisualLoop();
    if(vloop)
    {
        if (!vparams) vparams = sofa::core::visual::VisualParams::defaultInstance();
        vparams->update();

        vloop->drawStep(vparams);
    }
    else
    {
        serr<<"ERROR in draw() : VisualLoop expected at the root node"<<sendl;
        return;
    }
}

/// Export a scene to an OBJ 3D Scene
void Simulation::exportOBJ ( Node* root, const char* filename, bool exportMTL )
{
    if ( !root ) return;
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();
    std::ofstream fout ( filename );

    fout << "# Generated from SOFA Simulation" << std::endl;

    if ( !exportMTL )
    {
        ExportOBJVisitor act ( params, &fout );
        root->execute ( &act );
    }
    else
    {
        const char *path1 = strrchr ( filename, '/' );
        const char *path2 = strrchr ( filename, '\\' );
        const char* path = ( path1==NULL ) ? ( ( path2==NULL ) ?filename : path2+1 ) : ( path2==NULL ) ? path1+1 : ( ( path1-filename ) > ( path2-filename ) ) ? path1+1 : path2+1;

        const char *ext = strrchr ( path, '.' );

        if ( !ext ) ext = path + strlen ( path );
        std::string mtlfilename ( path, ext );
        mtlfilename += ".mtl";
        std::string mtlpathname ( filename, ext );
        mtlpathname += ".mtl";
        std::ofstream mtl ( mtlpathname.c_str() );
        mtl << "# Generated from SOFA Simulation" << std::endl;
        fout << "mtllib "<<mtlfilename<<'\n';

        ExportOBJVisitor act ( params, &fout,&mtl );
        root->execute ( &act );
    }
}

void Simulation::dumpState ( Node* root, std::ofstream& out )
{
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();
    out<<root->getTime() <<" ";
    WriteStateVisitor ( params, out ).execute ( root );
    out<<endl;
}

/// Load a scene from a file
Node::SPtr Simulation::load ( const char *filename )
{
    SceneLoader *loader = SceneLoaderFactory::getInstance()->getEntryFileName(filename);

    if (loader)
    {
        sRoot = loader->load(filename);
        return sRoot;
    }

    // unable to load file
    serr << "Error : extension ("<<sofa::helper::system::SetDirectory::GetExtension(filename)<<") not handled" << sendl;
    return NULL;
}

/// Delete a scene from memory. After this call the pointer is invalid
void Simulation::unload(Node::SPtr root)
{
    if ( !root ) return;
    sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance();
    //if (dynamic_cast<Node*>(this->getContext()) == root)
    //{
    //    this->setContext(NULL);
    //}
    root->detachFromGraph();
    root->execute<CleanupVisitor>(params);
    root->execute<DeleteVisitor>(params);
}

} // namespace simulation

} // namespace sofa
<|endoftext|>


<commit_before>#include <istream>

#include "parsers/bpn.hh"
#include "parsers/parse.hh"
#include "parsers/prod.hh"
#include "parsers/tina.hh"
#include "parsers/xml.hh"

namespace pnmc { namespace parsers {

/*------------------------------------------------------------------------------------------------*/

std::shared_ptr<pn::net>
parse(const conf::pnmc_configuration& conf, std::istream& in)
{
  std::shared_ptr<pn::net> net_ptr;

  switch (conf.file_type)
  {
    case (conf::input_format::bpn)  : return parsers::bpn(in);
    case (conf::input_format::prod) : return parsers::prod(in);
    case (conf::input_format::tina) : return parsers::tina(in);
    case (conf::input_format::xml)  : break;
  }
  return parsers::xml(in);
}

/*------------------------------------------------------------------------------------------------*/

}} // namespace pnmc::parsers
<commit_msg>Remove unused variable.<commit_after>#include <istream>

#include "parsers/bpn.hh"
#include "parsers/parse.hh"
#include "parsers/prod.hh"
#include "parsers/tina.hh"
#include "parsers/xml.hh"

namespace pnmc { namespace parsers {

/*------------------------------------------------------------------------------------------------*/

std::shared_ptr<pn::net>
parse(const conf::pnmc_configuration& conf, std::istream& in)
{
  switch (conf.file_type)
  {
    case (conf::input_format::bpn)  : return parsers::bpn(in);
    case (conf::input_format::prod) : return parsers::prod(in);
    case (conf::input_format::tina) : return parsers::tina(in);
    case (conf::input_format::xml)  : break;
  }
  return parsers::xml(in);
}

/*------------------------------------------------------------------------------------------------*/

}} // namespace pnmc::parsers
<|endoftext|>


<commit_before>#include "board.hpp"

#include <cstring>

#include <boost/lexical_cast.hpp>

#include "exception.hpp"
#include "walk_move.hpp"

namespace Quoridor {

Board::Board(int row_num, int col_num) : sides_(), pawn_sides_(), walls_()
{
    set_size(row_num, col_num);

    sides_.push_back(std::pair<int, int>(0, 0));
    sides_.push_back(std::pair<int, int>(2, 0));
    sides_.push_back(std::pair<int, int>(1, 0));
    sides_.push_back(std::pair<int, int>(3, 0));
}

Board::~Board()
{
}

void Board::set_size(int row_num, int col_num)
{
    if (row_num <= 0) {
        throw Exception("illegal row number: "
                + boost::lexical_cast<std::string>(row_num));
    }
    if (col_num <= 0) {
        throw Exception("illegal column number: "
                + boost::lexical_cast<std::string>(col_num));
    }
    row_num_ = row_num;
    col_num_ = col_num;

    bg_.set_size(row_num_, col_num_);
}

int Board::next_side() const
{
    for (auto &side : sides_) {
        if (side.second == 0) {
            side.second = 1;
            return side.first;
        }
    }
    return -1;
}

int Board::add_pawn(std::shared_ptr<Pawn> pawn)
{
    pawn_sides_[pawn] = next_side();
    int n;

    switch (pawn_sides_[pawn]) {
    case 0:
        n = col_num_ / 2;
        break;
    case 1:
        n = row_num_ / 2;
        break;
    case 2:
        n = (row_num_ - 1) * col_num_ + col_num_ / 2;
        break;
    case 3:
        n = (row_num_ / 2) * col_num_ + col_num_ - 1;
        break;
    default:
        throw Exception("invalid pawn side: "
                + boost::lexical_cast<std::string>(pawn_sides_[pawn]));
    }

    occ_nodes_[n] = pawn;
    pawn_nodes_[pawn] = n;

    return 0;
}

void Board::add_occupied(const pos_t &pos, std::shared_ptr<Pawn> pawn)
{
    int n = pos.row * col_num_ + pos.col;

    if (occ_nodes_.count(n) > 0) {
        throw Exception("cell (" + boost::lexical_cast<std::string>(pos.row)
                + ":" + boost::lexical_cast<std::string>(pos.col)
                + ") is already occupied");
    }

    occ_nodes_[n] = pawn;
    pawn_nodes_[pawn] = n;
}

void Board::rm_occupied(const pos_t &pos)
{
    int n = pos.row * col_num_ + pos.col;
    occ_nodes_.erase(n);
}

pos_t Board::pawn_pos(std::shared_ptr<Pawn> pawn) const
{
    int node = pawn_nodes_.at(pawn);
    pos_t pos;
    pos.row = row(node);
    pos.col = col(node);
    return pos;
}

bool Board::is_at_opposite_side(std::shared_ptr<Pawn> pawn) const
{
    int n = pawn_nodes_.at(pawn);
    switch (pawn_sides_.at(pawn)) {
    case 0:
        return row(n) == row_num_ - 1;
    case 1:
        return col(n) == col_num_ - 1;
    case 2:
        return row(n) == 0;
    case 3:
        return col(n) == 0;
    default:
        throw Exception("invalid board side: "
                + boost::lexical_cast<std::string>(pawn_sides_.at(pawn)));
    }
}

int Board::make_walking_move(int dir, std::shared_ptr<Pawn> pawn)
{
    dir = recalc_dir(dir, pawn);
    int cur_node = pawn_nodes_[pawn];
    int goal_node = cur_node;
    int r_goal_node = cur_node;

    switch (dir) {
        case WalkMove::Direction::kForward:
        goal_node += col_num_;
        r_goal_node = goal_node + col_num_;
        break;
    case WalkMove::Direction::kRight:
        ++goal_node;
        r_goal_node = goal_node + 1;
        break;
    case WalkMove::Direction::kBackward:
        goal_node -= col_num_;
        r_goal_node = goal_node - col_num_;
        break;
    case WalkMove::Direction::kLeft:
        --goal_node;
        r_goal_node = goal_node - 1;
        break;
    case WalkMove::Direction::kEnd:
    default:
        return -1;
    }

    if (is_possible_move(cur_node, goal_node)) {
        // the goal node is occupied by another pawn
        if (occ_nodes_.count(goal_node) > 0) {
            if (is_possible_move(goal_node, r_goal_node)) {
                goal_node = r_goal_node;
            }
            else {
                return -2;
            }
        }
    }
    else {
        return -1;
    }

    // update pawn's position
    occ_nodes_.erase(pawn_nodes_[pawn]);
    pawn_nodes_[pawn] = goal_node;
    occ_nodes_[goal_node] = pawn;

    return 0;
}

int Board::add_wall(const Wall &wall)
{
    int line_lim = (wall.orientation() ? col_num() : row_num()) - 1;
    int start_pos_lim = (wall.orientation() ? row_num() : col_num()) - 1;
    if ((wall.line() >= line_lim)
            || (wall.end_pos() >= start_pos_lim)) {
        return -1;
    }

    if (wall_intersects(wall)) {
        return -1;
    }

    walls_[wall.orientation()][wall.line()].insert(std::map<int, Wall>::value_type(wall.start_pos(), Wall(wall)));

    int node1;
    int node2;
    for (int i = 0; i < wall.cnt(); ++i) {
        if (wall.orientation() == 0) {
            node1 = wall.line() * row_num_ + wall.start_pos() + i;
            node2 = (wall.line() + 1) * row_num_ + wall.start_pos() + i;
        }
        else {
            node1 = (wall.start_pos() + i) * row_num_ + wall.line();
            node2 = (wall.start_pos() + i) * row_num_ + wall.line() + 1;
        }
        std::cout << "removing edge " << node1 << ":" << node2 << std::endl;
        bg_.remove_edges(node1, node2);
    }

    return 0;
}

int Board::try_add_wall(const Wall &wall)
{
    int line_lim = (wall.orientation() ? col_num() : row_num()) - 1;
    int start_pos_lim = (wall.orientation() ? row_num() : col_num()) - 1;
    if ((wall.line() >= line_lim)
            || (wall.end_pos() >= start_pos_lim)) {
        return -1;
    }

    if (wall_intersects(wall)) {
        return -1;
    }

    bg_.reset_filters();

    int node1;
    int node2;
    for (int i = 0; i < wall.cnt(); ++i) {
        if (wall.orientation() == 0) {
            node1 = wall.line() * row_num_ + wall.start_pos() + i;
            node2 = (wall.line() + 1) * row_num_ + wall.start_pos() + i;
        }
        else {
            node1 = (wall.start_pos() + i) * row_num_ + wall.line();
            node2 = (wall.start_pos() + i) * row_num_ + wall.line() + 1;
        }

        bg_.filter_edges(node1, node2);
    }

    bool path_blocked = true;

    for (auto pawn_node : pawn_nodes_) {
        std::vector<int> nodes;
        int side = pawn_sides_[pawn_node.first];
        path_blocked = true;

        side_nodes(side, &nodes);
        for (auto node : nodes) {
            if (bg_.is_path_exists(pawn_node.second, node)) {
                path_blocked = false;
                break;
            }
        }

        /* wall blocks all pathes to the opposite side for one of pawns */
        if (path_blocked) {
            break;
        }
    }

    if (path_blocked) {
        return -1;
    }

    return 0;
}

int Board::recalc_dir(int dir, std::shared_ptr<Pawn> pawn)
{
    return (dir + pawn_sides_[pawn]) % 4;
}

bool Board::is_possible_move(int cur_node, int goal_node) const
{
    return bg_.is_neighbours(cur_node, goal_node);
}

bool Board::wall_intersects(const Wall &wall) const
{
    // check intersections
    if (walls_.count(1 - wall.orientation()) > 0) {
        for (int i = 0; i < wall.cnt() - 1; ++i) {
            // there are walls on the intersected line
            if (walls_.at(1 - wall.orientation()).count(wall.start_pos()) != 0) {
                auto line_walls = walls_.at(1 - wall.orientation()).at(wall.start_pos() + i);
                auto it = line_walls.upper_bound(wall.line());

                // all walls on the line are settled before new wall
                if (it == line_walls.end()) {
                    auto rit = line_walls.rbegin();
                    if (rit->second.end_pos() >= wall.line()) {
                        return true;
                    }
                }
                else if (it != line_walls.begin()) {
                    --it;
                    if (it->second.end_pos() >= wall.line()) {
                        return true;
                    }
                }
            }
        }
    }

    // check overlaps
    if (walls_.count(wall.orientation()) > 0) {
        if (walls_.at(wall.orientation()).count(wall.line()) != 0) {
            auto line_walls = walls_.at(wall.orientation()).at(wall.line());
            auto it = line_walls.upper_bound(wall.start_pos());

            // all walls on the line are settled before new wall
            if (it == line_walls.end()) {
                auto rit = line_walls.rbegin();
                if (rit->second.end_pos() >= wall.start_pos()) {
                    return true;
                }
            }
            else {
                // check if new wall overlaps over next wall on the line
                if (wall.end_pos() >= it->second.start_pos()) {
                    return true;
                }

                if (it != line_walls.begin()) {
                    --it;
                    if (it->second.end_pos() >= wall.start_pos()) {
                        return true;
                    }
                }
            }
        }
    }

    return false;
}

void Board::side_nodes(int side, std::vector<int> *nodes) const
{
    switch (side) {
    case 0:
        for (int i = 0; i < col_num_; ++i) {
            nodes->push_back(i);
        }
        break;
    case 1:
        for (int i = 0; i < row_num_; ++i) {
            nodes->push_back(i * col_num_);
        }
        break;
    case 2:
        for (int i = 0; i < col_num_; ++i) {
            nodes->push_back((row_num_ - 1 ) * col_num_ + i);
        }
        break;
    case 3:
        for (int i = 0; i < row_num_; ++i) {
            nodes->push_back(i * col_num_ + col_num_ - 1);
        }
        break;
    default:
        break;
    }
}

}  /* namespace Quoridor */
<commit_msg>Allow only even sizes of the Boaed.<commit_after>#include "board.hpp"

#include <cstring>

#include <boost/lexical_cast.hpp>

#include "exception.hpp"
#include "walk_move.hpp"

namespace Quoridor {

Board::Board(int row_num, int col_num) : sides_(), pawn_sides_(), walls_()
{
    set_size(row_num, col_num);

    sides_.push_back(std::pair<int, int>(0, 0));
    sides_.push_back(std::pair<int, int>(2, 0));
    sides_.push_back(std::pair<int, int>(1, 0));
    sides_.push_back(std::pair<int, int>(3, 0));
}

Board::~Board()
{
}

void Board::set_size(int row_num, int col_num)
{
    if (row_num <= 0) {
        throw Exception("illegal row number: "
                + boost::lexical_cast<std::string>(row_num));
    }
    if (col_num <= 0) {
        throw Exception("illegal column number: "
                + boost::lexical_cast<std::string>(col_num));
    }
    if (row_num % 2 == 0) {
        throw Exception("row number must be odd: "
                + boost::lexical_cast<std::string>(row_num));
    }
    if (col_num % 2 == 0) {
        throw Exception("column number must be odd: "
                + boost::lexical_cast<std::string>(col_num));
    }

    row_num_ = row_num;
    col_num_ = col_num;

    bg_.set_size(row_num_, col_num_);
}

int Board::next_side() const
{
    for (auto &side : sides_) {
        if (side.second == 0) {
            side.second = 1;
            return side.first;
        }
    }
    return -1;
}

int Board::add_pawn(std::shared_ptr<Pawn> pawn)
{
    pawn_sides_[pawn] = next_side();
    int n;

    switch (pawn_sides_[pawn]) {
    case 0:
        n = col_num_ / 2;
        break;
    case 1:
        n = row_num_ / 2;
        break;
    case 2:
        n = (row_num_ - 1) * col_num_ + col_num_ / 2;
        break;
    case 3:
        n = (row_num_ / 2) * col_num_ + col_num_ - 1;
        break;
    default:
        throw Exception("invalid pawn side: "
                + boost::lexical_cast<std::string>(pawn_sides_[pawn]));
    }

    occ_nodes_[n] = pawn;
    pawn_nodes_[pawn] = n;

    return 0;
}

void Board::add_occupied(const pos_t &pos, std::shared_ptr<Pawn> pawn)
{
    int n = pos.row * col_num_ + pos.col;

    if (occ_nodes_.count(n) > 0) {
        throw Exception("cell (" + boost::lexical_cast<std::string>(pos.row)
                + ":" + boost::lexical_cast<std::string>(pos.col)
                + ") is already occupied");
    }

    occ_nodes_[n] = pawn;
    pawn_nodes_[pawn] = n;
}

void Board::rm_occupied(const pos_t &pos)
{
    int n = pos.row * col_num_ + pos.col;
    occ_nodes_.erase(n);
}

pos_t Board::pawn_pos(std::shared_ptr<Pawn> pawn) const
{
    int node = pawn_nodes_.at(pawn);
    pos_t pos;
    pos.row = row(node);
    pos.col = col(node);
    return pos;
}

bool Board::is_at_opposite_side(std::shared_ptr<Pawn> pawn) const
{
    int n = pawn_nodes_.at(pawn);
    switch (pawn_sides_.at(pawn)) {
    case 0:
        return row(n) == row_num_ - 1;
    case 1:
        return col(n) == col_num_ - 1;
    case 2:
        return row(n) == 0;
    case 3:
        return col(n) == 0;
    default:
        throw Exception("invalid board side: "
                + boost::lexical_cast<std::string>(pawn_sides_.at(pawn)));
    }
}

int Board::make_walking_move(int dir, std::shared_ptr<Pawn> pawn)
{
    dir = recalc_dir(dir, pawn);
    int cur_node = pawn_nodes_[pawn];
    int goal_node = cur_node;
    int r_goal_node = cur_node;

    switch (dir) {
        case WalkMove::Direction::kForward:
        goal_node += col_num_;
        r_goal_node = goal_node + col_num_;
        break;
    case WalkMove::Direction::kRight:
        ++goal_node;
        r_goal_node = goal_node + 1;
        break;
    case WalkMove::Direction::kBackward:
        goal_node -= col_num_;
        r_goal_node = goal_node - col_num_;
        break;
    case WalkMove::Direction::kLeft:
        --goal_node;
        r_goal_node = goal_node - 1;
        break;
    case WalkMove::Direction::kEnd:
    default:
        return -1;
    }

    if (is_possible_move(cur_node, goal_node)) {
        // the goal node is occupied by another pawn
        if (occ_nodes_.count(goal_node) > 0) {
            if (is_possible_move(goal_node, r_goal_node)) {
                goal_node = r_goal_node;
            }
            else {
                return -2;
            }
        }
    }
    else {
        return -1;
    }

    // update pawn's position
    occ_nodes_.erase(pawn_nodes_[pawn]);
    pawn_nodes_[pawn] = goal_node;
    occ_nodes_[goal_node] = pawn;

    return 0;
}

int Board::add_wall(const Wall &wall)
{
    int line_lim = (wall.orientation() ? col_num() : row_num()) - 1;
    int start_pos_lim = (wall.orientation() ? row_num() : col_num()) - 1;
    if ((wall.line() >= line_lim)
            || (wall.end_pos() >= start_pos_lim)) {
        return -1;
    }

    if (wall_intersects(wall)) {
        return -1;
    }

    walls_[wall.orientation()][wall.line()].insert(std::map<int, Wall>::value_type(wall.start_pos(), Wall(wall)));

    int node1;
    int node2;
    for (int i = 0; i < wall.cnt(); ++i) {
        if (wall.orientation() == 0) {
            node1 = wall.line() * row_num_ + wall.start_pos() + i;
            node2 = (wall.line() + 1) * row_num_ + wall.start_pos() + i;
        }
        else {
            node1 = (wall.start_pos() + i) * row_num_ + wall.line();
            node2 = (wall.start_pos() + i) * row_num_ + wall.line() + 1;
        }
        std::cout << "removing edge " << node1 << ":" << node2 << std::endl;
        bg_.remove_edges(node1, node2);
    }

    return 0;
}

int Board::try_add_wall(const Wall &wall)
{
    int line_lim = (wall.orientation() ? col_num() : row_num()) - 1;
    int start_pos_lim = (wall.orientation() ? row_num() : col_num()) - 1;
    if ((wall.line() >= line_lim)
            || (wall.end_pos() >= start_pos_lim)) {
        return -1;
    }

    if (wall_intersects(wall)) {
        return -1;
    }

    bg_.reset_filters();

    int node1;
    int node2;
    for (int i = 0; i < wall.cnt(); ++i) {
        if (wall.orientation() == 0) {
            node1 = wall.line() * row_num_ + wall.start_pos() + i;
            node2 = (wall.line() + 1) * row_num_ + wall.start_pos() + i;
        }
        else {
            node1 = (wall.start_pos() + i) * row_num_ + wall.line();
            node2 = (wall.start_pos() + i) * row_num_ + wall.line() + 1;
        }

        bg_.filter_edges(node1, node2);
    }

    bool path_blocked = true;

    for (auto pawn_node : pawn_nodes_) {
        std::vector<int> nodes;
        int side = pawn_sides_[pawn_node.first];
        path_blocked = true;

        side_nodes(side, &nodes);
        for (auto node : nodes) {
            if (bg_.is_path_exists(pawn_node.second, node)) {
                path_blocked = false;
                break;
            }
        }

        /* wall blocks all pathes to the opposite side for one of pawns */
        if (path_blocked) {
            break;
        }
    }

    if (path_blocked) {
        return -1;
    }

    return 0;
}

int Board::recalc_dir(int dir, std::shared_ptr<Pawn> pawn)
{
    return (dir + pawn_sides_[pawn]) % 4;
}

bool Board::is_possible_move(int cur_node, int goal_node) const
{
    return bg_.is_neighbours(cur_node, goal_node);
}

bool Board::wall_intersects(const Wall &wall) const
{
    // check intersections
    if (walls_.count(1 - wall.orientation()) > 0) {
        for (int i = 0; i < wall.cnt() - 1; ++i) {
            // there are walls on the intersected line
            if (walls_.at(1 - wall.orientation()).count(wall.start_pos()) != 0) {
                auto line_walls = walls_.at(1 - wall.orientation()).at(wall.start_pos() + i);
                auto it = line_walls.upper_bound(wall.line());

                // all walls on the line are settled before new wall
                if (it == line_walls.end()) {
                    auto rit = line_walls.rbegin();
                    if (rit->second.end_pos() >= wall.line()) {
                        return true;
                    }
                }
                else if (it != line_walls.begin()) {
                    --it;
                    if (it->second.end_pos() >= wall.line()) {
                        return true;
                    }
                }
            }
        }
    }

    // check overlaps
    if (walls_.count(wall.orientation()) > 0) {
        if (walls_.at(wall.orientation()).count(wall.line()) != 0) {
            auto line_walls = walls_.at(wall.orientation()).at(wall.line());
            auto it = line_walls.upper_bound(wall.start_pos());

            // all walls on the line are settled before new wall
            if (it == line_walls.end()) {
                auto rit = line_walls.rbegin();
                if (rit->second.end_pos() >= wall.start_pos()) {
                    return true;
                }
            }
            else {
                // check if new wall overlaps over next wall on the line
                if (wall.end_pos() >= it->second.start_pos()) {
                    return true;
                }

                if (it != line_walls.begin()) {
                    --it;
                    if (it->second.end_pos() >= wall.start_pos()) {
                        return true;
                    }
                }
            }
        }
    }

    return false;
}

void Board::side_nodes(int side, std::vector<int> *nodes) const
{
    switch (side) {
    case 0:
        for (int i = 0; i < col_num_; ++i) {
            nodes->push_back(i);
        }
        break;
    case 1:
        for (int i = 0; i < row_num_; ++i) {
            nodes->push_back(i * col_num_);
        }
        break;
    case 2:
        for (int i = 0; i < col_num_; ++i) {
            nodes->push_back((row_num_ - 1 ) * col_num_ + i);
        }
        break;
    case 3:
        for (int i = 0; i < row_num_; ++i) {
            nodes->push_back(i * col_num_ + col_num_ - 1);
        }
        break;
    default:
        break;
    }
}

}  /* namespace Quoridor */
<|endoftext|>


<commit_before>#include <node.h>
#include <v8.h>
#include <phidget21.h>

using namespace v8;

// ------------------------------------------
// Globals
// ------------------------------------------
extern "C" {
    CPhidgetBridgeHandle bridge = 0;
}

// ------------------------------------------
// Event handlers
// ------------------------------------------

int CCONV AttachHandler(CPhidgetHandle ADVSERVO, void *userptr)
{
    int serialNo;
    const char *name;

    CPhidget_getDeviceName (ADVSERVO, &name);
    CPhidget_getSerialNumber(ADVSERVO, &serialNo);
    printf("%s %10d attached!\n", name, serialNo);

    return 0;
}

int CCONV DetachHandler(CPhidgetHandle ADVSERVO, void *userptr)
{
    int serialNo;
    const char *name;

    CPhidget_getDeviceName (ADVSERVO, &name);
    CPhidget_getSerialNumber(ADVSERVO, &serialNo);
    printf("%s %10d detached!\n", name, serialNo);

    return 0;
}

int CCONV ErrorHandler(CPhidgetHandle ADVSERVO, void *userptr, int ErrorCode, const char *Description)
{
    printf("Error handled. %d - %s\n", ErrorCode, Description);
    return 0;
}

int CCONV BridgeDataHandler(CPhidgetBridgeHandle ADVSERVO, void *usrptr, int Index, double Value)
{
    printf("Bridge: %d > Current Data: %f\n", Index, Value);
    return 0;
}

int display_properties(CPhidgetBridgeHandle phid)
{
    int serialNo, version;
    int numSensor, rateMax, rateMin;
    const char* ptr;

    CPhidget_getDeviceType((CPhidgetHandle)phid, &ptr);
    CPhidget_getSerialNumber((CPhidgetHandle)phid, &serialNo);
    CPhidget_getDeviceVersion((CPhidgetHandle)phid, &version);

    CPhidgetBridge_getInputCount((CPhidgetBridgeHandle) phid, &numSensor);
    CPhidgetBridge_getDataRateMax((CPhidgetBridgeHandle) phid, &rateMax);
    CPhidgetBridge_getDataRateMin((CPhidgetBridgeHandle) phid, &rateMin);

    printf("%s\n", ptr);
    printf("Serial Number: %10d\nVersion: %8d\n# Sensor: %d\nData Rate: %d ~ %d\n",
                    serialNo, version, numSensor, rateMax, rateMin);

    return 0;
}

// ------------------------------------------
// Method abstractions
// ------------------------------------------

Handle<Value>
attach(const Arguments& args)
{
    HandleScope scope;

    int result;
    const char *err;
    CPhidgetBridgeHandle bridge;

    // Create the bridge object
    CPhidgetBridge_create(&bridge);

    // Register event handlers
    CPhidget_set_OnAttach_Handler((CPhidgetHandle)bridge, AttachHandler, NULL);
    CPhidget_set_OnDetach_Handler((CPhidgetHandle)bridge, DetachHandler, NULL);
    CPhidget_set_OnError_Handler((CPhidgetHandle)bridge, ErrorHandler, NULL);

    // Registers a callback that will run when the sensor value is changed.
    // Requires the handle for the Phidget, the function that will be called,
    // and an arbitrary pointer that will be supplied to the callback function (may be NULL).
    //CPhidgetBridge_set_OnBridgeData_Handler((CPhidgetBridgeHandle)bridge, BridgeDataHandler, NULL);

    // Open the device for connections
    CPhidget_open((CPhidgetHandle)bridge, -1);

    // Get the program to wait for an advanced bridge device to be attached
    printf("Waiting for Phidget to be attached....\n");
    if((result = CPhidget_waitForAttachment((CPhidgetHandle)bridge, 10000)))
    {
        CPhidget_getErrorDescription(result, &err);
        return ThrowException(Exception::Error(String::New("Could not attach to device.")));
    }

    // Display the properties of the attached device
    display_properties(bridge);

    return scope.Close(Integer::NewFromUnsigned(0));
}

Handle<Value>
close(const Arguments& args)
{
    HandleScope scope;

    CPhidget_close((CPhidgetHandle)bridge);
    CPhidget_delete((CPhidgetHandle)bridge);
    printf("Phidget Bridge is closed.\n");

    return scope.Close(Integer::NewFromUnsigned(0));
}

Handle<Value>
getValue(const Arguments& args)
{
    double value;

    HandleScope scope;
    CPhidgetBridge_getBridgeValue(bridge, args[0]->Int32Value(), &value);
    return scope.Close(Number::New(value));
}

Handle<Value>
getMax(const Arguments& args)
{
    double max;

    HandleScope scope;
    CPhidgetBridge_getBridgeMax(bridge, args[0]->Int32Value(), &max);
    return scope.Close(Integer::NewFromUnsigned(max));
}

Handle<Value>
getMin(const Arguments& args)
{
    double min;

    HandleScope scope;
    CPhidgetBridge_getBridgeMin(bridge, args[0]->Int32Value(), &min);
    return scope.Close(Integer::NewFromUnsigned(min));
}

Handle<Value>
setEnabled(const Arguments& args)
{
    HandleScope scope;
    CPhidgetBridge_setEnabled(bridge, args[0]->Int32Value(), args[1]->Int32Value());
    return scope.Close(Integer::NewFromUnsigned(0));
}

Handle<Value>
getEnabled(const Arguments& args)
{
    int enabled;
    HandleScope scope;
    CPhidgetBridge_getEnabled(bridge, args[0]->Int32Value(), &enabled);
    if(enabled)
        return scope.Close(Boolean::New(true));
    else
        return scope.Close(Boolean::New(false));
}

Handle<Value>
setGain(const Arguments& args)
{
    CPhidgetBridge_Gain gain;
    switch(args[1]->Int32Value()) {
        case 1:
            gain = PHIDGET_BRIDGE_GAIN_1;
            break;
        case 2:
            gain = PHIDGET_BRIDGE_GAIN_8;
            break;
        case 3:
            gain = PHIDGET_BRIDGE_GAIN_16;
            break;
        case 4:
            gain = PHIDGET_BRIDGE_GAIN_32;
            break;
        case 5:
            gain = PHIDGET_BRIDGE_GAIN_64;
            break;
        case 6:
            gain = PHIDGET_BRIDGE_GAIN_128;
            break;
        default:
            gain = PHIDGET_BRIDGE_GAIN_UNKNOWN;
    }
    HandleScope scope;
    CPhidgetBridge_setGain(bridge, args[0]->Int32Value(), gain);
    return scope.Close(Integer::NewFromUnsigned(0));
}

Handle<Value>
getGain(const Arguments& args)
{
    CPhidgetBridge_Gain gain;
    HandleScope scope;
    CPhidgetBridge_getGain(bridge, args[0]->Int32Value(), &gain);
    return scope.Close(Integer::NewFromUnsigned(gain));
}

Handle<Value>
setDataRate(const Arguments& args)
{
    HandleScope scope;
    CPhidgetBridge_setDataRate(bridge, args[0]->Int32Value());
    return scope.Close(Integer::NewFromUnsigned(0));
}

Handle<Value>
getDataRate(const Arguments& args)
{
    int dataRate;
    HandleScope scope;
    CPhidgetBridge_getDataRate(bridge, &dataRate);
    return scope.Close(Integer::NewFromUnsigned(dataRate));
}

// ------------------------------------------
// Module
// ------------------------------------------

void init(Handle<Object> target)
{
    // Connection
    target->Set(String::New("attach"), FunctionTemplate::New(attach)->GetFunction());
    target->Set(String::New("close"), FunctionTemplate::New(close)->GetFunction());

    // Bridge manipulation
    target->Set(String::New("setEnabled"), FunctionTemplate::New(setEnabled)->GetFunction());
    target->Set(String::New("setGain"), FunctionTemplate::New(setGain)->GetFunction());
    target->Set(String::New("setDataRate"), FunctionTemplate::New(setDataRate)->GetFunction());

    // Status
    target->Set(String::New("getValue"), FunctionTemplate::New(getValue)->GetFunction());
    target->Set(String::New("getMax"), FunctionTemplate::New(getMax)->GetFunction());
    target->Set(String::New("getMin"), FunctionTemplate::New(getMin)->GetFunction());
    target->Set(String::New("getEnabled"), FunctionTemplate::New(getEnabled)->GetFunction());
    target->Set(String::New("getGain"), FunctionTemplate::New(getGain)->GetFunction());
    target->Set(String::New("getDataRate"), FunctionTemplate::New(getDataRate)->GetFunction());
}

NODE_MODULE(binding_bridge, init);
<commit_msg>remove servo<commit_after>#include <phidget21.h>
#include <node.h>
#include <v8.h>

using namespace v8;

// ------------------------------------------
// Globals
// ------------------------------------------
extern "C" {
    CPhidgetBridgeHandle bridge = 0;
}

// ------------------------------------------
// Event handlers
// ------------------------------------------

int CCONV AttachHandler(CPhidgetHandle ADVSERVO, void *userptr)
{
    int serialNo;
    const char *name;

    CPhidget_getDeviceName (ADVSERVO, &name);
    CPhidget_getSerialNumber(ADVSERVO, &serialNo);
    printf("%s %10d attached!\n", name, serialNo);

    return 0;
}

int CCONV DetachHandler(CPhidgetHandle ADVSERVO, void *userptr)
{
    int serialNo;
    const char *name;

    CPhidget_getDeviceName (ADVSERVO, &name);
    CPhidget_getSerialNumber(ADVSERVO, &serialNo);
    printf("%s %10d detached!\n", name, serialNo);

    return 0;
}

int CCONV ErrorHandler(CPhidgetHandle ADVSERVO, void *userptr, int ErrorCode, const char *Description)
{
    printf("Error handled. %d - %s\n", ErrorCode, Description);
    return 0;
}

int CCONV BridgeDataHandler(CPhidgetBridgeHandle ADVSERVO, void *usrptr, int Index, double Value)
{
    printf("Bridge: %d > Current Data: %f\n", Index, Value);
    return 0;
}

int display_properties(CPhidgetBridgeHandle phid)
{
    int serialNo, version;
    int numSensor, rateMax, rateMin;
    const char* ptr;

    CPhidget_getDeviceType((CPhidgetHandle)phid, &ptr);
    CPhidget_getSerialNumber((CPhidgetHandle)phid, &serialNo);
    CPhidget_getDeviceVersion((CPhidgetHandle)phid, &version);

    CPhidgetBridge_getInputCount((CPhidgetBridgeHandle) phid, &numSensor);
    CPhidgetBridge_getDataRateMax((CPhidgetBridgeHandle) phid, &rateMax);
    CPhidgetBridge_getDataRateMin((CPhidgetBridgeHandle) phid, &rateMin);

    printf("%s\n", ptr);
    printf("Serial Number: %10d\nVersion: %8d\n# Sensor: %d\nData Rate: %d ~ %d\n",
                    serialNo, version, numSensor, rateMax, rateMin);

    return 0;
}

// ------------------------------------------
// Method abstractions
// ------------------------------------------

Handle<Value>
attach(const Arguments& args)
{
    HandleScope scope;

    int result;
    const char *err;
    CPhidgetBridgeHandle bridge;

    // Create the bridge object
    CPhidgetBridge_create(&bridge);

    // Register event handlers
    CPhidget_set_OnAttach_Handler((CPhidgetHandle)bridge, AttachHandler, NULL);
    CPhidget_set_OnDetach_Handler((CPhidgetHandle)bridge, DetachHandler, NULL);
    CPhidget_set_OnError_Handler((CPhidgetHandle)bridge, ErrorHandler, NULL);

    // Registers a callback that will run when the sensor value is changed.
    // Requires the handle for the Phidget, the function that will be called,
    // and an arbitrary pointer that will be supplied to the callback function (may be NULL).
    //CPhidgetBridge_set_OnBridgeData_Handler((CPhidgetBridgeHandle)bridge, BridgeDataHandler, NULL);

    // Open the device for connections
    CPhidget_open((CPhidgetHandle)bridge, -1);

    // Get the program to wait for an advanced bridge device to be attached
    printf("Waiting for Phidget to be attached....\n");
    if((result = CPhidget_waitForAttachment((CPhidgetHandle)bridge, 10000)))
    {
        CPhidget_getErrorDescription(result, &err);
        return ThrowException(Exception::Error(String::New("Could not attach to device.")));
    }

    // Display the properties of the attached device
    display_properties(bridge);

    return scope.Close(Integer::NewFromUnsigned(0));
}

Handle<Value>
close(const Arguments& args)
{
    HandleScope scope;

    CPhidget_close((CPhidgetHandle)bridge);
    CPhidget_delete((CPhidgetHandle)bridge);
    printf("Phidget Bridge is closed.\n");

    return scope.Close(Integer::NewFromUnsigned(0));
}

Handle<Value>
getValue(const Arguments& args)
{
    double value;

    HandleScope scope;
    CPhidgetBridge_getBridgeValue(bridge, args[0]->Int32Value(), &value);
    return scope.Close(Number::New(value));
}

Handle<Value>
getMax(const Arguments& args)
{
    double max;

    HandleScope scope;
    CPhidgetBridge_getBridgeMax(bridge, args[0]->Int32Value(), &max);
    return scope.Close(Integer::NewFromUnsigned(max));
}

Handle<Value>
getMin(const Arguments& args)
{
    double min;

    HandleScope scope;
    CPhidgetBridge_getBridgeMin(bridge, args[0]->Int32Value(), &min);
    return scope.Close(Integer::NewFromUnsigned(min));
}

Handle<Value>
setEnabled(const Arguments& args)
{
    HandleScope scope;
    CPhidgetBridge_setEnabled(bridge, args[0]->Int32Value(), args[1]->Int32Value());
    return scope.Close(Integer::NewFromUnsigned(0));
}

Handle<Value>
getEnabled(const Arguments& args)
{
    int enabled;
    HandleScope scope;
    CPhidgetBridge_getEnabled(bridge, args[0]->Int32Value(), &enabled);
    if(enabled)
        return scope.Close(Boolean::New(true));
    else
        return scope.Close(Boolean::New(false));
}

Handle<Value>
setGain(const Arguments& args)
{
    CPhidgetBridge_Gain gain;
    switch(args[1]->Int32Value()) {
        case 1:
            gain = PHIDGET_BRIDGE_GAIN_1;
            break;
        case 2:
            gain = PHIDGET_BRIDGE_GAIN_8;
            break;
        case 3:
            gain = PHIDGET_BRIDGE_GAIN_16;
            break;
        case 4:
            gain = PHIDGET_BRIDGE_GAIN_32;
            break;
        case 5:
            gain = PHIDGET_BRIDGE_GAIN_64;
            break;
        case 6:
            gain = PHIDGET_BRIDGE_GAIN_128;
            break;
        default:
            gain = PHIDGET_BRIDGE_GAIN_UNKNOWN;
    }
    HandleScope scope;
    CPhidgetBridge_setGain(bridge, args[0]->Int32Value(), gain);
    return scope.Close(Integer::NewFromUnsigned(0));
}

Handle<Value>
getGain(const Arguments& args)
{
    CPhidgetBridge_Gain gain;
    HandleScope scope;
    CPhidgetBridge_getGain(bridge, args[0]->Int32Value(), &gain);
    return scope.Close(Integer::NewFromUnsigned(gain));
}

Handle<Value>
setDataRate(const Arguments& args)
{
    HandleScope scope;
    CPhidgetBridge_setDataRate(bridge, args[0]->Int32Value());
    return scope.Close(Integer::NewFromUnsigned(0));
}

Handle<Value>
getDataRate(const Arguments& args)
{
    int dataRate;
    HandleScope scope;
    CPhidgetBridge_getDataRate(bridge, &dataRate);
    return scope.Close(Integer::NewFromUnsigned(dataRate));
}

// ------------------------------------------
// Module
// ------------------------------------------

void init(Handle<Object> target)
{
    // Connection
    target->Set(String::New("attach"), FunctionTemplate::New(attach)->GetFunction());
    target->Set(String::New("close"), FunctionTemplate::New(close)->GetFunction());

    // Bridge manipulation
    target->Set(String::New("setEnabled"), FunctionTemplate::New(setEnabled)->GetFunction());
    target->Set(String::New("setGain"), FunctionTemplate::New(setGain)->GetFunction());
    target->Set(String::New("setDataRate"), FunctionTemplate::New(setDataRate)->GetFunction());

    // Status
    target->Set(String::New("getValue"), FunctionTemplate::New(getValue)->GetFunction());
    target->Set(String::New("getMax"), FunctionTemplate::New(getMax)->GetFunction());
    target->Set(String::New("getMin"), FunctionTemplate::New(getMin)->GetFunction());
    target->Set(String::New("getEnabled"), FunctionTemplate::New(getEnabled)->GetFunction());
    target->Set(String::New("getGain"), FunctionTemplate::New(getGain)->GetFunction());
    target->Set(String::New("getDataRate"), FunctionTemplate::New(getDataRate)->GetFunction());
}

NODE_MODULE(binding_bridge, init);
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
//
//  File: ThreadSpecificPool.hpp
//
//  For more information, please see: http://www.nektar.info/
//
//  The MIT License
//
//  Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
//  Department of Aeronautics, Imperial College London (UK), and Scientific
//  Computing and Imaging Institute, University of Utah (USA).
//
//  License for the specific language governing rights and limitations under
//  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.
//
//  Description:
//
//
////////////////////////////////////////////////////////////////////////////////

#ifndef NEKATAR_LIB_UTILITES_THREAD_SPECIFIC_POOL_HPP
#define NEKATAR_LIB_UTILITES_THREAD_SPECIFIC_POOL_HPP

#include <boost/thread/tss.hpp>
#include <boost/pool/pool.hpp>
#include <loki/Singleton.h>
#include <map>
#include <LibUtilities/BasicUtils/ErrorUtil.hpp>

namespace Nektar
{
    namespace detail
    {
        /// \brief A memory pool which exists on a thread by thread basis.
        /// \param ByteSize The number of bytes in each chunk allocated by the pool.
        ///
        /// Provides a simple, thread specific memory pool that is based on byte size.
        /// The pool allocates and deallocates raw memory - the user is responsible for
        /// calling appropriate constructors/destructors when allocating objects.
        ///
        /// Example:
        ///
        /// \code
        /// ThreadSpecificPool<sizeof(TestClass)> pool;
        /// void* memory = pool.allocate();
        ///
        /// // Construct the object in the memory returned by the pool.
        /// TestClass* t = new (memory) TestClass;
        ///
        /// // Do stuff with t.
        ///
        /// // Destruct t and return it.
        /// t->~TestClass();
        /// pool.deallocate(t);
        /// \endcode
        class ThreadSpecificPool
        {
            public:
                ThreadSpecificPool(unsigned int ByteSize) :
                    m_pool(),
                    m_blockSize(ByteSize)
                {
                    // We can do the new in the constructor list because the thread specific
                    // pointer doesn't have a supporting constructor.
                    m_pool.reset(new boost::pool<>(ByteSize));
                }

                ~ThreadSpecificPool()
                {
                    // The documentation isn't particularly clear if delete needs to be called manually
                    // or if the thread specific pointer will call delete for me.  Looking through the
                    // boost code doesn't make it any clearer.
                }

                /// \brief Allocate a block of memory of size ByteSize.
                /// \throw std::bad_alloc if memory is exhausted.
                void* Allocate()
                {
                    void* result = m_pool->malloc();

#if defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)
                    memset(result, 0, m_blockSize);
#endif //defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)

                    return result;
                }

                /// \brief Deallocate memory claimed by an earlier call to allocate.
                ///
                /// \attention It is an error to deallocate memory not allocated
                /// from this pool.  Doing this will result in undefined behavior.
                void Deallocate(const void* p)
                {
#if defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)
                    // The idea here is to fill the returned memory with some known
                    // pattern, then detect that pattern on the allocate.  If the
                    // pattern is no longer there then some memory corruption has
                    // occurred.  However, I'm not sure how to distinguish between first
                    // time allocations and repeat allocations.

                    //memset(p, '+', m_pool->get_requested_size());
#endif //defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)

                    m_pool->free(const_cast<void*>(p));
                }

            private:
                boost::thread_specific_ptr<boost::pool<> > m_pool;
                unsigned int m_blockSize;
        };
    }

    class MemPool
    {
        public:
            typedef Loki::SingletonHolder<MemPool ,
                Loki::CreateUsingNew,
                Loki::PhoenixSingleton > Type;
            typedef std::map<unsigned int, boost::shared_ptr<detail::ThreadSpecificPool> > PoolMapType;

        public:
            MemPool() :
                m_fourBytePool(4),
                m_pools(),
                m_upperBound(1024)
            {
                typedef PoolMapType::value_type PairType;
                m_pools.insert(PairType(8, boost::shared_ptr<detail::ThreadSpecificPool>(new detail::ThreadSpecificPool(8))));
                m_pools.insert(PairType(16, boost::shared_ptr<detail::ThreadSpecificPool>(new detail::ThreadSpecificPool(16))));
                m_pools.insert(PairType(32, boost::shared_ptr<detail::ThreadSpecificPool>(new detail::ThreadSpecificPool(32))));
                m_pools.insert(PairType(64, boost::shared_ptr<detail::ThreadSpecificPool>(new detail::ThreadSpecificPool(64))));
                m_pools.insert(PairType(128, boost::shared_ptr<detail::ThreadSpecificPool>(new detail::ThreadSpecificPool(128))));
                m_pools.insert(PairType(256, boost::shared_ptr<detail::ThreadSpecificPool>(new detail::ThreadSpecificPool(256))));
                m_pools.insert(PairType(512, boost::shared_ptr<detail::ThreadSpecificPool>(new detail::ThreadSpecificPool(512))));
                m_pools.insert(PairType(1024, boost::shared_ptr<detail::ThreadSpecificPool>(new detail::ThreadSpecificPool(1024))));
            }

            ~MemPool()
            {
            }

            /// \brief Allocate a block of memory of size ByteSize.
            /// \throw std::bad_alloc if memory is exhausted.
            void* Allocate(unsigned int bytes)
            {
                if( bytes <= 4 )
                {
                    return m_fourBytePool.Allocate();
                }
                else if( bytes > m_upperBound )
                {
                    return ::operator new(bytes);
                }
                else
                {
                    PoolMapType::iterator iter = m_pools.lower_bound(bytes);
                    ASSERTL1(iter != m_pools.end(), "The memory manager is mishandling a memory request for " +
                        boost::lexical_cast<std::string>(bytes) + " bytes of memory.");

                    return (*iter).second->Allocate();
                }
            }

            /// \brief Deallocate memory claimed by an earlier call to allocate.
            ///
            /// \attention It is an error to deallocate memory not allocated
            /// from this pool.  Doing this will result in undefined behavior.
            void Deallocate(void* p, unsigned int bytes)
            {
                if( bytes <= 4 )
                {
                    m_fourBytePool.Deallocate(p);
                }
                else if( bytes > m_upperBound )
                {
                    ::operator delete(p);
                }
                else
                {
                    PoolMapType::iterator iter = m_pools.lower_bound(bytes);
                    ASSERTL1(iter != m_pools.end(), "The memory manager is mishandling a memory request for " +
                        boost::lexical_cast<std::string>(bytes) + " bytes of memory.");

                    (*iter).second->Deallocate(p);
                }
            }

        private:
            detail::ThreadSpecificPool m_fourBytePool;
            std::map<unsigned int, boost::shared_ptr<detail::ThreadSpecificPool> > m_pools;
            unsigned int m_upperBound;
    };

}

#endif //NEKATAR_LIB_UTILITES_THREAD_SPECIFIC_POOL_HPP

/**
    $Log: ThreadSpecificPool.hpp,v $
    Revision 1.4  2008/05/16 05:43:22  bnelson
    Updated the memory manager so it is faster choosing the allocator to use, doesn't use the pools for anything larger than 1024 bytes, and doesn't issue a warning for large allocations.

    Revision 1.3  2007/05/14 23:49:55  bnelson
    Updated pool using Singletons to correctly allocate static Arrays.

    Revision 1.2  2007/04/06 04:36:22  bnelson
    Updated for const-correctness.

    Revision 1.1  2006/06/01 09:17:24  kirby
    *** empty log message ***

    Revision 1.1  2006/05/04 18:57:44  kirby
    *** empty log message ***

    Revision 1.1  2006/02/23 07:53:23  bnelson
    *** empty log message ***

**/

<commit_msg>Fixed the shutdown crash.<commit_after>////////////////////////////////////////////////////////////////////////////////
//
//  File: ThreadSpecificPool.hpp
//
//  For more information, please see: http://www.nektar.info/
//
//  The MIT License
//
//  Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
//  Department of Aeronautics, Imperial College London (UK), and Scientific
//  Computing and Imaging Institute, University of Utah (USA).
//
//  License for the specific language governing rights and limitations under
//  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.
//
//  Description:
//
//
////////////////////////////////////////////////////////////////////////////////

#ifndef NEKATAR_LIB_UTILITES_THREAD_SPECIFIC_POOL_HPP
#define NEKATAR_LIB_UTILITES_THREAD_SPECIFIC_POOL_HPP

#include <boost/thread/tss.hpp>
#include <boost/pool/pool.hpp>
#include <loki/Singleton.h>
#include <map>
#include <LibUtilities/BasicUtils/ErrorUtil.hpp>

namespace Nektar
{
    namespace detail
    {
        /// \brief A memory pool which exists on a thread by thread basis.
        /// \param ByteSize The number of bytes in each chunk allocated by the pool.
        ///
        /// Provides a simple, thread specific memory pool that is based on byte size.
        /// The pool allocates and deallocates raw memory - the user is responsible for
        /// calling appropriate constructors/destructors when allocating objects.
        ///
        /// Example:
        ///
        /// \code
        /// ThreadSpecificPool<sizeof(TestClass)> pool;
        /// void* memory = pool.allocate();
        ///
        /// // Construct the object in the memory returned by the pool.
        /// TestClass* t = new (memory) TestClass;
        ///
        /// // Do stuff with t.
        ///
        /// // Destruct t and return it.
        /// t->~TestClass();
        /// pool.deallocate(t);
        /// \endcode
        class ThreadSpecificPool
        {
            public:
                ThreadSpecificPool(unsigned int ByteSize) :
                    m_pool(),
                    m_blockSize(ByteSize)
                {
                    // We can do the new in the constructor list because the thread specific
                    // pointer doesn't have a supporting constructor.
                    m_pool.reset(new boost::pool<>(ByteSize));
                }

                ~ThreadSpecificPool()
                {
                    // The documentation isn't particularly clear if delete needs to be called manually
                    // or if the thread specific pointer will call delete for me.  Looking through the
                    // boost code doesn't make it any clearer.
                }

                /// \brief Allocate a block of memory of size ByteSize.
                /// \throw std::bad_alloc if memory is exhausted.
                void* Allocate()
                {
                    void* result = m_pool->malloc();

#if defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)
                    memset(result, 0, m_blockSize);
#endif //defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)

                    return result;
                }

                /// \brief Deallocate memory claimed by an earlier call to allocate.
                ///
                /// \attention It is an error to deallocate memory not allocated
                /// from this pool.  Doing this will result in undefined behavior.
                void Deallocate(const void* p)
                {
#if defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)
                    // The idea here is to fill the returned memory with some known
                    // pattern, then detect that pattern on the allocate.  If the
                    // pattern is no longer there then some memory corruption has
                    // occurred.  However, I'm not sure how to distinguish between first
                    // time allocations and repeat allocations.

                    //memset(p, '+', m_pool->get_requested_size());
#endif //defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)

                    m_pool->free(const_cast<void*>(p));
                }

            private:
                boost::thread_specific_ptr<boost::pool<> > m_pool;
                unsigned int m_blockSize;
        };
    }

    class MemPool
    {
        public:
            typedef Loki::SingletonHolder<MemPool ,
                Loki::CreateUsingNew,
                Loki::NoDestroy > Type;
            typedef std::map<unsigned int, boost::shared_ptr<detail::ThreadSpecificPool> > PoolMapType;

        public:
            MemPool() :
                m_fourBytePool(4),
                m_pools(),
                m_upperBound(1024)
            {
                // The m_pools data member stores a collection of thread specific pools of varying size.  All memory requests
                // up to and including the largest pool size will be allocated from a pool (note that this means you may receive
                // more memory than you asked for).  For example, if there is a pool for 8 bytes and the next largest pool is 32
                // bytes, then a request for 10 bytes will return a 32 byte chunk of memory from the 32 byte pool.

                typedef PoolMapType::value_type PairType;
                m_pools.insert(PairType(8, boost::shared_ptr<detail::ThreadSpecificPool>(new detail::ThreadSpecificPool(8))));
                m_pools.insert(PairType(16, boost::shared_ptr<detail::ThreadSpecificPool>(new detail::ThreadSpecificPool(16))));
                m_pools.insert(PairType(32, boost::shared_ptr<detail::ThreadSpecificPool>(new detail::ThreadSpecificPool(32))));
                m_pools.insert(PairType(64, boost::shared_ptr<detail::ThreadSpecificPool>(new detail::ThreadSpecificPool(64))));
                m_pools.insert(PairType(128, boost::shared_ptr<detail::ThreadSpecificPool>(new detail::ThreadSpecificPool(128))));
                m_pools.insert(PairType(256, boost::shared_ptr<detail::ThreadSpecificPool>(new detail::ThreadSpecificPool(256))));
                m_pools.insert(PairType(512, boost::shared_ptr<detail::ThreadSpecificPool>(new detail::ThreadSpecificPool(512))));
                m_pools.insert(PairType(1024, boost::shared_ptr<detail::ThreadSpecificPool>(new detail::ThreadSpecificPool(1024))));
            }

            ~MemPool()
            {
            }

            /// \brief Allocate a block of memory of size ByteSize.
            /// \throw std::bad_alloc if memory is exhausted.
            /// \param bytes The number of bytes to allocate.
            ///
            /// If the bytes parameter specifies a size that is handled by memory pools then the memory
            /// is allocated from the pool.  Otherwise the memory is allocated with a call to new.
            ///
            /// Important: All memory allocated from this method must be returned to the pool
            /// via the Deallocate method.  Deleting pointers allocated from the memory pool with the
            /// delete operator will result in undefined behavior.
            void* Allocate(unsigned int bytes)
            {
                if( bytes <= 4 )
                {
                    return m_fourBytePool.Allocate();
                }
                else if( bytes > m_upperBound )
                {
                    return ::operator new(bytes);
                }
                else
                {
                    PoolMapType::iterator iter = m_pools.lower_bound(bytes);
                    ASSERTL1(iter != m_pools.end(), "The memory manager is mishandling a memory request for " +
                        boost::lexical_cast<std::string>(bytes) + " bytes of memory.");

                    return (*iter).second->Allocate();
                }
            }

            /// \brief Deallocate memory claimed by an earlier call to allocate.
            ///
            /// \attention It is an error to deallocate memory not allocated
            /// from this pool.  Doing this will result in undefined behavior.
            void Deallocate(void* p, unsigned int bytes)
            {
                if( bytes <= 4 )
                {
                    m_fourBytePool.Deallocate(p);
                }
                else if( bytes > m_upperBound )
                {
                    ::operator delete(p);
                }
                else
                {
                    PoolMapType::iterator iter = m_pools.lower_bound(bytes);
                    ASSERTL1(iter != m_pools.end(), "The memory manager is mishandling a memory request for " +
                        boost::lexical_cast<std::string>(bytes) + " bytes of memory.");

                    (*iter).second->Deallocate(p);
                }
            }

        private:
            detail::ThreadSpecificPool m_fourBytePool;
            std::map<unsigned int, boost::shared_ptr<detail::ThreadSpecificPool> > m_pools;
            unsigned int m_upperBound;
    };

}

#endif //NEKATAR_LIB_UTILITES_THREAD_SPECIFIC_POOL_HPP

/**
    $Log: ThreadSpecificPool.hpp,v $
    Revision 1.5  2008/05/21 01:38:27  bnelson
    Added a debug feature to clear memory being allocated.

    Revision 1.4  2008/05/16 05:43:22  bnelson
    Updated the memory manager so it is faster choosing the allocator to use, doesn't use the pools for anything larger than 1024 bytes, and doesn't issue a warning for large allocations.

    Revision 1.3  2007/05/14 23:49:55  bnelson
    Updated pool using Singletons to correctly allocate static Arrays.

    Revision 1.2  2007/04/06 04:36:22  bnelson
    Updated for const-correctness.

    Revision 1.1  2006/06/01 09:17:24  kirby
    *** empty log message ***

    Revision 1.1  2006/05/04 18:57:44  kirby
    *** empty log message ***

    Revision 1.1  2006/02/23 07:53:23  bnelson
    *** empty log message ***

**/

<|endoftext|>