<commit_before>/*
MIT License

Copyright (c) 2017 Chris McArthur, prince.chrismc(at)gmail(dot)com

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

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

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

#include <string>
#include <iostream>

#include "GL/glew.h"       // include GL Extension Wrangler
#include "glm/gtc/matrix_transform.hpp" //glm::lookAt
#include "CImg.h"

#include "GlfwWindow.h"
#include "Shader.h"

using cimg_library::CImg;
using cimg_library::CImgDisplay;

int main()
{
   std::cout << "Welcome to Image Height Map Generator!" << std::endl;

   // Create a GLFWwindow
   GlfwWindow window("Image Height Map by Christopher McArthur", GlfwWindow::DEFAULT_WIDTH, GlfwWindow::DEFAULT_HEIGHT);
   if (!window()) // Make sure it exists
   {
      return -1;
   }

   // Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
   glewExperimental = GL_TRUE;
   // Initialize GLEW to setup the OpenGL Function pointers
   if (glewInit() != GLEW_OK)
   {
      std::cout << "Failed to initialize GLEW" << std::endl;
      return -1;
   }

   // Build and compile our shader program
   VertexShader vertexShader("shaders/vertex.shader");
   FragmentShader fragmentShader("shaders/fragment.shader");
   // make sure they are ready to use
   if (!vertexShader() || !fragmentShader())
   {
      return -1;
   }

   ShaderLinker* shaderProgram = &ShaderLinker::GetInstance();
   if (!shaderProgram->Link(&vertexShader, &fragmentShader))
   {
      return -1;
   }

   // Constant vectors
   const glm::vec3 center(0.0f, 0.0f, 0.0f);
   const glm::vec3 up(0.0f, 0.0f, 1.0f);
   const glm::vec3 eye(0.0f, -5.0f, 3.0f);

   CImg<unsigned char> image("assets/depth.bmp"); // load the image
   CImgDisplay display(image, "Image");           // create window displaying image

   // Game loop
   while (! ~window)
   {
      // Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
      glfwPollEvents();

      // Render
      // Clear the colorbuffer
      glClearColor(0.05f, 0.075f, 0.075f, 1.0f);
      glClear(GL_COLOR_BUFFER_BIT);

      glm::mat4 view_matrix;
      view_matrix = glm::lookAt(eye, center, up);
      shaderProgram->SetShaderMat4("view_matrix", view_matrix);

      shaderProgram->SetShaderMat4("projection_matrix", window.GetProjectionMatrix());

      ++window; // swap buffers
   }

   return 0;
}
<commit_msg>now loading all the points and displaying them in gl window<commit_after>/*
MIT License

Copyright (c) 2017 Chris McArthur, prince.chrismc(at)gmail(dot)com

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

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

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

#include <string>
#include <iostream>
#include <vector>

#include "GL/glew.h"       // include GL Extension Wrangler
#include "glm/gtc/matrix_transform.hpp" //glm::lookAt
#include "CImg.h"

#include "GlfwWindow.h"
#include "Shader.h"

using cimg_library::CImg;
using cimg_library::CImgDisplay;

enum class ObjectColors { RED, GREEN, BLUE, GREY, YELLOW, TEAL };

int main()
{
   std::cout << "Welcome to Image Height Map Generator!" << std::endl;

   // Create a GLFWwindow
   GlfwWindow window("Image Height Map by Christopher McArthur", GlfwWindow::DEFAULT_WIDTH, GlfwWindow::DEFAULT_HEIGHT);
   if (!window()) // Make sure it exists
   {
      return -1;
   }

   // Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
   glewExperimental = GL_TRUE;
   // Initialize GLEW to setup the OpenGL Function pointers
   if (glewInit() != GLEW_OK)
   {
      std::cout << "Failed to initialize GLEW" << std::endl;
      return -1;
   }

   // Build and compile our shader program
   VertexShader vertexShader("shaders/vertex.shader");
   FragmentShader fragmentShader("shaders/fragment.shader");
   if (!vertexShader() || !fragmentShader()) // make sure they are ready to use
   {
      return -1;
   }

   ShaderLinker* shaderProgram = &ShaderLinker::GetInstance();
   if (!shaderProgram->Link(&vertexShader, &fragmentShader))
   {
      return -1;
   }

   // Constant vectors
   const glm::vec3 center(0.0f, 0.0f, 0.0f);
   const glm::vec3 up(0.0f, 1.0f, 0.0f);
   const glm::vec3 eye(0.0f, 50.0f, -50.0f);

   // ---------------------------------------------------------------------------------------------
   std::cout << "Processing image....";
   CImg<float> image("assets/depth.bmp"); // load the image
   CImgDisplay display(image, "Image");           // create window displaying image

   int x = (0 - image.width()/2), z = (0 - image.height() / 2);
   std::vector<glm::vec3> verticies_all;

   for (CImg<float>::iterator it = image.begin(); it < image.end(); ++it)
   {
      verticies_all.emplace_back(glm::vec3(x++, *it, z));
      if(x == image.width()) {x = (0 - image.width() / 2); z += 1; }
   }
   std::cout << "  Completed!" <<std::endl;

   GLuint VAO_all_pts, VBO_all_pts;
   glGenVertexArrays(1, &VAO_all_pts);
   glBindVertexArray(VAO_all_pts);

   glGenBuffers(1, &VBO_all_pts);
   glBindBuffer(GL_ARRAY_BUFFER, VBO_all_pts);
   glBufferData(GL_ARRAY_BUFFER, verticies_all.size() * sizeof(glm::vec3), &verticies_all.front(), GL_STATIC_DRAW);
   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
   glEnableVertexAttribArray(0);
   glBindBuffer(GL_ARRAY_BUFFER, 0);

   glBindVertexArray(0);
   // ---------------------------------------------------------------------------------------------

   // Game loop
   while (! ~window)
   {
      // Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
      glfwPollEvents();

      // Render
      // Clear the colorbuffer
      glClearColor(0.05f, 0.075f, 0.075f, 1.0f);
      glClear(GL_COLOR_BUFFER_BIT);

      glm::mat4 view_matrix;
      view_matrix = glm::lookAt(eye, center, up);
      shaderProgram->SetShaderMat4("view_matrix", view_matrix);

      shaderProgram->SetShaderMat4("projection_matrix", window.GetProjectionMatrix());

      glm::mat4 model_matrix = glm::scale(glm::mat4(), glm::vec3(0.05f));
      shaderProgram->SetShaderMat4("model_matrix", model_matrix);

      shaderProgram->SetShaderInt("object_color", (GLint)ObjectColors::GREY);
      glBindVertexArray(VAO_all_pts);
      glDrawArrays(GL_POINTS, 0, (GLsizei)verticies_all.size());
      glBindVertexArray(0);

      ++window; // swap buffers
   }

   return 0;
}
<|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

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

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

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

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

#include <mitkNavigationDataSequentialPlayer.h>
#include <mitkStandardFileLocations.h>
#include "mitkTestingMacros.h"
#include <mitkTestFixture.h>
#include "mitkNavigationDataReaderXML.h"

#include <iostream>
#include <sstream>

//foe exceptions
#include "mitkIGTException.h"
#include "mitkIGTIOException.h"

class mitkNavigationDataSequentialPlayerTestSuite : public mitk::TestFixture
{
  CPPUNIT_TEST_SUITE(mitkNavigationDataSequentialPlayerTestSuite);
  MITK_TEST(TestStandardWorkflow);
  MITK_TEST(TestRestartWithNewNavigationDataSet);
  MITK_TEST(TestSetFileNameException);
  MITK_TEST(TestGoToSnapshotException);
  MITK_TEST(TestSetXMLStringException);
  MITK_TEST(TestDoubleUpdate);
  CPPUNIT_TEST_SUITE_END();

private:
  /** Members used inside the different test methods. All members are initialized via setUp().*/
  vnl_vector<mitk::ScalarType> tTool0Snapshot1;
  vnl_vector<mitk::ScalarType> tTool1Snapshot2;
  mitk::Quaternion qTool0Snapshot0;
  mitk::Quaternion qTool1Snapshot1;
  mitk::NavigationDataSet::Pointer NavigationDataSet;

  mitk::NavigationDataSequentialPlayer::Pointer player;

