<commit_before>#ifndef __MODEL_HPP_INCLUDED
#define __MODEL_HPP_INCLUDED

// Include GLEW
#ifndef __GL_GLEW_H_INCLUDED
#define __GL_GLEW_H_INCLUDED
#include <GL/glew.h>
#endif

// Include GLFW
#ifndef __GLFW3_H_INCLUDED
#define __GLFW3_H_INCLUDED
#include <glfw3.h>
#endif

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp>
#endif

#include <iostream>
#include <queue> // std::queue
#include <string.h>
#include "globals.hpp"
#include "shader.hpp"
#include "heightmap_loader.hpp"
#include "objloader.hpp"

namespace model
{
    class World
    {
        public:
            // constructor.
            World();

            // destructor.
            ~World();

            // this method renders the entire world, one shader at a time.
            void render();

            // this method sets a shader pointer.
            void set_pointer(GLuint shaderID, void* shader_pointer);

            // this method gets a shader pointer.
            void* get_pointer(GLuint shaderID);

            // this method gets a shader ID and removes it from the `free_shaderID_queue` if it was popped from the queue.
            GLuint get_shaderID();

        private:
            std::vector<void*> shader_pointer_vector;
            std::queue<GLuint> free_shaderID_queue;
    };

    class Shader
    {
        public:
            // constructor.
            Shader(ShaderStruct shader_struct);

            // destructor.
            ~Shader();

            // this method renders all species using this shader.
            void render();

            // this method sets a species pointer.
            void set_pointer(GLuint speciesID, void* species_pointer);

            // this method gets a species pointer.
            void* get_pointer(GLuint speciesID);

            // this method gets a species ID and removes it from the `free_speciesID_queue` if it was popped from the queue.
            GLuint get_speciesID();

            // this method sets pointer to this shader to NULL, sets `world_pointer` according to the input, and requests a new `shaderID` from the new world.
            void switch_to_new_world(model::World *new_world_pointer);

            model::World *world_pointer;          // pointer to the world.

            GLuint shaderID;                      // shader ID, returned by `model::World->get_shaderID()`.

            std::string vertex_shader;            // filename of vertex shader.
            std::string fragment_shader;          // filename of fragment shader.

            GLuint programID;                     // shaders' programID, returned by `LoadShaders`.

        private:
            std::vector<void*> species_pointer_vector;
            std::queue<GLuint> free_speciesID_queue;

            const char *char_vertex_shader;
            const char *char_fragment_shader;
    };

    class Graph
    {
        public:
            // constructor.
            Graph();

            // destructor.
            ~Graph();

            // this method sets a node pointer.
            void set_pointer(GLuint nodeID, void* node_pointer);

            // this method gets a node pointer.
            void* get_pointer(GLuint nodeID);

            // this method gets a node ID and removes it from the `free_nodeID_queue` if it was popped from the queue.
            GLuint get_nodeID();

        private:
            std::vector<void*> node_pointer_vector;
            std::queue<GLuint> free_nodeID_queue;
    };

    // `Node` is not a subclass of `Graph` because if the graph splits, node may be transferred to an another graph.
    // Transferring a node to a new graph naturally requires appropriate reindexing of `nodeID`s.
    // The graph in which a node belongs is accessible through `void* graph_pointer` (must be cast to `model::Graph*`).
    class Node
    {
        public:
            // constructor.
            Node(NodeStruct node_struct);

            // destructor.
            ~Node();

            // this method creates a bidirectional link.
            // creating of bidirectional links is not possible before all nodes are created.
            void create_bidirectional_link(GLuint nodeID);

            // this method deletes a bidirectional link.
            // deleting of links is not possible before all nodes are created.
            void delete_bidirectional_link(GLuint nodeID);

            // this method transfers this node to a new graph.
            // links will not be changed.
            // all nodes that are to be transferred must be transferred separately.
            // before transfering any node to a new graph,
            // all links to nodes that do not belong to the new graph of this node must be deleted with separate `delete_bidirectional_link` calls.
            void transfer_to_new_graph(model::Graph *new_graph_pointer);

            GLuint nodeID;
            model::Graph *graph_pointer;

            // nodes do not keep pointers to neighbor nodes, because all pointer values are not known yet before all nodes are created.
            std::vector<GLuint> neighbor_nodeIDs;

        private:
            // this method creates an unidirectional link.
            // in the constructor only unidirectional links can be created.
            void create_unidirectional_link(GLuint nodeID);

            // this method deletes an unidirectional link.
            void delete_unidirectional_link(GLuint nodeID);

            glm::vec3 coordinate_vector;
    };

    class Species
    {
        public:
            // constructor.
            Species(SpeciesStruct species_struct);

            // destructor.
            ~Species();

            // this method renders all objects of this species.
            void render();

            // this method sets a object pointer.
            void set_pointer(GLuint objectID, void* object_pointer);

            // this method gets a object pointer.
            void* get_pointer(GLuint objectID);

            // this method gets a object ID and removes it from the `free_objectID_queue` if it was popped from the queue.
            GLuint get_objectID();

            // this method sets pointer to this species to NULL, sets `shader_pointer` according to the input, and requests a new `speciesID` from the new shader.
            void switch_to_new_shader(model::Shader *new_shader_pointer);

            model::Shader *shader_pointer;           // pointer to the shader.

            std::string model_file_format;           // type of the model file, eg. `"bmp"`.
            std::string model_filename;              // filename of the model file.
            std::string texture_file_format;         // type of the model file, eg. `"bmp"`.
            std::string texture_filename;            // filename of the model file.
            std::string color_channel;               // color channel in use: `"red"`, `"green"`, `"blue"`, `"mean"` or `"all"`.
            std::vector<ObjectStruct> object_vector; // vector of individual objects of this species.
            glm::vec3 lightPos;                      // light position.

            void *vertex_UV_pointer;                 // pointer to the vertex & UV species (not yet in use!).
            void *texture_pointer;                   // pointer to the texture species (not yet in use!).

            // The rest fields are created in the constructor.
            GLuint MatrixID;
            GLuint ViewMatrixID;
            GLuint ModelMatrixID;
            GLuint vertexPosition_modelspaceID;
            GLuint vertexUVID;
            GLuint vertexNormal_modelspaceID;

            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object.

            std::vector<GLuint> indices;           // the deleted vertices will be reused (though it is not required, if there's enough memory).
            std::vector<glm::vec3> indexed_vertices;
            std::vector<glm::vec2> indexed_UVs;
            std::vector<glm::vec3> indexed_normals;

            GLuint vertexbuffer;
            GLuint uvbuffer;
            GLuint normalbuffer;
            GLuint elementbuffer;

            glm::mat4 ProjectionMatrix;
            glm::mat4 ViewMatrix;
        private:
            GLuint speciesID;                      // species ID, returned by `model::World->get_speciesID()`.
            GLuint lightID;                        // light ID, returned by `glGetUniformLocation(programID, "LightPosition_worldspace");`.
            GLuint texture;                        // Texture, returned by `load_DDS_texture` or `load_BMP_texture`.
            GLuint textureID;                      // texture ID, returned by `glGetUniformLocation(programID, "myTextureSampler");`.
            const char *char_model_file_format;
            const char *char_model_filename;
            const char *char_texture_file_format;
            const char *char_texture_filename;
            const char *char_color_channel;

            std::vector<void*> object_pointer_vector;
            std::queue<GLuint> free_objectID_queue;
    };

    class Object
    {
        public:
            // constructor.
            Object(ObjectStruct object_struct);

            // destructor.
            ~Object();

            // this method renders this object.
            void render();

            // this method sets pointer to this object to NULL, sets `species_pointer` according to the input, and requests a new `objectID` from the new species.
            void switch_to_new_species(model::Species *new_species_pointer);

            model::Species *species_pointer;       // pointer to the species.

            GLuint objectID;                      // object ID, returned by `model::Species->get_objectID()`.

            bool has_entered;
            glm::vec3 coordinate_vector;           // rotate vector.
            GLfloat rotate_angle;                  // rotate angle.
            glm::vec3 rotate_vector;               // rotate vector.
            glm::vec3 translate_vector;            // translate vector.

            // The rest fields are created in the constructor.
            glm::mat4 model_matrix;                // model matrix.
            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object. not used at the moment.

            glm::mat4 MVP_matrix;                  // model view projection matrix.
    };
}

#endif
<commit_msg>`class Species`: `model::Shader *shader_pointer` on `private`-muuttuja.<commit_after>#ifndef __MODEL_HPP_INCLUDED
#define __MODEL_HPP_INCLUDED

// Include GLEW
#ifndef __GL_GLEW_H_INCLUDED
#define __GL_GLEW_H_INCLUDED
#include <GL/glew.h>
#endif

// Include GLFW
#ifndef __GLFW3_H_INCLUDED
#define __GLFW3_H_INCLUDED
#include <glfw3.h>
#endif

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp>
#endif

#include <iostream>
#include <queue> // std::queue
#include <string.h>
#include "globals.hpp"
#include "shader.hpp"
#include "heightmap_loader.hpp"
#include "objloader.hpp"

namespace model
{
    class World
    {
        public:
            // constructor.
            World();

            // destructor.
            ~World();

            // this method renders the entire world, one shader at a time.
            void render();

            // this method sets a shader pointer.
            void set_pointer(GLuint shaderID, void* shader_pointer);

            // this method gets a shader pointer.
            void* get_pointer(GLuint shaderID);

            // this method gets a shader ID and removes it from the `free_shaderID_queue` if it was popped from the queue.
            GLuint get_shaderID();

        private:
            std::vector<void*> shader_pointer_vector;
            std::queue<GLuint> free_shaderID_queue;
    };

    class Shader
    {
        public:
            // constructor.
            Shader(ShaderStruct shader_struct);

            // destructor.
            ~Shader();

            // this method renders all species using this shader.
            void render();

            // this method sets a species pointer.
            void set_pointer(GLuint speciesID, void* species_pointer);

            // this method gets a species pointer.
            void* get_pointer(GLuint speciesID);

            // this method gets a species ID and removes it from the `free_speciesID_queue` if it was popped from the queue.
            GLuint get_speciesID();

            // this method sets pointer to this shader to NULL, sets `world_pointer` according to the input, and requests a new `shaderID` from the new world.
            void switch_to_new_world(model::World *new_world_pointer);

            model::World *world_pointer;          // pointer to the world.

            GLuint shaderID;                      // shader ID, returned by `model::World->get_shaderID()`.

            std::string vertex_shader;            // filename of vertex shader.
            std::string fragment_shader;          // filename of fragment shader.

            GLuint programID;                     // shaders' programID, returned by `LoadShaders`.

        private:
            std::vector<void*> species_pointer_vector;
            std::queue<GLuint> free_speciesID_queue;

            const char *char_vertex_shader;
            const char *char_fragment_shader;
    };

    class Graph
    {
        public:
            // constructor.
            Graph();

