<commit_before>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   EC_Ruler.cpp
 *  @brief  EC_Ruler enables visual highlighting effect for of scene entity.
 *  @note   The entity must have EC_OgrePlaceable and EC_OgreMesh (if mesh) or
 *          EC_OgreCustomObject (if prim) components available in advance.
 */

#include "StableHeaders.h"
#include "DebugOperatorNew.h"
#include "EC_Ruler.h"
#include "ModuleInterface.h"
#include "Entity.h"
#include "Renderer.h"
#include "OgreMaterialUtils.h"
#include "EC_OgrePlaceable.h"
#include "EC_OgreMesh.h"
#include "EC_OgreCustomObject.h"
#include "LoggingFunctions.h"
#include <Ogre.h>

DEFINE_POCO_LOGGING_FUNCTIONS("EC_Ruler")

#include "MemoryLeakCheck.h"

EC_Ruler::EC_Ruler(Foundation::ModuleInterface *module) :
    Foundation::ComponentInterface(module->GetFramework()),
    typeAttr_(this, "ruler type", EC_Ruler::Rotation),
    visibleAttr_(this, "visible", false),
    axisAttr_(this, "axis", EC_Ruler::X),
    localAttr_(this, "local", false),
    radiusAttr_(this, "radius", 5),
    segmentsAttr_(this, "segments", 29),
    rulerObject(0),
    sceneNode_(0),
    type(EC_Ruler::Rotation)
{
    renderer_ = module->GetFramework()->GetServiceManager()->GetService<OgreRenderer::Renderer>(Foundation::Service::ST_Renderer);

    QObject::connect(this, SIGNAL(OnChanged()), this, SLOT(UpdateRuler()));
}

EC_Ruler::~EC_Ruler()
{
    // OgreRendering module might be already deleted. If so, the cloned entity is also already deleted.
    // In this case, just set pointer to 0.
    if (!renderer_.expired())
    {
        Ogre::SceneManager *sceneMgr = renderer_.lock()->GetSceneManager();
            sceneMgr->destroyManualObject(rulerObject);
    }
    else
    {
        rulerObject = 0;
        sceneNode_ = 0;
    }
}

void  EC_Ruler::Show()
{
    if (!rulerObject)
        Create();

    if (!rulerObject)
    {
        LogError("EC_Ruler not initialized properly.");
        return;
    }

    if (rulerObject)
        rulerObject->setVisible(true);
}

void  EC_Ruler::Hide()
{
    if (!rulerObject)
        Create();

    if (!rulerObject)
    {
        LogError("EC_Ruler not initialized properly.");
        return;
    }

    if (rulerObject)
        rulerObject->setVisible(false);
}

bool EC_Ruler::IsVisible() const
{
    if (rulerObject)
        return rulerObject->isVisible();

    return false;
}

void EC_Ruler::Create()
{
    if (renderer_.expired())
        return;

    Ogre::SceneManager *scene_mgr= renderer_.lock()->GetSceneManager();
    assert(scene_mgr);
    if (!scene_mgr)
        return;

    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (!entity)
        return;

    OgreRenderer::EC_OgrePlaceable *placeable = entity->GetComponent<OgreRenderer::EC_OgrePlaceable>().get();
    assert(placeable);
    if (!placeable)
        return;
    sceneNode_ = placeable->GetSceneNode();

    assert(sceneNode_);
    if (!sceneNode_)
        return;

    if(scene_mgr->hasManualObject("translateRuler")){
        rulerObject = scene_mgr->getManualObject("translateRuler");
        if(rulerObject->isAttached())
#if OGRE_VERSION_MINOR <= 6 && OGRE_VERSION_MAJOR <= 1
            rulerObject->detatchFromParent();
#else
            rulerObject->detachFromParent();
#endif
    } else {
        rulerObject = scene_mgr->createManualObject("translateRuler");
    }

    switch(typeAttr_.Get()) {
        case EC_Ruler::Rotation:
            SetupRotationRuler();
            break;
        case EC_Ruler::Translation:
            SetupTranslateRuler();
            break;
        case EC_Ruler::Scale:
            SetupScaleRuler();
            break;
    }

    if(localAttr_.Get()) {
        sceneNode_->attachObject(rulerObject);
    } else {
        // get translateNode only when we are working in world space
        if(scene_mgr->hasSceneNode("translateNode")) {
            globalSceneNode = scene_mgr->getSceneNode("translateNode");
        } else {
            globalSceneNode = scene_mgr->getRootSceneNode()->createChildSceneNode("translateNode");
            globalSceneNode->setVisible(true);
        }
        assert(globalSceneNode);
        if(!globalSceneNode)
            return;

        globalSceneNode->setPosition(sceneNode_->getParent()->getPosition());
        globalSceneNode->attachObject(rulerObject);
    }
}

void EC_Ruler::SetupScaleRuler()
{
    if(!rulerObject)
        return;

    float x, y, z;
    x = y = z = 0;

    float size = radiusAttr_.Get();

    switch(axisAttr_.Get()) {
        case EC_Ruler::X:
            x = size;
            break;
        case EC_Ruler::Y:
            y = size;
            break;
        case EC_Ruler::Z:
            z = size;
            break;
        default:
            x = size;
            y = size;
    }
    rulerObject->clear();
    rulerObject->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_LIST);
    rulerObject->position(0, 0, 0);
    rulerObject->position(x, y, z);
    rulerObject->end();
}

void EC_Ruler::SetupRotationRuler()
{
    if(!rulerObject)
        return;
    float const radius = radiusAttr_.Get();
    float const segments = segmentsAttr_.Get();

    rulerObject->clear();
    rulerObject->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_STRIP);

    unsigned i = 0;
    for(float theta = 0; theta <= 2 * Ogre::Math::PI; theta += Ogre::Math::PI / segments) {
        switch(axisAttr_.Get()) {
            case EC_Ruler::X:
                rulerObject->position(0, radius * cos(theta), radius * sin(theta));
                break;
            case EC_Ruler::Y:
                rulerObject->position(radius * cos(theta), radius * sin(theta), 0);
                break;
            case EC_Ruler::Z:
                rulerObject->position(radius * cos(theta), 0, radius * sin(theta));
                break;
        }
        rulerObject->index(i++);
    }
    rulerObject->index(0); // Close the line = circle
    rulerObject->end();
}

void EC_Ruler::SetupTranslateRuler() {
    if(!rulerObject)
        return;

    float x, y, z;
    x = y = z = 0;

    float size = radiusAttr_.Get();

    // Note, this arbitrary order is result from Py Code
    // TODO: Fix this to something more unified (0 = x, 1 = y, 2 = z) throughout
    // manipulator widget code
    switch(axisAttr_.Get()) {
        case EC_Ruler::X:
            x = size;
            break;
        case EC_Ruler::Y:
            y = size;
            break;
        case EC_Ruler::Z:
            z = size;
            break;
        default:
            x = size;
            y = size;
    }
    rulerObject->clear();
    rulerObject->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_LIST);
    rulerObject->position(x, y, z);
    rulerObject->position(-x, -y, -z);
    rulerObject->end();
}

void EC_Ruler::SetType(EC_Ruler::Type type) {
}

void EC_Ruler::StartDrag() {}

void EC_Ruler::EndDrag() {}

void EC_Ruler::UpdateRuler() {
    Create();

    if(visibleAttr_.Get()) {
        Show();
    } else {
        Hide();
    }
}

<commit_msg>Disable shadows on transform rulers.<commit_after>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   EC_Ruler.cpp
 *  @brief  EC_Ruler enables visual highlighting effect for of scene entity.
 *  @note   The entity must have EC_OgrePlaceable and EC_OgreMesh (if mesh) or
 *          EC_OgreCustomObject (if prim) components available in advance.
 */

#include "StableHeaders.h"
#include "DebugOperatorNew.h"
#include "EC_Ruler.h"
#include "ModuleInterface.h"
#include "Entity.h"
#include "Renderer.h"
#include "OgreMaterialUtils.h"
#include "EC_OgrePlaceable.h"
#include "EC_OgreMesh.h"
#include "EC_OgreCustomObject.h"
#include "LoggingFunctions.h"
#include <Ogre.h>

DEFINE_POCO_LOGGING_FUNCTIONS("EC_Ruler")

#include "MemoryLeakCheck.h"

EC_Ruler::EC_Ruler(Foundation::ModuleInterface *module) :
    Foundation::ComponentInterface(module->GetFramework()),
    typeAttr_(this, "ruler type", EC_Ruler::Rotation),
    visibleAttr_(this, "visible", false),
    axisAttr_(this, "axis", EC_Ruler::X),
    localAttr_(this, "local", false),
    radiusAttr_(this, "radius", 5),
    segmentsAttr_(this, "segments", 29),
    rulerObject(0),
    sceneNode_(0),
    type(EC_Ruler::Rotation)
{
    renderer_ = module->GetFramework()->GetServiceManager()->GetService<OgreRenderer::Renderer>(Foundation::Service::ST_Renderer);

    QObject::connect(this, SIGNAL(OnChanged()), this, SLOT(UpdateRuler()));
}

EC_Ruler::~EC_Ruler()
{
    // OgreRendering module might be already deleted. If so, the cloned entity is also already deleted.
    // In this case, just set pointer to 0.
    if (!renderer_.expired())
    {
        Ogre::SceneManager *sceneMgr = renderer_.lock()->GetSceneManager();
            sceneMgr->destroyManualObject(rulerObject);
    }
    else
    {
        rulerObject = 0;
        sceneNode_ = 0;
    }
}

void  EC_Ruler::Show()
{
    if (!rulerObject)
        Create();

    if (!rulerObject)
    {
        LogError("EC_Ruler not initialized properly.");
        return;
    }

    if (rulerObject)
        rulerObject->setVisible(true);
}

void  EC_Ruler::Hide()
{
    if (!rulerObject)
        Create();

    if (!rulerObject)
    {
        LogError("EC_Ruler not initialized properly.");
        return;
    }

    if (rulerObject)
        rulerObject->setVisible(false);
}

bool EC_Ruler::IsVisible() const
{
    if (rulerObject)
        return rulerObject->isVisible();

    return false;
}

void EC_Ruler::Create()
{
    if (renderer_.expired())
        return;

    Ogre::SceneManager *scene_mgr= renderer_.lock()->GetSceneManager();
    assert(scene_mgr);
    if (!scene_mgr)
        return;

    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (!entity)
        return;

    OgreRenderer::EC_OgrePlaceable *placeable = entity->GetComponent<OgreRenderer::EC_OgrePlaceable>().get();
    assert(placeable);
    if (!placeable)
        return;
    sceneNode_ = placeable->GetSceneNode();

    assert(sceneNode_);
    if (!sceneNode_)
        return;

    if(scene_mgr->hasManualObject("translateRuler")){
        rulerObject = scene_mgr->getManualObject("translateRuler");
        if(rulerObject->isAttached())
#if OGRE_VERSION_MINOR <= 6 && OGRE_VERSION_MAJOR <= 1
            rulerObject->detatchFromParent();
#else
            rulerObject->detachFromParent();
#endif
    } else {
        rulerObject = scene_mgr->createManualObject("translateRuler");
    }

    switch(typeAttr_.Get()) {
        case EC_Ruler::Rotation:
            SetupRotationRuler();
            break;
        case EC_Ruler::Translation:
            SetupTranslateRuler();
            break;
        case EC_Ruler::Scale:
            SetupScaleRuler();
            break;
    }

    if(localAttr_.Get()) {
        sceneNode_->attachObject(rulerObject);
    } else {
        // get translateNode only when we are working in world space
        if(scene_mgr->hasSceneNode("translateNode")) {
            globalSceneNode = scene_mgr->getSceneNode("translateNode");
        } else {
            globalSceneNode = scene_mgr->getRootSceneNode()->createChildSceneNode("translateNode");
            globalSceneNode->setVisible(true);
        }
        assert(globalSceneNode);
        if(!globalSceneNode)
            return;

        globalSceneNode->setPosition(sceneNode_->getParent()->getPosition());
        globalSceneNode->attachObject(rulerObject);
    }
}