public:

  void setUp(){
    tTool0Snapshot1 = vnl_vector<mitk::ScalarType>(3);
    tTool1Snapshot2 = vnl_vector<mitk::ScalarType>(3);
    mitk::Quaternion qTool0Snapshot0;
    mitk::Quaternion qTool1Snapshot1;

    player = mitk::NavigationDataSequentialPlayer::New();
    std::string file = GetTestDataFilePath("IGT-Data/NavigationDataTestData_2ToolsDouble.xml");
    mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New();
    NavigationDataSet =reader->Read(file);
  }

  void tearDown()
  {
  }

  bool runLoop()
  {
    player->Update();
    mitk::NavigationData::Pointer nd0;
    mitk::NavigationData::Pointer nd1;
    for(unsigned int i=0; i<player->GetNumberOfSnapshots(); ++i)
    {
      nd0 = player->GetOutput(0);
      nd1 = player->GetOutput(1);

      // test some values
      if(nd0.IsNull() || nd1.IsNull()) return false;

      if(i==0)
      {
        mitk::NavigationData::Pointer ref0 = NavigationDataSet->GetNavigationDataForIndex(0,0);
        mitk::NavigationData::Pointer ref1 = NavigationDataSet->GetNavigationDataForIndex(1,0);
        if (!(ref0->GetOrientation().as_vector() == nd0->GetOrientation().as_vector())) {return false;}
        if (!(ref1->GetOrientation().as_vector() == nd1->GetOrientation().as_vector())) {return false;}
        if (!(ref0->GetPosition().GetVnlVector() == nd0->GetPosition().GetVnlVector())) {return false;}
        if (!(ref1->GetPosition().GetVnlVector() == nd1->GetPosition().GetVnlVector())) {return false;}
      }
      else if(i==1)
      {
        if (!(tTool0Snapshot1 == nd0->GetPosition().GetVnlVector())) {return false;}
        else if (!(qTool1Snapshot1.as_vector() == nd1->GetOrientation().as_vector())) {return false;}
      }
      else if(i==2) // should be repeated
      {
        if (!(tTool1Snapshot2 == nd1->GetPosition().GetVnlVector())) {return false;}
      }

      // Goto next Snapshot
      player->GoToNextSnapshot();
      player->Update();
    }
    return true;
  }

  void TestStandardWorkflow()
  {
    // create test values valid for the xml data above
    tTool0Snapshot1[0] = -336.65;
    tTool0Snapshot1[1] = 138.5;
    tTool0Snapshot1[2]= -2061.07;
    tTool1Snapshot2[0] = -56.93;
    tTool1Snapshot2[1] = 233.79;
    tTool1Snapshot2[2]= -2042.6;
    vnl_vector_fixed<mitk::ScalarType,4> qVec;
    qVec[0] = 0.0085;
    qVec[1] = -0.0576;
    qVec[2]= -0.0022;
    qVec[3]= 0.9982;
    qTool0Snapshot0 = mitk::Quaternion(qVec);
    qVec[0] = 0.4683;
    qVec[1] = 0.0188;
    qVec[2]= -0.8805;
    qVec[3]= 0.0696;
    qTool1Snapshot1 = mitk::Quaternion(qVec);

    //test SetXMLString()
    player->SetNavigationDataSet(NavigationDataSet);

    MITK_TEST_CONDITION(player->GetNumberOfSnapshots() == 3,"Testing method SetXMLString with 3 navigation datas.");
    MITK_TEST_CONDITION(player->GetNumberOfIndexedOutputs() == 2,"Testing number of outputs");

    //rest repeat
    player->SetRepeat(true);

    MITK_TEST_CONDITION(runLoop(),"Testing first run.");
    MITK_TEST_CONDITION(runLoop(),"Testing second run."); //repeat is on should work a second time

    // now test the go to snapshot function
    player->GoToSnapshot(2);
    mitk::NavigationData::Pointer nd1 = player->GetOutput(1);
    MITK_TEST_CONDITION(tTool1Snapshot2 == nd1->GetPosition().GetVnlVector(),
      "Testing GoToSnapshot() [1]");

    MITK_TEST_OUTPUT( << tTool1Snapshot2 << "\t" << nd1->GetPosition().GetVnlVector());

    player->GoToSnapshot(0);
    mitk::NavigationData::Pointer nd0 = player->GetOutput();
    MITK_TEST_CONDITION(qTool0Snapshot0.as_vector() == nd0->GetOrientation().as_vector(),
      "Testing GoToSnapshot() [2]");

    MITK_TEST_OUTPUT( << qTool0Snapshot0.as_vector() << "\t" <<nd0->GetOrientation().as_vector() );

    player->GoToSnapshot(2);

    // and a third time
    MITK_TEST_CONDITION(runLoop(),"Tested if repeat works again.");
  }

  void TestRestartWithNewNavigationDataSet()
  {
    mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New();

    mitk::NavigationDataSequentialPlayer::Pointer player(mitk::NavigationDataSequentialPlayer::New());

    std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData_2ToolsDouble.xml", "Modules/IGT/Testing/Data");

    player->SetNavigationDataSet(reader->Read(file));
    mitk::NavigationData::PositionType nd1 = player->GetOutput(0)->GetPosition();
    player->SetNavigationDataSet(reader->Read(file));
    player->Update();
    mitk::NavigationData::PositionType nd2 = player->GetOutput(0)->GetPosition();

    MITK_TEST_CONDITION(nd1 == nd2, "First output must be the same after setting same navigation data again.");

    // setting new NavigationDataSet with different tool count should result in an exception
    file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData.xml", "Modules/IGT/Testing/Data");
    MITK_TEST_FOR_EXCEPTION(mitk::IGTException, player->SetNavigationDataSet(reader->Read(file)));
  }

  void TestSetFileNameException()
  { //testing exception if file name hasnt been set
    mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer = mitk::NavigationDataSequentialPlayer::New();
    bool exceptionThrown=false;
    try
    {
      mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New();
      myTestPlayer->SetNavigationDataSet(reader->Read(""));
    }
    catch(mitk::IGTIOException)
    {
      exceptionThrown=true;
      MITK_TEST_OUTPUT(<<"Tested exception for the case when file version is wrong in SetFileName. Application should not crash.");
    }
    MITK_TEST_CONDITION(exceptionThrown, "Testing SetFileName method if exception (if file name hasnt been set) was thrown.");

    //testing ReInItXML method if data element is not found
    mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer1 = mitk::NavigationDataSequentialPlayer::New();
    std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestDataInvalidTags.xml", "Modules/IGT/Testing/Data");
    bool exceptionThrown1=false;
    try
    {
      mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New();
      myTestPlayer1->SetNavigationDataSet(reader->Read(file));
    }
    catch(mitk::IGTException)
    {
      exceptionThrown1=true;
    }
    MITK_TEST_CONDITION(exceptionThrown1, "Testing SetFileName method if exception (if data element not found) was thrown.");
  }

  void TestGoToSnapshotException()
  {
    //testing GoToSnapShot for exception
    mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer2 = mitk::NavigationDataSequentialPlayer::New();
    std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData_2Tools.xml", "Modules/IGT/Testing/Data");
    mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New();
    myTestPlayer2->SetNavigationDataSet(reader->Read(file));

    bool exceptionThrown2=false;
    try
    {
      unsigned int invalidSnapshot = 1000;
      myTestPlayer2->GoToSnapshot(invalidSnapshot);
    }
    catch(mitk::IGTException)
    {
      exceptionThrown2=true;
    }
    MITK_TEST_CONDITION(exceptionThrown2, "Testing if exception is thrown when GoToSnapShot method is called with an index that doesn't exist.");
  }

  void TestSetXMLStringException()
  {
    mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer3 = mitk::NavigationDataSequentialPlayer::New();

    bool exceptionThrown3=false;

    //The string above XML_INVALID_TESTSTRING is a wrong string, some element were deleted in above
    try
    {
      std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("InvalidVersionNavigationDataTestData.xml", "Modules/IGT/Testing/Data");
      mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New();
      myTestPlayer3->SetNavigationDataSet(reader->Read(file));
    }
    catch(mitk::IGTIOException)
    {
      exceptionThrown3=true;
    }
    MITK_TEST_CONDITION(exceptionThrown3, "Testing SetXMLString method with an invalid XML string.");
  }

  void TestDoubleUpdate()
  {
    std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData_2Tools.xml", "Modules/IGT/Testing/Data");

    mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New();
    player->SetNavigationDataSet(reader->Read(file));

    player->Update();
    mitk::Quaternion nd1Orientation = player->GetOutput()->GetOrientation();

    player->Update();
    mitk::Quaternion nd2Orientation = player->GetOutput()->GetOrientation();

    MITK_TEST_CONDITION(nd1Orientation.as_vector() == nd2Orientation.as_vector(), "Output must be the same no matter if Update() was called between.");

    MITK_TEST_CONDITION(player->GoToNextSnapshot(), "There must be a next snapshot available.");
    player->Update();
    mitk::Quaternion nd3Orientation = player->GetOutput()->GetOrientation();

    MITK_TEST_CONDITION(nd1Orientation.as_vector() != nd3Orientation.as_vector(), "Output must be different if GoToNextSnapshot() was called between.");
  }
};
MITK_TEST_SUITE_REGISTRATION(mitkNavigationDataSequentialPlayer)<commit_msg>SequentialDataPlayerTest now correctly tests order of retrieved navigation Datas<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

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

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

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

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

#include <mitkNavigationDataSequentialPlayer.h>
#include <mitkStandardFileLocations.h>
#include "mitkTestingMacros.h"
#include <mitkTestFixture.h>
#include "mitkNavigationDataReaderXML.h"

#include <iostream>
#include <sstream>

//foe exceptions
#include "mitkIGTException.h"
#include "mitkIGTIOException.h"

class mitkNavigationDataSequentialPlayerTestSuite : public mitk::TestFixture
{
  CPPUNIT_TEST_SUITE(mitkNavigationDataSequentialPlayerTestSuite);
  MITK_TEST(TestStandardWorkflow);
  MITK_TEST(TestRestartWithNewNavigationDataSet);
  MITK_TEST(TestSetFileNameException);
  MITK_TEST(TestGoToSnapshotException);
  MITK_TEST(TestSetXMLStringException);
  MITK_TEST(TestDoubleUpdate);
  CPPUNIT_TEST_SUITE_END();

private:
  /** Members used inside the different test methods. All members are initialized via setUp().*/
  vnl_vector<mitk::ScalarType> tTool0Snapshot1;
  vnl_vector<mitk::ScalarType> tTool1Snapshot2;
  mitk::Quaternion qTool0Snapshot0;
  mitk::Quaternion qTool1Snapshot1;
  mitk::NavigationDataSet::Pointer NavigationDataSet;