            // destructor.
            ~Graph();

            // this method sets a node pointer.
            void set_pointer(GLuint nodeID, void* node_pointer);

            // this method gets a node pointer.
            void* get_pointer(GLuint nodeID);

            // this method gets a node ID and removes it from the `free_nodeID_queue` if it was popped from the queue.
            GLuint get_nodeID();

        private:
            std::vector<void*> node_pointer_vector;
            std::queue<GLuint> free_nodeID_queue;
    };

    // `Node` is not a subclass of `Graph` because if the graph splits, node may be transferred to an another graph.
    // Transferring a node to a new graph naturally requires appropriate reindexing of `nodeID`s.
    // The graph in which a node belongs is accessible through `void* graph_pointer` (must be cast to `model::Graph*`).
    class Node
    {
        public:
            // constructor.
            Node(NodeStruct node_struct);

            // destructor.
            ~Node();

            // this method creates a bidirectional link.
            // creating of bidirectional links is not possible before all nodes are created.
            void create_bidirectional_link(GLuint nodeID);

            // this method deletes a bidirectional link.
            // deleting of links is not possible before all nodes are created.
            void delete_bidirectional_link(GLuint nodeID);

            // this method transfers this node to a new graph.
            // links will not be changed.
            // all nodes that are to be transferred must be transferred separately.
            // before transfering any node to a new graph,
            // all links to nodes that do not belong to the new graph of this node must be deleted with separate `delete_bidirectional_link` calls.
            void transfer_to_new_graph(model::Graph *new_graph_pointer);

            GLuint nodeID;
            model::Graph *graph_pointer;

            // nodes do not keep pointers to neighbor nodes, because all pointer values are not known yet before all nodes are created.
            std::vector<GLuint> neighbor_nodeIDs;

        private:
            // this method creates an unidirectional link.
            // in the constructor only unidirectional links can be created.
            void create_unidirectional_link(GLuint nodeID);

            // this method deletes an unidirectional link.
            void delete_unidirectional_link(GLuint nodeID);

            glm::vec3 coordinate_vector;
    };

    class Species
    {
        public:
            // constructor.
            Species(SpeciesStruct species_struct);

            // destructor.
            ~Species();

            // this method renders all objects of this species.
            void render();

            // this method sets a object pointer.
            void set_pointer(GLuint objectID, void* object_pointer);

            // this method gets a object pointer.
            void* get_pointer(GLuint objectID);

            // this method gets a object ID and removes it from the `free_objectID_queue` if it was popped from the queue.
            GLuint get_objectID();

            // this method sets pointer to this species to NULL, sets `shader_pointer` according to the input, and requests a new `speciesID` from the new shader.
            void switch_to_new_shader(model::Shader *new_shader_pointer);

            std::string model_file_format;           // type of the model file, eg. `"bmp"`.
            std::string model_filename;              // filename of the model file.
            std::string texture_file_format;         // type of the model file, eg. `"bmp"`.
            std::string texture_filename;            // filename of the model file.
            std::string color_channel;               // color channel in use: `"red"`, `"green"`, `"blue"`, `"mean"` or `"all"`.
            std::vector<ObjectStruct> object_vector; // vector of individual objects of this species.
            glm::vec3 lightPos;                      // light position.

            void *vertex_UV_pointer;                 // pointer to the vertex & UV species (not yet in use!).
            void *texture_pointer;                   // pointer to the texture species (not yet in use!).

            // The rest fields are created in the constructor.
            GLuint MatrixID;
            GLuint ViewMatrixID;
            GLuint ModelMatrixID;
            GLuint vertexPosition_modelspaceID;
            GLuint vertexUVID;
            GLuint vertexNormal_modelspaceID;

            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object.

            std::vector<GLuint> indices;           // the deleted vertices will be reused (though it is not required, if there's enough memory).
            std::vector<glm::vec3> indexed_vertices;
            std::vector<glm::vec2> indexed_UVs;
            std::vector<glm::vec3> indexed_normals;

            GLuint vertexbuffer;
            GLuint uvbuffer;
            GLuint normalbuffer;
            GLuint elementbuffer;

            glm::mat4 ProjectionMatrix;
            glm::mat4 ViewMatrix;
        private:
            model::Shader *shader_pointer;         // pointer to the shader.

            GLuint speciesID;                      // species ID, returned by `model::World->get_speciesID()`.
            GLuint lightID;                        // light ID, returned by `glGetUniformLocation(programID, "LightPosition_worldspace");`.
            GLuint texture;                        // Texture, returned by `load_DDS_texture` or `load_BMP_texture`.
            GLuint textureID;                      // texture ID, returned by `glGetUniformLocation(programID, "myTextureSampler");`.
            const char *char_model_file_format;
            const char *char_model_filename;
            const char *char_texture_file_format;
            const char *char_texture_filename;
            const char *char_color_channel;

            std::vector<void*> object_pointer_vector;
            std::queue<GLuint> free_objectID_queue;
    };

    class Object
    {
        public:
            // constructor.
            Object(ObjectStruct object_struct);

            // destructor.
            ~Object();

            // this method renders this object.
            void render();

            // this method sets pointer to this object to NULL, sets `species_pointer` according to the input, and requests a new `objectID` from the new species.
            void switch_to_new_species(model::Species *new_species_pointer);

            model::Species *species_pointer;       // pointer to the species.

            GLuint objectID;                      // object ID, returned by `model::Species->get_objectID()`.

            bool has_entered;
            glm::vec3 coordinate_vector;           // rotate vector.
            GLfloat rotate_angle;                  // rotate angle.
            glm::vec3 rotate_vector;               // rotate vector.
            glm::vec3 translate_vector;            // translate vector.

            // The rest fields are created in the constructor.
            glm::mat4 model_matrix;                // model matrix.
            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object. not used at the moment.

            glm::mat4 MVP_matrix;                  // model view projection matrix.
    };
}

#endif
<|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 "mitkSceneReaderV1.h"
#include "mitkSerializerMacros.h"
#include "mitkBaseRenderer.h"
#include "mitkPropertyListDeserializer.h"
#include "mitkProgressBar.h"
#include "mitkIOUtil.h"
#include "Poco/Path.h"
#include <mitkRenderingModeProperty.h>

MITK_REGISTER_SERIALIZER(SceneReaderV1)

namespace
{

typedef std::pair<mitk::DataNode::Pointer, std::list<std::string> >   NodesAndParentsPair;

bool NodeSortByLayerIsLessThan( const NodesAndParentsPair& left, const NodesAndParentsPair& right )
{
  if ( left.first.IsNotNull() && right.first.IsNotNull() )
  {
    int leftLayer;
    int rightLayer;
    if ( left.first->GetIntProperty("layer", leftLayer) && right.first->GetIntProperty("layer", rightLayer) )
    {
      return leftLayer < rightLayer;
    }
    else
    {
      // fall back to name sort
      return left.first->GetName() < right.first->GetName();
    }
  }

  // in all other cases, fall back to stupid pointer comparison
  // this is not reasonable but at least answers the sorting
  // question clearly
  return left.first.GetPointer() < right.first.GetPointer();
}

}

bool mitk::SceneReaderV1::LoadScene( TiXmlDocument& document, const std::string& workingDirectory, DataStorage* storage )
{
  assert(storage);
  bool error(false);

  // TODO prepare to detect errors (such as cycles) from wrongly written or edited xml files

  //Get number of elements to initialze progress bar
  //   1. if there is a <data type="..." file="..."> element,
    //        - construct a name for the appropriate serializer
    //        - try to instantiate this serializer via itk object factory
    //        - if serializer could be created, use it to read the file into a BaseData object
    //        - if successful, call the new node's SetData(..)

    // create a node for the tag "data" and test if node was created
  typedef std::vector<mitk::DataNode::Pointer> DataNodeVector;
  DataNodeVector DataNodes;
  unsigned int listSize = 0;
  for( TiXmlElement* element = document.FirstChildElement("node"); element != NULL; element = element->NextSiblingElement("node") )
  {
    ++listSize;
  }

  ProgressBar::GetInstance()->AddStepsToDo(listSize * 2);

  for (TiXmlElement* element = document.FirstChildElement("node"); element != NULL; element = element->NextSiblingElement("node"))
  {
      DataNodes.push_back(LoadBaseDataFromDataTag(element->FirstChildElement("data"), workingDirectory, error));
      ProgressBar::GetInstance()->Progress();
  }

  // iterate all nodes
  // first level nodes should be <node> elements
  DataNodeVector::iterator nit = DataNodes.begin();
  for( TiXmlElement* element = document.FirstChildElement("node"); element != NULL || nit != DataNodes.end(); element = element->NextSiblingElement("node"), ++nit )
  {
    mitk::DataNode::Pointer node = *nit;
    // in case dataXmlElement is valid test whether it containts the "properties" child tag
    // and process further if and only if yes
    TiXmlElement *dataXmlElement = element->FirstChildElement("data");
    if( dataXmlElement && dataXmlElement->FirstChildElement("properties") )
    {
      TiXmlElement *baseDataElement = dataXmlElement->FirstChildElement("properties");
      if ( node->GetData() )
      {
        DecorateBaseDataWithProperties( node->GetData(), baseDataElement, workingDirectory);
      }
      else
      {
        MITK_WARN << "BaseData properties stored in scene file, but BaseData could not be read" << std::endl;
      }
    }

    //   2. check child nodes
    const char* uida = element->Attribute("UID");
    std::string uid("");

    if (uida)
    {
      uid = uida;
      m_NodeForID[uid] = node.GetPointer();
      m_IDForNode[ node.GetPointer() ] = uid;
    }
    else
    {
      MITK_ERROR << "No UID found for current node. Node will have no parents.";
      error = true;
    }

    //   3. if there are <properties> nodes,
    //        - instantiate the appropriate PropertyListDeSerializer
    //        - use them to construct PropertyList objects
    //        - add these properties to the node (if necessary, use renderwindow name)
    bool success = DecorateNodeWithProperties(node, element, workingDirectory);
    if (!success)
    {
      MITK_ERROR << "Could not load properties for node.";
      error = true;
    }

    // remember node for later adding to DataStorage
    m_OrderedNodePairs.push_back( std::make_pair( node, std::list<std::string>() ) );

    //   4. if there are <source> elements, remember parent objects
    for( TiXmlElement* source = element->FirstChildElement("source"); source != NULL; source = source->NextSiblingElement("source") )
    {
      const char* sourceUID = source->Attribute("UID");
      if (sourceUID)
      {
        m_OrderedNodePairs.back().second.push_back( std::string(sourceUID) );
      }
    }

    ProgressBar::GetInstance()->Progress();
  } // end for all <node>

  // sort our nodes by their "layer" property
  // (to be inserted in that order)
  m_OrderedNodePairs.sort( &NodeSortByLayerIsLessThan );

  // remove all unknown parent UIDs
  for (OrderedNodesList::iterator nodesIter = m_OrderedNodePairs.begin();
       nodesIter != m_OrderedNodePairs.end();
       ++nodesIter)
  {
    for (std::list<std::string>::iterator parentsIter = nodesIter->second.begin();
         parentsIter != nodesIter->second.end();)
    {
      if (m_NodeForID.find( *parentsIter ) == m_NodeForID.end())
      {
        parentsIter = nodesIter->second.erase( parentsIter );
        MITK_WARN << "Found a DataNode with unknown parents. Will add it to DataStorage without any parent objects.";
        error = true;
      }
      else
      {
        ++parentsIter;
      }
    }
  }

  // repeat the following loop ...
  //   ... for all created nodes
  unsigned int lastMapSize(0);
  while ( lastMapSize != m_OrderedNodePairs.size()) // this is to prevent infinite loops; each iteration must at least add one node to DataStorage
  {
    lastMapSize = m_OrderedNodePairs.size();

    // iterate (layer) ordered nodes backwards
    // we insert the highest layers first
    for (OrderedNodesList::iterator nodesIter = m_OrderedNodePairs.begin();
         nodesIter != m_OrderedNodePairs.end();
         ++nodesIter)
    {
      bool addThisNode(true);

      // if any parent node is not yet in DataStorage, skip node for now and check later
      for (std::list<std::string>::iterator parentsIter = nodesIter->second.begin();
           parentsIter != nodesIter->second.end();
           ++parentsIter)
      {
        if ( !storage->Exists( m_NodeForID[ *parentsIter ] ) )
        {
          addThisNode = false;
          break;
        }
      }

      if (addThisNode)
      {
        DataStorage::SetOfObjects::Pointer parents = DataStorage::SetOfObjects::New();
        for ( std::list<std::string>::iterator parentsIter = nodesIter->second.begin();
              parentsIter != nodesIter->second.end();
              ++parentsIter )
        {
           parents->push_back(m_NodeForID[*parentsIter]);
        }

        // if all parents are found in datastorage (or are unknown), add node to DataStorage
        storage->Add(nodesIter->first, parents);

        // remove this node from m_OrderedNodePairs
        m_OrderedNodePairs.erase( nodesIter );

        // break this for loop because iterators are probably invalid
        break;
      }
    }
  }

  // All nodes that are still in m_OrderedNodePairs at this point are not part of a proper directed graph structure. We'll add such nodes without any parent information.
  for (OrderedNodesList::iterator nodesIter = m_OrderedNodePairs.begin();
       nodesIter != m_OrderedNodePairs.end();
       ++nodesIter)
  {
    storage->Add( nodesIter->first );
    MITK_WARN << "Encountered node that is not part of a directed graph structure. Will be added to DataStorage without parents.";
    error = true;
  }

  return !error;
}