void EC_Ruler::SetupScaleRuler()
{
    if(!rulerObject)
        return;

    float x, y, z;
    x = y = z = 0;

    float size = radiusAttr_.Get();

    switch(axisAttr_.Get()) {
        case EC_Ruler::X:
            x = size;
            break;
        case EC_Ruler::Y:
            y = size;
            break;
        case EC_Ruler::Z:
            z = size;
            break;
        default:
            x = size;
            y = size;
    }
    rulerObject->clear();
    rulerObject->setCastShadows(false);
    rulerObject->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_LIST);
    rulerObject->position(0, 0, 0);
    rulerObject->position(x, y, z);
    rulerObject->end();
}

void EC_Ruler::SetupRotationRuler()
{
    if(!rulerObject)
        return;
    float const radius = radiusAttr_.Get();
    float const segments = segmentsAttr_.Get();

    rulerObject->clear();
    rulerObject->setCastShadows(false);
    rulerObject->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_STRIP);

    unsigned i = 0;
    for(float theta = 0; theta <= 2 * Ogre::Math::PI; theta += Ogre::Math::PI / segments) {
        switch(axisAttr_.Get()) {
            case EC_Ruler::X:
                rulerObject->position(0, radius * cos(theta), radius * sin(theta));
                break;
            case EC_Ruler::Y:
                rulerObject->position(radius * cos(theta), radius * sin(theta), 0);
                break;
            case EC_Ruler::Z:
                rulerObject->position(radius * cos(theta), 0, radius * sin(theta));
                break;
        }
        rulerObject->index(i++);
    }
    rulerObject->index(0); // Close the line = circle
    rulerObject->end();
}

void EC_Ruler::SetupTranslateRuler() {
    if(!rulerObject)
        return;

    float x, y, z;
    x = y = z = 0;

    float size = radiusAttr_.Get();

    // Note, this arbitrary order is result from Py Code
    // TODO: Fix this to something more unified (0 = x, 1 = y, 2 = z) throughout
    // manipulator widget code
    switch(axisAttr_.Get()) {
        case EC_Ruler::X:
            x = size;
            break;
        case EC_Ruler::Y:
            y = size;
            break;
        case EC_Ruler::Z:
            z = size;
            break;
        default:
            x = size;
            y = size;
    }
    rulerObject->clear();
    rulerObject->setCastShadows(false);
    rulerObject->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_LIST);
    rulerObject->position(x, y, z);
    rulerObject->position(-x, -y, -z);
    rulerObject->end();
}

void EC_Ruler::SetType(EC_Ruler::Type type) {
}

void EC_Ruler::StartDrag() {}

void EC_Ruler::EndDrag() {}

void EC_Ruler::UpdateRuler() {
    Create();

    if(visibleAttr_.Get()) {
        Show();
    } else {
        Hide();
    }
}

<|endoftext|>


<commit_before>/* Siconos-sample , Copyright INRIA 2005-2011.
 * Siconos is a program dedicated to modeling, simulation and control
 * of non smooth dynamical systems.
 * Siconos is a free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * Siconos 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Siconos; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Contact: Vincent ACARY vincent.acary@inrialpes.fr
 */

/*!\file Disks.cpp

  Some Disks (2D), friction, and walls.
  Direct description of the model without XML input.  Simulation with
  a Time-Stepping scheme.
*/

// Siconos
#include <SiconosPointers.hpp>

#include <TimeStepping.hpp>
#include <FrictionContact.hpp>
#include <MoreauJeanOSI.hpp>
#include <NewtonImpactFrictionNSL.hpp>
//#include <Siconos/IO/SiconosRestart.hpp>

#include "Disks.hpp"

#include <Disk.hpp>
#include <Circle.hpp>
#include <DiskPlanR.hpp>
#include <SpaceFilter.hpp>

using namespace std;

/* do nothing if solver does not converge */
void localCheckSolverOuput(int, Simulation*)
{};

double A(double t)
{
  return 0. ;
}
double B(double t)
{
  return 1. ;
}
double C(double t)
{
  return 0.0;//1.1*cos(32.*M_PI*t) ;
}
double DA(double t)
{
  return 0. ;
}
double DB(double t)
{
  return 0. ;
}
double DC(double t)
{
  return 0.0;//-1.1*32.*M_PI*sin(32.*M_PI*t) ;
}

// ================= Creation of the model =======================
void Disks::init()
{

  SP::TimeDiscretisation timedisc_;
  SP::TimeStepping simulation_;
  SP::FrictionContact osnspb_;

  // User-defined main parameters

  double t0 = 0;                   // initial computation time

  double T =  std::numeric_limits<double>::infinity();

  double h = 0.01;                // time step
  double g = 9.81;

  double theta = 0.5;              // theta for MoreauJeanOSI integrator

  std::string solverName = "NSGS";

  // -----------------------------------------
  // --- Dynamical systems && interactions ---
  // -----------------------------------------

  double R;
  double m;

  try
  {

    // ------------
    // --- Init ---
    // ------------

    std::cout << "====> Model loading ..." << std::endl << std::endl;

    _plans.reset(new SimpleMatrix("plans.dat", true));
    if (_plans->size(0) == 0)
    {
      /* default plans */
      double A1 = P1A;
      double B1 = P1B;
      double C1 = P1C;

      double A2 = P2A;
      double B2 = P2B;
      double C2 = P2C;

      _plans.reset(new SimpleMatrix(6, 6));
      _plans->zero();
      (*_plans)(0, 0) = 0;
      (*_plans)(0, 1) = 1;
      (*_plans)(0, 2) = -GROUND;

      (*_plans)(1, 0) = 1;
      (*_plans)(1, 1) = 0;
      (*_plans)(1, 2) = WALL;

      (*_plans)(2, 0) = 1;
      (*_plans)(2, 1) = 0;
      (*_plans)(2, 2) = -WALL;

      (*_plans)(3, 0) = 0;
      (*_plans)(3, 1) = 1;
      (*_plans)(3, 2) = -TOP;

      (*_plans)(4, 0) = A1;
      (*_plans)(4, 1) = B1;
      (*_plans)(4, 2) = C1;

      (*_plans)(5, 0) = A2;
      (*_plans)(5, 1) = B2;
      (*_plans)(5, 2) = C2;

    }

    /* set center positions */
    for (unsigned int i = 0 ; i < _plans->size(0); ++i)
    {
      SP::DiskPlanR tmpr;
      tmpr.reset(new DiskPlanR(1, (*_plans)(i, 0), (*_plans)(i, 1), (*_plans)(i, 2),
                               (*_plans)(i, 3), (*_plans)(i, 4), (*_plans)(i, 5)));
      (*_plans)(i, 3) = tmpr->getXCenter();
      (*_plans)(i, 4) = tmpr->getYCenter();
    }

    /*    _moving_plans.reset(new FMatrix(1,6));
        (*_moving_plans)(0,0) = &A;
        (*_moving_plans)(0,1) = &B;
        (*_moving_plans)(0,2) = &C;
        (*_moving_plans)(0,3) = &DA;
        (*_moving_plans)(0,4) = &DB;
        (*_moving_plans)(0,5) = &DC;*/

    SP::SiconosMatrix Disks;
    Disks.reset(new SimpleMatrix("disks.dat", true));

    // -- OneStepIntegrators --
    SP::OneStepIntegrator osi;
    osi.reset(new MoreauJeanOSI(theta));

    // -- Model --
    _model.reset(new Model(t0, T));

    for (unsigned int i = 0; i < Disks->size(0); i++)
    {
      R = Disks->getValue(i, 2);
      m = Disks->getValue(i, 3);

      SP::SiconosVector qTmp;
      SP::SiconosVector vTmp;

      qTmp.reset(new SiconosVector(NDOF));
      vTmp.reset(new SiconosVector(NDOF));
      vTmp->zero();
      (*qTmp)(0) = (*Disks)(i, 0);
      (*qTmp)(1) = (*Disks)(i, 1);

      SP::LagrangianDS body;
      if (R > 0)
        body.reset(new Disk(R, m, qTmp, vTmp));
      else
        body.reset(new Circle(-R, m, qTmp, vTmp));

      // -- Set external forces (weight) --
      SP::SiconosVector FExt;
      FExt.reset(new SiconosVector(NDOF));
      FExt->zero();
      FExt->setValue(1, -m * g);
      body->setFExtPtr(FExt);

      // add the dynamical system to the one step integrator
      osi->insertDynamicalSystem(body);

      // add the dynamical system in the non smooth dynamical system
      _model->nonSmoothDynamicalSystem()->insertDynamicalSystem(body);

    }

    _model->nonSmoothDynamicalSystem()->setSymmetric(true);

    // ------------------
    // --- Simulation ---
    // ------------------

    // -- Time discretisation --
    timedisc_.reset(new TimeDiscretisation(t0, h));

    // -- OneStepNsProblem --
    osnspb_.reset(new FrictionContact(2));

    osnspb_->numericsSolverOptions()->iparam[0] = 100; // Max number of
    // iterations
    osnspb_->numericsSolverOptions()->iparam[1] = 20; // compute error
    // iterations
    osnspb_->numericsSolverOptions()->dparam[0] = 1e-3; // Tolerance

    osnspb_->setMaxSize(6 * ((3 * Ll * Ll + 3 * Ll) / 2 - Ll));
    osnspb_->setMStorageType(1);            // Sparse storage
    osnspb_->setNumericsVerboseMode(0);

    osnspb_->setKeepLambdaAndYState(true);  // inject previous solution

    // -- Simulation --
    simulation_.reset(new TimeStepping(timedisc_));

    std11::static_pointer_cast<TimeStepping>(simulation_)->setNewtonMaxIteration(3);

    simulation_->insertIntegrator(osi);
    simulation_->insertNonSmoothProblem(osnspb_);

    simulation_->setCheckSolverFunction(localCheckSolverOuput);

    // --- Simulation initialization ---

    std::cout << "====> Simulation initialisation ..." << std::endl << std::endl;

    SP::NonSmoothLaw nslaw(new NewtonImpactFrictionNSL(0, 0, 0.3, 2));

    _playground.reset(new SpaceFilter(3, 6, _model, nslaw, _plans, _moving_plans));

    _model->initialize(simulation_);

  }

  catch (SiconosException e)
  {
    std::cout << e.report() << std::endl;
    exit(1);
  }
  catch (...)
  {
    std::cout << "Exception caught in Disks::init()" << std::endl;
    exit(1);
  }
}

// =========================== End of model definition ===========================

// ================================= Computation =================================

void Disks::compute()
{
  try
  {

    _playground->buildInteractions(_model->currentTime());

    _model->simulation()->advanceToEvent();

    _model->simulation()->processEvents();

    //    Siconos::save(_model, "Disks.bin");

  }

  catch (SiconosException e)
  {
    std::cout << e.report() << std::endl;
  }
  catch (...)
  {
    std::cout << "Exception caught in SiconosBodies::compute()" << std::endl;
  }
}
<commit_msg>Update Disks example<commit_after>/* Siconos-sample , Copyright INRIA 2005-2011.
 * Siconos is a program dedicated to modeling, simulation and control
 * of non smooth dynamical systems.
 * Siconos is a free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * Siconos 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Siconos; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Contact: Vincent ACARY vincent.acary@inrialpes.fr
 */

/*!\file Disks.cpp

  Some Disks (2D), friction, and walls.
  Direct description of the model without XML input.  Simulation with
  a Time-Stepping scheme.
*/

// Siconos
#include <SiconosPointers.hpp>

#include <TimeStepping.hpp>
#include <FrictionContact.hpp>
#include <MoreauJeanOSI.hpp>
#include <NewtonImpactFrictionNSL.hpp>
//#include <Siconos/IO/SiconosRestart.hpp>