  mitk::NavigationDataSequentialPlayer::Pointer player;

public:

  void setUp(){
    tTool0Snapshot1 = vnl_vector<mitk::ScalarType>(3);
    tTool1Snapshot2 = vnl_vector<mitk::ScalarType>(3);
    mitk::Quaternion qTool0Snapshot0;
    mitk::Quaternion qTool1Snapshot1;

    player = mitk::NavigationDataSequentialPlayer::New();
    std::string file = GetTestDataFilePath("IGT-Data/NavigationDataTestData_2ToolsDouble.xml");
    mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New();
    NavigationDataSet =reader->Read(file);
  }

  void tearDown()
  {
  }

  bool runLoop()
  {
    player->Update();
    mitk::NavigationData::Pointer nd0;
    mitk::NavigationData::Pointer nd1;
    for(unsigned int i=0; i<player->GetNumberOfSnapshots(); ++i)
    {
      nd0 = player->GetOutput(0);
      nd1 = player->GetOutput(1);

      // test some values
      if(nd0.IsNull() || nd1.IsNull()) return false;

      if(i==0)
      {
        mitk::NavigationData::Pointer ref0 = NavigationDataSet->GetNavigationDataForIndex(0,0);
        mitk::NavigationData::Pointer ref1 = NavigationDataSet->GetNavigationDataForIndex(0,1);
        if (!(ref0->GetOrientation().as_vector() == nd0->GetOrientation().as_vector())) {return false;}
        if (!(ref1->GetOrientation().as_vector() == nd1->GetOrientation().as_vector())) {return false;}
        if (!(ref0->GetPosition().GetVnlVector() == nd0->GetPosition().GetVnlVector())) {return false;}
        if (!(ref1->GetPosition().GetVnlVector() == nd1->GetPosition().GetVnlVector())) {return false;}
      }
      else if(i==1)
      {
        mitk::NavigationData::Pointer ref0 = NavigationDataSet->GetNavigationDataForIndex(1,0);
        mitk::NavigationData::Pointer ref1 = NavigationDataSet->GetNavigationDataForIndex(1,1);
        if (!(ref0->GetOrientation().as_vector() == nd0->GetOrientation().as_vector())) {return false;}
        if (!(ref1->GetOrientation().as_vector() == nd1->GetOrientation().as_vector())) {return false;}
        if (!(ref0->GetPosition().GetVnlVector() == nd0->GetPosition().GetVnlVector())) {return false;}
        if (!(ref1->GetPosition().GetVnlVector() == nd1->GetPosition().GetVnlVector())) {return false;}
      }
      else if(i==2) // should be repeated
      {
        mitk::NavigationData::Pointer ref0 = NavigationDataSet->GetNavigationDataForIndex(2,0);
        mitk::NavigationData::Pointer ref1 = NavigationDataSet->GetNavigationDataForIndex(2,1);
        if (!(ref0->GetOrientation().as_vector() == nd0->GetOrientation().as_vector())) {return false;}
        if (!(ref1->GetOrientation().as_vector() == nd1->GetOrientation().as_vector())) {return false;}
        if (!(ref0->GetPosition().GetVnlVector() == nd0->GetPosition().GetVnlVector())) {return false;}
        if (!(ref1->GetPosition().GetVnlVector() == nd1->GetPosition().GetVnlVector())) {return false;}
      }

      // Goto next Snapshot
      player->GoToNextSnapshot();
      player->Update();
    }
    return true;
  }

  void TestStandardWorkflow()
  {
    // create test values valid for the xml data above
    tTool0Snapshot1[0] = -336.65;
    tTool0Snapshot1[1] = 138.5;
    tTool0Snapshot1[2]= -2061.07;
    tTool1Snapshot2[0] = -56.93;
    tTool1Snapshot2[1] = 233.79;
    tTool1Snapshot2[2]= -2042.6;
    vnl_vector_fixed<mitk::ScalarType,4> qVec;
    qVec[0] = 0.0085;
    qVec[1] = -0.0576;
    qVec[2]= -0.0022;
    qVec[3]= 0.9982;
    qTool0Snapshot0 = mitk::Quaternion(qVec);
    qVec[0] = 0.4683;
    qVec[1] = 0.0188;
    qVec[2]= -0.8805;
    qVec[3]= 0.0696;
    qTool1Snapshot1 = mitk::Quaternion(qVec);

    //test SetXMLString()
    player->SetNavigationDataSet(NavigationDataSet);

    MITK_TEST_CONDITION(player->GetNumberOfSnapshots() == 3,"Testing method SetXMLString with 3 navigation datas.");
    MITK_TEST_CONDITION(player->GetNumberOfIndexedOutputs() == 2,"Testing number of outputs");

    //rest repeat
    player->SetRepeat(true);

    MITK_TEST_CONDITION(runLoop(),"Testing first run.");
    MITK_TEST_CONDITION(runLoop(),"Testing second run."); //repeat is on should work a second time

    // now test the go to snapshot function
    player->GoToSnapshot(2);
    mitk::NavigationData::Pointer nd1 = player->GetOutput(1);
    MITK_TEST_CONDITION(tTool1Snapshot2 == nd1->GetPosition().GetVnlVector(),
      "Testing GoToSnapshot() [1]");

    MITK_TEST_OUTPUT( << tTool1Snapshot2 << "\t" << nd1->GetPosition().GetVnlVector());

    player->GoToSnapshot(0);
    mitk::NavigationData::Pointer nd0 = player->GetOutput();
    MITK_TEST_CONDITION(qTool0Snapshot0.as_vector() == nd0->GetOrientation().as_vector(),
      "Testing GoToSnapshot() [2]");

    MITK_TEST_OUTPUT( << qTool0Snapshot0.as_vector() << "\t" <<nd0->GetOrientation().as_vector() );

    player->GoToSnapshot(2);

    // and a third time
    MITK_TEST_CONDITION(runLoop(),"Tested if repeat works again.");
  }

  void TestRestartWithNewNavigationDataSet()
  {
    mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New();

    mitk::NavigationDataSequentialPlayer::Pointer player(mitk::NavigationDataSequentialPlayer::New());

    std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData_2ToolsDouble.xml", "Modules/IGT/Testing/Data");

    player->SetNavigationDataSet(reader->Read(file));
    mitk::NavigationData::PositionType nd1 = player->GetOutput(0)->GetPosition();
    player->SetNavigationDataSet(reader->Read(file));
    player->Update();
    mitk::NavigationData::PositionType nd2 = player->GetOutput(0)->GetPosition();

    MITK_TEST_CONDITION(nd1 == nd2, "First output must be the same after setting same navigation data again.");

    // setting new NavigationDataSet with different tool count should result in an exception
    file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData.xml", "Modules/IGT/Testing/Data");
    MITK_TEST_FOR_EXCEPTION(mitk::IGTException, player->SetNavigationDataSet(reader->Read(file)));
  }

  void TestSetFileNameException()
  { //testing exception if file name hasnt been set
    mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer = mitk::NavigationDataSequentialPlayer::New();
    bool exceptionThrown=false;
    try
    {
      mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New();
      myTestPlayer->SetNavigationDataSet(reader->Read(""));
    }
    catch(mitk::IGTIOException)
    {
      exceptionThrown=true;
      MITK_TEST_OUTPUT(<<"Tested exception for the case when file version is wrong in SetFileName. Application should not crash.");
    }
    MITK_TEST_CONDITION(exceptionThrown, "Testing SetFileName method if exception (if file name hasnt been set) was thrown.");

    //testing ReInItXML method if data element is not found
    mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer1 = mitk::NavigationDataSequentialPlayer::New();
    std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestDataInvalidTags.xml", "Modules/IGT/Testing/Data");
    bool exceptionThrown1=false;
    try
    {
      mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New();
      myTestPlayer1->SetNavigationDataSet(reader->Read(file));
    }
    catch(mitk::IGTException)
    {
      exceptionThrown1=true;
    }
    MITK_TEST_CONDITION(exceptionThrown1, "Testing SetFileName method if exception (if data element not found) was thrown.");
  }

  void TestGoToSnapshotException()
  {
    //testing GoToSnapShot for exception
    mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer2 = mitk::NavigationDataSequentialPlayer::New();
    std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData_2Tools.xml", "Modules/IGT/Testing/Data");
    mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New();
    myTestPlayer2->SetNavigationDataSet(reader->Read(file));

    bool exceptionThrown2=false;
    try
    {
      unsigned int invalidSnapshot = 1000;
      myTestPlayer2->GoToSnapshot(invalidSnapshot);
    }
    catch(mitk::IGTException)
    {
      exceptionThrown2=true;
    }
    MITK_TEST_CONDITION(exceptionThrown2, "Testing if exception is thrown when GoToSnapShot method is called with an index that doesn't exist.");
  }