mitk::DataNode::Pointer mitk::SceneReaderV1::LoadBaseDataFromDataTag( TiXmlElement* dataElement, const std::string& workingDirectory, bool& error )
{
  DataNode::Pointer node;

  if (dataElement)
  {
    const char* filename = dataElement->Attribute("file");
    if ( filename )
    {
      try
      {
        std::vector<BaseData::Pointer> baseData = IOUtil::Load( workingDirectory + Poco::Path::separator() + filename );
        if (baseData.size() > 1)
        {
          MITK_WARN << "Discarding multiple base data results from " << filename << " except the first one.";
        }
        node = DataNode::New();
        node->SetData(baseData.front());
      }
      catch (std::exception& e)
      {
        MITK_ERROR << "Error during attempt to read '" << filename << "'. Exception says: " << e.what();
        error = true;
      }

      if (node.IsNull())
      {
        MITK_ERROR << "Error during attempt to read '" << filename << "'. Factory returned NULL object.";
        error = true;
      }
    }
  }

  // in case there was no <data> element we create a new empty node (for appending a propertylist later)
  if (node.IsNull())
  {
    node = DataNode::New();
  }

  return node;
}

void mitk::SceneReaderV1::ClearNodePropertyListWithExceptions(DataNode& node, PropertyList& propertyList)
{
  // Basically call propertyList.Clear(), but implement exceptions (see bug 19354)
  BaseData* data = node.GetData();

  PropertyList::Pointer propertiesToKeep = PropertyList::New();

  if (dynamic_cast<Image*>(data))
  {
    /*
      Older scene files (before changes of bug 17547) could contain
      a RenderingMode property with value "LevelWindow_Color".
      Since bug 17547 this value has been removed and replaced by
      the default value LookupTable_LevelWindow_Color.

      This new default value does only result in "black-to-white"
      CT images (or others) if there is a corresponding lookup
      table. Such a lookup table is provided as a default value
      by the Image mapper. Since that value was never present in
      older scene files, we do well in not removing the new
      default value here. Otherwise the mapper would fall back
      to another default which is all the colors of the rainbow :-(
    */
    BaseProperty::Pointer lutProperty = propertyList.GetProperty("LookupTable");
    propertiesToKeep->SetProperty("LookupTable", lutProperty);
  }

  propertyList.Clear();

  propertyList.ConcatenatePropertyList(propertiesToKeep);
}

bool mitk::SceneReaderV1::DecorateNodeWithProperties(DataNode* node, TiXmlElement* nodeElement, const std::string& workingDirectory)
{
  assert(node);
  assert(nodeElement);
  bool error(false);

  for( TiXmlElement* properties = nodeElement->FirstChildElement("properties"); properties != NULL; properties = properties->NextSiblingElement("properties") )
  {
    const char* propertiesfilea( properties->Attribute("file") );
    std::string propertiesfile( propertiesfilea ? propertiesfilea : "" );

    const char* renderwindowa( properties->Attribute("renderwindow") );
    std::string renderwindow( renderwindowa ? renderwindowa : "" );

    PropertyList::Pointer propertyList = node->GetPropertyList(renderwindow); // DataNode implementation always returns a propertylist
    ClearNodePropertyListWithExceptions(*node, *propertyList);

    // use deserializer to construct new properties
    PropertyListDeserializer::Pointer deserializer = PropertyListDeserializer::New();

    deserializer->SetFilename(workingDirectory + Poco::Path::separator() + propertiesfile);
    bool success = deserializer->Deserialize();
    error |= !success;
    PropertyList::Pointer readProperties = deserializer->GetOutput();

    if (readProperties.IsNotNull())
    {
      propertyList->ConcatenatePropertyList( readProperties, true ); // true = replace
    }
    else
    {
      MITK_ERROR << "Property list reader did not return a property list. This is an implementation error. Please tell your developer.";
      error = true;
    }
  }

  return !error;
}

bool mitk::SceneReaderV1::DecorateBaseDataWithProperties(BaseData::Pointer data, TiXmlElement *baseDataNodeElem, const std::string &workingDir)
{
  // check given variables, initialize error variable
  assert(baseDataNodeElem);
  bool error(false);

  // get the file name stored in the <properties ...> tag
  const char* baseDataPropertyFile( baseDataNodeElem->Attribute("file") );
  // check if the filename was found
  if(baseDataPropertyFile)
  {
    //PropertyList::Pointer dataPropList = data->GetPropertyList();

    PropertyListDeserializer::Pointer propertyDeserializer = PropertyListDeserializer::New();

    // initialize the property reader
    propertyDeserializer->SetFilename(workingDir + Poco::Path::separator() + baseDataPropertyFile);
    bool ioSuccess = propertyDeserializer->Deserialize();
    error = !ioSuccess;

    // get the output
    PropertyList::Pointer inProperties = propertyDeserializer->GetOutput();

    // store the read-in properties to the given node or throw error otherwise
    if( inProperties.IsNotNull() )
    {
      data->SetPropertyList( inProperties );
    }
    else
    {
      MITK_ERROR << "The property deserializer did not return a (valid) property list.";
      error = true;
    }
  }
  else
  {
    MITK_ERROR << "Function DecorateBaseDataWithProperties(...) called with false TiXmlElement. \n \t ->Given element does not contain a 'file' attribute. \n";
    error = true;
  }

  return !error;
}

<commit_msg>Keep multi-component flag for old scene files<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 "mitkSceneReaderV1.h"
#include "mitkSerializerMacros.h"
#include "mitkBaseRenderer.h"
#include "mitkPropertyListDeserializer.h"
#include "mitkProgressBar.h"
#include "mitkIOUtil.h"
#include "Poco/Path.h"
#include <mitkRenderingModeProperty.h>

MITK_REGISTER_SERIALIZER(SceneReaderV1)

namespace
{

typedef std::pair<mitk::DataNode::Pointer, std::list<std::string> >   NodesAndParentsPair;

bool NodeSortByLayerIsLessThan( const NodesAndParentsPair& left, const NodesAndParentsPair& right )
{
  if ( left.first.IsNotNull() && right.first.IsNotNull() )
  {
    int leftLayer;
    int rightLayer;
    if ( left.first->GetIntProperty("layer", leftLayer) && right.first->GetIntProperty("layer", rightLayer) )
    {
      return leftLayer < rightLayer;
    }
    else
    {
      // fall back to name sort
      return left.first->GetName() < right.first->GetName();
    }
  }

  // in all other cases, fall back to stupid pointer comparison
  // this is not reasonable but at least answers the sorting
  // question clearly
  return left.first.GetPointer() < right.first.GetPointer();
}

}