#include "Disks.hpp"
#include "Model.hpp"
#include "NonSmoothDynamicalSystem.hpp"
#include "TimeDiscretisation.hpp"
#include <Disk.hpp>
#include <Circle.hpp>
#include <DiskPlanR.hpp>
#include <SpaceFilter.hpp>

using namespace std;

/* do nothing if solver does not converge */
void localCheckSolverOuput(int, Simulation*)
{};

double A(double t)
{
  return 0. ;
}
double B(double t)
{
  return 1. ;
}
double C(double t)
{
  return 0.0;//1.1*cos(32.*M_PI*t) ;
}
double DA(double t)
{
  return 0. ;
}
double DB(double t)
{
  return 0. ;
}
double DC(double t)
{
  return 0.0;//-1.1*32.*M_PI*sin(32.*M_PI*t) ;
}

// ================= Creation of the model =======================
void Disks::init()
{

  SP::TimeDiscretisation timedisc_;
  SP::TimeStepping simulation_;
  SP::FrictionContact osnspb_;

  // User-defined main parameters

  double t0 = 0;                   // initial computation time

  double T =  std::numeric_limits<double>::infinity();

  double h = 0.01;                // time step
  double g = 9.81;

  double theta = 0.5;              // theta for MoreauJeanOSI integrator

  std::string solverName = "NSGS";

  // -----------------------------------------
  // --- Dynamical systems && interactions ---
  // -----------------------------------------

  double R;
  double m;

  try
  {

    // ------------
    // --- Init ---
    // ------------

    std::cout << "====> Model loading ..." << std::endl << std::endl;

    _plans.reset(new SimpleMatrix("plans.dat", true));
    if (_plans->size(0) == 0)
    {
      /* default plans */
      double A1 = P1A;
      double B1 = P1B;
      double C1 = P1C;

      double A2 = P2A;
      double B2 = P2B;
      double C2 = P2C;

      _plans.reset(new SimpleMatrix(6, 6));
      _plans->zero();
      (*_plans)(0, 0) = 0;
      (*_plans)(0, 1) = 1;
      (*_plans)(0, 2) = -GROUND;

      (*_plans)(1, 0) = 1;
      (*_plans)(1, 1) = 0;
      (*_plans)(1, 2) = WALL;

      (*_plans)(2, 0) = 1;
      (*_plans)(2, 1) = 0;
      (*_plans)(2, 2) = -WALL;

      (*_plans)(3, 0) = 0;
      (*_plans)(3, 1) = 1;
      (*_plans)(3, 2) = -TOP;

      (*_plans)(4, 0) = A1;
      (*_plans)(4, 1) = B1;
      (*_plans)(4, 2) = C1;

      (*_plans)(5, 0) = A2;
      (*_plans)(5, 1) = B2;
      (*_plans)(5, 2) = C2;

    }

    /* set center positions */
    for (unsigned int i = 0 ; i < _plans->size(0); ++i)
    {
      SP::DiskPlanR tmpr;
      tmpr.reset(new DiskPlanR(1, (*_plans)(i, 0), (*_plans)(i, 1), (*_plans)(i, 2),
                               (*_plans)(i, 3), (*_plans)(i, 4), (*_plans)(i, 5)));
      (*_plans)(i, 3) = tmpr->getXCenter();
      (*_plans)(i, 4) = tmpr->getYCenter();
    }

    /*    _moving_plans.reset(new FMatrix(1,6));
        (*_moving_plans)(0,0) = &A;
        (*_moving_plans)(0,1) = &B;
        (*_moving_plans)(0,2) = &C;
        (*_moving_plans)(0,3) = &DA;
        (*_moving_plans)(0,4) = &DB;
        (*_moving_plans)(0,5) = &DC;*/

    SP::SiconosMatrix Disks;
    Disks.reset(new SimpleMatrix("disks.dat", true));

    // -- OneStepIntegrators --
    SP::OneStepIntegrator osi;
    osi.reset(new MoreauJeanOSI(theta));

    // -- Model --
    _model.reset(new Model(t0, T));

    for (unsigned int i = 0; i < Disks->size(0); i++)
    {
      R = Disks->getValue(i, 2);
      m = Disks->getValue(i, 3);

      SP::SiconosVector qTmp;
      SP::SiconosVector vTmp;

      qTmp.reset(new SiconosVector(NDOF));
      vTmp.reset(new SiconosVector(NDOF));
      vTmp->zero();
      (*qTmp)(0) = (*Disks)(i, 0);
      (*qTmp)(1) = (*Disks)(i, 1);

      SP::LagrangianDS body;
      if (R > 0)
        body.reset(new Disk(R, m, qTmp, vTmp));
      else
        body.reset(new Circle(-R, m, qTmp, vTmp));

      // -- Set external forces (weight) --
      SP::SiconosVector FExt;
      FExt.reset(new SiconosVector(NDOF));
      FExt->zero();
      FExt->setValue(1, -m * g);
      body->setFExtPtr(FExt);

      // add the dynamical system to the one step integrator
      osi->insertDynamicalSystem(body);

      // add the dynamical system in the non smooth dynamical system
      _model->nonSmoothDynamicalSystem()->insertDynamicalSystem(body);

    }

    _model->nonSmoothDynamicalSystem()->setSymmetric(true);

    // ------------------
    // --- Simulation ---
    // ------------------

    // -- Time discretisation --
    timedisc_.reset(new TimeDiscretisation(t0, h));

    // -- OneStepNsProblem --
    osnspb_.reset(new FrictionContact(2));

    osnspb_->numericsSolverOptions()->iparam[0] = 100; // Max number of
    // iterations
    osnspb_->numericsSolverOptions()->iparam[1] = 20; // compute error
    // iterations
    osnspb_->numericsSolverOptions()->dparam[0] = 1e-3; // Tolerance

    osnspb_->setMaxSize(6 * ((3 * Ll * Ll + 3 * Ll) / 2 - Ll));
    osnspb_->setMStorageType(1);            // Sparse storage
    osnspb_->setNumericsVerboseMode(0);

    osnspb_->setKeepLambdaAndYState(true);  // inject previous solution

    // -- Simulation --
    simulation_.reset(new TimeStepping(timedisc_));

    std11::static_pointer_cast<TimeStepping>(simulation_)->setNewtonMaxIteration(3);

    simulation_->insertIntegrator(osi);
    simulation_->insertNonSmoothProblem(osnspb_);

    simulation_->setCheckSolverFunction(localCheckSolverOuput);

    // --- Simulation initialization ---

    std::cout << "====> Simulation initialisation ..." << std::endl << std::endl;

    SP::NonSmoothLaw nslaw(new NewtonImpactFrictionNSL(0, 0, 0.3, 2));

    _playground.reset(new SpaceFilter(3, 6, _model, nslaw, _plans, _moving_plans));

    _model->initialize(simulation_);

  }

  catch (SiconosException e)
  {
    std::cout << e.report() << std::endl;
    exit(1);
  }
  catch (...)
  {
    std::cout << "Exception caught in Disks::init()" << std::endl;
    exit(1);
  }
}

// =========================== End of model definition ===========================

// ================================= Computation =================================

void Disks::compute()
{
  try
  {

    _playground->buildInteractions(_model->currentTime());

    _model->simulation()->advanceToEvent();

    _model->simulation()->processEvents();

    //    Siconos::save(_model, "Disks.bin");

  }

  catch (SiconosException e)
  {
    std::cout << e.report() << std::endl;
  }
  catch (...)
  {
    std::cout << "Exception caught in SiconosBodies::compute()" << std::endl;
  }
}
<|endoftext|>


<commit_before>#include <bits/stdc++.h>
using namespace std;

void insertionSort(int array[], int size)
{
	int i = 0, j = 0, tempElement = 0, tempIndex = 0, flag = 0;
	for (i = 1; i < size; i++)
	{
		tempElement = array[i];
		for (j = i - 1; j >= 0; j--)
		{
			if (array[j] > tempElement)
				array[j + 1] = array[j];
			else
				flag = 1;
			break;
		}
		if (flag == 1 || j == -1)
		{
			flag = 0;
			array[j + 1] = tempElement;
		}
	}
}

void display(int array[], int size)
{
	int i = 0;
	for (i = 0; i < size; i++)
		cout << array[i] << " ";
	cout << endl;
}

int main()
{
	int array[] = {5, 4, 233, 32, 1, 4, 34, 3, 23};
	int size = sizeof(array) / sizeof(array[0]);
	cout << "unsorted array is :" << endl;
	display(array, size);
	insertionSort(array, size);
	cout << "sorted array is :" << endl;
	display(array, size);
}
<commit_msg>minute changes updated comments<commit_after>#include <bits/stdc++.h>
using namespace std;

void insertionSort(int array[], int size)
{
	int i = 0, j = 0, tempElement = 0, tempIndex = 0, flag = 0;
	for (i = 1; i < size; i++)
	{
		tempElement = array[i]; //taking an array element into tempElement
		for (j = i - 1; j >= 0; j--)
		{
			if (array[j] > tempElement)
				array[j + 1] = array[j];
			else
				flag = 1; //checking if we got the correct position of tempElement
			break;
		}
		if (flag == 1 || j == -1) //condition checking if we got correct position of tempElement or not
		{
			flag = 0;
			array[j + 1] = tempElement; //putting tempElement to it correct position
		}
	}
}

void display(int array[], int size)
{
	int i = 0;
	for (i = 0; i < size; i++)
		cout << array[i] << " ";
	cout << endl;
}

int main()
{
	int array[] = {5, 4, 233, 32, 1, 4, 34, 3, 23};
	int size = sizeof(array) / sizeof(array[0]);
	cout << "unsorted array is :" << endl;
	display(array, size); //display unsorted array
	insertionSort(array, size);
	cout << "sorted array is :" << endl;
	display(array, size); //display the sorted array
}
<|endoftext|>


<commit_before>/*
**
** Author(s):
**  - Pierre ROULLON <proullon@aldebaran-robotics.com>
**
** Copyright (C) 2012 Aldebaran Robotics
*/

#include <qi/log.hpp>
#include <qitype/signature.hpp>
#include <qitype/genericobjectbuilder.hpp>
#include <qitype/genericobject.hpp>
#include <qitype/genericvalue.hpp>
#include <qitype/typedispatcher.hpp>
#include <qitype/type.hpp>

#include <jnitools.hpp>
#include <jobjectconverter.hpp>
#include <map_jni.hpp>
#include <list_jni.hpp>
#include <tuple_jni.hpp>

using namespace qi;

struct toJObject
{
    toJObject(jobject *result)
      : result(result), jni_version(QI_JNI_MIN_VERSION)
    {
      if (JVM()->GetEnv((void **) &env, jni_version) != JNI_OK)
        qiLogFatal("qimessaging.jni") << "Cannot initialize Java environment.";
    }

    void visitUnknown(qi::GenericValuePtr value)
    {
      throwJavaError(env, "Error in conversion: Unable to convert unknown type in Java");
    }

    void visitInt(qi::int64_t value, bool isSigned, int byteSize)
    {
      // Clear all remaining exceptions
      env->ExceptionClear();

      // Get Integer class template
      // ... or Boolean if byteSize is 0
      jclass cls = env->FindClass(byteSize == 0 ? "java/lang/Boolean" : "java/lang/Integer");
      if (env->ExceptionCheck())
      {
        throwJavaError(env, "GenericValue to Integer : FindClass error");
        return;
      }

      // Find constructor method ID
      jmethodID mid = env->GetMethodID(cls, "<init>", byteSize == 0 ? "(Z)V" : "(I)V");
      if (!mid)
      {
        env->DeleteLocalRef(cls);
        throwJavaError(env, "GenericValue to Integer : GetMethodID error");
        return;
      }

      // Instanciate new Integer, yeah !
      jint jval = value;
      *result = env->NewObject(cls, mid, jval);
      checkForError();
      env->DeleteLocalRef(cls);
    }