  void TestSetXMLStringException()
  {
    mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer3 = mitk::NavigationDataSequentialPlayer::New();

    bool exceptionThrown3=false;

    //The string above XML_INVALID_TESTSTRING is a wrong string, some element were deleted in above
    try
    {
      std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("InvalidVersionNavigationDataTestData.xml", "Modules/IGT/Testing/Data");
      mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New();
      myTestPlayer3->SetNavigationDataSet(reader->Read(file));
    }
    catch(mitk::IGTIOException)
    {
      exceptionThrown3=true;
    }
    MITK_TEST_CONDITION(exceptionThrown3, "Testing SetXMLString method with an invalid XML string.");
  }

  void TestDoubleUpdate()
  {
    std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData_2Tools.xml", "Modules/IGT/Testing/Data");

    mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New();
    player->SetNavigationDataSet(reader->Read(file));

    player->Update();
    mitk::Quaternion nd1Orientation = player->GetOutput()->GetOrientation();

    player->Update();
    mitk::Quaternion nd2Orientation = player->GetOutput()->GetOrientation();

    MITK_TEST_CONDITION(nd1Orientation.as_vector() == nd2Orientation.as_vector(), "Output must be the same no matter if Update() was called between.");

    MITK_TEST_CONDITION(player->GoToNextSnapshot(), "There must be a next snapshot available.");
    player->Update();
    mitk::Quaternion nd3Orientation = player->GetOutput()->GetOrientation();

    MITK_TEST_CONDITION(nd1Orientation.as_vector() != nd3Orientation.as_vector(), "Output must be different if GoToNextSnapshot() was called between.");
  }
};
MITK_TEST_SUITE_REGISTRATION(mitkNavigationDataSequentialPlayer)<|endoftext|>


<commit_before>//====================================================================================================================//
// File:          qcan_socket.cpp                                                                                //
// Description:   CAN socket class                                                                                //
//                                                                                //
// Copyright (C) MicroControl GmbH & Co. KG                                                                           //
// 53844 Troisdorf - Germany                                                                                //
// www.microcontrol.net                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the   //
// following conditions are met:                                                                                //
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions, the following   //
//    disclaimer and the referenced file 'LICENSE'.                                                                   //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the       //
//    following disclaimer in the documentation and/or other materials provided with the distribution.                //
// 3. Neither the name of MicroControl nor the names of its contributors may be used to endorse or promote products   //
//    derived from this software without specific prior written permission.                                           //
//                                                                                //
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance     //
// with the License. You may obtain a copy of the License at                                                          //
//                                                                                //
//    http://www.apache.org/licenses/LICENSE-2.0                                                                      //
//                                                                                //
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed   //
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for  //
// the specific language governing permissions and limitations under the License.                                     //
//                                                                                //
//====================================================================================================================//

/*--------------------------------------------------------------------------------------------------------------------*\
** Include files                                                                                **
**                                                                                **
\*--------------------------------------------------------------------------------------------------------------------*/

#include "qcan_socket.hpp"

#include <QtCore/QDebug>

#include <QtNetwork/QNetworkInterface>