bool mitk::SceneReaderV1::LoadScene( TiXmlDocument& document, const std::string& workingDirectory, DataStorage* storage )
{
  assert(storage);
  bool error(false);

  // TODO prepare to detect errors (such as cycles) from wrongly written or edited xml files

  //Get number of elements to initialze progress bar
  //   1. if there is a <data type="..." file="..."> element,
    //        - construct a name for the appropriate serializer
    //        - try to instantiate this serializer via itk object factory
    //        - if serializer could be created, use it to read the file into a BaseData object
    //        - if successful, call the new node's SetData(..)

    // create a node for the tag "data" and test if node was created
  typedef std::vector<mitk::DataNode::Pointer> DataNodeVector;
  DataNodeVector DataNodes;
  unsigned int listSize = 0;
  for( TiXmlElement* element = document.FirstChildElement("node"); element != NULL; element = element->NextSiblingElement("node") )
  {
    ++listSize;
  }

  ProgressBar::GetInstance()->AddStepsToDo(listSize * 2);

  for (TiXmlElement* element = document.FirstChildElement("node"); element != NULL; element = element->NextSiblingElement("node"))
  {
      DataNodes.push_back(LoadBaseDataFromDataTag(element->FirstChildElement("data"), workingDirectory, error));
      ProgressBar::GetInstance()->Progress();
  }

  // iterate all nodes
  // first level nodes should be <node> elements
  DataNodeVector::iterator nit = DataNodes.begin();
  for( TiXmlElement* element = document.FirstChildElement("node"); element != NULL || nit != DataNodes.end(); element = element->NextSiblingElement("node"), ++nit )
  {
    mitk::DataNode::Pointer node = *nit;
    // in case dataXmlElement is valid test whether it containts the "properties" child tag
    // and process further if and only if yes
    TiXmlElement *dataXmlElement = element->FirstChildElement("data");
    if( dataXmlElement && dataXmlElement->FirstChildElement("properties") )
    {
      TiXmlElement *baseDataElement = dataXmlElement->FirstChildElement("properties");
      if ( node->GetData() )
      {
        DecorateBaseDataWithProperties( node->GetData(), baseDataElement, workingDirectory);
      }
      else
      {
        MITK_WARN << "BaseData properties stored in scene file, but BaseData could not be read" << std::endl;
      }
    }

    //   2. check child nodes
    const char* uida = element->Attribute("UID");
    std::string uid("");

    if (uida)
    {
      uid = uida;
      m_NodeForID[uid] = node.GetPointer();
      m_IDForNode[ node.GetPointer() ] = uid;
    }
    else
    {
      MITK_ERROR << "No UID found for current node. Node will have no parents.";
      error = true;
    }

    //   3. if there are <properties> nodes,
    //        - instantiate the appropriate PropertyListDeSerializer
    //        - use them to construct PropertyList objects
    //        - add these properties to the node (if necessary, use renderwindow name)
    bool success = DecorateNodeWithProperties(node, element, workingDirectory);
    if (!success)
    {
      MITK_ERROR << "Could not load properties for node.";
      error = true;
    }

    // remember node for later adding to DataStorage
    m_OrderedNodePairs.push_back( std::make_pair( node, std::list<std::string>() ) );

    //   4. if there are <source> elements, remember parent objects
    for( TiXmlElement* source = element->FirstChildElement("source"); source != NULL; source = source->NextSiblingElement("source") )
    {
      const char* sourceUID = source->Attribute("UID");
      if (sourceUID)
      {
        m_OrderedNodePairs.back().second.push_back( std::string(sourceUID) );
      }
    }

    ProgressBar::GetInstance()->Progress();
  } // end for all <node>

  // sort our nodes by their "layer" property
  // (to be inserted in that order)
  m_OrderedNodePairs.sort( &NodeSortByLayerIsLessThan );

  // remove all unknown parent UIDs
  for (OrderedNodesList::iterator nodesIter = m_OrderedNodePairs.begin();
       nodesIter != m_OrderedNodePairs.end();
       ++nodesIter)
  {
    for (std::list<std::string>::iterator parentsIter = nodesIter->second.begin();
         parentsIter != nodesIter->second.end();)
    {
      if (m_NodeForID.find( *parentsIter ) == m_NodeForID.end())
      {
        parentsIter = nodesIter->second.erase( parentsIter );
        MITK_WARN << "Found a DataNode with unknown parents. Will add it to DataStorage without any parent objects.";
        error = true;
      }
      else
      {
        ++parentsIter;
      }
    }
  }

  // repeat the following loop ...
  //   ... for all created nodes
  unsigned int lastMapSize(0);
  while ( lastMapSize != m_OrderedNodePairs.size()) // this is to prevent infinite loops; each iteration must at least add one node to DataStorage
  {
    lastMapSize = m_OrderedNodePairs.size();

    // iterate (layer) ordered nodes backwards
    // we insert the highest layers first
    for (OrderedNodesList::iterator nodesIter = m_OrderedNodePairs.begin();
         nodesIter != m_OrderedNodePairs.end();
         ++nodesIter)
    {
      bool addThisNode(true);

      // if any parent node is not yet in DataStorage, skip node for now and check later
      for (std::list<std::string>::iterator parentsIter = nodesIter->second.begin();
           parentsIter != nodesIter->second.end();
           ++parentsIter)
      {
        if ( !storage->Exists( m_NodeForID[ *parentsIter ] ) )
        {
          addThisNode = false;
          break;
        }
      }

      if (addThisNode)
      {
        DataStorage::SetOfObjects::Pointer parents = DataStorage::SetOfObjects::New();
        for ( std::list<std::string>::iterator parentsIter = nodesIter->second.begin();
              parentsIter != nodesIter->second.end();
              ++parentsIter )
        {
           parents->push_back(m_NodeForID[*parentsIter]);
        }

        // if all parents are found in datastorage (or are unknown), add node to DataStorage
        storage->Add(nodesIter->first, parents);

        // remove this node from m_OrderedNodePairs
        m_OrderedNodePairs.erase( nodesIter );

        // break this for loop because iterators are probably invalid
        break;
      }
    }
  }

  // All nodes that are still in m_OrderedNodePairs at this point are not part of a proper directed graph structure. We'll add such nodes without any parent information.
  for (OrderedNodesList::iterator nodesIter = m_OrderedNodePairs.begin();
       nodesIter != m_OrderedNodePairs.end();
       ++nodesIter)
  {
    storage->Add( nodesIter->first );
    MITK_WARN << "Encountered node that is not part of a directed graph structure. Will be added to DataStorage without parents.";
    error = true;
  }

  return !error;
}

mitk::DataNode::Pointer mitk::SceneReaderV1::LoadBaseDataFromDataTag( TiXmlElement* dataElement, const std::string& workingDirectory, bool& error )
{
  DataNode::Pointer node;

  if (dataElement)
  {
    const char* filename = dataElement->Attribute("file");
    if ( filename )
    {
      try
      {
        std::vector<BaseData::Pointer> baseData = IOUtil::Load( workingDirectory + Poco::Path::separator() + filename );
        if (baseData.size() > 1)
        {
          MITK_WARN << "Discarding multiple base data results from " << filename << " except the first one.";
        }
        node = DataNode::New();
        node->SetData(baseData.front());
      }
      catch (std::exception& e)
      {
        MITK_ERROR << "Error during attempt to read '" << filename << "'. Exception says: " << e.what();
        error = true;
      }

      if (node.IsNull())
      {
        MITK_ERROR << "Error during attempt to read '" << filename << "'. Factory returned NULL object.";
        error = true;
      }
    }
  }

  // in case there was no <data> element we create a new empty node (for appending a propertylist later)
  if (node.IsNull())
  {
    node = DataNode::New();
  }

  return node;
}

void mitk::SceneReaderV1::ClearNodePropertyListWithExceptions(DataNode& node, PropertyList& propertyList)
{
  // Basically call propertyList.Clear(), but implement exceptions (see bug 19354)
  BaseData* data = node.GetData();

  PropertyList::Pointer propertiesToKeep = PropertyList::New();

  if (dynamic_cast<Image*>(data))
  {
    /*
      Older scene files (before changes of bug 17547) could contain
      a RenderingMode property with value "LevelWindow_Color".
      Since bug 17547 this value has been removed and replaced by
      the default value LookupTable_LevelWindow_Color.

      This new default value does only result in "black-to-white"
      CT images (or others) if there is a corresponding lookup
      table. Such a lookup table is provided as a default value
      by the Image mapper. Since that value was never present in
      older scene files, we do well in not removing the new
      default value here. Otherwise the mapper would fall back
      to another default which is all the colors of the rainbow :-(
    */
    BaseProperty::Pointer lutProperty = propertyList.GetProperty("LookupTable");
    propertiesToKeep->SetProperty("LookupTable", lutProperty);

    /*
      Older scene files (before changes of T14807) may contain
      multi-component images without the "Image.Displayed Component"
      property.

      As the treatment as multi-component image and the corresponding
      visualization options hinges on that property we should not delete
      it, if it was added by the mapper.
      Old diffusion images might contain the "DisplayChannel" property
      which stores the same information, however ignoring it is an acceptable
      loss of precision as usually which channel is selected is not terribly
      important.

      This is a fix for the issue reported in T19919.
    */
    BaseProperty::Pointer compProperty = propertyList.GetProperty("Image.Displayed Component");
    if (compProperty.IsNotNull())
    {
      propertiesToKeep->SetProperty("Image.Displayed Component", compProperty);
    }
  }

  propertyList.Clear();

  propertyList.ConcatenatePropertyList(propertiesToKeep);
}

bool mitk::SceneReaderV1::DecorateNodeWithProperties(DataNode* node, TiXmlElement* nodeElement, const std::string& workingDirectory)
{
  assert(node);
  assert(nodeElement);
  bool error(false);

  for( TiXmlElement* properties = nodeElement->FirstChildElement("properties"); properties != NULL; properties = properties->NextSiblingElement("properties") )
  {
    const char* propertiesfilea( properties->Attribute("file") );
    std::string propertiesfile( propertiesfilea ? propertiesfilea : "" );

    const char* renderwindowa( properties->Attribute("renderwindow") );
    std::string renderwindow( renderwindowa ? renderwindowa : "" );

    PropertyList::Pointer propertyList = node->GetPropertyList(renderwindow); // DataNode implementation always returns a propertylist
    ClearNodePropertyListWithExceptions(*node, *propertyList);

    // use deserializer to construct new properties
    PropertyListDeserializer::Pointer deserializer = PropertyListDeserializer::New();

    deserializer->SetFilename(workingDirectory + Poco::Path::separator() + propertiesfile);
    bool success = deserializer->Deserialize();
    error |= !success;
    PropertyList::Pointer readProperties = deserializer->GetOutput();

    if (readProperties.IsNotNull())
    {
      propertyList->ConcatenatePropertyList( readProperties, true ); // true = replace
    }
    else
    {
      MITK_ERROR << "Property list reader did not return a property list. This is an implementation error. Please tell your developer.";
      error = true;
    }
  }

  return !error;
}

bool mitk::SceneReaderV1::DecorateBaseDataWithProperties(BaseData::Pointer data, TiXmlElement *baseDataNodeElem, const std::string &workingDir)
{
  // check given variables, initialize error variable
  assert(baseDataNodeElem);
  bool error(false);

  // get the file name stored in the <properties ...> tag
  const char* baseDataPropertyFile( baseDataNodeElem->Attribute("file") );
  // check if the filename was found
  if(baseDataPropertyFile)
  {
    //PropertyList::Pointer dataPropList = data->GetPropertyList();

    PropertyListDeserializer::Pointer propertyDeserializer = PropertyListDeserializer::New();

    // initialize the property reader
    propertyDeserializer->SetFilename(workingDir + Poco::Path::separator() + baseDataPropertyFile);
    bool ioSuccess = propertyDeserializer->Deserialize();
    error = !ioSuccess;

    // get the output
    PropertyList::Pointer inProperties = propertyDeserializer->GetOutput();

    // store the read-in properties to the given node or throw error otherwise
    if( inProperties.IsNotNull() )
    {
      data->SetPropertyList( inProperties );
    }
    else
    {
      MITK_ERROR << "The property deserializer did not return a (valid) property list.";
      error = true;
    }
  }
  else
  {
    MITK_ERROR << "Function DecorateBaseDataWithProperties(...) called with false TiXmlElement. \n \t ->Given element does not contain a 'file' attribute. \n";
    error = true;
  }

  return !error;
}