    void visitString(char *data, size_t len)//qi::TypeString* type, void* storage)
    {
      if (data)
        *result = (jobject) env->NewStringUTF(data);
      else
        *result = (jobject) env->NewStringUTF("");
      checkForError();
    }

    void visitVoid()
    {
      jclass cls = env->FindClass("java/lang/Void");
      jmethodID mid = env->GetMethodID(cls, "<init>", "()V");
      *result = env->NewObject(cls, mid);
      checkForError();
    }

    void visitFloat(double value, int byteSize)
    {
      // Clear all remaining exceptions
      env->ExceptionClear();

      // Get Float class template
      jclass cls = env->FindClass("java/lang/Float");
      if (env->ExceptionCheck())
      {
        throwJavaError(env, "GenericValue to Float : FindClass error");
        return;
      }

      // Find constructor method ID
      jmethodID mid = env->GetMethodID(cls, "<init>","(F)V");
      if (!mid)
      {
        env->DeleteLocalRef(cls);
        throwJavaError(env, "GenericValue to Float : GetMethodID error");
        return;
      }

      // Instanciate new Float, yeah !
      jfloat jval = value;
      *result = env->NewObject(cls, mid, jval);
      env->DeleteLocalRef(cls);
      checkForError();
    }

    void visitList(qi::GenericIterator it, qi::GenericIterator end)
    {
      JNIList list; // this is OK.

      for(; it != end; ++it)
      {
        jobject current = (*it).to<jobject>();
        list.push_back(current);
      }

      it.destroy();
      end.destroy();
      *result = list.object();
    }

    void visitMap(qi::GenericIterator it, qi::GenericIterator end)
    {
      jobject key, value;
      JNIHashTable ht;

      for (; it != end; ++it)
      {
        key = JObject_from_GenericValue((*it)[0]);
        value = JObject_from_GenericValue((*it)[1]);

        ht.setItem(key, value);
      }

      *result = ht.object();
      it.destroy();
      end.destroy();
    }

    void visitObject(qi::GenericObject obj)
    {
      throw std::runtime_error("Cannot convert GenericObject to Jobject.");

      /*jclass cls = env->FindClass("com/aldebaran/qimessaging/GenericObject");
      if (!cls)
      {
        qiLogError("qimessaging.jni") << "Cannot convert GenericObject to Java object";
        return;
      }

      jmethodID mid = env->GetMethodID(cls, "<init>", "(J)V");
      if (!cls)
      {
        qiLogError("qimessaging.jni") << "Cannot convert GenericObject to Java object";
        return;
      }

      *result = env->NewObject(cls, mid, (jlong) ptr);*/
    }

    void visitPointer(qi::GenericValuePtr pointee)
    {
      throwJavaError(env, "Error in conversion: Unable to convert pointer in Java");
    }

    void visitTuple(const std::vector<qi::GenericValuePtr>& tuple)
    {
      JNITuple jtuple(tuple.size());
      int i = 0;

      for(std::vector<qi::GenericValuePtr>::const_iterator it = tuple.begin(); it != tuple.end(); ++it)
      {
        jobject current = (*it).to<jobject>();
        jtuple.set(i++, current);
      }

      *result = jtuple.object();
    }

    void visitDynamic(qi::GenericValuePtr pointee)
    {
      *result = JObject_from_GenericValue(pointee);
    }

    void visitRaw(qi::GenericValuePtr value)
    {
      // Not tested.
      /* Encapuslate the buffer in ByteBuffer */
      qi::Buffer buf = value.as<qi::Buffer>();

      // Create a new ByteBuffer and reserve enough space
      jclass cls = env->FindClass("java/lang/ByteBuffer");
      jmethodID mid = env->GetMethodID(cls, "init","(I)V");
      jobject ar = env->NewObject(cls, mid, buf.size() + 1);

      // Put qi::Buffer content into ByteByffer
      mid = env->GetMethodID(cls, "put","([B]II)[LJava/lang/ByteBuffer;");
      *result = env->CallObjectMethod(ar, mid, buf.data(), 0, buf.size());

      checkForError();
      env->DeleteLocalRef(cls);
      env->DeleteLocalRef(ar);
    }

    void visitIterator(qi::GenericValuePtr v)
    {
      visitUnknown(v);
    }

    void checkForError()
    {
      if (result == NULL)
        throwJavaError(env, "Error in conversion to JObject");
    }

    jobject* result;
    int      jni_version;
    JNIEnv*  env;

}; // !toJObject

jobject JObject_from_GenericValue(qi::GenericValuePtr val)
{
  jobject result= NULL;
  toJObject tjo(&result);
  qi::typeDispatch<toJObject>(tjo, val);
  return result;
}

void JObject_from_GenericValue(qi::GenericValuePtr val, jobject* target)
{
  toJObject tal(target);
  qi::typeDispatch<toJObject>(tal, val);
}

qi::GenericValuePtr GenericValue_from_JObject_List(jobject val)
{
  JNIEnv* env;
  JNIList list(val);
  std::vector<qi::GenericValue>& res = *new std::vector<qi::GenericValue>();
  int size = 0;

  JVM()->GetEnv((void **) &env, QI_JNI_MIN_VERSION);

  size = list.size();
  res.reserve(size);
  for (int i = 0; i < size; i++)
  {
    jobject current = list.get(i);
    //qi::GenericValuePtr currentGVP = qi::GenericValuePtr(current);
    res.push_back(qi::GenericValue(GenericValue_from_JObject(current).first));
  }

  return qi::GenericValueRef(res);
}

qi::GenericValuePtr GenericValue_from_JObject_Map(jobject hashtable)
{
  JNIEnv* env;
  std::map<qi::GenericValue, qi::GenericValue>& res = *new std::map<qi::GenericValue, qi::GenericValue>();
  JNIHashTable ht(hashtable);
  jobject key, value;

  JVM()->GetEnv((void **) &env, QI_JNI_MIN_VERSION);

  JNIEnumeration keys = ht.keys();
  while (keys.hasNextElement())
  {
    key = keys.nextElement();
    value = ht.at(key);
    qi::GenericValuePtr newKey = GenericValue_from_JObject(key).first;
    qi::GenericValuePtr newValue = GenericValue_from_JObject(value).first;
    res[qi::GenericValue(newKey)] = newValue;
    env->DeleteLocalRef(key);
    env->DeleteLocalRef(value);
  }
  return qi::GenericValueRef(res);
}

qi::GenericValuePtr GenericValue_from_JObject_Tuple(jobject val)
{
  JNITuple tuple(val);
  int i = 0;
  std::vector<qi::GenericValuePtr>& res = *new std::vector<qi::GenericValuePtr>();

  while (i < tuple.size())
  {
    qi::GenericValuePtr value = GenericValue_from_JObject(tuple.get(i)).first;
    res.push_back(value);
    i++;
  }

  return qi::makeGenericTuple(res);
}

std::pair<qi::GenericValuePtr, bool> GenericValue_from_JObject(jobject val)
{
  qi::GenericValuePtr res;
  JNIEnv* env;
  bool copy = false;

  if (!val)
    throw std::runtime_error("Unable to convert JObject in GenericValue (Value is null)");

  if (JVM()->AttachCurrentThread((envPtr) &env, (void *) 0) != JNI_OK)
    throw std::runtime_error("Cannot attach current thread to JVM for conversion.");

  if (JVM()->GetEnv((void **) &env, QI_JNI_MIN_VERSION) != JNI_OK)
    throw std::runtime_error("No JNIEnvironment available for conversion.");

  jclass stringClass = env->FindClass("java/lang/String");
  jclass int32Class = env->FindClass("java/lang/Integer");
  jclass floatClass = env->FindClass("java/lang/Float");
  jclass doubleClass = env->FindClass("java/lang/Double");
  jclass boolClass = env->FindClass("java/lang/Boolean");
  jclass longClass = env->FindClass("java/lang/Long");
  jclass mapClass = env->FindClass("java/util/Map");
  jclass listClass = env->FindClass("java/util/ArrayList");
  jclass tupleClass = env->FindClass("com/aldebaran/qimessaging/Tuple");

  if (val == NULL)
  {
    res = qi::GenericValuePtr(qi::typeOf<void>());
  }
  else if (env->IsInstanceOf(val, stringClass))
  {
    std::string tmp = std::string(env->GetStringUTFChars((jstring) val, 0));
    res = qi::GenericValueRef(*new std::string(tmp));
    copy = true;
  }
  else if (env->IsInstanceOf(val, floatClass))
  {
    jmethodID mid = env->GetMethodID(floatClass, "floatValue","()F");
    jfloat v = env->CallFloatMethod(val, mid);
    res = qi::GenericValueRef((float)v).clone();
    copy = true;
  }
  else if (env->IsInstanceOf(val, doubleClass)) // If double, convert to float
  {
    jmethodID mid = env->GetMethodID(doubleClass, "doubleValue","()D");
    jfloat v = (jfloat) env->CallDoubleMethod(val, mid);
    res = qi::GenericValueRef((float)v).clone();
    copy = true;
  }
  else if (env->IsInstanceOf(val, longClass))
  {
    jmethodID mid = env->GetMethodID(longClass, "longValue","()L");
    jlong v = env->CallLongMethod(val, mid);
    res = qi::GenericValueRef(v).clone();
    copy = true;
  }
  else if (env->IsInstanceOf(val, boolClass))
  {
    jmethodID mid = env->GetMethodID(boolClass, "booleanValue","()Z");
    jboolean v = env->CallBooleanMethod(val, mid);
    res = qi::GenericValueRef((bool) v).clone();
    copy = true;
  }
  else if (env->IsInstanceOf(val, int32Class))
  {
    jmethodID mid = env->GetMethodID(int32Class, "intValue","()I");
    jint v = env->CallIntMethod(val, mid);
    res = qi::GenericValueRef((int) v).clone();
    copy = true;
  }
  else if (env->IsInstanceOf(val, listClass))
  {
    copy = true;
    res = GenericValue_from_JObject_List(val);
  }
  else if (env->IsInstanceOf(val, mapClass))
  {
    copy = true;
    res = GenericValue_from_JObject_Map(val);
  }
  else if (env->IsInstanceOf(val, tupleClass))
  {
    res = GenericValue_from_JObject_Tuple(val);
  }
  else
  {
    throw std::runtime_error("Unable to convert JObject in GenericValue");
  }

  env->DeleteLocalRef(stringClass);
  env->DeleteLocalRef(int32Class);
  env->DeleteLocalRef(floatClass);
  env->DeleteLocalRef(doubleClass);
  env->DeleteLocalRef(boolClass);
  env->DeleteLocalRef(longClass);
  env->DeleteLocalRef(mapClass);
  env->DeleteLocalRef(listClass);
  env->DeleteLocalRef(tupleClass);

  return std::make_pair(res, copy);
}

/*
 * Define this struct to add jobject to the type system.
 * That way we can manipulate jobject transparently.
 * - We have to override clone and destroy here to be compliant
 *   with the java reference counting. Otherwise, the value could
 *   be Garbage Collected as we try to manipulate it.
 * - We register the type as 'jobject' since java methods manipulates
 *   objects only by this typedef pointer, never by value and we do not want to copy
 *   a jobject.
 */
class JObjectType: public qi::TypeDynamic
{
  public:

    virtual const qi::TypeInfo& info()
    {
      //qiLogFatal("qimessaging.jni") << "info";
      static qi::TypeInfo* result = 0;
      if (!result)
      {
        result = new qi::TypeInfo(typeid(jobject));
        std::cout << result->asString() << std::endl;
      }

      return *result;
    }

    virtual void* initializeStorage(void* ptr = 0)
    {
      // ptr is jobject* (aka _jobject**)
      return ptr;
    }