/*--------------------------------------------------------------------------------------------------------------------*\
** Definitions                                                                                **
**                                                                                **
\*--------------------------------------------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------------------------------------------*\
** Class methods                                                                                **
**                                                                                **
\*--------------------------------------------------------------------------------------------------------------------*/

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
QCanSocket::QCanSocket(QObject * pclParentV)
{
   if (pclParentV != Q_NULLPTR)
   {
      this->setParent(pclParentV);
   }

   //---------------------------------------------------------------------------------------------------
   // set default values for host address and port
   //
   clServerHostAddrP = QHostAddress(QHostAddress::LocalHost);
   uwServerPortP     = QCAN_WEB_SOCKET_DEFAULT_PORT;

   //---------------------------------------------------------------------------------------------------
   // create a local and a WebSocket by default, the selection which one is used will be done in
   // setHostAddress().
   //
   pclLocalSocketP = new QLocalSocket(this);
   pclWebSocketP   = new QWebSocket("", QWebSocketProtocol::VersionLatest, this);

   //---------------------------------------------------------------------------------------------------
   // the socket is not connected yet and the default connection method is "local"
   //
   btIsLocalConnectionP = true;
   btIsConnectedP       = false;

   //---------------------------------------------------------------------------------------------------
   // No socket errors available yet
   //
   slSocketErrorP = 0;

   clUuidP = QUuid::createUuid();

   teCanStateP = eCAN_STATE_BUS_ACTIVE;

}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket()                                                                                //
// destructor                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
QCanSocket::~QCanSocket()
{
   delete (pclLocalSocketP);
   delete (pclWebSocketP);
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::connectNetwork()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
bool QCanSocket::connectNetwork(const CAN_Channel_e & teChannelR)
{
   bool btResultT = false;

   //---------------------------------------------------------------------------------------------------
   // create a new socket
   //
   if (btIsConnectedP == false)
   {

      if (btIsLocalConnectionP == false)
      {
         qDebug() << "QCanSocket::connectNetwork(" << teChannelR << "- WebSocket";

         //----------------------------------------------------------------------------------------
         // create new WebSocket
         //
         pclWebSocketP->abort();
         QString clSocketUrlT = QString("ws://") + clServerHostAddrP.toString() + QString(":%1").arg(uwServerPortP);
         clSocketUrlT += QString("/%1").arg(teChannelR);
         qDebug() << "QCanSocket::connectNetwork(" << teChannelR << ") -" << clSocketUrlT;
         pclWebSocketP->open(clSocketUrlT);

         //----------------------------------------------------------------------------------------
         // make signal / slot connection for WebSocket
         //
         connect( pclWebSocketP, &QWebSocket::connected,             this, &QCanSocket::onSocketConnect);

         connect( pclWebSocketP, &QWebSocket::disconnected,          this, &QCanSocket::onSocketDisconnect);

         connect( pclWebSocketP, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error),
                  this, &QCanSocket::onSocketErrorWeb);

         connect( pclWebSocketP, &QWebSocket::binaryMessageReceived, this, &QCanSocket::onSocketReceiveWeb);

         btResultT = true;
      }
      else
      {
         qDebug() << "QCanSocket::connectNetwork(" << teChannelR << ") - LocalSocket";

         //----------------------------------------------------------------------------------------
         // create new local socket
         //
         pclLocalSocketP->abort();

         //----------------------------------------------------------------------------------------
         // make signal / slot connection for local socket
         //
         connect( pclLocalSocketP, &QLocalSocket::connected,      this, &QCanSocket::onSocketConnect);

         connect( pclLocalSocketP, &QLocalSocket::disconnected,   this, &QCanSocket::onSocketDisconnect);

         connect( pclLocalSocketP, QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error),
                  this, &QCanSocket::onSocketErrorLocal);

         connect( pclLocalSocketP, &QLocalSocket::readyRead,      this, &QCanSocket::onSocketReceiveLocal);

         //----------------------------------------------------------------------------------------
         // connect to local server
         //
         pclLocalSocketP->connectToServer(QString("CANpieServerChannel%1").arg(teChannelR));
         qDebug() << "QCanSocket::connectNetwork() -" << pclLocalSocketP->fullServerName();

         btResultT = true;
      }
   }

   return(btResultT);
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::disconnectNetwork()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
void QCanSocket::disconnectNetwork(void)
{
   qDebug() << "QCanSocket::disconnectNetwork() ";

   if (btIsLocalConnectionP == false)
   {
      pclWebSocketP->disconnect();
   }
   else
   {
      disconnect(pclLocalSocketP, 0, 0, 0);
      pclLocalSocketP->disconnectFromServer();
   }

   btIsConnectedP = false;
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::error()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
QAbstractSocket::SocketError QCanSocket::error() const
{
   return((QAbstractSocket::SocketError) slSocketErrorP);
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::errorString()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
QString QCanSocket::errorString() const
{
   QString  clErrorT;

   switch (slSocketErrorP)
   {
      case QAbstractSocket::ConnectionRefusedError:
         clErrorT = qPrintable(tr("connection refused or timed out.")                           );
         break;

      case QAbstractSocket::RemoteHostClosedError:
         clErrorT = qPrintable(tr("server closed the connection.")                              );
         break;

      case QAbstractSocket::HostNotFoundError:
         clErrorT = qPrintable(tr("server address was not found.")                              );
         break;

      case QAbstractSocket::SocketAccessError:
         clErrorT = qPrintable(tr("application lacked the required privileges.")                );
         break;

      case QAbstractSocket::SocketResourceError:
         clErrorT = qPrintable(tr("local system ran out of resources.")                         );
         break;

      case QAbstractSocket::SocketTimeoutError:
         clErrorT = qPrintable(tr("operation timed out.")                                       );
         break;

      case QAbstractSocket::NetworkError:
         clErrorT = qPrintable(tr("error occurred with the network (e.g. cable plugged out.")   );
         break;

      case QAbstractSocket::AddressInUseError:
         clErrorT = qPrintable(tr("address is already in use.")                                 );
         break;

      default:
         clErrorT = qPrintable(tr("unknown reason")                                             );
         break;
   }

   return (clErrorT);
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::framesAvailable()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
int32_t QCanSocket::framesAvailable(void) const
{
   return (clReceiveFifoP.size());
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::onSocketConnect()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
void QCanSocket::onSocketConnect(void)
{
   qDebug() << "QCanSocket::onSocketConnect() ";

   //---------------------------------------------------------------------------------------------------
   // send signal about connection state and keep it in local variable
   //
   btIsConnectedP = true;
   emit connected();
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::onSocketDisconnect()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
void QCanSocket::onSocketDisconnect(void)
{
   qDebug() << "QCanSocket::onSocketDisconnect() ";

   //---------------------------------------------------------------------------------------------------
   // send signal about connection state and keep it in local variable
   //
   btIsConnectedP = false;
   emit disconnected();
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::onSocketErrorLocal()                                                                                //
// handle error conditions of local socket                                                                            //
//--------------------------------------------------------------------------------------------------------------------//
void QCanSocket::onSocketErrorLocal(QLocalSocket::LocalSocketError teSocketErrorV)
{

   qDebug() << "QCanSocket::onSocketErrorLocal() " << teSocketErrorV;
   qDebug() << pclLocalSocketP->errorString();

   switch(teSocketErrorV)
   {
      //-------------------------------------------------------------------------------------------
      // abort all operations and disconnect socket
      //
      case QLocalSocket::PeerClosedError:
      case QLocalSocket::ConnectionError:
         pclLocalSocketP->abort();
         btIsConnectedP = false;
         emit disconnected();
         break;

      default:

         break;

   }

   //---------------------------------------------------------------------------------------------------
   // Store socket error and send signal:
   // Since the enumeration values for LocalSocketError are derived from QAbstractSocket::SocketError
   // inside the header file QtNetwork/qlocalsocket.h we can simply cast it.
   //
   slSocketErrorP = teSocketErrorV;
   emit error( (QAbstractSocket::SocketError) teSocketErrorV);
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::onSocketErrorWeb()                                                                                //
//  handle error conditions of WebSocket                                                                              //
//--------------------------------------------------------------------------------------------------------------------//
void QCanSocket::onSocketErrorWeb(QAbstractSocket::SocketError teSocketErrorV)
{
   qDebug() << "QCanSocket::onSocketErrorWeb()   -" << teSocketErrorV;

   switch(teSocketErrorV)
   {
      //-------------------------------------------------------------
      // abort all operations and disconnect socket
      //
      case QAbstractSocket::RemoteHostClosedError:
      case QAbstractSocket::NetworkError:
         pclWebSocketP->abort();
         btIsConnectedP = false;
         emit disconnected();
         break;

      default:

         break;

   }

   //----------------------------------------------------------------
   // store socket error and send signal
   //
   slSocketErrorP = teSocketErrorV;
   emit error(teSocketErrorV);
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::onSocketReceiveLocal()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
void QCanSocket::onSocketReceiveLocal(void)
{
   uint32_t    ulFrameCountT;
   bool        btValidFrameT     = false;
   bool        btSignalNewFrameT = false;

   ulFrameCountT = pclLocalSocketP->bytesAvailable() / QCAN_FRAME_ARRAY_SIZE;
   while (ulFrameCountT)
   {
      clReceiveDataP = pclLocalSocketP->read(QCAN_FRAME_ARRAY_SIZE);
      btValidFrameT  = clReceiveFrameP.fromByteArray(clReceiveDataP);
      if (btValidFrameT)
      {
         //-----------------------------------------------------------------------------------
         // Store frame in FIFO
         //
         clReceiveMutexP.lock();
         clReceiveFifoP.enqueue(clReceiveFrameP);
         btSignalNewFrameT = true;
         clReceiveMutexP.unlock();

         //-----------------------------------------------------------------------------------
         // If the frame type is an error frame, store the for the actual CAN state
         //
         if (clReceiveFrameP.frameType() == QCanFrame::eFRAME_TYPE_ERROR)
         {
            teCanStateP = clReceiveFrameP.errorState();
         }
      }

      ulFrameCountT--;
   }

   //---------------------------------------------------------------------------------------------------
   // Emit signal only once when new data arrived. The flag 'btReceiveSignalSendP' is cleared inside
   // the read() method.
   //
   if (btSignalNewFrameT == true)
   {
      emit readyRead();
   }
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::onSocketReceiveWeb()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
void QCanSocket::onSocketReceiveWeb(const QByteArray &clMessageR)
{
   bool        btValidFrameT     = false;
   bool        btSignalNewFrameT = false;

   btValidFrameT  = clReceiveFrameP.fromByteArray(clMessageR);
   if (btValidFrameT)
   {
      //-----------------------------------------------------------------------------------
      // Store frame in FIFO
      //
      clReceiveMutexP.lock();
      clReceiveFifoP.enqueue(clReceiveFrameP);
      btSignalNewFrameT = true;
      clReceiveMutexP.unlock();

      //-----------------------------------------------------------------------------------
      // If the frame type is an error frame, store the for the actual CAN state
      //
      if (clReceiveFrameP.frameType() == QCanFrame::eFRAME_TYPE_ERROR)
      {
         teCanStateP = clReceiveFrameP.errorState();
      }
   }

   //---------------------------------------------------------------------------------------------------
   // Emit signal only once when new data arrived. The flag 'btReceiveSignalSendP' is cleared inside
   // the read() method.
   //
   if (btSignalNewFrameT == true)
   {
      emit readyRead();
   }

}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::read()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
bool QCanSocket::read(QCanFrame & clFrameR)
{
   bool btResultT = false;

   clReceiveMutexP.lock();
   if (clReceiveFifoP.size() > 0)
   {
      clFrameR = clReceiveFifoP.dequeue();         // read message from queue
      btResultT = true;                            // message has been updated
   }
   clReceiveMutexP.unlock();

   return (btResultT);
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::setHostAddress()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
void QCanSocket::setHostAddress(QHostAddress clHostAddressV, uint16_t uwPortV)
{
   if(btIsConnectedP == false)
   {
      clServerHostAddrP = clHostAddressV;
      uwServerPortP     = uwPortV;

      if (clHostAddressV == QHostAddress::LocalHost)
      {
         btIsLocalConnectionP = true;
      }
      else
      {
         btIsLocalConnectionP = false;
      }
   }
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::write()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
bool QCanSocket::write(const QCanFrame & clFrameR)
{
   bool  btResultT = false;

   if (btIsConnectedP == true)
   {
      QByteArray  clDatagramT = clFrameR.toByteArray();

      if (btIsLocalConnectionP == false)
      {
         if (pclWebSocketP->sendBinaryMessage(clDatagramT) == QCAN_FRAME_ARRAY_SIZE)
         {
            pclWebSocketP->flush();
            btResultT = true;
         }
      }
      else
      {
         if (pclLocalSocketP->write(clDatagramT) == QCAN_FRAME_ARRAY_SIZE)
         {
            pclLocalSocketP->flush();
            btResultT = true;
         }
      }
   }

   return(btResultT);
}

<commit_msg>Fix error string<commit_after>//====================================================================================================================//
// File:          qcan_socket.cpp                                                                                //
// Description:   CAN socket class                                                                                //
//                                                                                //
// Copyright (C) MicroControl GmbH & Co. KG                                                                           //
// 53844 Troisdorf - Germany                                                                                //
// www.microcontrol.net                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the   //
// following conditions are met:                                                                                //
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions, the following   //
//    disclaimer and the referenced file 'LICENSE'.                                                                   //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the       //
//    following disclaimer in the documentation and/or other materials provided with the distribution.                //
// 3. Neither the name of MicroControl nor the names of its contributors may be used to endorse or promote products   //
//    derived from this software without specific prior written permission.                                           //
//                                                                                //
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance     //
// with the License. You may obtain a copy of the License at                                                          //
//                                                                                //
//    http://www.apache.org/licenses/LICENSE-2.0                                                                      //
//                                                                                //
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed   //
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for  //
// the specific language governing permissions and limitations under the License.                                     //
//                                                                                //
//====================================================================================================================//

/*--------------------------------------------------------------------------------------------------------------------*\
** Include files                                                                                **
**                                                                                **
\*--------------------------------------------------------------------------------------------------------------------*/

#include "qcan_socket.hpp"

#include <QtCore/QDebug>

#include <QtNetwork/QNetworkInterface>

/*--------------------------------------------------------------------------------------------------------------------*\
** Definitions                                                                                **
**                                                                                **
\*--------------------------------------------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------------------------------------------*\
** Class methods                                                                                **
**                                                                                **
\*--------------------------------------------------------------------------------------------------------------------*/

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
QCanSocket::QCanSocket(QObject * pclParentV)
{
   if (pclParentV != Q_NULLPTR)
   {
      this->setParent(pclParentV);
   }

   //---------------------------------------------------------------------------------------------------
   // set default values for host address and port
   //
   clServerHostAddrP = QHostAddress(QHostAddress::LocalHost);
   uwServerPortP     = QCAN_WEB_SOCKET_DEFAULT_PORT;

   //---------------------------------------------------------------------------------------------------
   // create a local and a WebSocket by default, the selection which one is used will be done in
   // setHostAddress().
   //
   pclLocalSocketP = new QLocalSocket(this);
   pclWebSocketP   = new QWebSocket("", QWebSocketProtocol::VersionLatest, this);

   //---------------------------------------------------------------------------------------------------
   // the socket is not connected yet and the default connection method is "local"
   //
   btIsLocalConnectionP = true;
   btIsConnectedP       = false;

   //---------------------------------------------------------------------------------------------------
   // No socket errors available yet
   //
   slSocketErrorP = 0;

   clUuidP = QUuid::createUuid();

   teCanStateP = eCAN_STATE_BUS_ACTIVE;

}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket()                                                                                //
// destructor                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
QCanSocket::~QCanSocket()
{
   delete (pclLocalSocketP);
   delete (pclWebSocketP);
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::connectNetwork()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
bool QCanSocket::connectNetwork(const CAN_Channel_e & teChannelR)
{
   bool btResultT = false;

   //---------------------------------------------------------------------------------------------------
   // create a new socket
   //
   if (btIsConnectedP == false)
   {

      if (btIsLocalConnectionP == false)
      {
         qDebug() << "QCanSocket::connectNetwork(" << teChannelR << "- WebSocket";

         //----------------------------------------------------------------------------------------
         // create new WebSocket
         //
         pclWebSocketP->abort();
         QString clSocketUrlT = QString("ws://") + clServerHostAddrP.toString() + QString(":%1").arg(uwServerPortP);
         clSocketUrlT += QString("/%1").arg(teChannelR);
         qDebug() << "QCanSocket::connectNetwork(" << teChannelR << ") -" << clSocketUrlT;
         pclWebSocketP->open(clSocketUrlT);

         //----------------------------------------------------------------------------------------
         // make signal / slot connection for WebSocket
         //
         connect( pclWebSocketP, &QWebSocket::connected,             this, &QCanSocket::onSocketConnect);

         connect( pclWebSocketP, &QWebSocket::disconnected,          this, &QCanSocket::onSocketDisconnect);

         connect( pclWebSocketP, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error),
                  this, &QCanSocket::onSocketErrorWeb);

         connect( pclWebSocketP, &QWebSocket::binaryMessageReceived, this, &QCanSocket::onSocketReceiveWeb);

         btResultT = true;
      }
      else
      {
         qDebug() << "QCanSocket::connectNetwork(" << teChannelR << ") - LocalSocket";

         //----------------------------------------------------------------------------------------
         // create new local socket
         //
         pclLocalSocketP->abort();

         //----------------------------------------------------------------------------------------
         // make signal / slot connection for local socket
         //
         connect( pclLocalSocketP, &QLocalSocket::connected,      this, &QCanSocket::onSocketConnect);

         connect( pclLocalSocketP, &QLocalSocket::disconnected,   this, &QCanSocket::onSocketDisconnect);

         connect( pclLocalSocketP, QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error),
                  this, &QCanSocket::onSocketErrorLocal);

         connect( pclLocalSocketP, &QLocalSocket::readyRead,      this, &QCanSocket::onSocketReceiveLocal);

         //----------------------------------------------------------------------------------------
         // connect to local server
         //
         pclLocalSocketP->connectToServer(QString("CANpieServerChannel%1").arg(teChannelR));
         qDebug() << "QCanSocket::connectNetwork() -" << pclLocalSocketP->fullServerName();

         btResultT = true;
      }
   }

   return(btResultT);
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::disconnectNetwork()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
void QCanSocket::disconnectNetwork(void)
{
   qDebug() << "QCanSocket::disconnectNetwork() ";

   if (btIsLocalConnectionP == false)
   {
      pclWebSocketP->disconnect();
   }
   else
   {
      disconnect(pclLocalSocketP, 0, 0, 0);
      pclLocalSocketP->disconnectFromServer();
   }

   btIsConnectedP = false;
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::error()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
QAbstractSocket::SocketError QCanSocket::error() const
{
   return((QAbstractSocket::SocketError) slSocketErrorP);
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::errorString()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
QString QCanSocket::errorString() const
{
   QString  clErrorT;

   switch (slSocketErrorP)
   {
      case QAbstractSocket::ConnectionRefusedError:
         clErrorT = qPrintable(tr("connection refused or timed out.")                           );
         break;

      case QAbstractSocket::RemoteHostClosedError:
         clErrorT = qPrintable(tr("server closed the connection.")                              );
         break;

      case QAbstractSocket::HostNotFoundError:
         clErrorT = qPrintable(tr("server address was not found.")                              );
         break;

      case QAbstractSocket::SocketAccessError:
         clErrorT = qPrintable(tr("application lacked the required privileges.")                );
         break;

      case QAbstractSocket::SocketResourceError:
         clErrorT = qPrintable(tr("local system ran out of resources.")                         );
         break;

      case QAbstractSocket::SocketTimeoutError:
         clErrorT = qPrintable(tr("operation timed out.")                                       );
         break;

      case QAbstractSocket::NetworkError:
         clErrorT = qPrintable(tr("error occurred with the network (e.g. cable plugged out).")  );
         break;

      case QAbstractSocket::AddressInUseError:
         clErrorT = qPrintable(tr("address is already in use.")                                 );
         break;

      default:
         clErrorT = qPrintable(tr("unknown reason")                                             );
         break;
   }

   return (clErrorT);
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::framesAvailable()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
int32_t QCanSocket::framesAvailable(void) const
{
   return (clReceiveFifoP.size());
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::onSocketConnect()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
void QCanSocket::onSocketConnect(void)
{
   qDebug() << "QCanSocket::onSocketConnect() ";

   //---------------------------------------------------------------------------------------------------
   // send signal about connection state and keep it in local variable
   //
   btIsConnectedP = true;
   emit connected();
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::onSocketDisconnect()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
void QCanSocket::onSocketDisconnect(void)
{
   qDebug() << "QCanSocket::onSocketDisconnect() ";

   //---------------------------------------------------------------------------------------------------
   // send signal about connection state and keep it in local variable
   //
   btIsConnectedP = false;
   emit disconnected();
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::onSocketErrorLocal()                                                                                //
// handle error conditions of local socket                                                                            //
//--------------------------------------------------------------------------------------------------------------------//
void QCanSocket::onSocketErrorLocal(QLocalSocket::LocalSocketError teSocketErrorV)
{

   qDebug() << "QCanSocket::onSocketErrorLocal() " << teSocketErrorV;
   qDebug() << pclLocalSocketP->errorString();

   switch(teSocketErrorV)
   {
      //-------------------------------------------------------------------------------------------
      // abort all operations and disconnect socket
      //
      case QLocalSocket::PeerClosedError:
      case QLocalSocket::ConnectionError:
         pclLocalSocketP->abort();
         btIsConnectedP = false;
         emit disconnected();
         break;

      default:

         break;

   }

   //---------------------------------------------------------------------------------------------------
   // Store socket error and send signal:
   // Since the enumeration values for LocalSocketError are derived from QAbstractSocket::SocketError
   // inside the header file QtNetwork/qlocalsocket.h we can simply cast it.
   //
   slSocketErrorP = teSocketErrorV;
   emit error( (QAbstractSocket::SocketError) teSocketErrorV);
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::onSocketErrorWeb()                                                                                //
//  handle error conditions of WebSocket                                                                              //
//--------------------------------------------------------------------------------------------------------------------//
void QCanSocket::onSocketErrorWeb(QAbstractSocket::SocketError teSocketErrorV)
{
   qDebug() << "QCanSocket::onSocketErrorWeb()   -" << teSocketErrorV;

   switch(teSocketErrorV)
   {
      //-------------------------------------------------------------
      // abort all operations and disconnect socket
      //
      case QAbstractSocket::RemoteHostClosedError:
      case QAbstractSocket::NetworkError:
         pclWebSocketP->abort();
         btIsConnectedP = false;
         emit disconnected();
         break;

      default:

         break;

   }

   //----------------------------------------------------------------
   // store socket error and send signal
   //
   slSocketErrorP = teSocketErrorV;
   emit error(teSocketErrorV);
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::onSocketReceiveLocal()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
void QCanSocket::onSocketReceiveLocal(void)
{
   uint32_t    ulFrameCountT;
   bool        btValidFrameT     = false;
   bool        btSignalNewFrameT = false;

   ulFrameCountT = pclLocalSocketP->bytesAvailable() / QCAN_FRAME_ARRAY_SIZE;
   while (ulFrameCountT)
   {
      clReceiveDataP = pclLocalSocketP->read(QCAN_FRAME_ARRAY_SIZE);
      btValidFrameT  = clReceiveFrameP.fromByteArray(clReceiveDataP);
      if (btValidFrameT)
      {
         //-----------------------------------------------------------------------------------
         // Store frame in FIFO
         //
         clReceiveMutexP.lock();
         clReceiveFifoP.enqueue(clReceiveFrameP);
         btSignalNewFrameT = true;
         clReceiveMutexP.unlock();

         //-----------------------------------------------------------------------------------
         // If the frame type is an error frame, store the for the actual CAN state
         //
         if (clReceiveFrameP.frameType() == QCanFrame::eFRAME_TYPE_ERROR)
         {
            teCanStateP = clReceiveFrameP.errorState();
         }
      }

      ulFrameCountT--;
   }

   //---------------------------------------------------------------------------------------------------
   // Emit signal only once when new data arrived. The flag 'btReceiveSignalSendP' is cleared inside
   // the read() method.
   //
   if (btSignalNewFrameT == true)
   {
      emit readyRead();
   }
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::onSocketReceiveWeb()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
void QCanSocket::onSocketReceiveWeb(const QByteArray &clMessageR)
{
   bool        btValidFrameT     = false;
   bool        btSignalNewFrameT = false;

   btValidFrameT  = clReceiveFrameP.fromByteArray(clMessageR);
   if (btValidFrameT)
   {
      //-----------------------------------------------------------------------------------
      // Store frame in FIFO
      //
      clReceiveMutexP.lock();
      clReceiveFifoP.enqueue(clReceiveFrameP);
      btSignalNewFrameT = true;
      clReceiveMutexP.unlock();

      //-----------------------------------------------------------------------------------
      // If the frame type is an error frame, store the for the actual CAN state
      //
      if (clReceiveFrameP.frameType() == QCanFrame::eFRAME_TYPE_ERROR)
      {
         teCanStateP = clReceiveFrameP.errorState();
      }
   }

   //---------------------------------------------------------------------------------------------------
   // Emit signal only once when new data arrived. The flag 'btReceiveSignalSendP' is cleared inside
   // the read() method.
   //
   if (btSignalNewFrameT == true)
   {
      emit readyRead();
   }

}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::read()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
bool QCanSocket::read(QCanFrame & clFrameR)
{
   bool btResultT = false;

   clReceiveMutexP.lock();
   if (clReceiveFifoP.size() > 0)
   {
      clFrameR = clReceiveFifoP.dequeue();         // read message from queue
      btResultT = true;                            // message has been updated
   }
   clReceiveMutexP.unlock();

   return (btResultT);
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::setHostAddress()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
void QCanSocket::setHostAddress(QHostAddress clHostAddressV, uint16_t uwPortV)
{
   if(btIsConnectedP == false)
   {
      clServerHostAddrP = clHostAddressV;
      uwServerPortP     = uwPortV;

      if (clHostAddressV == QHostAddress::LocalHost)
      {
         btIsLocalConnectionP = true;
      }
      else
      {
         btIsLocalConnectionP = false;
      }
   }
}

//--------------------------------------------------------------------------------------------------------------------//
// QCanSocket::write()                                                                                //
//                                                                                //
//--------------------------------------------------------------------------------------------------------------------//
bool QCanSocket::write(const QCanFrame & clFrameR)
{
   bool  btResultT = false;

   if (btIsConnectedP == true)
   {
      QByteArray  clDatagramT = clFrameR.toByteArray();

      if (btIsLocalConnectionP == false)
      {
         if (pclWebSocketP->sendBinaryMessage(clDatagramT) == QCAN_FRAME_ARRAY_SIZE)
         {
            pclWebSocketP->flush();
            btResultT = true;
         }
      }
      else
      {
         if (pclLocalSocketP->write(clDatagramT) == QCAN_FRAME_ARRAY_SIZE)
         {
            pclLocalSocketP->flush();
            btResultT = true;
         }
      }
   }

   return(btResultT);
}

<|endoftext|>


<commit_before>/*
Highly Optimized Object-oriented Many-particle Dynamics -- Blue Edition
(HOOMD-blue) Open Source Software License Copyright 2009-2015 The Regents of
the University of Michigan All rights reserved.

HOOMD-blue may contain modifications ("Contributions") provided, and to which
copyright is held, by various Contributors who have granted The Regents of the
University of Michigan the right to modify and/or distribute such Contributions.

You may redistribute, use, and create derivate works of HOOMD-blue, in source
and binary forms, provided you abide by the following conditions:

* Redistributions of source code must retain the above copyright notice, this
list of conditions, and the following disclaimer both in the code and
prominently in any materials provided with the distribution.

* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions, and the following disclaimer in the documentation and/or
other materials provided with the distribution.

* All publications and presentations based on HOOMD-blue, including any reports
or published results obtained, in whole or in part, with HOOMD-blue, will
acknowledge its use according to the terms posted at the time of submission on:
http://codeblue.umich.edu/hoomd-blue/citations.html

* Any electronic documents citing HOOMD-Blue will link to the HOOMD-Blue website:
http://codeblue.umich.edu/hoomd-blue/

* Apart from the above required attributions, neither the name of the copyright
holder nor the names of HOOMD-blue's contributors may be used to endorse or
promote products derived from this software without specific prior written
permission.

Disclaimer

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND/OR ANY
WARRANTIES THAT THIS SOFTWARE IS FREE OF INFRINGEMENT ARE DISCLAIMED.

IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

// Maintainer: joaander

#include "TwoStepLangevinBase.h"

#include <boost/python.hpp>
using namespace boost::python;
using namespace std;

/*! \file TwoStepLangevinBase.h
    \brief Contains code for the TwoStepLangevinBase class
*/

/*! \param sysdef SystemDefinition this method will act on. Must not be NULL.
    \param group The group of particles this integration method is to work on
    \param T Temperature set point as a function of time
    \param seed Random seed to use in generating random numbers
    \param use_lambda If true, gamma=lambda*diameter, otherwise use a per-type gamma via setGamma()
    \param lambda Scale factor to convert diameter to gamma
*/
TwoStepLangevinBase::TwoStepLangevinBase(boost::shared_ptr<SystemDefinition> sysdef,
                           boost::shared_ptr<ParticleGroup> group,
                           boost::shared_ptr<Variant> T,
                           unsigned int seed,
                           bool use_lambda,
                           Scalar lambda)
    : IntegrationMethodTwoStep(sysdef, group), m_T(T), m_seed(seed), m_use_lambda(use_lambda), m_lambda(lambda), m_warned_aniso(false)
    {
    m_exec_conf->msg->notice(5) << "Constructing TwoStepLangevinBase" << endl;

    if (use_lambda)
        m_exec_conf->msg->notice(2) << "integrate.langevin/bd is determining gamma from particle diameters" << endl;
    else
        m_exec_conf->msg->notice(2) << "integrate.langevin/bd is using specified gamma values" << endl;

    // Hash the User's Seed to make it less likely to be a low positive integer
    m_seed = m_seed*0x12345677 + 0x12345 ; m_seed^=(m_seed>>16); m_seed*= 0x45679;

    // allocate memory for the per-type gamma storage and initialize them to 1.0
    GPUVector<Scalar> gamma(m_pdata->getNTypes(), m_exec_conf);
    m_gamma.swap(gamma);
    ArrayHandle<Scalar> h_gamma(m_gamma, access_location::host, access_mode::overwrite);
    for (unsigned int i = 0; i < m_gamma.size(); i++)
        h_gamma.data[i] = Scalar(1.0);

    // allocate memory for the per-type gamma_r storage and initialize them to 0.0 (no rotational noise by default)
    GPUVector<Scalar> gamma_r(m_pdata->getNTypes(), m_exec_conf);
    m_gamma_r.swap(gamma_r);
    ArrayHandle<Scalar> h_gamma_r(m_gamma_r, access_location::host, access_mode::overwrite);
    for (unsigned int i = 0; i < m_gamma_r.size(); i++)
        h_gamma_r.data[i] = Scalar(0.0);

    // connect to the ParticleData to receive notifications when the maximum number of particles changes
    m_num_type_change_connection = m_pdata->connectNumTypesChange(boost::bind(&TwoStepLangevinBase::slotNumTypesChange, this));
    }

TwoStepLangevinBase::~TwoStepLangevinBase()
    {
    m_exec_conf->msg->notice(5) << "Destroying TwoStepLangevinBase" << endl;
    m_num_type_change_connection.disconnect();
    }

void TwoStepLangevinBase::slotNumTypesChange()
    {
    // skip the reallocation if the number of types does not change
    // this keeps old parameters when restoring a snapshot
    // it will result in invalid coefficients if the snapshot has a different type id -> name mapping
    if (m_pdata->getNTypes() == m_gamma.size())
        return;

    // re-allocate memory for the per-type gamma storage and initialize them to 1.0
    unsigned int old_ntypes = m_gamma.size();
    m_gamma.resize(m_pdata->getNTypes());
    m_gamma_r.resize(m_pdata->getNTypes());

    ArrayHandle<Scalar> h_gamma(m_gamma, access_location::host, access_mode::readwrite);
    ArrayHandle<Scalar> h_gamma_r(m_gamma_r, access_location::host, access_mode::readwrite);

    for (unsigned int i = old_ntypes; i < m_gamma.size(); i++)
        {
        h_gamma.data[i] = Scalar(1.0);
        h_gamma_r.data[i] = Scalar(1.0);
        }
    }

/*! \param typ Particle type to set gamma for
    \param gamma The gamma value to set
*/
void TwoStepLangevinBase::setGamma(unsigned int typ, Scalar gamma)
    {
    // check for user errors
    if (m_use_lambda)
        {
        m_exec_conf->msg->error() << "Trying to set gamma when it is set to be the diameter! " << typ << endl;
        throw runtime_error("Error setting params in TwoStepLangevinBase");
        }
    if (typ >= m_pdata->getNTypes())
        {
        m_exec_conf->msg->error() << "Trying to set gamma for a non existent type! " << typ << endl;
        throw runtime_error("Error setting params in TwoStepLangevinBase");
        }

    ArrayHandle<Scalar> h_gamma(m_gamma, access_location::host, access_mode::readwrite);
    h_gamma.data[typ] = gamma;
    }

/*! \param typ Particle type to set gamma_r (2D rotational noise) for
    \param gamma The gamma_r value to set
*/
void TwoStepLangevinBase::setGamma_r(unsigned int typ, Scalar gamma_r)
    {
    // check for user errors
    if (gamma_r < 0)
        {
        m_exec_conf->msg->error() << "gamma_r should be positive or 0! " << typ << endl;
        throw runtime_error("Error setting params in TwoStepLangevinBase");
        }
    if (typ >= m_pdata->getNTypes())
        {
        m_exec_conf->msg->error() << "Trying to set gamma for a non existent type! " << typ << endl;
        throw runtime_error("Error setting params in TwoStepLangevinBase");
        }

    ArrayHandle<Scalar> h_gamma_r(m_gamma_r, access_location::host, access_mode::readwrite);
    h_gamma_r.data[typ] = gamma_r;
    }

void export_TwoStepLangevinBase()
    {
    class_<TwoStepLangevinBase, boost::shared_ptr<TwoStepLangevinBase>, bases<IntegrationMethodTwoStep>, boost::noncopyable>
        ("TwoStepLangevinBase", init< boost::shared_ptr<SystemDefinition>,
                                boost::shared_ptr<ParticleGroup>,
                                boost::shared_ptr<Variant>,
                                unsigned int,
                                bool,
                                Scalar
                                >())
        .def("setT", &TwoStepLangevinBase::setT)
        .def("setGamma", &TwoStepLangevinBase::setGamma)
        ;
    }
<commit_msg>minor_bug_fixes<commit_after>/*
Highly Optimized Object-oriented Many-particle Dynamics -- Blue Edition
(HOOMD-blue) Open Source Software License Copyright 2009-2015 The Regents of
the University of Michigan All rights reserved.

HOOMD-blue may contain modifications ("Contributions") provided, and to which
copyright is held, by various Contributors who have granted The Regents of the
University of Michigan the right to modify and/or distribute such Contributions.

You may redistribute, use, and create derivate works of HOOMD-blue, in source
and binary forms, provided you abide by the following conditions:

* Redistributions of source code must retain the above copyright notice, this
list of conditions, and the following disclaimer both in the code and
prominently in any materials provided with the distribution.

* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions, and the following disclaimer in the documentation and/or
other materials provided with the distribution.

* All publications and presentations based on HOOMD-blue, including any reports
or published results obtained, in whole or in part, with HOOMD-blue, will
acknowledge its use according to the terms posted at the time of submission on:
http://codeblue.umich.edu/hoomd-blue/citations.html

* Any electronic documents citing HOOMD-Blue will link to the HOOMD-Blue website:
http://codeblue.umich.edu/hoomd-blue/

* Apart from the above required attributions, neither the name of the copyright
holder nor the names of HOOMD-blue's contributors may be used to endorse or
promote products derived from this software without specific prior written
permission.

Disclaimer

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND/OR ANY
WARRANTIES THAT THIS SOFTWARE IS FREE OF INFRINGEMENT ARE DISCLAIMED.

IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

// Maintainer: joaander

#include "TwoStepLangevinBase.h"

#include <boost/python.hpp>
using namespace boost::python;
using namespace std;

/*! \file TwoStepLangevinBase.h
    \brief Contains code for the TwoStepLangevinBase class
*/

/*! \param sysdef SystemDefinition this method will act on. Must not be NULL.
    \param group The group of particles this integration method is to work on
    \param T Temperature set point as a function of time
    \param seed Random seed to use in generating random numbers
    \param use_lambda If true, gamma=lambda*diameter, otherwise use a per-type gamma via setGamma()
    \param lambda Scale factor to convert diameter to gamma
*/
TwoStepLangevinBase::TwoStepLangevinBase(boost::shared_ptr<SystemDefinition> sysdef,
                           boost::shared_ptr<ParticleGroup> group,
                           boost::shared_ptr<Variant> T,
                           unsigned int seed,
                           bool use_lambda,
                           Scalar lambda)
    : IntegrationMethodTwoStep(sysdef, group), m_T(T), m_seed(seed), m_use_lambda(use_lambda), m_lambda(lambda), m_warned_aniso(false)
    {
    m_exec_conf->msg->notice(5) << "Constructing TwoStepLangevinBase" << endl;

    if (use_lambda)
        m_exec_conf->msg->notice(2) << "integrate.langevin/bd is determining gamma from particle diameters" << endl;
    else
        m_exec_conf->msg->notice(2) << "integrate.langevin/bd is using specified gamma values" << endl;

    // Hash the User's Seed to make it less likely to be a low positive integer
    m_seed = m_seed*0x12345677 + 0x12345 ; m_seed^=(m_seed>>16); m_seed*= 0x45679;

    // allocate memory for the per-type gamma storage and initialize them to 1.0
    GPUVector<Scalar> gamma(m_pdata->getNTypes(), m_exec_conf);
    m_gamma.swap(gamma);
    ArrayHandle<Scalar> h_gamma(m_gamma, access_location::host, access_mode::overwrite);
    for (unsigned int i = 0; i < m_gamma.size(); i++)
        h_gamma.data[i] = Scalar(1.0);

    // allocate memory for the per-type gamma_r storage and initialize them to 0.0 (no rotational noise by default)
    GPUVector<Scalar> gamma_r(m_pdata->getNTypes(), m_exec_conf);
    m_gamma_r.swap(gamma_r);
    ArrayHandle<Scalar> h_gamma_r(m_gamma_r, access_location::host, access_mode::overwrite);
    for (unsigned int i = 0; i < m_gamma_r.size(); i++)
        h_gamma_r.data[i] = Scalar(0.0);

    // connect to the ParticleData to receive notifications when the maximum number of particles changes
    m_num_type_change_connection = m_pdata->connectNumTypesChange(boost::bind(&TwoStepLangevinBase::slotNumTypesChange, this));
    }

TwoStepLangevinBase::~TwoStepLangevinBase()
    {
    m_exec_conf->msg->notice(5) << "Destroying TwoStepLangevinBase" << endl;
    m_num_type_change_connection.disconnect();
    }

void TwoStepLangevinBase::slotNumTypesChange()
    {
    // skip the reallocation if the number of types does not change
    // this keeps old parameters when restoring a snapshot
    // it will result in invalid coefficients if the snapshot has a different type id -> name mapping
    if (m_pdata->getNTypes() == m_gamma.size())
        return;

    // re-allocate memory for the per-type gamma storage and initialize them to 1.0
    unsigned int old_ntypes = m_gamma.size();
    m_gamma.resize(m_pdata->getNTypes());
    m_gamma_r.resize(m_pdata->getNTypes());

    ArrayHandle<Scalar> h_gamma(m_gamma, access_location::host, access_mode::readwrite);
    ArrayHandle<Scalar> h_gamma_r(m_gamma_r, access_location::host, access_mode::readwrite);

    for (unsigned int i = old_ntypes; i < m_gamma.size(); i++)
        {
        h_gamma.data[i] = Scalar(1.0);
        h_gamma_r.data[i] = Scalar(1.0);
        }
    }

/*! \param typ Particle type to set gamma for
    \param gamma The gamma value to set
*/
void TwoStepLangevinBase::setGamma(unsigned int typ, Scalar gamma)
    {
    // check for user errors
    if (m_use_lambda)
        {
        m_exec_conf->msg->error() << "Trying to set gamma when it is set to be the diameter! " << typ << endl;
        throw runtime_error("Error setting params in TwoStepLangevinBase");
        }
    if (typ >= m_pdata->getNTypes())
        {
        m_exec_conf->msg->error() << "Trying to set gamma for a non existent type! " << typ << endl;
        throw runtime_error("Error setting params in TwoStepLangevinBase");
        }

    ArrayHandle<Scalar> h_gamma(m_gamma, access_location::host, access_mode::readwrite);
    h_gamma.data[typ] = gamma;
    }

/*! \param typ Particle type to set gamma_r (2D rotational noise) for
    \param gamma The gamma_r value to set
*/
void TwoStepLangevinBase::setGamma_r(unsigned int typ, Scalar gamma_r)
    {
    // check for user errors
    if (gamma_r < 0)
        {
        m_exec_conf->msg->error() << "gamma_r should be positive or 0! " << typ << endl;
        throw runtime_error("Error setting params in TwoStepLangevinBase");
        }
    if (typ >= m_pdata->getNTypes())
        {
        m_exec_conf->msg->error() << "Trying to set gamma for a non existent type! " << typ << endl;
        throw runtime_error("Error setting params in TwoStepLangevinBase");
        }

    ArrayHandle<Scalar> h_gamma_r(m_gamma_r, access_location::host, access_mode::readwrite);
    h_gamma_r.data[typ] = gamma_r;
    }

void export_TwoStepLangevinBase()
    {
    class_<TwoStepLangevinBase, boost::shared_ptr<TwoStepLangevinBase>, bases<IntegrationMethodTwoStep>, boost::noncopyable>
        ("TwoStepLangevinBase", init< boost::shared_ptr<SystemDefinition>,
                                boost::shared_ptr<ParticleGroup>,
                                boost::shared_ptr<Variant>,
                                unsigned int,
                                bool,
                                Scalar
                                >())
        .def("setT", &TwoStepLangevinBase::setT)
        .def("setGamma", &TwoStepLangevinBase::setGamma)
        .def("setGamma_r", &TwoStepLangevinBase::setGamma_r)
        ;
    }
<|endoftext|>