<|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 "mitkTestingMacros.h"
#include "mitkToolManager.h"
#include "mitkStandaloneDataStorage.h"
#include "mitkCoreObjectFactory.h"
#include "mitkGlobalInteraction.h"

class mitkToolManagerTestClass { public:

static void TestToolManagerWithOutTools(mitk::ToolManager::Pointer toolManager)
{
  MITK_TEST_CONDITION( toolManager->GetTools().size() == 0, "Get empty tool list" )
  MITK_TEST_CONDITION( toolManager->GetToolById(0) == NULL, "Get empty tool by id" )
}

static void TestToolManagerWithTools(mitk::ToolManager::Pointer toolManager)
{
  MITK_TEST_CONDITION( toolManager->GetTools().size() > 0, "Get tool list with size 1" )
  MITK_TEST_CONDITION( toolManager->GetToolById(0) != NULL, "Test GetToolById() method" )
  MITK_TEST_CONDITION( toolManager->ActivateTool(0) == true, "Activate tool" )
  MITK_TEST_CONDITION( toolManager->GetActiveToolID() == 0, "Check for right tool id" )

  mitk::Tool* tool = toolManager->GetActiveTool();
  MITK_TEST_CONDITION( tool != NULL, "Check for right tool" )
}

static void TestSetterMethods(mitk::ToolManager::Pointer toolManager)
{
  MITK_TEST_CONDITION( toolManager->GetReferenceData().size() == 0, "Get reference data size (0)" )

  mitk::DataNode::Pointer nodeEmpty = mitk::DataNode::New();
  toolManager->SetReferenceData(nodeEmpty);
  MITK_TEST_CONDITION( toolManager->GetReferenceData().size() == 1, "Get reference data size (1)" )
  MITK_TEST_CONDITION( toolManager->GetReferenceData(0) == nodeEmpty, "Check if it is the right reference data" )
  MITK_TEST_CONDITION( toolManager->GetReferenceData()[0] == nodeEmpty, "Check if it is the right reference data vector" )

  mitk::DataNode::Pointer nodeEmpty2 = mitk::DataNode::New();
  toolManager->SetWorkingData(nodeEmpty2);
  MITK_TEST_CONDITION( toolManager->GetWorkingData().size() == 1, "Get working data size (1)" )
  MITK_TEST_CONDITION( toolManager->GetWorkingData(0) == nodeEmpty2, "Check if it is the right working data" )
  MITK_TEST_CONDITION( toolManager->GetWorkingData()[0] == nodeEmpty2, "Check if it is the right working data vector" )
}

};

int mitkToolManagerTest(int /* argc */, char* /*argv*/[])
{
  // always start with this!
  MITK_TEST_BEGIN("ToolManager")

  // Global interaction must(!) be initialized if used
  mitk::GlobalInteraction::GetInstance()->Initialize("global");

  // instantiation
  mitk::StandaloneDataStorage::Pointer dataStorage = mitk::StandaloneDataStorage::New();
  mitk::ToolManager::Pointer toolManager = mitk::ToolManager::New(dataStorage.GetPointer());

  // first test: did this work?
  // using MITK_TEST_CONDITION_REQUIRED makes the test stop after failure, since
  // it makes no sense to continue without an object.
  MITK_TEST_CONDITION_REQUIRED(toolManager.IsNotNull(),"Testing instantiation")

  // write your own tests here and use the macros from mitkTestingMacros.h !!!
  // do not write to std::cout and do not return from this function yourself!
  //mitkToolManagerTestClass::TestToolManagerWithOutTools(toolManager);

  //now we add one tool
  toolManager = mitk::ToolManager::New(dataStorage.GetPointer());

  //start test with tool
  mitkToolManagerTestClass::TestToolManagerWithTools(toolManager);

  //now the setter methods
  mitkToolManagerTestClass::TestSetterMethods(toolManager);

  // always end with this!
  MITK_TEST_END()
}
<commit_msg>COMP: Try to find out what causes the segfault.<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 "mitkTestingMacros.h"
#include "mitkToolManager.h"
#include "mitkStandaloneDataStorage.h"
#include "mitkCoreObjectFactory.h"
#include "mitkGlobalInteraction.h"

class mitkToolManagerTestClass { public:

static void TestToolManagerWithOutTools(mitk::ToolManager::Pointer toolManager)
{
  MITK_TEST_CONDITION( toolManager->GetTools().size() == 0, "Get empty tool list" )
  MITK_TEST_CONDITION( toolManager->GetToolById(0) == NULL, "Get empty tool by id" )
}

static void TestToolManagerWithTools(mitk::ToolManager::Pointer toolManager)
{
  MITK_TEST_CONDITION( toolManager->GetTools().size() > 0, "Get tool list with size 1" )
  MITK_TEST_CONDITION( toolManager->GetToolById(0) != NULL, "Test GetToolById() method" )
  MITK_TEST_CONDITION( toolManager->ActivateTool(0) == true, "Activate tool" )
  MITK_TEST_CONDITION( toolManager->GetActiveToolID() == 0, "Check for right tool id" )

  mitk::Tool* tool = toolManager->GetActiveTool();
  MITK_TEST_CONDITION( tool != NULL, "Check for right tool" )
}

static void TestSetterMethods(mitk::ToolManager::Pointer toolManager)
{
  MITK_TEST_CONDITION( toolManager->GetReferenceData().size() == 0, "Get reference data size (0)" )

  mitk::DataNode::Pointer nodeEmpty = mitk::DataNode::New();
  toolManager->SetReferenceData(nodeEmpty);
  MITK_TEST_CONDITION( toolManager->GetReferenceData().size() == 1, "Get reference data size (1)" )
  MITK_TEST_CONDITION( toolManager->GetReferenceData(0) == nodeEmpty, "Check if it is the right reference data" )
  MITK_TEST_CONDITION( toolManager->GetReferenceData()[0] == nodeEmpty, "Check if it is the right reference data vector" )

  mitk::DataNode::Pointer nodeEmpty2 = mitk::DataNode::New();
  toolManager->SetWorkingData(nodeEmpty2);
  MITK_TEST_CONDITION( toolManager->GetWorkingData().size() == 1, "Get working data size (1)" )
  MITK_TEST_CONDITION( toolManager->GetWorkingData(0) == nodeEmpty2, "Check if it is the right working data" )
  MITK_TEST_CONDITION( toolManager->GetWorkingData()[0] == nodeEmpty2, "Check if it is the right working data vector" )
}

};

int mitkToolManagerTest(int /* argc */, char* /*argv*/[])
{
  // always start with this!
  MITK_TEST_BEGIN("ToolManager")

  // Global interaction must(!) be initialized if used
  /*TEMP mitk::GlobalInteraction::GetInstance()->Initialize("global");

  // instantiation
  mitk::StandaloneDataStorage::Pointer dataStorage = mitk::StandaloneDataStorage::New();
  mitk::ToolManager::Pointer toolManager = mitk::ToolManager::New(dataStorage.GetPointer());

  // first test: did this work?
  // using MITK_TEST_CONDITION_REQUIRED makes the test stop after failure, since
  // it makes no sense to continue without an object.
  MITK_TEST_CONDITION_REQUIRED(toolManager.IsNotNull(),"Testing instantiation")

  // write your own tests here and use the macros from mitkTestingMacros.h !!!
  // do not write to std::cout and do not return from this function yourself!
  //mitkToolManagerTestClass::TestToolManagerWithOutTools(toolManager);

  //now we add one tool
  toolManager = mitk::ToolManager::New(dataStorage.GetPointer());

  //start test with tool
  mitkToolManagerTestClass::TestToolManagerWithTools(toolManager);

  //now the setter methods
  mitkToolManagerTestClass::TestSetterMethods(toolManager);TEMP*/

  // always end with this!
  MITK_TEST_END()
}
<|endoftext|>


<commit_before>#include "Hardware.h"

#define PIN_LED_R 14
#define PIN_LED_G 13
#define PIN_LED_B 10

#define PIN_MOTOR_I_PWM 22
#define PIN_MOTOR_I_DIR 27
#define PIN_MOTOR_J_PWM 24
#define PIN_MOTOR_J_DIR 28
#define PIN_MOTOR_K_PWM 25
#define PIN_MOTOR_K_DIR 29

#define PIN_LINE_LED 12

Hardware::Hardware() {
    wiringPiSetup();

    /// initialize LED software pwms
    softPwmCreate(PIN_LED_R,0,255);
    softPwmCreate(PIN_LED_G,0,255);
    softPwmCreate(PIN_LED_B,0,255);

    /// initialize motor software pwms
    softPwmCreate(PIN_MOTOR_I_PWM,0,100);
    softPwmCreate(PIN_MOTOR_J_PWM,0,100);
    softPwmCreate(PIN_MOTOR_K_PWM,0,100);

    /// initialize motor direction outputs
    pinMode(PIN_MOTOR_I_DIR,OUTPUT);
    pinMode(PIN_MOTOR_J_DIR,OUTPUT);
    pinMode(PIN_MOTOR_K_DIR,OUTPUT);

    pinMode(PIN_LINE_LED,OUTPUT);
}

void Hardware::setLED(int r, int g, int b) {
    softPwmWrite(PIN_LED_R,r);
    softPwmWrite(PIN_LED_G,g);
    softPwmWrite(PIN_LED_B,b);
}

int Hardware::readLine() {
    digitalWrite(PIN_LINE_LED,1);
    usleep(200);

    long long longest = readLineSensor(0);
    int longPin = 0;
    for (int i=1; i<8; i++) {
        long long iTime = readLineSensor(i);
        if (iTime < longest) {
            longest = iTime;
            longPin = i;
        }
    } return longPin;
}

long long Hardware::readLineSensor(int i) {
    pinMode(i,OUTPUT);
    digitalWrite(i,1);
    usleep(10);

    pinMode(i,INPUT);
    pullUpDnControl(i,PUD_OFF);

    auto start = std::chrono::high_resolution_clock::now();
    while (digitalRead(i));
    auto elapsed = std::chrono::high_resolution_clock::now() - start;
    long long microseconds = std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count();
}

void Hardware::goHolonomic(int x, int y, int r) {
    double i = y*sqrt(3)/2 + x/2 + r;
    double j = y*sqrt(3)/2 - x/2 - r;
    double k = x - r;

    double coef = 100.0/(((i>j)?i:j)>k?((i>j)?i:j):k);

    setMotors(i*coef,j*coef,k*coef);
}

void Hardware::setMotors(int i, int j, int k) {
    digitalWrite(PIN_MOTOR_I_DIR,i>0);
    softPwmWrite(PIN_MOTOR_I_PWM,abs(i));

    digitalWrite(PIN_MOTOR_J_DIR,j>0);
    softPwmWrite(PIN_MOTOR_J_PWM,abs(j));

    digitalWrite(PIN_MOTOR_K_DIR,k>0);
    softPwmWrite(PIN_MOTOR_K_PWM,abs(k));
}