    virtual void* ptrFromStorage(void** s)
    {
      jobject* tmp = (jobject*) s;
      return *tmp;
    }

    virtual qi::GenericValuePtr get(void* storage)
    {
      return GenericValue_from_JObject(*((jobject*)ptrFromStorage(&storage))).first;
    }

    virtual void set(void** storage, qi::GenericValuePtr src)
    {
      // storage is jobject*
      // We will assign *storage to target, so we need it to be allocated
      jobject *target = new jobject;

      // Giving jobject* to JObject_from_GenericValue
      JObject_from_GenericValue(src, target);

      JNIEnv *env;
      JVM()->GetEnv((void **) &env, QI_JNI_MIN_VERSION);
      JVM()->AttachCurrentThread((envPtr) &env, (void *) 0);
      env->NewGlobalRef(*target);

      *storage = target;
    }

    virtual void* clone(void* obj)
    {
      jobject*    ginstance = (jobject*) obj;

      if (!obj)
        return 0;

      jobject* cloned = new jobject;
      *cloned = JObject_from_GenericValue(qi::GenericValueRef(*ginstance));

      return cloned;
    }

    virtual void destroy(void* obj)
    {
      // void* obj is a jobject

      // We cannot delete GlobalRef, because it's shared with JVM.
      // FIXME: Find a way to delete the local one.
      // Atm it destroys object because JVM hasn't set its ref onto jobject
      // when destroy is called.
    }

    virtual bool less(void* a, void* b)
    {
      jobject* pa = (jobject*) ptrFromStorage(&a);
      jobject* pb = (jobject*) ptrFromStorage(&b);

      // call Object.compare
      return *pa < *pb;
    }
};

/* Register jobject -> See the above comment for explanations */
QI_TYPE_REGISTER_CUSTOM(jobject, JObjectType);

<commit_msg>Java bindings: Add visitObjectPtr to converter.<commit_after>/*
**
** Author(s):
**  - Pierre ROULLON <proullon@aldebaran-robotics.com>
**
** Copyright (C) 2012 Aldebaran Robotics
*/

#include <qi/log.hpp>
#include <qitype/signature.hpp>
#include <qitype/genericobjectbuilder.hpp>
#include <qitype/genericobject.hpp>
#include <qitype/genericvalue.hpp>
#include <qitype/typedispatcher.hpp>
#include <qitype/type.hpp>

#include <jnitools.hpp>
#include <jobjectconverter.hpp>
#include <map_jni.hpp>
#include <list_jni.hpp>
#include <tuple_jni.hpp>

using namespace qi;

struct toJObject
{
    toJObject(jobject *result)
      : result(result), jni_version(QI_JNI_MIN_VERSION)
    {
      if (JVM()->GetEnv((void **) &env, jni_version) != JNI_OK)
        qiLogFatal("qimessaging.jni") << "Cannot initialize Java environment.";
    }

    void visitUnknown(qi::GenericValuePtr value)
    {
      throwJavaError(env, "Error in conversion: Unable to convert unknown type in Java");
    }

    void visitInt(qi::int64_t value, bool isSigned, int byteSize)
    {
      // Clear all remaining exceptions
      env->ExceptionClear();

      // Get Integer class template
      // ... or Boolean if byteSize is 0
      jclass cls = env->FindClass(byteSize == 0 ? "java/lang/Boolean" : "java/lang/Integer");
      if (env->ExceptionCheck())
      {
        throwJavaError(env, "GenericValue to Integer : FindClass error");
        return;
      }

      // Find constructor method ID
      jmethodID mid = env->GetMethodID(cls, "<init>", byteSize == 0 ? "(Z)V" : "(I)V");
      if (!mid)
      {
        env->DeleteLocalRef(cls);
        throwJavaError(env, "GenericValue to Integer : GetMethodID error");
        return;
      }

      // Instanciate new Integer, yeah !
      jint jval = value;
      *result = env->NewObject(cls, mid, jval);
      checkForError();
      env->DeleteLocalRef(cls);
    }

    void visitString(char *data, size_t len)//qi::TypeString* type, void* storage)
    {
      if (data)
        *result = (jobject) env->NewStringUTF(data);
      else
        *result = (jobject) env->NewStringUTF("");
      checkForError();
    }

    void visitVoid()
    {
      jclass cls = env->FindClass("java/lang/Void");
      jmethodID mid = env->GetMethodID(cls, "<init>", "()V");
      *result = env->NewObject(cls, mid);
      checkForError();
    }

    void visitFloat(double value, int byteSize)
    {
      // Clear all remaining exceptions
      env->ExceptionClear();

      // Get Float class template
      jclass cls = env->FindClass("java/lang/Float");
      if (env->ExceptionCheck())
      {
        throwJavaError(env, "GenericValue to Float : FindClass error");
        return;
      }

      // Find constructor method ID
      jmethodID mid = env->GetMethodID(cls, "<init>","(F)V");
      if (!mid)
      {
        env->DeleteLocalRef(cls);
        throwJavaError(env, "GenericValue to Float : GetMethodID error");
        return;
      }

      // Instanciate new Float, yeah !
      jfloat jval = value;
      *result = env->NewObject(cls, mid, jval);
      env->DeleteLocalRef(cls);
      checkForError();
    }

    void visitList(qi::GenericIterator it, qi::GenericIterator end)
    {
      JNIList list; // this is OK.

      for(; it != end; ++it)
      {
        jobject current = (*it).to<jobject>();
        list.push_back(current);
      }

      it.destroy();
      end.destroy();
      *result = list.object();
    }

    void visitMap(qi::GenericIterator it, qi::GenericIterator end)
    {
      jobject key, value;
      JNIHashTable ht;

      for (; it != end; ++it)
      {
        key = JObject_from_GenericValue((*it)[0]);
        value = JObject_from_GenericValue((*it)[1]);

        ht.setItem(key, value);
      }

      *result = ht.object();
      it.destroy();
      end.destroy();
    }

    void visitObject(qi::GenericObject obj)
    {
      throw std::runtime_error("Cannot convert GenericObject to Jobject.");

      /*jclass cls = env->FindClass("com/aldebaran/qimessaging/GenericObject");
      if (!cls)
      {
        qiLogError("qimessaging.jni") << "Cannot convert GenericObject to Java object";
        return;
      }

      jmethodID mid = env->GetMethodID(cls, "<init>", "(J)V");
      if (!cls)
      {
        qiLogError("qimessaging.jni") << "Cannot convert GenericObject to Java object";
        return;
      }

      *result = env->NewObject(cls, mid, (jlong) ptr);*/
    }

    void visitObjectPtr(qi::ObjectPtr o)
    {
      throw std::runtime_error("Cannot convert ObjectPtr to Jobject.");
    }

    void visitPointer(qi::GenericValuePtr pointee)
    {
      throwJavaError(env, "Error in conversion: Unable to convert pointer in Java");
    }

    void visitTuple(const std::vector<qi::GenericValuePtr>& tuple)
    {
      JNITuple jtuple(tuple.size());
      int i = 0;

      for(std::vector<qi::GenericValuePtr>::const_iterator it = tuple.begin(); it != tuple.end(); ++it)
      {
        jobject current = (*it).to<jobject>();
        jtuple.set(i++, current);
      }

      *result = jtuple.object();
    }

    void visitDynamic(qi::GenericValuePtr pointee)
    {
      *result = JObject_from_GenericValue(pointee);
    }

    void visitRaw(qi::GenericValuePtr value)
    {
      // Not tested.
      /* Encapuslate the buffer in ByteBuffer */
      qi::Buffer buf = value.as<qi::Buffer>();

      // Create a new ByteBuffer and reserve enough space
      jclass cls = env->FindClass("java/lang/ByteBuffer");
      jmethodID mid = env->GetMethodID(cls, "init","(I)V");
      jobject ar = env->NewObject(cls, mid, buf.size() + 1);

      // Put qi::Buffer content into ByteByffer
      mid = env->GetMethodID(cls, "put","([B]II)[LJava/lang/ByteBuffer;");
      *result = env->CallObjectMethod(ar, mid, buf.data(), 0, buf.size());

      checkForError();
      env->DeleteLocalRef(cls);
      env->DeleteLocalRef(ar);
    }

    void visitIterator(qi::GenericValuePtr v)
    {
      visitUnknown(v);
    }

    void checkForError()
    {
      if (result == NULL)
        throwJavaError(env, "Error in conversion to JObject");
    }

    jobject* result;
    int      jni_version;
    JNIEnv*  env;

}; // !toJObject

jobject JObject_from_GenericValue(qi::GenericValuePtr val)
{
  jobject result= NULL;
  toJObject tjo(&result);
  qi::typeDispatch<toJObject>(tjo, val);
  return result;
}

void JObject_from_GenericValue(qi::GenericValuePtr val, jobject* target)
{
  toJObject tal(target);
  qi::typeDispatch<toJObject>(tal, val);
}

qi::GenericValuePtr GenericValue_from_JObject_List(jobject val)
{
  JNIEnv* env;
  JNIList list(val);
  std::vector<qi::GenericValue>& res = *new std::vector<qi::GenericValue>();
  int size = 0;

  JVM()->GetEnv((void **) &env, QI_JNI_MIN_VERSION);

  size = list.size();
  res.reserve(size);
  for (int i = 0; i < size; i++)
  {
    jobject current = list.get(i);
    //qi::GenericValuePtr currentGVP = qi::GenericValuePtr(current);
    res.push_back(qi::GenericValue(GenericValue_from_JObject(current).first));
  }

  return qi::GenericValueRef(res);
}

qi::GenericValuePtr GenericValue_from_JObject_Map(jobject hashtable)
{
  JNIEnv* env;
  std::map<qi::GenericValue, qi::GenericValue>& res = *new std::map<qi::GenericValue, qi::GenericValue>();
  JNIHashTable ht(hashtable);
  jobject key, value;

  JVM()->GetEnv((void **) &env, QI_JNI_MIN_VERSION);

  JNIEnumeration keys = ht.keys();
  while (keys.hasNextElement())
  {
    key = keys.nextElement();
    value = ht.at(key);
    qi::GenericValuePtr newKey = GenericValue_from_JObject(key).first;
    qi::GenericValuePtr newValue = GenericValue_from_JObject(value).first;
    res[qi::GenericValue(newKey)] = newValue;
    env->DeleteLocalRef(key);
    env->DeleteLocalRef(value);
  }
  return qi::GenericValueRef(res);
}

qi::GenericValuePtr GenericValue_from_JObject_Tuple(jobject val)
{
  JNITuple tuple(val);
  int i = 0;
  std::vector<qi::GenericValuePtr>& res = *new std::vector<qi::GenericValuePtr>();

  while (i < tuple.size())
  {
    qi::GenericValuePtr value = GenericValue_from_JObject(tuple.get(i)).first;
    res.push_back(value);
    i++;
  }

  return qi::makeGenericTuple(res);
}

std::pair<qi::GenericValuePtr, bool> GenericValue_from_JObject(jobject val)
{
  qi::GenericValuePtr res;
  JNIEnv* env;
  bool copy = false;

  if (!val)
    throw std::runtime_error("Unable to convert JObject in GenericValue (Value is null)");

  if (JVM()->AttachCurrentThread((envPtr) &env, (void *) 0) != JNI_OK)
    throw std::runtime_error("Cannot attach current thread to JVM for conversion.");

  if (JVM()->GetEnv((void **) &env, QI_JNI_MIN_VERSION) != JNI_OK)
    throw std::runtime_error("No JNIEnvironment available for conversion.");

  jclass stringClass = env->FindClass("java/lang/String");
  jclass int32Class = env->FindClass("java/lang/Integer");
  jclass floatClass = env->FindClass("java/lang/Float");
  jclass doubleClass = env->FindClass("java/lang/Double");
  jclass boolClass = env->FindClass("java/lang/Boolean");
  jclass longClass = env->FindClass("java/lang/Long");
  jclass mapClass = env->FindClass("java/util/Map");
  jclass listClass = env->FindClass("java/util/ArrayList");
  jclass tupleClass = env->FindClass("com/aldebaran/qimessaging/Tuple");

  if (val == NULL)
  {
    res = qi::GenericValuePtr(qi::typeOf<void>());
  }
  else if (env->IsInstanceOf(val, stringClass))
  {
    std::string tmp = std::string(env->GetStringUTFChars((jstring) val, 0));
    res = qi::GenericValueRef(*new std::string(tmp));
    copy = true;
  }
  else if (env->IsInstanceOf(val, floatClass))
  {
    jmethodID mid = env->GetMethodID(floatClass, "floatValue","()F");
    jfloat v = env->CallFloatMethod(val, mid);
    res = qi::GenericValueRef((float)v).clone();
    copy = true;
  }
  else if (env->IsInstanceOf(val, doubleClass)) // If double, convert to float
  {
    jmethodID mid = env->GetMethodID(doubleClass, "doubleValue","()D");
    jfloat v = (jfloat) env->CallDoubleMethod(val, mid);
    res = qi::GenericValueRef((float)v).clone();
    copy = true;
  }
  else if (env->IsInstanceOf(val, longClass))
  {
    jmethodID mid = env->GetMethodID(longClass, "longValue","()L");
    jlong v = env->CallLongMethod(val, mid);
    res = qi::GenericValueRef(v).clone();
    copy = true;
  }
  else if (env->IsInstanceOf(val, boolClass))
  {
    jmethodID mid = env->GetMethodID(boolClass, "booleanValue","()Z");
    jboolean v = env->CallBooleanMethod(val, mid);
    res = qi::GenericValueRef((bool) v).clone();
    copy = true;
  }
  else if (env->IsInstanceOf(val, int32Class))
  {
    jmethodID mid = env->GetMethodID(int32Class, "intValue","()I");
    jint v = env->CallIntMethod(val, mid);
    res = qi::GenericValueRef((int) v).clone();
    copy = true;
  }
  else if (env->IsInstanceOf(val, listClass))
  {
    copy = true;
    res = GenericValue_from_JObject_List(val);
  }
  else if (env->IsInstanceOf(val, mapClass))
  {
    copy = true;
    res = GenericValue_from_JObject_Map(val);
  }
  else if (env->IsInstanceOf(val, tupleClass))
  {
    res = GenericValue_from_JObject_Tuple(val);
  }
  else
  {
    throw std::runtime_error("Unable to convert JObject in GenericValue");
  }

  env->DeleteLocalRef(stringClass);
  env->DeleteLocalRef(int32Class);
  env->DeleteLocalRef(floatClass);
  env->DeleteLocalRef(doubleClass);
  env->DeleteLocalRef(boolClass);
  env->DeleteLocalRef(longClass);
  env->DeleteLocalRef(mapClass);
  env->DeleteLocalRef(listClass);
  env->DeleteLocalRef(tupleClass);

  return std::make_pair(res, copy);
}

/*
 * Define this struct to add jobject to the type system.
 * That way we can manipulate jobject transparently.
 * - We have to override clone and destroy here to be compliant
 *   with the java reference counting. Otherwise, the value could
 *   be Garbage Collected as we try to manipulate it.
 * - We register the type as 'jobject' since java methods manipulates
 *   objects only by this typedef pointer, never by value and we do not want to copy
 *   a jobject.
 */
class JObjectType: public qi::TypeDynamic
{
  public:

    virtual const qi::TypeInfo& info()
    {
      //qiLogFatal("qimessaging.jni") << "info";
      static qi::TypeInfo* result = 0;
      if (!result)
      {
        result = new qi::TypeInfo(typeid(jobject));
        std::cout << result->asString() << std::endl;
      }

      return *result;
    }

    virtual void* initializeStorage(void* ptr = 0)
    {
      // ptr is jobject* (aka _jobject**)
      return ptr;
    }

    virtual void* ptrFromStorage(void** s)
    {
      jobject* tmp = (jobject*) s;
      return *tmp;
    }

    virtual qi::GenericValuePtr get(void* storage)
    {
      return GenericValue_from_JObject(*((jobject*)ptrFromStorage(&storage))).first;
    }

    virtual void set(void** storage, qi::GenericValuePtr src)
    {
      // storage is jobject*
      // We will assign *storage to target, so we need it to be allocated
      jobject *target = new jobject;

      // Giving jobject* to JObject_from_GenericValue
      JObject_from_GenericValue(src, target);

      JNIEnv *env;
      JVM()->GetEnv((void **) &env, QI_JNI_MIN_VERSION);
      JVM()->AttachCurrentThread((envPtr) &env, (void *) 0);
      env->NewGlobalRef(*target);

      *storage = target;
    }

    virtual void* clone(void* obj)
    {
      jobject*    ginstance = (jobject*) obj;

      if (!obj)
        return 0;

      jobject* cloned = new jobject;
      *cloned = JObject_from_GenericValue(qi::GenericValueRef(*ginstance));

      return cloned;
    }

    virtual void destroy(void* obj)
    {
      // void* obj is a jobject

      // We cannot delete GlobalRef, because it's shared with JVM.
      // FIXME: Find a way to delete the local one.
      // Atm it destroys object because JVM hasn't set its ref onto jobject
      // when destroy is called.
    }

    virtual bool less(void* a, void* b)
    {
      jobject* pa = (jobject*) ptrFromStorage(&a);
      jobject* pb = (jobject*) ptrFromStorage(&b);

      // call Object.compare
      return *pa < *pb;
    }
};

/* Register jobject -> See the above comment for explanations */
QI_TYPE_REGISTER_CUSTOM(jobject, JObjectType);

<|endoftext|>


<commit_before>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM 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) version 2.1 dated February 1999.

#ifndef MFEM_TABLE
#define MFEM_TABLE

// Data types for Table.

#include "mem_alloc.hpp"
#include "array.hpp"

namespace mfem
{

/// Helper struct for defining a connectivity table, see Table::MakeFromList.
struct Connection
{
   int from, to;
   Connection(int from, int to) : from(from), to(to) {}

   bool operator== (const Connection &rhs) const
   { return (from == rhs.from) && (to == rhs.to); }
   bool operator< (const Connection &rhs) const
   { return (from == rhs.from) ? (to < rhs.to) : (from < rhs.from); }
};

/** Data type Table. Table stores the connectivity of elements of TYPE I
    to elements of TYPE II, for example, it may be Element-To-Face
    connectivity table, etc. */
class Table
{
protected:

   /// size is the number of TYPE I elements.
   int size;

   /** Arrays for the connectivity information in the CSR storage.
       I is of size "size+1", J is of size the number of connections
       between TYPE I to TYPE II elements (actually stored I[size]). */
   int *I, *J;

public:
   /// Creates an empty table
   Table() { size = -1; I = J = NULL; }

   /// Copy constructor
   Table(const Table &);

   /// Create a table with an upper limit for the number of connections.
   explicit Table (int dim, int connections_per_row = 3);

   /** Create a table from a list of connections, see MakeFromList. */
   Table(int nrows, Array<Connection> &list) : size(-1), I(NULL), J(NULL)
   { MakeFromList(nrows, list); }

   /** Create a table with one entry per row with column indices given
       by 'partitioning'. */
   Table (int nrows, int *partitioning);

   /// Next 7 methods are used together with the default constructor
   void MakeI (int nrows);
   void AddAColumnInRow (int r) { I[r]++; }
   void AddColumnsInRow (int r, int ncol) { I[r] += ncol; }
   void MakeJ();
   void AddConnection (int r, int c) { J[I[r]++] = c; }
   void AddConnections (int r, const int *c, int nc);
   void ShiftUpI();

   /// Set the size and the number of connections for the table.
   void SetSize(int dim, int connections_per_row);

   /** Set the rows and the number of all connections for the table.
       Does NOT initialize the whole array I ! (I[0]=0 and I[rows]=nnz only) */
   void SetDims(int rows, int nnz);

   /// Returns the number of TYPE I elements.
   inline int Size() const { return size; }

   /** Returns the number of connections in the table. If Finalize() is
       not called, it returns the number of possible connections established
       by the used constructor. Otherwise, it is exactly the number of
       established connections before calling Finalize(). */
   inline int Size_of_connections() const { return I[size]; }

   /** Returns index of the connection between element i of TYPE I and
       element j of TYPE II. If there is no connection between element i
       and element j established in the table, then the return value is -1. */
   int operator() (int i, int j) const;

   /// Return row i in array row (the Table must be finalized)
   void GetRow(int i, Array<int> &row) const;

   int RowSize(int i) const { return I[i+1]-I[i]; }

   const int *GetRow(int i) const { return J+I[i]; }
   int *GetRow(int i) { return J+I[i]; }

   int *GetI() { return I; }
   int *GetJ() { return J; }
   const int *GetI() const { return I; }
   const int *GetJ() const { return J; }

   /// @brief Sort the column (TYPE II) indices in each row.
   void SortRows();

   void SetIJ(int *newI, int *newJ, int newsize = -1);

   /** Establish connection between element i and element j in the table.
       The return value is the index of the connection. It returns -1 if it
       fails to establish the connection. Possibilities are there is not
       enough memory on row i to establish connection to j, an attempt to
       establish new connection after calling Finalize(). */
   int Push( int i, int j );

   /** Finalize the table initialization. The function may be called
       only once, after the table has been initialized, in order to compress
       array J (by getting rid of -1's in array J). Calling this function
       will "freeze" the table and function Push will work no more.
       Note: The table is functional even without calling Finalize(). */
   void Finalize();

   /** Create the table from a list of connections {(from, to)}, where 'from'
       is a TYPE I index and 'to' is a TYPE II index. The list is assumed to be
       sorted and free of duplicities, i.e., you need to call Array::Sort and
       Array::Unique before calling this method. */
   void MakeFromList(int nrows, const Array<Connection> &list);

   /// Returns the number of TYPE II elements (after Finalize() is called).
   int Width() const;

   /// Call this if data has been stolen.
   void LoseData() { size = -1; I = J = NULL; }

   /// Prints the table to stream out.
   void Print(std::ostream & out = std::cout, int width = 4) const;
   void PrintMatlab(std::ostream & out) const;

   void Save(std::ostream &out) const;
   void Load(std::istream &in);

   void Copy(Table & copy) const;
   void Swap(Table & other);

   void Clear();

   long MemoryUsage() const;

   /// Destroys Table.
   ~Table();
};

/// Specialization of the template function Swap<> for class Table
template <> inline void Swap<Table>(Table &a, Table &b)
{
   a.Swap(b);
}

///  Transpose a Table
void Transpose (const Table &A, Table &At, int _ncols_A = -1);
Table * Transpose (const Table &A);

///  Transpose an Array<int>
void Transpose(const Array<int> &A, Table &At, int _ncols_A = -1);

///  C = A * B  (as boolean matrices)
void Mult (const Table &A, const Table &B, Table &C);
Table * Mult (const Table &A, const Table &B);

/** Data type STable. STable is similar to Table, but it's for symmetric
    connectivity, i.e. TYPE I is equivalent to TYPE II. In the first
    dimension we put the elements with smaller index. */

class STable : public Table
{
public:
   /// Creates table with fixed number of connections.
   STable (int dim, int connections_per_row = 3);

   /** Returns index of the connection between element i of TYPE I and
       element j of TYPE II. If there is no connection between element i
       and element j established in the table, then the return value is -1. */
   int operator() (int i, int j) const;

   /** Establish connection between element i and element j in the table.
       The return value is the index of the connection. It returns -1 if it
       fails to establish the connection. Possibilities are there is not
       enough memory on row i to establish connection to j, an attempt to
       establish new connection after calling Finalize(). */
   int Push( int i, int j );