Hardware::~Hardware() {
    setLED(0,0,0);
    setMotors(0,0,0);

    usleep(100000);
}
<commit_msg>actually return stuff lol<commit_after>#include "Hardware.h"

#define PIN_LED_R 14
#define PIN_LED_G 13
#define PIN_LED_B 10

#define PIN_MOTOR_I_PWM 22
#define PIN_MOTOR_I_DIR 27
#define PIN_MOTOR_J_PWM 24
#define PIN_MOTOR_J_DIR 28
#define PIN_MOTOR_K_PWM 25
#define PIN_MOTOR_K_DIR 29

#define PIN_LINE_LED 12

Hardware::Hardware() {
    wiringPiSetup();

    /// initialize LED software pwms
    softPwmCreate(PIN_LED_R,0,255);
    softPwmCreate(PIN_LED_G,0,255);
    softPwmCreate(PIN_LED_B,0,255);

    /// initialize motor software pwms
    softPwmCreate(PIN_MOTOR_I_PWM,0,100);
    softPwmCreate(PIN_MOTOR_J_PWM,0,100);
    softPwmCreate(PIN_MOTOR_K_PWM,0,100);

    /// initialize motor direction outputs
    pinMode(PIN_MOTOR_I_DIR,OUTPUT);
    pinMode(PIN_MOTOR_J_DIR,OUTPUT);
    pinMode(PIN_MOTOR_K_DIR,OUTPUT);

    pinMode(PIN_LINE_LED,OUTPUT);
}

void Hardware::setLED(int r, int g, int b) {
    softPwmWrite(PIN_LED_R,r);
    softPwmWrite(PIN_LED_G,g);
    softPwmWrite(PIN_LED_B,b);
}

int Hardware::readLine() {
    digitalWrite(PIN_LINE_LED,1);
    usleep(200);

    long long longest = readLineSensor(0);
    int longPin = 0;
    for (int i=1; i<8; i++) {
        long long iTime = readLineSensor(i);
        if (iTime < longest) {
            longest = iTime;
            longPin = i;
        }
    } return longPin;
}

long long Hardware::readLineSensor(int i) {
    pinMode(i,OUTPUT);
    digitalWrite(i,1);
    usleep(10);

    pinMode(i,INPUT);
    pullUpDnControl(i,PUD_OFF);

    auto start = std::chrono::high_resolution_clock::now();
    while (digitalRead(i));
    auto elapsed = std::chrono::high_resolution_clock::now() - start;

    return std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count();
}

void Hardware::goHolonomic(int x, int y, int r) {
    double i = y*sqrt(3)/2 + x/2 + r;
    double j = y*sqrt(3)/2 - x/2 - r;
    double k = x - r;

    double coef = 100.0/(((i>j)?i:j)>k?((i>j)?i:j):k);

    setMotors(i*coef,j*coef,k*coef);
}

void Hardware::setMotors(int i, int j, int k) {
    digitalWrite(PIN_MOTOR_I_DIR,i>0);
    softPwmWrite(PIN_MOTOR_I_PWM,abs(i));

    digitalWrite(PIN_MOTOR_J_DIR,j>0);
    softPwmWrite(PIN_MOTOR_J_PWM,abs(j));

    digitalWrite(PIN_MOTOR_K_DIR,k>0);
    softPwmWrite(PIN_MOTOR_K_PWM,abs(k));
}