   /// Destroys STable.
   ~STable() {}
};

class DSTable
{
private:
   class Node
   {
   public:
      Node *Prev;
      int  Column, Index;
   };

   int  NumRows, NumEntries;
   Node **Rows;
#ifdef MFEM_USE_MEMALLOC
   MemAlloc <Node, 1024> NodesMem;
#endif

   int Push_(int r, int c);
   int Index(int r, int c) const;

public:
   DSTable(int nrows);
   int NumberOfRows() const { return (NumRows); }
   int NumberOfEntries() const { return (NumEntries); }
   int Push(int a, int b)
   { return ((a <= b) ? Push_(a, b) : Push_(b, a)); }
   int operator()(int a, int b) const
   { return ((a <= b) ? Index(a, b) : Index(b, a)); }
   ~DSTable();

   class RowIterator
   {
   private:
      Node *n;
   public:
      RowIterator (const DSTable &t, int r) { n = t.Rows[r]; }
      int operator!() { return (n != NULL); }
      void operator++() { n = n->Prev; }
      int Column() { return (n->Column); }
      int Index() { return (n->Index); }
   };
};

}

#endif
<commit_msg>Table.hpp uses std::ostream and std::istream. Add missing headers from STL<commit_after>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM 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) version 2.1 dated February 1999.

#ifndef MFEM_TABLE
#define MFEM_TABLE

// Data types for Table.

#include "mem_alloc.hpp"
#include "array.hpp"
#include <ostream>
#include <istream>

namespace mfem
{

/// Helper struct for defining a connectivity table, see Table::MakeFromList.
struct Connection
{
   int from, to;
   Connection(int from, int to) : from(from), to(to) {}

   bool operator== (const Connection &rhs) const
   { return (from == rhs.from) && (to == rhs.to); }
   bool operator< (const Connection &rhs) const
   { return (from == rhs.from) ? (to < rhs.to) : (from < rhs.from); }
};

/** Data type Table. Table stores the connectivity of elements of TYPE I
    to elements of TYPE II, for example, it may be Element-To-Face
    connectivity table, etc. */
class Table
{
protected:

   /// size is the number of TYPE I elements.
   int size;

   /** Arrays for the connectivity information in the CSR storage.
       I is of size "size+1", J is of size the number of connections
       between TYPE I to TYPE II elements (actually stored I[size]). */
   int *I, *J;

public:
   /// Creates an empty table
   Table() { size = -1; I = J = NULL; }

   /// Copy constructor
   Table(const Table &);

   /// Create a table with an upper limit for the number of connections.
   explicit Table (int dim, int connections_per_row = 3);

   /** Create a table from a list of connections, see MakeFromList. */
   Table(int nrows, Array<Connection> &list) : size(-1), I(NULL), J(NULL)
   { MakeFromList(nrows, list); }

   /** Create a table with one entry per row with column indices given
       by 'partitioning'. */
   Table (int nrows, int *partitioning);

   /// Next 7 methods are used together with the default constructor
   void MakeI (int nrows);
   void AddAColumnInRow (int r) { I[r]++; }
   void AddColumnsInRow (int r, int ncol) { I[r] += ncol; }
   void MakeJ();
   void AddConnection (int r, int c) { J[I[r]++] = c; }
   void AddConnections (int r, const int *c, int nc);
   void ShiftUpI();

   /// Set the size and the number of connections for the table.
   void SetSize(int dim, int connections_per_row);

   /** Set the rows and the number of all connections for the table.
       Does NOT initialize the whole array I ! (I[0]=0 and I[rows]=nnz only) */
   void SetDims(int rows, int nnz);

   /// Returns the number of TYPE I elements.
   inline int Size() const { return size; }

   /** Returns the number of connections in the table. If Finalize() is
       not called, it returns the number of possible connections established
       by the used constructor. Otherwise, it is exactly the number of
       established connections before calling Finalize(). */
   inline int Size_of_connections() const { return I[size]; }

   /** Returns index of the connection between element i of TYPE I and
       element j of TYPE II. If there is no connection between element i
       and element j established in the table, then the return value is -1. */
   int operator() (int i, int j) const;

   /// Return row i in array row (the Table must be finalized)
   void GetRow(int i, Array<int> &row) const;

   int RowSize(int i) const { return I[i+1]-I[i]; }

   const int *GetRow(int i) const { return J+I[i]; }
   int *GetRow(int i) { return J+I[i]; }

   int *GetI() { return I; }
   int *GetJ() { return J; }
   const int *GetI() const { return I; }
   const int *GetJ() const { return J; }

   /// @brief Sort the column (TYPE II) indices in each row.
   void SortRows();

   void SetIJ(int *newI, int *newJ, int newsize = -1);

   /** Establish connection between element i and element j in the table.
       The return value is the index of the connection. It returns -1 if it
       fails to establish the connection. Possibilities are there is not
       enough memory on row i to establish connection to j, an attempt to
       establish new connection after calling Finalize(). */
   int Push( int i, int j );

   /** Finalize the table initialization. The function may be called
       only once, after the table has been initialized, in order to compress
       array J (by getting rid of -1's in array J). Calling this function
       will "freeze" the table and function Push will work no more.
       Note: The table is functional even without calling Finalize(). */
   void Finalize();

   /** Create the table from a list of connections {(from, to)}, where 'from'
       is a TYPE I index and 'to' is a TYPE II index. The list is assumed to be
       sorted and free of duplicities, i.e., you need to call Array::Sort and
       Array::Unique before calling this method. */
   void MakeFromList(int nrows, const Array<Connection> &list);

   /// Returns the number of TYPE II elements (after Finalize() is called).
   int Width() const;

   /// Call this if data has been stolen.
   void LoseData() { size = -1; I = J = NULL; }

   /// Prints the table to stream out.
   void Print(std::ostream & out = std::cout, int width = 4) const;
   void PrintMatlab(std::ostream & out) const;

   void Save(std::ostream &out) const;
   void Load(std::istream &in);

   void Copy(Table & copy) const;
   void Swap(Table & other);

   void Clear();

   long MemoryUsage() const;

   /// Destroys Table.
   ~Table();
};

/// Specialization of the template function Swap<> for class Table
template <> inline void Swap<Table>(Table &a, Table &b)
{
   a.Swap(b);
}

///  Transpose a Table
void Transpose (const Table &A, Table &At, int _ncols_A = -1);
Table * Transpose (const Table &A);

///  Transpose an Array<int>
void Transpose(const Array<int> &A, Table &At, int _ncols_A = -1);

///  C = A * B  (as boolean matrices)
void Mult (const Table &A, const Table &B, Table &C);
Table * Mult (const Table &A, const Table &B);

/** Data type STable. STable is similar to Table, but it's for symmetric
    connectivity, i.e. TYPE I is equivalent to TYPE II. In the first
    dimension we put the elements with smaller index. */

class STable : public Table
{
public:
   /// Creates table with fixed number of connections.
   STable (int dim, int connections_per_row = 3);

   /** Returns index of the connection between element i of TYPE I and
       element j of TYPE II. If there is no connection between element i
       and element j established in the table, then the return value is -1. */
   int operator() (int i, int j) const;

   /** Establish connection between element i and element j in the table.
       The return value is the index of the connection. It returns -1 if it
       fails to establish the connection. Possibilities are there is not
       enough memory on row i to establish connection to j, an attempt to
       establish new connection after calling Finalize(). */
   int Push( int i, int j );

   /// Destroys STable.
   ~STable() {}
};

class DSTable
{
private:
   class Node
   {
   public:
      Node *Prev;
      int  Column, Index;
   };

   int  NumRows, NumEntries;
   Node **Rows;
#ifdef MFEM_USE_MEMALLOC
   MemAlloc <Node, 1024> NodesMem;
#endif

   int Push_(int r, int c);
   int Index(int r, int c) const;

public:
   DSTable(int nrows);
   int NumberOfRows() const { return (NumRows); }
   int NumberOfEntries() const { return (NumEntries); }
   int Push(int a, int b)
   { return ((a <= b) ? Push_(a, b) : Push_(b, a)); }
   int operator()(int a, int b) const
   { return ((a <= b) ? Index(a, b) : Index(b, a)); }
   ~DSTable();

   class RowIterator
   {
   private:
      Node *n;
   public:
      RowIterator (const DSTable &t, int r) { n = t.Rows[r]; }
      int operator!() { return (n != NULL); }
      void operator++() { n = n->Prev; }
      int Column() { return (n->Column); }
      int Index() { return (n->Index); }
   };
};

}

#endif
<|endoftext|>


<commit_before>#include "nova_renderer/frontend/ui_renderer.hpp"

#include "nova_renderer/rhi/render_engine.hpp"
#include "nova_renderer/util/logger.hpp"

namespace nova::renderer {
    UiRenderpass::UiRenderpass(rhi::RenderEngine* device, const glm::vec2& framebuffer_size) {
        shaderpack::RenderPassCreateInfo rp_info = {};
        rp_info.name = UI_RENDER_PASS_NAME;
        rp_info.texture_inputs = {SCENE_OUTPUT_RENDER_TARGET_NAME};
        rp_info.texture_outputs = {{BACKBUFFER_NAME, shaderpack::PixelFormatEnum::RGBA8, false}};

        device->create_renderpass(rp_info, framebuffer_size)
            .map([&](rhi::Renderpass* rp) {
                renderpass = rp;
                return true;
            })
            .on_error([](const ntl::NovaError& err) { NOVA_LOG(ERROR) << "Could not create UI renderpass: " << err.to_string(); });
    }

    void UiRenderpass::render_renderpass_contents(rhi::CommandList* cmds, FrameContext& ctx) {}

    NullUiRenderpass::NullUiRenderpass(rhi::RenderEngine* device, const glm::vec2& framebuffer_size)
        : UiRenderpass(device, framebuffer_size) {}

    void NullUiRenderpass::render(rhi::CommandList* /* cmds */, FrameContext& /* ctx */) {
        // Intentionally empty
    }

    void NullUiRenderpass::render_ui(rhi::CommandList* /* cmds */, FrameContext& /* ctx */) {
        // Intentionally empty
    }
} // namespace nova::renderer
<commit_msg>[frontend] UI pass is marked as writing to backbuffer<commit_after>#include "nova_renderer/frontend/ui_renderer.hpp"

#include "nova_renderer/rhi/render_engine.hpp"
#include "nova_renderer/util/logger.hpp"

namespace nova::renderer {
    UiRenderpass::UiRenderpass(rhi::RenderEngine* device, const glm::vec2& framebuffer_size) {
        shaderpack::RenderPassCreateInfo rp_info = {};
        rp_info.name = UI_RENDER_PASS_NAME;
        rp_info.texture_inputs = {SCENE_OUTPUT_RENDER_TARGET_NAME};
        rp_info.texture_outputs = {{BACKBUFFER_NAME, shaderpack::PixelFormatEnum::RGBA8, false}};

        device->create_renderpass(rp_info, framebuffer_size)
            .map([&](rhi::Renderpass* rp) {
                renderpass = rp;
                return true;
            })
            .on_error([](const ntl::NovaError& err) { NOVA_LOG(ERROR) << "Could not create UI renderpass: " << err.to_string(); });

        writes_to_backbuffer = true;
    }

    void UiRenderpass::render_renderpass_contents(rhi::CommandList* cmds, FrameContext& ctx) {}

    NullUiRenderpass::NullUiRenderpass(rhi::RenderEngine* device, const glm::vec2& framebuffer_size)
        : UiRenderpass(device, framebuffer_size) {}

    void NullUiRenderpass::render(rhi::CommandList* /* cmds */, FrameContext& /* ctx */) {
        // Intentionally empty
    }

    void NullUiRenderpass::render_ui(rhi::CommandList* /* cmds */, FrameContext& /* ctx */) {
        // Intentionally empty
    }
} // namespace nova::renderer
<|endoftext|>