Hardware::~Hardware() {
    setLED(0,0,0);
    setMotors(0,0,0);

    usleep(100000);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 Joseph Thomson
 *
 * 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.
 */

#pragma once

#ifndef OBSERVER_HPP
#define OBSERVER_HPP

#include <functional>
#include <iosfwd>
#include <utility>

//==========
// observer
//==========

template <typename T>
class observer;

template <typename T>
constexpr T* get_pointer(observer<T> const&) noexcept;

template <typename T>
class observer
{
public:
    using element_type = T;

private:
    T* target;

public:
    constexpr explicit observer(T& r) noexcept :
        target(&r)
    {
    }

    constexpr explicit observer(T&&) noexcept = delete;

    template <typename U, typename = std::enable_if_t<std::is_convertible<U*, T*>::value>>
    constexpr observer(observer<U> const& i) noexcept :
        target(get_pointer(i))
    {
    }

    constexpr T& operator*() const noexcept
    {
        return *target;
    }

    constexpr T* operator->() const noexcept
    {
        return target;
    }

    constexpr explicit operator T*() const noexcept
    {
        return target;
    }

    void swap(observer& other) noexcept
    {
        using std::swap;
        swap(target, other.target);
    }
};

template <typename T>
constexpr observer<T> make_observer(T& r) noexcept
{
    return observer<T>(r);
}

template <typename T>
observer<T> make_observer(T&&) = delete;

template <typename T>
constexpr T* get_pointer(observer<T> const& i) noexcept
{
    return static_cast<T*>(i);
}

template <typename T>
void swap(observer<T>& lhs, observer<T>& rhs)
{
    lhs.swap(rhs);
}

template <typename T1, typename T2>
constexpr bool operator==(observer<T1> const& lhs, observer<T2> const& rhs) noexcept
{
    return get_pointer(lhs) == get_pointer(rhs);
}

template <typename T1, typename T2>
constexpr bool operator!=(observer<T1> const& lhs, observer<T2> const& rhs) noexcept
{
    return !(lhs == rhs);
}

template <typename T1, typename T2>
constexpr bool operator<(observer<T1> const& lhs, observer<T2> const& rhs) noexcept
{
    return std::less<std::common_type_t<T1*, T2*>>()(get_pointer(lhs), get_pointer(rhs));
}

template <typename T1, typename T2>
constexpr bool operator>(observer<T1> const& lhs, observer<T2> const& rhs) noexcept
{
    return rhs < lhs;
}

template <typename T1, typename T2>
constexpr bool operator<=(observer<T1> const& lhs, observer<T2> const& rhs) noexcept
{
    return !(rhs < lhs);
}

template <typename T1, typename T2>
constexpr bool operator>=(observer<T1> const& lhs, observer<T2> const& rhs) noexcept
{
    return !(lhs < rhs);
}

template <typename T>
std::ostream& operator<<(std::ostream& s, observer<T> const& i)
{
    return s << get_pointer(i);
}

namespace std
{

template <typename T>
struct hash<observer<T>>
{
    constexpr std::size_t operator()(observer<T> const& i) const noexcept
    {
        return hash<T*>()(get_pointer(i));
    }
};

} // namespace std

//==============
// observer_ptr
//==============

template <typename T>
class observer_ptr;

template <typename T>
constexpr T* get_pointer(observer_ptr<T> const&) noexcept;

template <typename T>
class observer_ptr
{
public:
    using element_type = T;

private:
    T* target;

public:
    constexpr observer_ptr() noexcept :
        target()
    {
    }

    constexpr explicit observer_ptr(T& r) noexcept :
        target(&r)
    {
    }

    constexpr explicit observer_ptr(T&&) noexcept = delete;

    constexpr observer_ptr(observer<T> const& i) noexcept :
        target(get_pointer(i))
    {
    }

    template <typename U, typename = std::enable_if_t<std::is_convertible<U*, T*>::value>>
    constexpr observer_ptr(observer<U> const& i) noexcept :
        target(get_pointer(i))
    {
    }

    template <typename U, typename = std::enable_if_t<std::is_convertible<U*, T*>::value>>
    constexpr observer_ptr(observer_ptr<U> const& i) noexcept :
        target(get_pointer(i))
    {
    }

    constexpr observer_ptr(std::nullptr_t) noexcept :
        target(nullptr)
    {
    }

    constexpr explicit observer_ptr(T* p) noexcept :
        target(p)
    {
    }

    constexpr explicit operator bool() const noexcept
    {
        return target != nullptr;
    }

    constexpr T& operator*() const
    {
        return *target;
    }

    constexpr T* operator->() const
    {
        return target;
    }

    constexpr explicit operator T*() const noexcept
    {
        return target;
    }

    void swap(observer_ptr& other) noexcept
    {
        using std::swap;
        swap(target, other.target);
    }
};

template <typename T>
constexpr T* get_pointer(observer_ptr<T> const& i) noexcept
{
    return static_cast<T*>(i);
}

template <typename T>
void swap(observer_ptr<T>& lhs, observer_ptr<T>& rhs) noexcept
{
    lhs.swap(rhs);
}

template <typename T1, typename T2>
constexpr bool operator==(observer_ptr<T1> const& lhs, observer_ptr<T2> const& rhs) noexcept
{
    return get_pointer(lhs) == get_pointer(rhs);
}

template <typename T1, typename T2>
constexpr bool operator==(observer_ptr<T1> const& lhs, observer<T2> const& rhs) noexcept
{
    return get_pointer(lhs) == get_pointer(rhs);
}

template <typename T1, typename T2>
constexpr bool operator==(observer<T1> const& lhs, observer_ptr<T2> const& rhs) noexcept
{
    return get_pointer(lhs) == get_pointer(rhs);
}

template <typename T>
constexpr bool operator==(observer_ptr<T> const& lhs, std::nullptr_t) noexcept
{
    return !lhs;
}

template <typename T>
constexpr bool operator==(std::nullptr_t, observer_ptr<T> const& rhs) noexcept
{
    return !rhs;
}

template <typename T1, typename T2>
constexpr bool operator!=(observer_ptr<T1> const& lhs, observer_ptr<T2> const& rhs) noexcept
{
    return !(lhs == rhs);
}

template <typename T1, typename T2>
constexpr bool operator!=(observer_ptr<T1> const& lhs, observer<T2> const& rhs) noexcept
{
    return !(lhs == rhs);
}

template <typename T1, typename T2>
constexpr bool operator!=(observer<T1> const& lhs, observer_ptr<T2> const& rhs) noexcept
{
    return !(lhs == rhs);
}

template <typename T>
constexpr bool operator!=(observer_ptr<T> const& lhs, std::nullptr_t) noexcept
{
    return !(lhs == nullptr);
}

template <typename T>
constexpr bool operator!=(std::nullptr_t, observer_ptr<T> const& rhs) noexcept
{
    return !(nullptr == rhs);
}

template <typename T1, typename T2>
constexpr bool operator<(observer_ptr<T1> const& lhs, observer_ptr<T2> const& rhs) noexcept
{
    return std::less<std::common_type_t<T1*, T2*>>()(get_pointer(lhs), get_pointer(rhs));
}

template <typename T1, typename T2>
constexpr bool operator<(observer_ptr<T1> const& lhs, observer<T2> const& rhs) noexcept
{
    return std::less<std::common_type_t<T1*, T2*>>()(get_pointer(lhs), get_pointer(rhs));
}

template <typename T1, typename T2>
constexpr bool operator<(observer<T1> const& lhs, observer_ptr<T2> const& rhs) noexcept
{
    return std::less<std::common_type_t<T1*, T2*>>()(get_pointer(lhs), get_pointer(rhs));
}

template <typename T>
constexpr bool operator<(observer_ptr<T> const& lhs, std::nullptr_t) noexcept
{
    return std::less<T*>()(get_pointer(lhs), nullptr);
}

template <typename T>
constexpr bool operator<(std::nullptr_t, observer_ptr<T> const& rhs) noexcept
{
    return std::less<T*>()(nullptr, get_pointer(rhs));
}

template <typename T1, typename T2>
constexpr bool operator>(observer_ptr<T1> const& lhs, observer_ptr<T2> const& rhs) noexcept
{
    return rhs < lhs;
}

template <typename T1, typename T2>
constexpr bool operator>(observer_ptr<T1> const& lhs, observer<T2> const& rhs) noexcept
{
    return rhs < lhs;
}

template <typename T1, typename T2>
constexpr bool operator>(observer<T1> const& lhs, observer_ptr<T2> const& rhs) noexcept
{
    return rhs < lhs;
}

template <typename T>
constexpr bool operator>(observer_ptr<T> const& lhs, std::nullptr_t) noexcept
{
    return nullptr < lhs;
}

template <typename T>
constexpr bool operator>(std::nullptr_t, observer_ptr<T> const& rhs) noexcept
{
    return rhs < nullptr;
}

template <typename T1, typename T2>
constexpr bool operator<=(observer_ptr<T1> const& lhs, observer_ptr<T2> const& rhs) noexcept
{
    return !(rhs < lhs);
}

template <typename T1, typename T2>
constexpr bool operator<=(observer_ptr<T1> const& lhs, observer<T2> const& rhs) noexcept
{
    return !(rhs < lhs);
}

template <typename T1, typename T2>
constexpr bool operator<=(observer<T1> const& lhs, observer_ptr<T2> const& rhs) noexcept
{
    return !(rhs < lhs);
}

template <typename T>
constexpr bool operator<=(observer_ptr<T> const& lhs, std::nullptr_t) noexcept
{
    return !(nullptr < lhs);
}

template <typename T>
constexpr bool operator<=(std::nullptr_t, observer_ptr<T> const& rhs) noexcept
{
    return !(rhs < nullptr);
}

template <typename T1, typename T2>
constexpr bool operator>=(observer_ptr<T1> const& lhs, observer_ptr<T2> const& rhs) noexcept
{
    return !(lhs < rhs);
}

template <typename T1, typename T2>
constexpr bool operator>=(observer_ptr<T1> const& lhs, observer<T2> const& rhs) noexcept
{
    return !(lhs < rhs);
}

template <typename T1, typename T2>
constexpr bool operator>=(observer<T1> const& lhs, observer_ptr<T2> const& rhs) noexcept
{
    return !(lhs < rhs);
}

template <typename T>
constexpr bool operator>=(observer_ptr<T> const& lhs, std::nullptr_t) noexcept
{
    return !(lhs < nullptr);
}

template <typename T>
constexpr bool operator>=(std::nullptr_t, observer_ptr<T> const& rhs) noexcept
{
    return !(nullptr < rhs);
}

template <typename T>
std::ostream& operator<<(std::ostream& s, observer_ptr<T> const& i)
{
    return s << get_pointer(i);
}

namespace std
{

template <typename T>
struct hash<observer_ptr<T>>
{
    constexpr std::size_t operator()(observer_ptr<T> const& i) const noexcept
    {
        return hash<T*>()(get_pointer(i));
    }
};

} // namespace std

#endif // OBSERVER_HPP
<commit_msg>Remove `observer_ptr<T>` entirely.<commit_after>/*
 * Copyright (c) 2016 Joseph Thomson
 *
 * 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.
 */

#ifndef GSL_OBSERVER_HPP
#define GSL_OBSERVER_HPP

#include <functional>
#include <type_traits>

namespace gsl
{

template <typename T>
class observer
{
public:
    using element_type = T;

    constexpr explicit observer(T& t) noexcept :
        ptr(&t)
    {
    }

    constexpr explicit observer(T&&) noexcept = delete;

    template <typename U, typename = std::enable_if_t<std::is_convertible<U*, T*>::value>>
    constexpr observer(observer<U> const& o) noexcept :
        ptr(static_cast<U*>(o))
    {
    }

    constexpr T& operator*() const noexcept
    {
        return *ptr;
    }

    constexpr T* operator->() const noexcept
    {
        return ptr;
    }

    constexpr explicit operator T*() const noexcept
    {
        return ptr;
    }

    void swap(observer& other) noexcept
    {
        using std::swap;
        swap(ptr, other.ptr);
    }

private:
    T* ptr;
};

template <typename T>
constexpr observer<T> make_observer(T& t) noexcept
{
    return observer<T>(t);
}

template <typename T>
observer<T> make_observer(T&&) = delete;

template <typename T>
void swap(observer<T>& lhs, observer<T>& rhs)
{
    lhs.swap(rhs);
}

template <typename T1, typename T2>
constexpr bool operator==(observer<T1> const& lhs, observer<T2> const& rhs) noexcept
{
    return static_cast<T1*>(lhs) == static_cast<T2*>(rhs);
}

template <typename T1, typename T2>
constexpr bool operator!=(observer<T1> const& lhs, observer<T2> const& rhs) noexcept
{
    return !(lhs == rhs);
}

} // namespace gsl

namespace std
{

template <typename T>
struct less<observer<T>>
{
    constexpr bool operator()(observer<T> const& lhs, observer<T> const& rhs) const noexcept
    {
        return less<T*>(static_cast<T*>(lhs), static_cast<T*>(rhs));
    }
};

template <typename T>
struct hash<observer<T>>
{
    constexpr std::size_t operator()(observer<T> const& o) const noexcept
    {
        return hash<T*>()(static_cast<T*>(o));
    }
};

} // namespace std

#endif // GSL_OBSERVER_HPP
<|endoftext|>


<commit_before>/*
 * wexcept.hpp
 * Classes to handle exceptions with const wchar_t* messages
 *
 * written by janus_wel<janus.wel.3@gmail.com>
 * This source code is in the public domain, and has NO WARRANTY.
 * */

#ifndef WEXCEPT_HPP
#define WEXCEPT_HPP

#include <exception>
#include <string>

namespace util {
    namespace exception {
        class wexception {
            public:
                virtual ~wexception(void) throw() {}
                virtual const wchar_t* what(void) const throw() = 0;
        };

        class wlogic_error : public wexception {
            protected:
                std::wstring errmsg;

            public:
                wlogic_error(std::wstring errmsg = std::wstring(L"")) throw() : errmsg(errmsg) {}
                virtual ~wlogic_error(void) throw() {}
                virtual const wchar_t* what(void) const throw() {
                    return errmsg.c_str();
                }
        };

        class wruntime_error : public wexception {
            protected:
                std::wstring errmsg;

            public:
                wruntime_error(std::wstring errmsg = std::wstring(L"")) throw() : errmsg(errmsg) {}
                virtual ~wruntime_error(void) throw() {}
                virtual const wchar_t* what(void) const throw() {
                    return errmsg.c_str();
                }
        };
    }
}

#endif // WEXCEPT_HPP

<commit_msg>Add some comments and change some return types<commit_after>/*
 * wexcept.hpp
 * Classes to handle exceptions with const wchar_t* messages
 *
 * written by janus_wel<janus.wel.3@gmail.com>
 * This source code is in the public domain, and has NO WARRANTY.
 * */

#ifndef WEXCEPT_HPP
#define WEXCEPT_HPP

#include <string>

// TODO?: Define other exceptions that are corresponding ones defined by <exception>.
namespace util {
    namespace exception {
        // base class
        class wexception {
            public:
                virtual ~wexception(void) throw() {}
                virtual const std::wstring& what(void) const throw() = 0;
        };

        // corresponding to std::logic_error
        class wlogic_error : public wexception {
            protected:
                std::wstring errmsg;

            public:
                wlogic_error(std::wstring errmsg = std::wstring(L"")) throw() : errmsg(errmsg) {}
                virtual ~wlogic_error(void) throw() {}
                virtual const std::wstring& what(void) const throw() {
                    return errmsg;
                }
        };

        // corresponding to std::runtime_error
        class wruntime_error : public wexception {
            protected:
                std::wstring errmsg;

            public:
                wruntime_error(std::wstring errmsg = std::wstring(L"")) throw() : errmsg(errmsg) {}
                virtual ~wruntime_error(void) throw() {}
                virtual const std::wstring& what(void) const throw() {
                    return errmsg;
                }
        };
    }
}

#endif // WEXCEPT_HPP

<|endoftext|>


<commit_before>#include "openCLUtilities.hpp"

cl::Context createCLContext(cl_device_type type, bool GLInterop, cl_vendor vendor) {
        // Get available platforms
        cl::vector<cl::Platform> platforms;
        cl::Platform::get(&platforms);

        if(platforms.size() == 0)
            throw cl::Error(1, "No OpenCL platforms were found");

        cl::Platform platform = platforms[0];

        // Use the preferred platform and create a context
        cl_context_properties cps[] = {
            CL_CONTEXT_PLATFORM, (cl_context_properties)(platform)(),
            0
        };
        try {
        cl::Context context = cl::Context(type, cps);

        return context;
    } catch(cl::Error error) {
        throw cl::Error(1, "Failed to create an OpenCL context!");
    }
}

cl::Program buildProgramFromSource(cl::Context context, std::string filename) {
        // Read source file
        std::ifstream sourceFile(filename.c_str());
        if(sourceFile.fail())
            throw cl::Error(1, "Failed to open OpenCL source file");
        std::string sourceCode(
            std::istreambuf_iterator<char>(sourceFile),
            (std::istreambuf_iterator<char>()));
        cl::Program::Sources source(1, std::make_pair(sourceCode.c_str(), sourceCode.length()+1));

        // Make program of the source code in the context
        cl::Program program = cl::Program(context, source);

        cl::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();

        // Build program for these specific devices
        try{
            program.build(devices);
        } catch(cl::Error error) {
            if(error.err() == CL_BUILD_PROGRAM_FAILURE) {
                std::cout << "Build log:\t" << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[0]) << std::endl;
            }
            throw error;
        }
        return program;

}