<commit_before>/*

This file is part of VROOM.

Copyright (c) 2015-2018, Julien Coupey.
All rights reserved (see LICENSE).

*/

#include "../include/rapidjson/document.h"
#include "../include/rapidjson/error/en.h"
#include <boost/asio.hpp>

#include "routing/orshttp_wrapper.h"
#include "utils/exception.h"

using boost::asio::ip::tcp;

namespace vroom {
namespace routing {

OrsHttpWrapper::OrsHttpWrapper(const std::string& profile, const Server& server)
  : OSRMWrapper(profile), _server(server) {
}

std::string OrsHttpWrapper::build_query(const std::vector<Location>& locations,
                                        std::string service,
                                        std::string extra_args = "") const {
  // Building query for ORS
  std::string query = "GET /v2/" + service;

  query += "?profile=" + _profile;

  // Adding locations.
  if (service == "routes") {
    query += "&coordinates=";
  } else {
    query += "&locations=";
  }
  for (auto const& location : locations) {
    query += std::to_string(location.lon()) + "," +
             std::to_string(location.lat()) + "|";
  }
  query.pop_back(); // Remove trailing '|'.

  if (!extra_args.empty()) {
    query += "&" + extra_args;
  }

  query += " HTTP/1.1\r\n";
  query += "Host: " + _server.host + "\r\n";
  query += "Accept: */*\r\n";
  query += "Connection: close\r\n\r\n";

  return query;
}

std::string OrsHttpWrapper::send_then_receive(std::string query) const {
  std::string response;

  try {
    boost::asio::io_service io_service;

    tcp::resolver r(io_service);

    tcp::resolver::query q(_server.host, _server.port);

    tcp::socket s(io_service);
    boost::asio::connect(s, r.resolve(q));

    boost::asio::write(s, boost::asio::buffer(query));

    char buf[512];
    boost::system::error_code error;
    for (;;) {
      std::size_t len = s.read_some(boost::asio::buffer(buf), error);
      response.append(buf, len);
      if (error == boost::asio::error::eof) {
        // Connection closed cleanly.
        break;
      } else {
        if (error) {
          throw boost::system::system_error(error);
        }
      }
    }
  } catch (boost::system::system_error& e) {
    throw Exception(ERROR::ROUTING,
                    "Failed to connect to ORS at " + _server.host + ":" +
                      _server.port);
  }
  return response;
}

Matrix<Cost>
OrsHttpWrapper::get_matrix(const std::vector<Location>& locs) const {
  std::string query = this->build_query(locs, "matrix");

  std::string response = this->send_then_receive(query);

  // Removing headers.
  std::string json_content = response.substr(response.find("{"));

  // Expected matrix size.
  std::size_t m_size = locs.size();

  // Checking everything is fine in the response.
  rapidjson::Document infos;
#ifdef NDEBUG
  infos.Parse(json_content.c_str());
#else
  assert(!infos.Parse(json_content.c_str()).HasParseError());
#endif
  if (infos.HasMember("error")) {
    throw Exception(ERROR::ROUTING,
                    "ORS matrix:" +
                      std::string(infos["error"]["message"].GetString()));
  }
  assert(infos["durations"].Size() == m_size);

  // Build matrix while checking for unfound routes to avoid
  // unexpected behavior (ORS raises 'null').
  Matrix<Cost> m(m_size);

  std::vector<unsigned> nb_unfound_from_loc(m_size, 0);
  std::vector<unsigned> nb_unfound_to_loc(m_size, 0);

  for (rapidjson::SizeType i = 0; i < infos["durations"].Size(); ++i) {
    const auto& line = infos["durations"][i];
    assert(line.Size() == m_size);
    for (rapidjson::SizeType j = 0; j < line.Size(); ++j) {
      if (line[j].IsNull()) {
        // No route found between i and j. Just storing info as we
        // don't know yet which location is responsible between i
        // and j.
        ++nb_unfound_from_loc[i];
        ++nb_unfound_to_loc[j];
      } else {
        auto cost = round_cost(line[j].GetDouble());
        m[i][j] = cost;
      }
    }
  }

  check_unfound(locs, nb_unfound_from_loc, nb_unfound_to_loc);

  return m;
}

void OrsHttpWrapper::add_route_info(Route& route) const {
  // Ordering locations for the given steps.
  std::vector<Location> ordered_locations;
  for (const auto& step : route.steps) {
    ordered_locations.push_back(step.location);
  }

  std::string extra_args = "geometry_simplify=false&continue_straight=false";

  std::string query =
    this->build_query(ordered_locations, "routes", extra_args);
  std::string response = this->send_then_receive(query);

  // Removing headers
  std::string json_content = response.substr(response.find("{"));

  // Checking everything is fine in the response.
  rapidjson::Document infos;
#ifdef NDEBUG
  infos.Parse(json_content.c_str());
#else
  assert(!infos.Parse(json_content.c_str()).HasParseError());
#endif
  if (infos.HasMember("error")) {
    throw Exception(ERROR::ROUTING,
                    "ORS routes: " +
                      std::string(infos["error"]["message"].GetString()));
  }

  // Total distance and route geometry.
  route.distance =
    round_cost(infos["routes"][0]["summary"]["distance"].GetDouble());
  route.geometry = std::move(infos["routes"][0]["geometry"].GetString());

  auto nb_legs = infos["routes"][0]["segments"].Size();
  assert(nb_legs == route.steps.size() - 1);

  // Accumulated travel distance stored for each step.
  double current_distance = 0;

  route.steps[0].distance = 0;

  for (rapidjson::SizeType i = 0; i < nb_legs; ++i) {
    // Update distance for step after current route leg.
    current_distance +=
      infos["routes"][0]["segments"][i]["distance"].GetDouble();
    route.steps[i + 1].distance = round_cost(current_distance);
  }
}

} // namespace routing
} // namespace vroom
<commit_msg>Update to ORS API version 2.<commit_after>/*

This file is part of VROOM.

Copyright (c) 2015-2018, Julien Coupey.
All rights reserved (see LICENSE).

*/

#include "../include/rapidjson/document.h"
#include "../include/rapidjson/error/en.h"
#include <boost/asio.hpp>

#include "routing/orshttp_wrapper.h"
#include "utils/exception.h"

using boost::asio::ip::tcp;

namespace vroom {
namespace routing {

OrsHttpWrapper::OrsHttpWrapper(const std::string& profile, const Server& server)
  : OSRMWrapper(profile), _server(server) {
}

std::string OrsHttpWrapper::build_query(const std::vector<Location>& locations,
                                        std::string service,
                                        std::string extra_args = "") const {
  // Adding locations.
  std::string body = "{\"";
  if (service == "routes") {
    body += "coordinates";
  } else {
    body += "locations";
  }
  body += "\":[";
  for (auto const& location : locations) {
    body += "[" + std::to_string(location.lon()) + "," +
             std::to_string(location.lat()) + "],";
  }
  body.pop_back(); // Remove trailing ','.
  body +="]}";

  // Building query for ORS

  std::string query = "POST /ors/v2/" + service + "/" + _profile;

  if (!extra_args.empty()) {
    query += "?" + extra_args;
  }

  query += " HTTP/1.1\r\n";
  query += "Accept: */*\r\n";
  query += "Content-Type: application/json\r\n";
  query += "Content-Length: " + std::to_string(body.size()) + "\r\n";
  query += "Host: " + _server.host + ":" + _server.port + "\r\n";
  query += "Connection: close\r\n";
  query += "\r\n" + body;

  return query;
}

std::string OrsHttpWrapper::send_then_receive(std::string query) const {
  std::string response;

  try {
    boost::asio::io_service io_service;

    tcp::resolver r(io_service);

    tcp::resolver::query q(_server.host, _server.port);

    tcp::socket s(io_service);
    boost::asio::connect(s, r.resolve(q));

    boost::asio::write(s, boost::asio::buffer(query));

    char buf[512];
    boost::system::error_code error;
    for (;;) {
      std::size_t len = s.read_some(boost::asio::buffer(buf), error);
      response.append(buf, len);
      if (error == boost::asio::error::eof) {
        // Connection closed cleanly.
        break;
      } else {
        if (error) {
          throw boost::system::system_error(error);
        }
      }
    }
  } catch (boost::system::system_error& e) {
    throw Exception(ERROR::ROUTING,
                    "Failed to connect to ORS at " + _server.host + ":" +
                      _server.port);
  }
  return response;
}

Matrix<Cost>
OrsHttpWrapper::get_matrix(const std::vector<Location>& locs) const {
  std::string query = this->build_query(locs, "matrix");
  std::string response = this->send_then_receive(query);

  // Removing headers.
  size_t json_start = response.find("{");
  size_t json_length = response.rfind("}") - json_start + 1;
  std::string json_content = response.substr(json_start, json_length);

  // Expected matrix size.
  std::size_t m_size = locs.size();

  // Checking everything is fine in the response.
  rapidjson::Document infos;
#ifdef NDEBUG
  infos.Parse(json_content.c_str());
#else
  assert(!infos.Parse(json_content.c_str()).HasParseError());
#endif
  if (infos.HasMember("error")) {
    throw Exception(ERROR::ROUTING,
                    "ORS matrix:" +
                      std::string(infos["error"]["message"].GetString()));
  }

  assert(infos["durations"].Size() == m_size);

  // Build matrix while checking for unfound routes to avoid
  // unexpected behavior (ORS raises 'null').
  Matrix<Cost> m(m_size);

  std::vector<unsigned> nb_unfound_from_loc(m_size, 0);
  std::vector<unsigned> nb_unfound_to_loc(m_size, 0);

  for (rapidjson::SizeType i = 0; i < infos["durations"].Size(); ++i) {
    const auto& line = infos["durations"][i];
    assert(line.Size() == m_size);
    for (rapidjson::SizeType j = 0; j < line.Size(); ++j) {
      if (line[j].IsNull()) {
        // No route found between i and j. Just storing info as we
        // don't know yet which location is responsible between i
        // and j.
        ++nb_unfound_from_loc[i];
        ++nb_unfound_to_loc[j];
      } else {
        auto cost = round_cost(line[j].GetDouble());
        m[i][j] = cost;
      }
    }
  }

  check_unfound(locs, nb_unfound_from_loc, nb_unfound_to_loc);

  return m;
}

void OrsHttpWrapper::add_route_info(Route& route) const {
  // Ordering locations for the given steps.
  std::vector<Location> ordered_locations;
  for (const auto& step : route.steps) {
    ordered_locations.push_back(step.location);
  }

  std::string extra_args = "geometry_simplify=false&continue_straight=false";

  std::string query =
    this->build_query(ordered_locations, "routes", extra_args);
  std::string response = this->send_then_receive(query);

  // Removing headers
  std::string json_content = response.substr(response.find("{"));

  // Checking everything is fine in the response.
  rapidjson::Document infos;
#ifdef NDEBUG
  infos.Parse(json_content.c_str());
#else
  assert(!infos.Parse(json_content.c_str()).HasParseError());
#endif
  if (infos.HasMember("error")) {
    throw Exception(ERROR::ROUTING,
                    "ORS routes: " +
                      std::string(infos["error"]["message"].GetString()));
  }

  // Total distance and route geometry.
  route.distance =
    round_cost(infos["routes"][0]["summary"]["distance"].GetDouble());
  route.geometry = std::move(infos["routes"][0]["geometry"].GetString());

  auto nb_legs = infos["routes"][0]["segments"].Size();
  assert(nb_legs == route.steps.size() - 1);

  // Accumulated travel distance stored for each step.
  double current_distance = 0;

  route.steps[0].distance = 0;

  for (rapidjson::SizeType i = 0; i < nb_legs; ++i) {
    // Update distance for step after current route leg.
    current_distance +=
      infos["routes"][0]["segments"][i]["distance"].GetDouble();
    route.steps[i + 1].distance = round_cost(current_distance);
  }
}

} // namespace routing
} // namespace vroom
<|endoftext|>