char *getCLErrorString(cl_int err) {
    switch (err) {
        case CL_SUCCESS:                          return (char *) "Success!";
        case CL_DEVICE_NOT_FOUND:                 return (char *) "Device not found.";
        case CL_DEVICE_NOT_AVAILABLE:             return (char *) "Device not available";
        case CL_COMPILER_NOT_AVAILABLE:           return (char *) "Compiler not available";
        case CL_MEM_OBJECT_ALLOCATION_FAILURE:    return (char *) "Memory object allocation failure";
        case CL_OUT_OF_RESOURCES:                 return (char *) "Out of resources";
        case CL_OUT_OF_HOST_MEMORY:               return (char *) "Out of host memory";
        case CL_PROFILING_INFO_NOT_AVAILABLE:     return (char *) "Profiling information not available";
        case CL_MEM_COPY_OVERLAP:                 return (char *) "Memory copy overlap";
        case CL_IMAGE_FORMAT_MISMATCH:            return (char *) "Image format mismatch";
        case CL_IMAGE_FORMAT_NOT_SUPPORTED:       return (char *) "Image format not supported";
        case CL_BUILD_PROGRAM_FAILURE:            return (char *) "Program build failure";
        case CL_MAP_FAILURE:                      return (char *) "Map failure";
        case CL_INVALID_VALUE:                    return (char *) "Invalid value";
        case CL_INVALID_DEVICE_TYPE:              return (char *) "Invalid device type";
        case CL_INVALID_PLATFORM:                 return (char *) "Invalid platform";
        case CL_INVALID_DEVICE:                   return (char *) "Invalid device";
        case CL_INVALID_CONTEXT:                  return (char *) "Invalid context";
        case CL_INVALID_QUEUE_PROPERTIES:         return (char *) "Invalid queue properties";
        case CL_INVALID_COMMAND_QUEUE:            return (char *) "Invalid command queue";
        case CL_INVALID_HOST_PTR:                 return (char *) "Invalid host pointer";
        case CL_INVALID_MEM_OBJECT:               return (char *) "Invalid memory object";
        case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR:  return (char *) "Invalid image format descriptor";
        case CL_INVALID_IMAGE_SIZE:               return (char *) "Invalid image size";
        case CL_INVALID_SAMPLER:                  return (char *) "Invalid sampler";
        case CL_INVALID_BINARY:                   return (char *) "Invalid binary";
        case CL_INVALID_BUILD_OPTIONS:            return (char *) "Invalid build options";
        case CL_INVALID_PROGRAM:                  return (char *) "Invalid program";
        case CL_INVALID_PROGRAM_EXECUTABLE:       return (char *) "Invalid program executable";
        case CL_INVALID_KERNEL_NAME:              return (char *) "Invalid kernel name";
        case CL_INVALID_KERNEL_DEFINITION:        return (char *) "Invalid kernel definition";
        case CL_INVALID_KERNEL:                   return (char *) "Invalid kernel";
        case CL_INVALID_ARG_INDEX:                return (char *) "Invalid argument index";
        case CL_INVALID_ARG_VALUE:                return (char *) "Invalid argument value";
        case CL_INVALID_ARG_SIZE:                 return (char *) "Invalid argument size";
        case CL_INVALID_KERNEL_ARGS:              return (char *) "Invalid kernel arguments";
        case CL_INVALID_WORK_DIMENSION:           return (char *) "Invalid work dimension";
        case CL_INVALID_WORK_GROUP_SIZE:          return (char *) "Invalid work group size";
        case CL_INVALID_WORK_ITEM_SIZE:           return (char *) "Invalid work item size";
        case CL_INVALID_GLOBAL_OFFSET:            return (char *) "Invalid global offset";
        case CL_INVALID_EVENT_WAIT_LIST:          return (char *) "Invalid event wait list";
        case CL_INVALID_EVENT:                    return (char *) "Invalid event";
        case CL_INVALID_OPERATION:                return (char *) "Invalid operation";
        case CL_INVALID_GL_OBJECT:                return (char *) "Invalid OpenGL object";
        case CL_INVALID_BUFFER_SIZE:              return (char *) "Invalid buffer size";
        case CL_INVALID_MIP_LEVEL:                return (char *) "Invalid mip-map level";
        default:                                  return (char *) "Unknown";
    }
}
<commit_msg>updated opencl utilities<commit_after>#include "openCLUtilities.hpp"

#if defined __APPLE__ || defined(MACOSX)
#else
    #if defined WIN32
    #else
        #include <GL/glx.h>
    #endif
#endif

cl::Context createCLContext(cl_device_type type, bool GLInterop, cl_vendor vendor) {
    // Get available platforms
    cl::vector<cl::Platform> platforms;
    cl::Platform::get(&platforms);

    // TODO: create vendor selecting mechanism

    if(platforms.size() == 0)
        throw cl::Error(1, "No OpenCL platforms were found");

    cl::Platform platform = platforms[0];

    // Use the preferred platform and create a context
    cl_context_properties * cps;
    if(GLInterop) {
        #ifdef __APPLE || defined(MACOSX)
        cps = new cl_context_properties[5];
        //TODO: Apple OpenGL interop
        #else
        cps = new cl_context_properties[7];
        #ifdef WIN32
        cps[0] = CL_GL_CONTEXT_KHR;
        cps[1] = (cl_context_properties)wglGetCurrentContext();
        cps[2] = CL_WGL_HDC_KHR;
        cps[3] = (cl_context_properties)wglGetCurrentDC();
        #else
        cps[0] = CL_GL_CONTEXT_KHR;
        cps[1] = (cl_context_properties)glXGetCurrentContext();
        cps[2] = CL_GLX_DISPLAY_KHR;
        cps[3] = (cl_context_properties)glXGetCurrentDisplay();
        #endif
        #endif // end if apple
        cps[4] = CL_CONTEXT_PLATFORM;
        cps[5] = (cl_context_properties)(platform)();
        cps[6] = 0;
    } else {
        cps = new cl_context_properties[3];
        cps[0] = CL_CONTEXT_PLATFORM;
        cps[1] = (cl_context_properties)(platform)();
        cps[2] = 0;
    }
    try {
        cl::Context context = cl::Context(type, cps);

        return context;
    } catch(cl::Error error) {
        throw cl::Error(1, "Failed to create an OpenCL context!");
    }
}

cl::Program buildProgramFromSource(cl::Context context, std::string filename) {
        // Read source file
        std::ifstream sourceFile(filename.c_str());
        if(sourceFile.fail())
            throw cl::Error(1, "Failed to open OpenCL source file");
        std::string sourceCode(
            std::istreambuf_iterator<char>(sourceFile),
            (std::istreambuf_iterator<char>()));
        cl::Program::Sources source(1, std::make_pair(sourceCode.c_str(), sourceCode.length()+1));

        // Make program of the source code in the context
        cl::Program program = cl::Program(context, source);

        cl::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();

        // Build program for these specific devices
        try{
            program.build(devices);
        } catch(cl::Error error) {
            if(error.err() == CL_BUILD_PROGRAM_FAILURE) {
                std::cout << "Build log:" << std::endl << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[0]) << std::endl;
            }
            throw error;
        }
        return program;

}

char *getCLErrorString(cl_int err) {
    switch (err) {
        case CL_SUCCESS:                          return (char *) "Success!";
        case CL_DEVICE_NOT_FOUND:                 return (char *) "Device not found.";
        case CL_DEVICE_NOT_AVAILABLE:             return (char *) "Device not available";
        case CL_COMPILER_NOT_AVAILABLE:           return (char *) "Compiler not available";
        case CL_MEM_OBJECT_ALLOCATION_FAILURE:    return (char *) "Memory object allocation failure";
        case CL_OUT_OF_RESOURCES:                 return (char *) "Out of resources";
        case CL_OUT_OF_HOST_MEMORY:               return (char *) "Out of host memory";
        case CL_PROFILING_INFO_NOT_AVAILABLE:     return (char *) "Profiling information not available";
        case CL_MEM_COPY_OVERLAP:                 return (char *) "Memory copy overlap";
        case CL_IMAGE_FORMAT_MISMATCH:            return (char *) "Image format mismatch";
        case CL_IMAGE_FORMAT_NOT_SUPPORTED:       return (char *) "Image format not supported";
        case CL_BUILD_PROGRAM_FAILURE:            return (char *) "Program build failure";
        case CL_MAP_FAILURE:                      return (char *) "Map failure";
        case CL_INVALID_VALUE:                    return (char *) "Invalid value";
        case CL_INVALID_DEVICE_TYPE:              return (char *) "Invalid device type";
        case CL_INVALID_PLATFORM:                 return (char *) "Invalid platform";
        case CL_INVALID_DEVICE:                   return (char *) "Invalid device";
        case CL_INVALID_CONTEXT:                  return (char *) "Invalid context";
        case CL_INVALID_QUEUE_PROPERTIES:         return (char *) "Invalid queue properties";
        case CL_INVALID_COMMAND_QUEUE:            return (char *) "Invalid command queue";
        case CL_INVALID_HOST_PTR:                 return (char *) "Invalid host pointer";
        case CL_INVALID_MEM_OBJECT:               return (char *) "Invalid memory object";
        case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR:  return (char *) "Invalid image format descriptor";
        case CL_INVALID_IMAGE_SIZE:               return (char *) "Invalid image size";
        case CL_INVALID_SAMPLER:                  return (char *) "Invalid sampler";
        case CL_INVALID_BINARY:                   return (char *) "Invalid binary";
        case CL_INVALID_BUILD_OPTIONS:            return (char *) "Invalid build options";
        case CL_INVALID_PROGRAM:                  return (char *) "Invalid program";
        case CL_INVALID_PROGRAM_EXECUTABLE:       return (char *) "Invalid program executable";
        case CL_INVALID_KERNEL_NAME:              return (char *) "Invalid kernel name";
        case CL_INVALID_KERNEL_DEFINITION:        return (char *) "Invalid kernel definition";
        case CL_INVALID_KERNEL:                   return (char *) "Invalid kernel";
        case CL_INVALID_ARG_INDEX:                return (char *) "Invalid argument index";
        case CL_INVALID_ARG_VALUE:                return (char *) "Invalid argument value";
        case CL_INVALID_ARG_SIZE:                 return (char *) "Invalid argument size";
        case CL_INVALID_KERNEL_ARGS:              return (char *) "Invalid kernel arguments";
        case CL_INVALID_WORK_DIMENSION:           return (char *) "Invalid work dimension";
        case CL_INVALID_WORK_GROUP_SIZE:          return (char *) "Invalid work group size";
        case CL_INVALID_WORK_ITEM_SIZE:           return (char *) "Invalid work item size";
        case CL_INVALID_GLOBAL_OFFSET:            return (char *) "Invalid global offset";
        case CL_INVALID_EVENT_WAIT_LIST:          return (char *) "Invalid event wait list";
        case CL_INVALID_EVENT:                    return (char *) "Invalid event";
        case CL_INVALID_OPERATION:                return (char *) "Invalid operation";
        case CL_INVALID_GL_OBJECT:                return (char *) "Invalid OpenGL object";
        case CL_INVALID_BUFFER_SIZE:              return (char *) "Invalid buffer size";
        case CL_INVALID_MIP_LEVEL:                return (char *) "Invalid mip-map level";
        default:                                  return (char *) "Unknown";
    }
}
<|endoftext|>


<commit_before><commit_msg>Made dashesy's changes to for loop that checks for additional parameters in OnFileConfig( )<commit_after><|endoftext|>