From 0b0e5fea5a54b001ee41c46e484c835d0692e2ad Mon Sep 17 00:00:00 2001
From: Markus Grotz <markus.grotz@kit.edu>
Date: Tue, 31 May 2016 13:51:51 +0200
Subject: [PATCH] moved EarlyVisionGraph lib to a separate component

---
 source/RobotAPI/components/CMakeLists.txt     |   2 +
 .../EarlyVisionGraph/CMakeLists.txt           |  34 ++
 .../EarlyVisionGraph/GraphGenerator.cpp       | 351 +++++++++++++
 .../EarlyVisionGraph/GraphGenerator.h         |  85 +++
 .../EarlyVisionGraph/GraphLookupTable.cpp     | 238 +++++++++
 .../EarlyVisionGraph/GraphLookupTable.h       |  65 +++
 .../components/EarlyVisionGraph/GraphMap.cpp  | 262 ++++++++++
 .../components/EarlyVisionGraph/GraphMap.h    |  74 +++
 .../EarlyVisionGraph/GraphProcessor.cpp       | 307 +++++++++++
 .../EarlyVisionGraph/GraphProcessor.h         |  50 ++
 .../GraphPyramidLookupTable.cpp               | 108 ++++
 .../GraphPyramidLookupTable.h                 |  52 ++
 .../EarlyVisionGraph/GraphTriangulation.cpp   | 423 +++++++++++++++
 .../EarlyVisionGraph/GraphTriangulation.h     |  52 ++
 .../EarlyVisionGraph/IntensityGraph.cpp       | 276 ++++++++++
 .../EarlyVisionGraph/IntensityGraph.h         |  97 ++++
 .../components/EarlyVisionGraph/MathTools.cpp | 488 ++++++++++++++++++
 .../components/EarlyVisionGraph/MathTools.h   |  72 +++
 .../EarlyVisionGraph/SphericalGraph.cpp       | 314 +++++++++++
 .../EarlyVisionGraph/SphericalGraph.h         | 165 ++++++
 .../components/EarlyVisionGraph/Structs.h     |  85 +++
 21 files changed, 3600 insertions(+)
 create mode 100644 source/RobotAPI/components/EarlyVisionGraph/CMakeLists.txt
 create mode 100644 source/RobotAPI/components/EarlyVisionGraph/GraphGenerator.cpp
 create mode 100644 source/RobotAPI/components/EarlyVisionGraph/GraphGenerator.h
 create mode 100644 source/RobotAPI/components/EarlyVisionGraph/GraphLookupTable.cpp
 create mode 100644 source/RobotAPI/components/EarlyVisionGraph/GraphLookupTable.h
 create mode 100644 source/RobotAPI/components/EarlyVisionGraph/GraphMap.cpp
 create mode 100644 source/RobotAPI/components/EarlyVisionGraph/GraphMap.h
 create mode 100644 source/RobotAPI/components/EarlyVisionGraph/GraphProcessor.cpp
 create mode 100644 source/RobotAPI/components/EarlyVisionGraph/GraphProcessor.h
 create mode 100644 source/RobotAPI/components/EarlyVisionGraph/GraphPyramidLookupTable.cpp
 create mode 100644 source/RobotAPI/components/EarlyVisionGraph/GraphPyramidLookupTable.h
 create mode 100644 source/RobotAPI/components/EarlyVisionGraph/GraphTriangulation.cpp
 create mode 100644 source/RobotAPI/components/EarlyVisionGraph/GraphTriangulation.h
 create mode 100644 source/RobotAPI/components/EarlyVisionGraph/IntensityGraph.cpp
 create mode 100644 source/RobotAPI/components/EarlyVisionGraph/IntensityGraph.h
 create mode 100644 source/RobotAPI/components/EarlyVisionGraph/MathTools.cpp
 create mode 100644 source/RobotAPI/components/EarlyVisionGraph/MathTools.h
 create mode 100644 source/RobotAPI/components/EarlyVisionGraph/SphericalGraph.cpp
 create mode 100644 source/RobotAPI/components/EarlyVisionGraph/SphericalGraph.h
 create mode 100644 source/RobotAPI/components/EarlyVisionGraph/Structs.h

diff --git a/source/RobotAPI/components/CMakeLists.txt b/source/RobotAPI/components/CMakeLists.txt
index fb09cfb0a..b596e7006 100644
--- a/source/RobotAPI/components/CMakeLists.txt
+++ b/source/RobotAPI/components/CMakeLists.txt
@@ -3,3 +3,5 @@ add_subdirectory(units)
 add_subdirectory(DebugDrawer)
 add_subdirectory(RobotState)
 
+
+add_subdirectory(EarlyVisionGraph)
\ No newline at end of file
diff --git a/source/RobotAPI/components/EarlyVisionGraph/CMakeLists.txt b/source/RobotAPI/components/EarlyVisionGraph/CMakeLists.txt
new file mode 100644
index 000000000..3398169a5
--- /dev/null
+++ b/source/RobotAPI/components/EarlyVisionGraph/CMakeLists.txt
@@ -0,0 +1,34 @@
+armarx_component_set_name("EarlyVisionGraph")
+
+
+find_package(Eigen3 QUIET)
+armarx_build_if(Eigen3_FOUND "Eigen3 not available")
+if(Eigen3_FOUND)
+    include_directories(${Eigen3_INCLUDE_DIR})
+endif()
+
+
+set(COMPONENT_LIBS "")
+
+
+set(SOURCES
+./MathTools.cpp
+./SphericalGraph.cpp
+./IntensityGraph.cpp
+./GraphLookupTable.cpp
+./GraphPyramidLookupTable.cpp
+#@TEMPLATE_LINE@@COMPONENT_PATH@/@COMPONENT_NAME@.cpp
+)
+set(HEADERS
+./Structs.h
+./MathTools.h
+./SphericalGraph.h
+./IntensityGraph.h
+./GraphLookupTable.h
+./GraphPyramidLookupTable.h
+#@TEMPLATE_LINE@@COMPONENT_PATH@/@COMPONENT_NAME@.h
+)
+
+
+armarx_add_component("${SOURCES}" "${HEADERS}")
+
diff --git a/source/RobotAPI/components/EarlyVisionGraph/GraphGenerator.cpp b/source/RobotAPI/components/EarlyVisionGraph/GraphGenerator.cpp
new file mode 100644
index 000000000..bf424e5b3
--- /dev/null
+++ b/source/RobotAPI/components/EarlyVisionGraph/GraphGenerator.cpp
@@ -0,0 +1,351 @@
+// *****************************************************************
+// Filename:    GraphGenerator.cpp
+// Copyright:   Kai Welke, Chair Prof. Dillmann (IAIM),
+//              Institute for Computer Science and Engineering (CSE),
+//              University of Karlsruhe. All rights reserved.
+// Author:      Kai Welke
+// Date:        08.07.2008
+// *****************************************************************
+
+#include "GraphGenerator.h"
+
+vector<Vec3d> CGraphGenerator::m_Vertices;
+vector<Face> CGraphGenerator::m_Faces;
+
+
+void CGraphGenerator::generateGraph(CSphericalGraph* pPlainGraph, EPolyhedronType nBaseType, int nLevels, float fRadius)
+{
+    initBasePolyhedron(nBaseType);
+    projectToSphere(fRadius);
+
+    for (int L = 0 ; L < nLevels ; L++)
+    {
+        subDivide();
+        projectToSphere(fRadius);
+    }
+
+    buildNodesAndEdges(pPlainGraph);
+}
+
+void CGraphGenerator::initBasePolyhedron(EPolyhedronType nBaseType)
+{
+    m_Vertices.clear();
+    m_Faces.clear();
+
+    switch (nBaseType)
+    {
+        case eTetrahedron:
+            generateTetrahedron();
+            break;
+
+        case eOctahedron:
+            generateOctahedron();
+            break;
+
+        case eIcosahedron:
+            generateIcosahedron();
+            break;
+
+        default:
+            printf("Wrong base type\n");
+            break;
+    }
+}
+
+void CGraphGenerator::generateTetrahedron()
+{
+    // vertices of a tetrahedron
+    float fSqrt3 = sqrt(3.0);
+    Vec3d v[4];
+
+    Math3d::SetVec(v[0], fSqrt3, fSqrt3, fSqrt3);
+    Math3d::SetVec(v[1], -fSqrt3, -fSqrt3, fSqrt3);
+    Math3d::SetVec(v[2], -fSqrt3, fSqrt3, -fSqrt3);
+    Math3d::SetVec(v[3], fSqrt3, -fSqrt3, -fSqrt3);
+
+    for (int i = 0 ; i < 4 ; i++)
+    {
+        m_Vertices.push_back(v[i]);
+    }
+
+    // structure describing a tetrahedron
+    Face f[4];
+    f[0].set(1, 2, 3);
+    f[1].set(1, 4, 2);
+    f[2].set(3, 2, 4);
+    f[3].set(4, 1, 3);
+
+    for (int i = 0 ; i < 4 ; i++)
+    {
+        f[i].m_n1--;
+        f[i].m_n2--;
+        f[i].m_n3--;
+        m_Faces.push_back(f[i]);
+    }
+}
+
+void CGraphGenerator::generateOctahedron()
+{
+    // Six equidistant points lying on the unit sphere
+    Vec3d v[6];
+    Math3d::SetVec(v[0], 1, 0, 0);
+    Math3d::SetVec(v[1], -1, 0, 0);
+    Math3d::SetVec(v[2], 0, 1, 0);
+    Math3d::SetVec(v[3], 0, -1, 0);
+    Math3d::SetVec(v[4], 0, 0, 1);
+    Math3d::SetVec(v[5], 0, 0, -1);
+
+    for (int i = 0 ; i < 6 ; i++)
+    {
+        m_Vertices.push_back(v[i]);
+    }
+
+    // Join vertices to create a unit octahedron
+    Face f[8];
+    f[0].set(1, 5, 3);
+    f[1].set(3, 5, 2);
+    f[2].set(2, 5, 4);
+    f[3].set(4, 5, 1);
+    f[4].set(1, 3, 6);
+    f[5].set(3, 2, 6);
+    f[6].set(2, 4, 6);
+    f[7].set(4, 1, 6);
+
+    for (int i = 0 ; i < 8 ; i++)
+    {
+        f[i].m_n1--;
+        f[i].m_n2--;
+        f[i].m_n3--;
+        m_Faces.push_back(f[i]);
+    }
+}
+
+void CGraphGenerator::generateIcosahedron()
+{
+    // Twelve vertices of icosahedron on unit sphere
+    float tau = 0.8506508084;
+    float one = 0.5257311121;
+
+    Vec3d v[12];
+
+    Math3d::SetVec(v[0], tau, one, 0);
+    Math3d::SetVec(v[1], -tau, one, 0);
+    Math3d::SetVec(v[2], -tau, -one, 0);
+    Math3d::SetVec(v[3], tau, -one, 0);
+    Math3d::SetVec(v[4], one, 0, tau);
+    Math3d::SetVec(v[5], one, 0, -tau);
+    Math3d::SetVec(v[6], -one, 0, -tau);
+    Math3d::SetVec(v[7], -one, 0, tau);
+    Math3d::SetVec(v[8], 0, tau, one);
+    Math3d::SetVec(v[9], 0, -tau, one);
+    Math3d::SetVec(v[10], 0, -tau, -one);
+    Math3d::SetVec(v[11], 0, tau, -one);
+
+    for (int i = 0 ; i < 12 ; i++)
+    {
+        m_Vertices.push_back(v[i]);
+    }
+
+
+    // Structure for unit icosahedron
+    Face f[20];
+    f[0].set(5,  8,  9);
+    f[1].set(5, 10,  8);
+    f[2].set(6, 12,  7);
+    f[3].set(6,  7, 11);
+    f[4].set(1,  4,  5);
+    f[5].set(1,  6,  4);
+    f[6].set(3,  2,  8);
+    f[7].set(3,  7,  2);
+    f[8].set(9, 12,  1);
+    f[9].set(9,  2, 12);
+    f[10].set(10,  4, 11);
+    f[11].set(10, 11, 3);
+    f[12].set(9,  1,  5);
+    f[13].set(12,  6,  1);
+    f[14].set(5,  4, 10);
+    f[15].set(6, 11,  4);
+    f[16].set(8,  2,  9);
+    f[17].set(7, 12,  2);
+    f[18].set(8, 10, 3);
+    f[19].set(7,  3, 11);
+
+    for (int i = 0 ; i < 20 ; i++)
+    {
+        f[i].m_n1--;
+        f[i].m_n2--;
+        f[i].m_n3--;
+        m_Faces.push_back(f[i]);
+    }
+}
+
+void CGraphGenerator::subDivide()
+{
+    // buffer new faces
+    vector<Face> faces;
+
+    // gp through all faces and subdivide
+    for (int f = 0 ; f < int(m_Faces.size()) ; f++)
+    {
+        // get the triangle vertex indices
+        int nA = m_Faces.at(f).m_n1;
+        int nB = m_Faces.at(f).m_n2;
+        int nC = m_Faces.at(f).m_n3;
+
+        // get the triangle vertex coordinates
+        Vec3d a = m_Vertices.at(nA);
+        Vec3d b = m_Vertices.at(nB);
+        Vec3d c = m_Vertices.at(nC);
+
+        // Now find the midpoints between vertices
+        Vec3d a_m, b_m, c_m;
+        Math3d::AddVecVec(a, b, a_m);
+        Math3d::MulVecScalar(a_m, 0.5, a_m);
+        Math3d::AddVecVec(b, c, b_m);
+        Math3d::MulVecScalar(b_m, 0.5, b_m);
+        Math3d::AddVecVec(c, a, c_m);
+        Math3d::MulVecScalar(c_m, 0.5, c_m);
+        /*      printf("a: %f,%f,%f\n", a.x,a.y,a.z);
+                printf("b: %f,%f,%f\n", b.x,b.y,b.z);
+                printf("c: %f,%f,%f\n", c.x,c.y,c.z);
+
+                printf("a<->b: %f,%f,%f\n", a_m.x,a_m.y,a_m.z);
+                printf("b<->c: %f,%f,%f\n", b_m.x,b_m.y,b_m.z);
+                printf("c<->a: %f,%f,%f\n", c_m.x,c_m.y,c_m.z);*/
+
+        // add vertices
+        int nA_m, nB_m, nC_m;
+
+        int nIndex;
+        nIndex = findVertex(a_m, 0.01);
+
+        if (nIndex == -1)
+        {
+            m_Vertices.push_back(a_m);
+            nA_m = m_Vertices.size() - 1;
+        }
+        else
+        {
+            nA_m = nIndex;
+        }
+
+        nIndex = findVertex(b_m, 0.01);
+
+        if (nIndex == -1)
+        {
+            m_Vertices.push_back(b_m);
+            nB_m = m_Vertices.size() - 1;
+        }
+        else
+        {
+            nB_m = nIndex;
+        }
+
+        nIndex = findVertex(c_m, 0.01);
+
+        if (nIndex == -1)
+        {
+            m_Vertices.push_back(c_m);
+            nC_m = m_Vertices.size() - 1;
+        }
+        else
+        {
+            nC_m = nIndex;
+        }
+
+        // Create new faces with orig vertices plus midpoints
+        Face f[4];
+        f[0].set(nA, nA_m, nC_m);
+        f[1].set(nA_m, nB, nB_m);
+        f[2].set(nC_m, nB_m, nC);
+        f[3].set(nA_m, nB_m, nC_m);
+
+        for (int i = 0 ; i < 4 ; i++)
+        {
+            faces.push_back(f[i]);
+        }
+    }
+
+    // assign new faces
+    m_Faces = faces;
+}
+
+void CGraphGenerator::projectToSphere(float fRadius)
+{
+    TSphereCoord coord;
+    Vec3d point;
+    coord.fDistance = 1.0f;
+
+    for (int v = 0 ; v < int(m_Vertices.size()) ; v++)
+    {
+        float X = m_Vertices.at(v).x;
+        float Y = m_Vertices.at(v).y;
+        float Z = m_Vertices.at(v).z;
+
+        float x, y, z;
+
+        // Convert Cartesian X,Y,Z to spherical (radians)
+        float theta = atan2(Y, X);
+        float phi   = atan2(sqrt(X * X + Y * Y), Z);
+
+        // Recalculate X,Y,Z for constant r, given theta & phi.
+        x = fRadius * sin(phi) * cos(theta);
+        y = fRadius * sin(phi) * sin(theta);
+        z = fRadius * cos(phi);
+
+        m_Vertices.at(v).x = x;
+        m_Vertices.at(v).y = y;
+        m_Vertices.at(v).z = z;
+    }
+}
+
+void CGraphGenerator::buildNodesAndEdges(CSphericalGraph* pGraph)
+{
+    // add nodes
+    TSphereCoord coord;
+
+    for (int v = 0 ; v < int(m_Vertices.size()) ; v++)
+    {
+        //      printf("Vertex: %f,%f,%f\n", m_Vertices.at(v).x, m_Vertices.at(v).y, m_Vertices.at(v).z);
+        MathTools::convert(m_Vertices.at(v), coord);
+        CSGNode* pNode = pGraph->getNewNode();
+        pNode->setPosition(coord);
+        pGraph->addNode(pNode);
+    }
+
+    // add edges
+    // go through all faces (assumes check for duplicate edges in spherical graph!?)
+    for (int f = 0 ; f < int(m_Faces.size()) ; f++)
+    {
+        //      printf(" %d,%d,%d\n", m_Faces.at(f).m_n1, m_Faces.at(f).m_n2, m_Faces.at(f).m_n3);
+        pGraph->addEdge(m_Faces.at(f).m_n1, m_Faces.at(f).m_n2);
+        pGraph->addEdge(m_Faces.at(f).m_n2, m_Faces.at(f).m_n3);
+        pGraph->addEdge(m_Faces.at(f).m_n3, m_Faces.at(f).m_n1);
+    }
+}
+
+int CGraphGenerator::findVertex(Vec3d position, float fEpsilon)
+{
+    float fDistance;
+    float fMinDistance = FLT_MAX;
+    int nIndex = -1;
+
+    for (int v = 0 ; v < int(m_Vertices.size()) ; v++)
+    {
+        fDistance = Math3d::Angle(position, m_Vertices.at(v));
+
+        if (fDistance < fMinDistance)
+        {
+            fMinDistance = fDistance;
+            nIndex = v;
+        }
+    }
+
+    if (fMinDistance > fEpsilon)
+    {
+        nIndex = -1;
+    }
+
+    return nIndex;
+}
+
diff --git a/source/RobotAPI/components/EarlyVisionGraph/GraphGenerator.h b/source/RobotAPI/components/EarlyVisionGraph/GraphGenerator.h
new file mode 100644
index 000000000..7904916da
--- /dev/null
+++ b/source/RobotAPI/components/EarlyVisionGraph/GraphGenerator.h
@@ -0,0 +1,85 @@
+// *****************************************************************
+// Filename:    GraphGenerator.h
+// Copyright:   Kai Welke, Chair Prof. Dillmann (IAIM),
+//              Institute for Computer Science and Engineering (CSE),
+//              University of Karlsruhe. All rights reserved.
+// Author:      Kai Welke
+// Date:        08.07.2008
+// *****************************************************************
+
+#ifndef _GRAPH_GENERATOR_H_
+#define _GRAPH_GENERATOR_H_
+
+// *****************************************************************
+// includes
+// *****************************************************************
+#include "Base/DataStructures/Graph/SphericalGraph.h"
+#include "Base/Math/MathTools.h"
+#include "Math/Math3d.h"
+#include <vector>
+#include <float.h>
+
+using namespace std;
+
+// *****************************************************************
+// enums
+// *****************************************************************
+enum EPolyhedronType
+{
+    eTetrahedron,
+    eOctahedron,
+    eIcosahedron
+};
+
+// *****************************************************************
+// implementation of class Face
+// *****************************************************************
+class Face
+{
+public:
+    Face() {};
+    Face(int n1, int n2, int n3)
+    {
+        set(n1, n2, n3);
+    };
+    ~Face() {};
+
+    void set(int n1, int n2, int n3)
+    {
+        m_n1 = n1;
+        m_n2 = n2 ;
+        m_n3 = n3;
+    };
+
+    int m_n1;
+    int m_n2;
+    int m_n3;
+};
+
+// *****************************************************************
+// implementation of CGraphGenerator
+// *****************************************************************
+class CGraphGenerator
+{
+public:
+    static void generateGraph(CSphericalGraph* pPlainGraph, EPolyhedronType nBaseType, int nLevels, float fRadius);
+
+private:
+    static void initBasePolyhedron(EPolyhedronType nBaseType);
+    static void generateTetrahedron();
+    static void generateOctahedron();
+    static void generateIcosahedron();
+    static void subDivide();
+    static void projectToSphere(float fRadius);
+    static void buildNodesAndEdges(CSphericalGraph* pGraph);
+    static int findVertex(Vec3d position, float fEpsilon);
+
+private:
+    CGraphGenerator() {};
+    ~CGraphGenerator() {};
+
+    static vector<Vec3d>    m_Vertices;
+    static vector<Face> m_Faces;
+};
+
+#endif /* _GRAPH_GENERATOR_H_ */
diff --git a/source/RobotAPI/components/EarlyVisionGraph/GraphLookupTable.cpp b/source/RobotAPI/components/EarlyVisionGraph/GraphLookupTable.cpp
new file mode 100644
index 000000000..a6e856c56
--- /dev/null
+++ b/source/RobotAPI/components/EarlyVisionGraph/GraphLookupTable.cpp
@@ -0,0 +1,238 @@
+// *****************************************************************
+// Filename:    GraphLookupTable.cpp
+// Copyright:   Kai Welke, Chair Prof. Dillmann (IAIM),
+//              Institute for Computer Science and Engineering (CSE),
+//              University of Karlsruhe. All rights reserved.
+// Author:      Kai Welke
+// Date:        10.10.2008
+// *****************************************************************
+
+// *****************************************************************
+// includes
+// *****************************************************************
+#include "GraphLookupTable.h"
+#include "MathTools.h"
+#include <float.h>
+
+// *****************************************************************
+// implementation of CGraphLookupTable
+// *****************************************************************
+// construction / destruction
+CGraphLookupTable::CGraphLookupTable(int nMaxZenithBins, int nMaxAzimuthBins)
+{
+    m_nMaxZenithBins = nMaxZenithBins;
+    m_nMaxAzimuthBins = nMaxAzimuthBins;
+
+    buildMemory();
+}
+
+CGraphLookupTable::~CGraphLookupTable()
+{
+    cleanMemory();
+}
+
+void CGraphLookupTable::buildLookupTable(CSphericalGraph* pGraph)
+{
+    reset();
+
+    TNodeList* pNodes = pGraph->getNodes();
+    int nSize = pNodes->size();
+
+    for (int n = 0 ; n < nSize ; n++)
+    {
+        CSGNode* pNode = pNodes->at(n);
+        addEntry(pNode->getPosition(), n);
+    }
+
+    m_pGraph = pGraph;
+}
+
+int CGraphLookupTable::getClosestNode(TSphereCoord position)
+{
+    bool bExact;
+    return getClosestNode(position, bExact);
+}
+
+int CGraphLookupTable::getClosestNode(Eigen::Vector3d position)
+{
+    bool bExact;
+    return getClosestNode(position, bExact);
+}
+
+int CGraphLookupTable::getClosestNode(Eigen::Vector3d position, bool& bExact)
+{
+    TSphereCoord coords;
+    MathTools::convert(position, coords);
+
+    return getClosestNode(coords, bExact);
+}
+
+
+int CGraphLookupTable::getClosestNode(TSphereCoord position, bool& bExact)
+{
+    int nIndex1, nIndex2;
+    nIndex1 = getZenithBinIndex(position.fPhi);
+    nIndex2 = getAzimuthBinIndex(position.fTheta, position.fPhi);
+
+    list<int>::iterator iter = m_ppTable[nIndex1][nIndex2].begin();
+
+    float fMinDistance = FLT_MAX;
+    int nBestIndex = -1;
+    float fDistance;
+
+    while (iter != m_ppTable[nIndex1][nIndex2].end())
+    {
+        fDistance = MathTools::getDistanceOnArc(position, m_pGraph->getNode(*iter)->getPosition());
+
+        if (fDistance < fMinDistance)
+        {
+            fMinDistance = fDistance;
+            nBestIndex = *iter;
+        }
+
+        iter++;
+    }
+
+    // retrieve distance to bounding
+    float fMinPhi, fMaxPhi, fMinTheta, fMaxTheta;
+
+    float fTestValues[4];
+    //  printf("Current position: phi %f, theta %f\n", position.fPhi, position.fTheta);
+
+    getBinMinMaxValues(nIndex1, nIndex2, fMinPhi, fMaxPhi, fMinTheta, fMaxTheta);
+    //  printf("B Phi: %f - %f\n", fMinPhi, fMaxPhi);
+    //  printf("B Theta: %f - %f\n", fMinTheta, fMaxTheta);
+
+    fTestValues[0] = fabs(fMinPhi - position.fPhi) * M_PI / 180.0f;
+    fTestValues[1] = fabs(fMaxPhi - position.fPhi) * M_PI / 180.0f;
+    fTestValues[2] = fabs(fMinTheta - position.fTheta) * M_PI / 180.0f;
+    fTestValues[3] = fabs(fMaxTheta - position.fTheta) * M_PI / 180.0f;
+    bExact = true;
+
+    //  printf("AzimuthDistance (min,max,current): (%f,%f,%f)\n", fTestValues[2], fTestValues[3], fMinDistance);
+    //  printf("ZenithDistance (min,max,current): (%f,%f,%f)\n", fTestValues[0], fTestValues[1], fMinDistance);
+
+    for (int i = 0 ; i < 4 ; i++)
+    {
+        if (fTestValues[i] < fMinDistance)
+        {
+            bExact = false;
+        }
+    }
+
+    return nBestIndex;
+}
+
+void CGraphLookupTable::reset()
+{
+    float fZenith;
+
+    for (int z = 0 ; z < getNumberZenithBins() ; z++)
+    {
+        fZenith = 180.0f / m_nMaxZenithBins * z;
+
+        for (int a = 0 ; a < getNumberAzimuthBins(fZenith) ; a++)
+        {
+            m_ppTable[z][a].clear();
+        }
+    }
+}
+
+// *****************************************************************
+// private methods
+// *****************************************************************
+void CGraphLookupTable::addEntry(TSphereCoord position, int nIndex)
+{
+    int nIndex1, nIndex2;
+    nIndex1 = getZenithBinIndex(position.fPhi);
+    nIndex2 = getAzimuthBinIndex(position.fTheta, position.fPhi);
+
+    m_ppTable[nIndex1][nIndex2].push_back(nIndex);
+}
+
+void CGraphLookupTable::buildMemory()
+{
+    float fZenith;
+
+    m_ppTable = new list<int>* [m_nMaxZenithBins];
+
+    for (int z = 0 ; z < m_nMaxZenithBins ; z++)
+    {
+        fZenith = 180.0f / m_nMaxZenithBins * z;
+        m_ppTable[z] = new list<int>[getNumberAzimuthBins(fZenith)];
+    }
+}
+
+void CGraphLookupTable::cleanMemory()
+{
+    for (int z = 0 ; z < m_nMaxZenithBins ; z++)
+    {
+        delete [] m_ppTable[z];
+    }
+
+    delete [] m_ppTable;
+}
+
+int CGraphLookupTable::getNumberZenithBins()
+{
+    return m_nMaxZenithBins;
+}
+
+int CGraphLookupTable::getNumberAzimuthBins(float fZenith)
+{
+    int nZenithBin = getZenithBinIndex(fZenith);
+
+    // 0 degree means 1 min bins
+    // 90 degree means max bins
+    int nMinBins = 1;
+    float fNumberBins;
+
+    if (getNumberZenithBins() > 1)
+    {
+        fNumberBins = sin(float(nZenithBin) / (getNumberZenithBins() - 1)  * M_PI) * (m_nMaxAzimuthBins - nMinBins) + nMinBins;
+    }
+    else
+    {
+        fNumberBins = 0.5f;
+    }
+
+    return int(fNumberBins + 0.5f);
+}
+
+int CGraphLookupTable::getAzimuthBinIndex(float fAzimuth, float fZenith)
+{
+    float fBinIndex = fAzimuth / 360.0f * (getNumberAzimuthBins(fZenith) - 1) + 0.5f;
+    return int(fBinIndex);
+}
+
+int CGraphLookupTable::getZenithBinIndex(float fZenith)
+{
+    float fBinIndex = fZenith / 180.0f * (m_nMaxZenithBins - 1) + 0.5f;
+    return int(fBinIndex);
+}
+
+void CGraphLookupTable::getBinMinMaxValues(int nZenithBinIndex, int nAzimuthBinIndex, float& fMinZenith, float& fMaxZenith, float& fMinAzimuth, float& fMaxAzimuth)
+{
+    if ((m_nMaxZenithBins - 1) == 0)
+    {
+        fMinZenith = -FLT_MAX;
+        fMaxZenith = FLT_MAX;
+    }
+    else
+    {
+        fMinZenith = (nZenithBinIndex - 0.5f) * 180.0f / (m_nMaxZenithBins - 1);
+        fMaxZenith = (nZenithBinIndex + 0.5f) * 180.0f / (m_nMaxZenithBins - 1);
+    }
+
+    if ((getNumberAzimuthBins((fMinZenith + fMaxZenith) / 2.0f) - 1) == 0)
+    {
+        fMinAzimuth = -FLT_MAX;
+        fMaxAzimuth = FLT_MAX;
+    }
+    else
+    {
+        fMinAzimuth = (nAzimuthBinIndex - 0.5f) * 360.0f / (getNumberAzimuthBins((fMinZenith + fMaxZenith) / 2.0f) - 1);
+        fMaxAzimuth = (nAzimuthBinIndex + 0.5f) * 360.0f / (getNumberAzimuthBins((fMinZenith + fMaxZenith) / 2.0f) - 1);
+    }
+}
+
diff --git a/source/RobotAPI/components/EarlyVisionGraph/GraphLookupTable.h b/source/RobotAPI/components/EarlyVisionGraph/GraphLookupTable.h
new file mode 100644
index 000000000..b97a195b3
--- /dev/null
+++ b/source/RobotAPI/components/EarlyVisionGraph/GraphLookupTable.h
@@ -0,0 +1,65 @@
+// *****************************************************************
+// Filename:    GraphLookupTable.h
+// Copyright:   Kai Welke, Chair Prof. Dillmann (IAIM),
+//              Institute for Computer Science and Engineering (CSE),
+//              University of Karlsruhe. All rights reserved.
+// Author:      Kai Welke
+// Date:        10.10.2008
+// *****************************************************************
+
+#ifndef _GRAPH_LOOKUP_TABLE_H_
+#define _GRAPH_LOOKUP_TABLE_H_
+
+// *****************************************************************
+// includes
+// *****************************************************************
+#include "SphericalGraph.h"
+#include <list>
+
+// *****************************************************************
+// namespace
+// *****************************************************************
+using namespace std;
+
+// *****************************************************************
+// decleration of CGraphLookupTable
+// *****************************************************************
+class CGraphLookupTable
+{
+public:
+    // construction / destruction
+    CGraphLookupTable(int nMaxZenithBins, int nMaxAzimuthBins);
+    ~CGraphLookupTable();
+
+    // build table
+    void buildLookupTable(CSphericalGraph* pGraph);
+
+    // operation
+    int getClosestNode(Eigen::Vector3d position);
+    int getClosestNode(TSphereCoord position);
+    int getClosestNode(Eigen::Vector3d position, bool& bExact);
+    int getClosestNode(TSphereCoord position, bool& bExact);
+
+private:
+    void buildMemory();
+    void cleanMemory();
+    void addEntry(TSphereCoord position, int nIndex);
+    void reset();
+
+    int getNumberZenithBins();
+    int getNumberAzimuthBins(float fZenith);
+    int getAzimuthBinIndex(float fAzimuth, float fZenith);
+    int getZenithBinIndex(float fZenith);
+
+    void getBinMinMaxValues(int nZenithBinIndex, int nAzimuthBinIndex, float& fMinZenith, float& fMaxZenith, float& fMinAzimuth, float& fMaxAzimuth);
+
+    int         m_nMaxZenithBins;
+    int         m_nMaxAzimuthBins;
+
+    list<int>**     m_ppTable;
+
+    CSphericalGraph*    m_pGraph;
+};
+
+
+#endif /* _GRAPH_LOOKUP_TABLE_H_ */
diff --git a/source/RobotAPI/components/EarlyVisionGraph/GraphMap.cpp b/source/RobotAPI/components/EarlyVisionGraph/GraphMap.cpp
new file mode 100644
index 000000000..deaeab33e
--- /dev/null
+++ b/source/RobotAPI/components/EarlyVisionGraph/GraphMap.cpp
@@ -0,0 +1,262 @@
+// *****************************************************************
+// Filename:    GraphMap.cpp
+// Copyright:   Kai Welke, Chair Prof. Dillmann (IAIM),
+//              Institute for Computer Science and Engineering (CSE),
+//              University of Karlsruhe. All rights reserved.
+// Author:      Kai Welke
+// Date:        9.08.2007
+// *****************************************************************
+
+// *****************************************************************
+// includes
+// *****************************************************************
+#include "GraphMap.h"
+#include "Base/Math/MathTools.h"
+#include "Base/DataStructures/Graph/GraphProcessor.h"
+#include <list>
+#include "Helpers/helpers.h"
+
+using namespace std;
+
+// *****************************************************************
+// implementation of CGraphMap
+// *****************************************************************
+// construction / destruction
+CGraphMap::CGraphMap(CIntensityGraph* pGraph, bool bUseLookup)
+{
+    m_pGraph = pGraph;
+    m_nNumberNodes = pGraph->getNodes()->size();
+
+    m_nWidth = (int) sqrt(float(m_nNumberNodes));
+    m_nHeight = m_nNumberNodes / m_nWidth + 1;
+
+    m_bUseLookup = bUseLookup;
+
+    // init lookup table
+    if (m_bUseLookup)
+    {
+        m_pLookupTable = new CGraphPyramidLookupTable(100, 100);
+        m_pLookupTable->buildLookupTable(pGraph);
+    }
+
+    // create float matrix
+    m_pMap = new CFloatMatrix(m_nWidth, m_nHeight);
+    m_bOwnMemory = true;
+    toMap();
+}
+
+CGraphMap::~CGraphMap()
+{
+    if (m_bOwnMemory)
+    {
+        delete m_pMap;
+    }
+
+    if (m_bUseLookup)
+    {
+        delete m_pLookupTable;
+    }
+}
+
+void CGraphMap::setMap(CFloatMatrix* pMap, bool bUpdateGraph)
+{
+    if (m_bOwnMemory)
+    {
+        delete m_pMap;
+    }
+
+    m_bOwnMemory = false;
+
+    m_pMap = pMap;
+    m_nWidth = pMap->columns;
+    m_nHeight = pMap->rows;
+
+    if (bUpdateGraph)
+    {
+        toGraph();
+    }
+}
+
+CFloatMatrix* CGraphMap::getMap()
+{
+    return m_pMap;
+}
+
+int CGraphMap::getWidth()
+{
+    return m_nWidth;
+}
+
+int CGraphMap::getHeight()
+{
+    return m_nHeight;
+}
+
+// manipulation
+void CGraphMap::applyGaussian(EOperation nOperation, Vec3d position, float fAmplitude, float fVariance)
+{
+    TSphereCoord coord;
+    MathTools::convert(position, coord);
+
+    applyGaussian(nOperation, coord, fAmplitude, fVariance);
+}
+
+void CGraphMap::applyGaussian(EOperation nOperation, TSphereCoord coord, float fAmplitude, float fVariance)
+{
+    int nNodeID = 0;
+
+    if (m_bUseLookup)
+    {
+        nNodeID = m_pLookupTable->getClosestNode(coord);
+    }
+    else
+    {
+        nNodeID = GraphProcessor::findClosestNode(m_pGraph, coord);
+    }
+
+    applyGaussian(nOperation, nNodeID, fAmplitude, fVariance);
+}
+
+void CGraphMap::applyGaussian(EOperation nOperation, int nNodeID, float fAmplitude, float fVariance)
+{
+    list<int> nodes;
+    vector<int> accomplished;
+
+    // store initial node
+    int nFirstNode = nNodeID;
+    TSphereCoord coord = m_pGraph->getNodes()->at(nFirstNode)->getPosition();
+    nodes.push_back(nFirstNode);
+
+    // eat nodelist
+    TSphereCoord cur_sc;
+    Vec3d ref, cur;
+    MathTools::convert(coord, ref);
+    float fIntensity;
+
+    while (nodes.size() > 0)
+    {
+        // retrieve first node
+        int nCurrentNode = nodes.front();
+        nodes.pop_front();
+        accomplished.push_back(nCurrentNode);
+
+        // calculate angle
+        cur_sc = m_pGraph->getNodes()->at(nCurrentNode)->getPosition();
+        MathTools::convert(cur_sc, cur);
+        float fAngle = Math3d::Angle(ref, cur);
+
+        // check if maximum angle
+        if (fAngle > 2.0 * fVariance)
+        {
+            continue;
+        }
+
+        // evaluate gaussian at angle
+        fIntensity = evaluateGaussian(fAngle, fAmplitude, fVariance);
+
+        // update graph and map
+        switch (nOperation)
+        {
+            case eSet:
+                m_pMap->data[nCurrentNode] = fIntensity;
+                break;
+
+            case eAdd:
+                m_pMap->data[nCurrentNode] += fIntensity;
+                break;
+
+            case eMultiply:
+                m_pMap->data[nCurrentNode] *= fIntensity;
+                break;
+
+            case eMax:
+                if (m_pMap->data[nCurrentNode] < fIntensity)
+                {
+                    m_pMap->data[nCurrentNode] = fIntensity;
+                }
+
+                break;
+
+            default:
+                printf("Illegal operation\n");
+                break;
+        }
+
+        // add neighbours to nodelist
+        vector<int>* pAdjacency =  m_pGraph->getNodeAdjacency(nCurrentNode);
+
+        // check for double nodes
+        int nAdjNode;
+
+        for (int a = 0 ; a < int(pAdjacency->size()) ; a++)
+        {
+            nAdjNode = pAdjacency->at(a);
+
+            // check if we already processed this node
+            bool bNewNode = true;
+
+            for (int c = 0 ; c < int(accomplished.size()) ; c++)
+                if (accomplished.at(c) == nAdjNode)
+                {
+                    bNewNode = false;
+                }
+
+            list<int>::iterator iter = nodes.begin();
+
+            while (iter != nodes.end())
+            {
+                if (*iter == nAdjNode)
+                {
+                    bNewNode = false;
+                }
+
+                iter++;
+            }
+
+
+            if (bNewNode)
+            {
+                nodes.push_back(nAdjNode);
+            }
+        }
+    }
+}
+
+void CGraphMap::updateGraph()
+{
+    toGraph();
+}
+
+void CGraphMap::updateMap()
+{
+    toMap();
+}
+
+float CGraphMap::evaluateGaussian(float fDist, float fAmplitude, float fVariance)
+{
+    return exp(- (fDist / fVariance * 2.0f)) * fAmplitude;
+}
+
+void CGraphMap::toGraph()
+{
+    float fIntensity;
+
+    for (int n = 0 ; n < m_nNumberNodes ; n++)
+    {
+        fIntensity = m_pMap->data[n];
+        ((CIntensityNode*) m_pGraph->getNodes()->at(n))->setIntensity(fIntensity);
+    }
+}
+
+void CGraphMap::toMap()
+{
+    float fIntensity;
+
+    for (int n = 0 ; n < m_nNumberNodes ; n++)
+    {
+        fIntensity = ((CIntensityNode*) m_pGraph->getNodes()->at(n))->getIntensity();
+        m_pMap->data[n] = fIntensity;
+    }
+}
+
+
diff --git a/source/RobotAPI/components/EarlyVisionGraph/GraphMap.h b/source/RobotAPI/components/EarlyVisionGraph/GraphMap.h
new file mode 100644
index 000000000..e8533388a
--- /dev/null
+++ b/source/RobotAPI/components/EarlyVisionGraph/GraphMap.h
@@ -0,0 +1,74 @@
+// *****************************************************************
+// Filename:    GraphMap.h
+// Copyright:   Kai Welke, Chair Prof. Dillmann (IAIM),
+//              Institute for Computer Science and Engineering (CSE),
+//              University of Karlsruhe. All rights reserved.
+// Author:      Kai Welke
+// Date:        12.06.2007
+// *****************************************************************
+
+#ifndef _GRAPH_MAP_H_
+#define _GRAPH_MAP_H_
+
+// *****************************************************************
+// includes
+// *****************************************************************
+#include "Base/DataStructures/Graph/IntensityGraph.h"
+#include "Base/DataStructures/Graph/GraphPyramidLookupTable.h"
+#include "Math/FloatMatrix.h"
+
+// *****************************************************************
+// enums
+// *****************************************************************
+enum EOperation
+{
+    eSet,
+    eAdd,
+    eMultiply,
+    eMax
+};
+
+// *****************************************************************
+// decleration of CGraphMap
+// *****************************************************************
+class CGraphMap
+{
+public:
+    // construction / destruction
+    CGraphMap(CIntensityGraph* pGraph, bool bUseLookup = false);
+    ~CGraphMap();
+
+    // getter / setter
+    void setMap(CFloatMatrix* pMap, bool bUpdateGraph = true);
+    CFloatMatrix* getMap();
+    int getWidth();
+    int getHeight();
+
+    // manipulation
+    void applyGaussian(EOperation nOperation, Vec3d position, float fAmplitude, float fVariance);
+    void applyGaussian(EOperation nOperation, TSphereCoord coord, float fAmplitude, float fVariance);
+    void applyGaussian(EOperation nOperation, int nNodeID, float fAmplitude, float fVariance);
+
+    // update
+    void updateGraph();
+    void updateMap();
+
+private:
+    float evaluateGaussian(float fDist, float fAmplitude, float fVariance);
+    void toGraph(); // update intensitygraph
+    void toMap();   // update intensitymap
+
+    CSphericalGraph*    m_pGraph;
+    int         m_nNumberNodes;
+    CFloatMatrix*       m_pMap;
+    bool            m_bOwnMemory;
+
+    int             m_nWidth;
+    int             m_nHeight;
+
+    bool            m_bUseLookup;
+    CGraphPyramidLookupTable*   m_pLookupTable;
+};
+
+
+#endif /* _GRAPH_MAP_H_ */
diff --git a/source/RobotAPI/components/EarlyVisionGraph/GraphProcessor.cpp b/source/RobotAPI/components/EarlyVisionGraph/GraphProcessor.cpp
new file mode 100644
index 000000000..c5faffd65
--- /dev/null
+++ b/source/RobotAPI/components/EarlyVisionGraph/GraphProcessor.cpp
@@ -0,0 +1,307 @@
+// *****************************************************************
+// Filename:    GraphProcessor.cpp
+// Copyright:   Kai Welke, Chair Prof. Dillmann (IAIM),
+//              Institute for Computer Science and Engineering (CSE),
+//              University of Karlsruhe. All rights reserved.
+// Author:      Kai Welke
+// Date:        12.06.2007
+// *****************************************************************
+
+
+// *****************************************************************
+// includes
+// *****************************************************************
+// system
+#include <math.h>
+#include <float.h>
+
+// local includes
+#include "GraphProcessor.h"
+#include "Base/Math/MathTools.h"
+#include "Base/Tools/DebugMemory.h"
+
+void GraphProcessor::transform(CSphericalGraph* pGraph, TTransform transform)
+{
+    TNodeList* pNodes = pGraph->getNodes();
+
+    TSphereCoord position, position_tr;
+
+    for (int n = 0 ; n < int(pNodes->size()) ; n++)
+    {
+        CSGNode* pNode = pNodes->at(n);
+        position = pNode->getPosition();
+        position_tr = MathTools::transform(position, transform);
+        pNode->setPosition(position_tr);
+    }
+}
+
+void GraphProcessor::inverseTransform(CSphericalGraph* pGraph, TTransform transform)
+{
+    TNodeList* pNodes = pGraph->getNodes();
+
+    TSphereCoord position, position_tr;
+
+    for (int n = 0 ; n < int(pNodes->size()) ; n++)
+    {
+        CSGNode* pNode = pNodes->at(n);
+        position = pNode->getPosition();
+        position_tr = MathTools::inverseTransform(position, transform);
+        pNode->setPosition(position_tr);
+    }
+}
+
+void GraphProcessor::invertPhi(CSphericalGraph* pGraph)
+{
+    TNodeList* pNodes = pGraph->getNodes();
+
+    TSphereCoord position;
+
+    for (int n = 0 ; n < int(pNodes->size()) ; n++)
+    {
+        CSGNode* pNode = pNodes->at(n);
+        position = pNode->getPosition();
+        position.fPhi = 360.0f - position.fPhi;
+        pNode->setPosition(position);
+    }
+}
+
+void GraphProcessor::invertTheta(CSphericalGraph* pGraph)
+{
+    TNodeList* pNodes = pGraph->getNodes();
+
+    TSphereCoord position;
+
+    for (int n = 0 ; n < int(pNodes->size()) ; n++)
+    {
+        CSGNode* pNode = pNodes->at(n);
+        position = pNode->getPosition();
+        position.fTheta = 180.0f - position.fTheta;
+        pNode->setPosition(position);
+    }
+}
+
+void GraphProcessor::copyGraphNodesAndEdges(CSphericalGraph* pSrcGraph, CSphericalGraph* pDstGraph)
+{
+    pDstGraph->clear();
+
+    TNodeList* pNodes = pSrcGraph->getNodes();
+    TEdgeList* pEdges = pSrcGraph->getEdges();
+
+    for (int n = 0 ; n < int(pNodes->size()) ; n++)
+    {
+        CSGNode* pNode = pNodes->at(n);
+        CSGNode* pNewNode = pDstGraph->getNewNode();
+        pNewNode->setPosition(pNode->getPosition());
+        pDstGraph->addNode(pNewNode);
+    }
+
+    for (int e = 0 ; e < int(pEdges->size()) ; e++)
+    {
+        CSGEdge* pEdge = pEdges->at(e);
+        pDstGraph->addEdge(pEdge->nIndex1, pEdge->nIndex2, pEdge->nLeftFace, pEdge->nRightFace);
+    }
+}
+
+int GraphProcessor::findClosestNode(CSphericalGraph* pGraph, TSphereCoord coord)
+{
+    TNodeList* pNodes = pGraph->getNodes();
+
+    float fMinDistance = FLT_MAX;
+    float fDistance = 0.0f;
+    int nIndex = -1;
+
+    for (int n = 0 ; n < int(pNodes->size()) ; n++)
+    {
+        CSGNode* pNode = pNodes->at(n);
+        fDistance = MathTools::getDistanceOnArc(pNode->getPosition(), coord);
+
+        if (fDistance < fMinDistance)
+        {
+            fMinDistance = fDistance;
+            nIndex = n;
+        }
+    }
+
+    return nIndex;
+}
+
+void GraphProcessor::findClosestNeighbours(CSphericalGraph* pGraph, int& s, int& t)
+{
+    TNodeList* pNodes = pGraph->getNodes();
+
+    float fMinDistance = FLT_MAX;
+    int nIndex1 = -1;
+    int nIndex2 = -1;
+    float fDistance;
+
+    for (int i = 0 ; i < int(pNodes->size()); i++)
+    {
+        for (int j = 0 ; j < int(pNodes->size()); j++)
+        {
+            if (i != j)
+            {
+                fDistance = MathTools::getDistanceOnArc(pNodes->at(i)->getPosition(), pNodes->at(j)->getPosition());
+
+                if (fDistance < fMinDistance)
+                {
+                    fMinDistance = fDistance;
+                    nIndex1 = i;
+                    nIndex2 = j;
+                }
+            }
+        }
+    }
+
+    s = nIndex1;
+    t = nIndex2;
+}
+
+int GraphProcessor::findEdge(CSphericalGraph* pGraph, int nIndex1, int nIndex2)
+{
+    TEdgeList* pEdges = pGraph->getEdges();
+
+    for (int e = 0 ; e < int(pEdges->size()) ; e++)
+    {
+        if ((pEdges->at(e)->nIndex1 == nIndex1) && (pEdges->at(e)->nIndex2 == nIndex2))
+        {
+            return e;
+        }
+
+        if ((pEdges->at(e)->nIndex1 == nIndex2) && (pEdges->at(e)->nIndex2 == nIndex1))
+        {
+            return e;
+        }
+    }
+
+    // not found
+    return -1;
+}
+
+bool GraphProcessor::insideCircumcircle(CSphericalGraph* pGraph, int nIndex1, int nIndex2, int nIndex3, int nPointIndex, bool& bInside)
+{
+    TNodeList* pNodes = pGraph->getNodes();
+
+    TSphereCoord center;
+    float fRadius;
+
+    if (!getCircumcircle(pGraph, nIndex1, nIndex2, nIndex3, center, fRadius))
+    {
+        return false;
+    }
+
+    TSphereCoord point = pNodes->at(nPointIndex)->getPosition();
+
+    // check with give coordinates
+    float fDistance = sqrt((center.fPhi - point.fPhi) * (center.fPhi - point.fPhi) + (center.fTheta - point.fTheta) * (center.fTheta - point.fTheta));
+
+    bInside = (fDistance < (fRadius + 0.0001));
+
+    return true;
+}
+
+bool GraphProcessor::getCircumcircle(CSphericalGraph* pGraph, int nIndex1, int nIndex2, int nIndex3, TSphereCoord& center, float& fRadius)
+{
+    TNodeList* pNodes = pGraph->getNodes();
+    float cp;
+
+    TSphereCoord s1, s2, s3;
+    s1 = pNodes->at(nIndex1)->getPosition();
+    s2 = pNodes->at(nIndex2)->getPosition();
+    s3 = pNodes->at(nIndex3)->getPosition();
+
+    cp = MathTools::CalculateCrossProductFromDifference(s1, s2, s3);
+
+    if (cp != 0.0)
+    {
+        float p1Sq, p2Sq, p3Sq;
+        float num;
+        float cx, cy;
+
+        p1Sq = s1.fPhi * s1.fPhi + s1.fTheta * s1.fTheta;
+        p2Sq = s2.fPhi * s2.fPhi  + s2.fTheta * s2.fTheta;
+        p3Sq = s3.fPhi * s3.fPhi  + s3.fTheta * s3.fTheta;
+
+        num = p1Sq * (s2.fTheta - s3.fTheta) + p2Sq * (s3.fTheta - s1.fTheta) + p3Sq * (s1.fTheta - s2.fTheta);
+        cx = num / (2.0f * cp);
+        num = p1Sq * (s3.fPhi - s2.fPhi) + p2Sq * (s1.fPhi - s3.fPhi) + p3Sq * (s2.fPhi - s1.fPhi);
+        cy = num / (2.0f * cp);
+
+        center.fPhi = cx;
+        center.fTheta = cy;
+
+        fRadius = sqrt((center.fPhi - s1.fPhi) * (center.fPhi - s1.fPhi) + (center.fTheta - s1.fTheta) * (center.fTheta - s1.fTheta)) ;
+        return true;
+    }
+    else
+    {
+        // points lie on a line
+        return false;
+    }
+}
+
+int GraphProcessor::getDelaunayNeighbour(CSphericalGraph* pGraph, CSGEdge* pEdge)
+{
+    TNodeList* pNodes = pGraph->getNodes();
+    float fMinRadius = FLT_MAX;
+    float fRadius;
+    int nIndex = -1;
+
+    // go through all points
+    for (int v = 0 ; v < int(pNodes->size()) ; v++)
+    {
+        if ((v == pEdge->nIndex1) || (v == pEdge->nIndex2))
+        {
+            continue;
+        }
+
+        // check if v is already connected to index1, index2
+        if (GraphProcessor::isEdgePresent(pGraph, pEdge->nIndex1, v))
+        {
+            continue;
+        }
+
+        if (GraphProcessor::isEdgePresent(pGraph, pEdge->nIndex2, v))
+        {
+            continue;
+        }
+
+        // check if v is an unconnected node
+        if (pGraph->getNodeAdjacency(v)->size() != 0)
+        {
+            continue;
+        }
+
+        TSphereCoord center;
+
+        getCircumcircle(pGraph, pEdge->nIndex1, pEdge->nIndex2, v, center, fRadius);
+
+        if (fRadius < fMinRadius)
+        {
+            fMinRadius = fRadius;
+            nIndex = v;
+        }
+    }
+
+    return nIndex;
+}
+
+bool GraphProcessor::isEdgePresent(CSphericalGraph* pGraph, int nIndex1, int nIndex2)
+{
+
+    bool bPresent = false;
+
+    vector<int>::iterator iter = pGraph->getNodeAdjacency(nIndex1)->begin();
+
+    while (iter != pGraph->getNodeAdjacency(nIndex1)->end())
+    {
+        if ((*iter) == nIndex2)
+        {
+            bPresent = true;
+        }
+
+        iter++;
+    }
+
+    return bPresent;
+}
+
diff --git a/source/RobotAPI/components/EarlyVisionGraph/GraphProcessor.h b/source/RobotAPI/components/EarlyVisionGraph/GraphProcessor.h
new file mode 100644
index 000000000..2a609783b
--- /dev/null
+++ b/source/RobotAPI/components/EarlyVisionGraph/GraphProcessor.h
@@ -0,0 +1,50 @@
+// *****************************************************************
+// Filename:    GraphProcessor.h
+// Copyright:   Kai Welke, Chair Prof. Dillmann (IAIM),
+//              Institute for Computer Science and Engineering (CSE),
+//              University of Karlsruhe. All rights reserved.
+// Author:      Kai Welke
+// Date:        12.06.2007
+// *****************************************************************
+
+#ifndef _GRAPH_PROCESSOR_H_
+#define _GRAPH_PROCESSOR_H_
+
+// *****************************************************************
+// forward declarations
+// *****************************************************************
+
+// *****************************************************************
+// includes
+// *****************************************************************
+#include "SphericalGraph.h"
+
+// *****************************************************************
+// namespace GraphProcessor
+// *****************************************************************
+namespace GraphProcessor
+{
+    // graph operations
+    void copyGraphNodesAndEdges(CSphericalGraph* pSrcGraph, CSphericalGraph* pDstGraph);
+
+    // graph coordinate transformations
+    void transform(CSphericalGraph* pGraph, TTransform transform);
+    void inverseTransform(CSphericalGraph* pGraph, TTransform transform);
+    void invertPhi(CSphericalGraph* pGraph);
+    void invertTheta(CSphericalGraph* pGraph);
+
+    // edge operations
+    int findEdge(CSphericalGraph* pGraph, int nIndex1, int nIndex2);
+    bool isEdgePresent(CSphericalGraph* pGraph, int nIndex1, int nIndex2);
+
+    // neighbour and node operations
+    int findClosestNode(CSphericalGraph* pGraph, TSphereCoord coord);
+    void findClosestNeighbours(CSphericalGraph* pGraph, int& s, int& t);
+    int getDelaunayNeighbour(CSphericalGraph* pGraph, CSGEdge* pEdge);
+
+    // circumcircle operations
+    bool insideCircumcircle(CSphericalGraph* pGraph, int nIndex1, int nIndex2, int nIndex3, int nPointIndex, bool& bInside);
+    bool getCircumcircle(CSphericalGraph* pGraph, int nIndex1, int nIndex2, int nIndex3, TSphereCoord& center, float& fRadius);
+};
+
+#endif /* _GRAPH_PROCESSOR_H_ */
diff --git a/source/RobotAPI/components/EarlyVisionGraph/GraphPyramidLookupTable.cpp b/source/RobotAPI/components/EarlyVisionGraph/GraphPyramidLookupTable.cpp
new file mode 100644
index 000000000..babc001fb
--- /dev/null
+++ b/source/RobotAPI/components/EarlyVisionGraph/GraphPyramidLookupTable.cpp
@@ -0,0 +1,108 @@
+// *****************************************************************
+// Filename:    GraphLookupTable.cpp
+// Copyright:   Kai Welke, Chair Prof. Dillmann (IAIM),
+//              Institute for Computer Science and Engineering (CSE),
+//              University of Karlsruhe. All rights reserved.
+// Author:      Kai Welke
+// Date:        10.10.2008
+// *****************************************************************
+
+// *****************************************************************
+// includes
+// *****************************************************************
+#include <cstdlib>
+#include "GraphPyramidLookupTable.h"
+#include "MathTools.h"
+
+// *****************************************************************
+// implementation of CGraphLookupTable
+// *****************************************************************
+// construction / destruction
+CGraphPyramidLookupTable::CGraphPyramidLookupTable(int nMaxZenithBins, int nMaxAzimuthBins)
+{
+    m_nMaxZenithBins = nMaxZenithBins;
+    m_nMaxAzimuthBins = nMaxAzimuthBins;
+
+    m_nSubDivision = 2;
+    m_nLevels = 0;
+
+    CGraphLookupTable* pTable;
+
+    while (nMaxZenithBins != 0)
+    {
+        pTable = new CGraphLookupTable(nMaxZenithBins, nMaxAzimuthBins);
+
+        m_Tables.push_back(pTable);
+
+        //      printf("Level %d: zenithbins: %d, azimuithbins: %d\n", m_nLevels, nMaxZenithBins, nMaxAzimuthBins);
+
+        m_nLevels++;
+        nMaxZenithBins /= m_nSubDivision;
+        nMaxAzimuthBins /= m_nSubDivision;
+    }
+
+}
+
+CGraphPyramidLookupTable::~CGraphPyramidLookupTable()
+{
+    list<CGraphLookupTable*>::iterator iter = m_Tables.begin();
+
+    while (iter != m_Tables.end())
+    {
+        delete *iter;
+
+        iter++;
+    }
+}
+
+void CGraphPyramidLookupTable::buildLookupTable(CSphericalGraph* pGraph)
+{
+    list<CGraphLookupTable*>::iterator iter = m_Tables.begin();
+
+    while (iter != m_Tables.end())
+    {
+        (*iter)->buildLookupTable(pGraph);
+
+        iter++;
+    }
+}
+
+int CGraphPyramidLookupTable::getClosestNode(Eigen::Vector3d position)
+{
+    TSphereCoord coords;
+    MathTools::convert(position, coords);
+
+    return getClosestNode(coords);
+}
+
+int CGraphPyramidLookupTable::getClosestNode(TSphereCoord position)
+{
+    bool bFinished = false;
+    list<CGraphLookupTable*>::iterator iter = m_Tables.begin();
+    int nIndex = -1;
+
+    int L = 0;
+
+    while (iter != m_Tables.end())
+    {
+        nIndex = (*iter)->getClosestNode(position, bFinished);
+        //      printf("Result in level %d: index %d, finished: %d\n",L,nIndex,bFinished);
+
+        if (bFinished)
+        {
+            break;
+        }
+
+        L++;
+        iter++;
+    }
+
+    if (!bFinished)
+    {
+        printf("CGraphPyramidLookupTable:: no closest node found\n");
+        exit(1);
+    }
+
+    return nIndex;
+}
+
diff --git a/source/RobotAPI/components/EarlyVisionGraph/GraphPyramidLookupTable.h b/source/RobotAPI/components/EarlyVisionGraph/GraphPyramidLookupTable.h
new file mode 100644
index 000000000..b871f1d0a
--- /dev/null
+++ b/source/RobotAPI/components/EarlyVisionGraph/GraphPyramidLookupTable.h
@@ -0,0 +1,52 @@
+// *****************************************************************
+// Filename:    GraphPyramidLookupTable.h
+// Copyright:   Kai Welke, Chair Prof. Dillmann (IAIM),
+//              Institute for Computer Science and Engineering (CSE),
+//              University of Karlsruhe. All rights reserved.
+// Author:      Kai Welke
+// Date:        10.10.2008
+// *****************************************************************
+
+#ifndef _GRAPH_PYRAMID_LOOKUP_TABLE_H_
+#define _GRAPH_PYRAMID_LOOKUP_TABLE_H_
+
+// *****************************************************************
+// includes
+// *****************************************************************
+#include "SphericalGraph.h"
+#include "GraphLookupTable.h"
+#include <list>
+
+// *****************************************************************
+// namespace
+// *****************************************************************
+using namespace std;
+
+// *****************************************************************
+// decleration of CGraphPyramidLookupTable
+// *****************************************************************
+class CGraphPyramidLookupTable
+{
+public:
+    // construction / destruction
+    CGraphPyramidLookupTable(int nMaxZenithBins, int nMaxAzimuthBins);
+    ~CGraphPyramidLookupTable();
+
+    // build table
+    void buildLookupTable(CSphericalGraph* pGraph);
+
+    // operation
+    int getClosestNode(Eigen::Vector3d position);
+    int getClosestNode(TSphereCoord position);
+
+private:
+    list<CGraphLookupTable*> m_Tables;
+    int         m_nSubDivision;
+    int         m_nLevels;
+
+    int         m_nMaxZenithBins;
+    int         m_nMaxAzimuthBins;
+};
+
+
+#endif /* _GRAPH_PYRAMID_LOOKUP_TABLE_H_ */
diff --git a/source/RobotAPI/components/EarlyVisionGraph/GraphTriangulation.cpp b/source/RobotAPI/components/EarlyVisionGraph/GraphTriangulation.cpp
new file mode 100644
index 000000000..495ebc843
--- /dev/null
+++ b/source/RobotAPI/components/EarlyVisionGraph/GraphTriangulation.cpp
@@ -0,0 +1,423 @@
+// *****************************************************************
+// Filename:    GraphProcessor.cpp
+// Copyright:   Kai Welke, Chair Prof. Dillmann (IAIM),
+//              Institute for Computer Science and Engineering (CSE),
+//              University of Karlsruhe. All rights reserved.
+// Author:      Kai Welke
+// Date:        12.06.2007
+// *****************************************************************
+
+
+// *****************************************************************
+// includes
+// *****************************************************************
+// local includes
+#include "GraphTriangulation.h"
+#include "GraphProcessor.h"
+#include "Base/Math/MathTools.h"
+#include "Base/Tools/DebugMemory.h"
+
+void GraphTriangulation::delaunayTriangulationQuadratic(CSphericalGraph* pGraph)
+{
+    TC3DNodeList* pC3DNodeList = new TC3DNodeList();
+    int nNodes = (int) pGraph->getNodes()->size();
+
+    for (int i = 0; i < nNodes; i++)
+    {
+        // project point to polar coordinates
+        Vec3d cartesian_point;
+        MathTools::convert(pGraph->getNode(i)->getPosition(), cartesian_point);
+
+        CC3DNode* pC3DNode = new CC3DNode(cartesian_point);
+        pC3DNodeList->push_back(pC3DNode);
+    }
+
+    // generate the delaunay triangulation by computing the
+    // convex hull of the sphere
+    CCHGiftWrap giftWrapping = CCHGiftWrap(pC3DNodeList);
+    CSphericalGraph* pCopy = new CSphericalGraph();
+    giftWrapping.generateConvexHull(pCopy);
+
+    // add edges from triangulated graph to pGraph
+    TEdgeList* pEdges = pCopy->getEdges();
+
+    for (int e = 0 ; e < pEdges->size() ; e++)
+    {
+        pGraph->addEdge(pEdges->at(e)->nIndex1, pEdges->at(e)->nIndex2);
+    }
+
+    delete pCopy;
+}
+
+
+void GraphTriangulation::triangulationQuadraticSpherical(CSphericalGraph* pGraph)
+{
+    int nNumberViews = (int) pGraph->getNodes()->size();
+
+    // create graph with nodes and nodes + 360
+    CSphericalGraph* pDoubleGraph = doubleNodes(pGraph);
+
+    // do triangulation on the double size graph
+    //triangulationQuadratic(pDoubleGraph);
+    triangulationQuartic(pDoubleGraph);
+
+    // insert detrmined edges in original graph
+    int nIndex1, nIndex2;
+    CSGEdge* pCurrentEdge;
+
+    for (int e = 0 ; e < int(pDoubleGraph->getEdges()->size()) ; e++)
+    {
+        pCurrentEdge = pDoubleGraph->getEdges()->at(e);
+        nIndex1 = pCurrentEdge->nIndex1;
+        nIndex2 = pCurrentEdge->nIndex2;
+
+        // HACK: delete outer edges
+        if ((pDoubleGraph->getNode(nIndex1)->getPosition().fTheta < 30.0) || (pDoubleGraph->getNode(nIndex1)->getPosition().fTheta > 690.0))
+        {
+            continue;
+        }
+
+        if ((pDoubleGraph->getNode(nIndex2)->getPosition().fTheta < 30.0) || (pDoubleGraph->getNode(nIndex2)->getPosition().fTheta > 690.0))
+        {
+            continue;
+        }
+
+        /*      if( (pDoubleGraph->getNode(nIndex1)->getPosition().fPhi < 30.0) || (pDoubleGraph->getNode(nIndex1)->getPosition().fPhi > 330.0))
+                    continue;
+                if( (pDoubleGraph->getNode(nIndex2)->getPosition().fPhi < 30.0) || (pDoubleGraph->getNode(nIndex2)->getPosition().fPhi > 330.0))
+                    continue;
+                if( (pDoubleGraph->getNode(nIndex1)->getPosition().fPhi < 180.0) && (pDoubleGraph->getNode(nIndex2)->getPosition().fPhi > 180.0))
+                    continue;
+                if( (pDoubleGraph->getNode(nIndex2)->getPosition().fPhi < 180.0) && (pDoubleGraph->getNode(nIndex1)->getPosition().fPhi > 180.0))
+                    continue;
+        */
+        // eliminate virtual nodes
+        if (nIndex1 >= nNumberViews)
+        {
+            nIndex1 %= nNumberViews;
+        }
+
+        if (nIndex2 >= nNumberViews)
+        {
+            nIndex2 %= nNumberViews;
+        }
+
+        // update graph
+        if (nIndex1 != nIndex2)
+            if (!GraphProcessor::isEdgePresent(pGraph, nIndex1, nIndex2))
+            {
+                pGraph->addEdge(nIndex1, nIndex2);
+            }
+    }
+
+    delete pDoubleGraph;
+}
+
+void GraphTriangulation::triangulationQuartic(CSphericalGraph* pGraph, float fThreshold)
+{
+    TNodeList* pNodes = pGraph->getNodes();
+
+    int     nNumberPoints = int(pNodes->size());
+    bool    bPointFree;
+    int     i, j, k, l;
+
+    for (i = 0 ; i < nNumberPoints - 2 ; i++)
+    {
+        printf("Round %d / %d\n", i, nNumberPoints - 2);
+
+        for (j = i + 1 ; j < nNumberPoints - 1  ; j++)
+        {
+            if (j != i)
+            {
+                for (k = j + 1; k < nNumberPoints; k++)
+                {
+                    if (k != i && k != j)
+                    {
+
+                        // check if this rectangle is point free
+                        bPointFree = true;
+
+                        for (l = 0; l < nNumberPoints ; l++)
+                        {
+                            // only if not one of the triangle points
+                            if (l != i && l != j && l != k)
+                            {
+                                bool bInside;
+
+                                if (!GraphProcessor::insideCircumcircle(pGraph, i, j, k, l, bInside))
+                                {
+                                    bPointFree = false;
+                                    break;
+                                }
+
+                                if (bInside)
+                                {
+                                    bPointFree = false;
+                                    break;
+                                }
+                            }
+                        }
+
+                        if (bPointFree)
+                        {
+                            TSphereCoord p_i, p_j, p_k;
+                            p_i = pNodes->at(i)->getPosition();
+                            p_j = pNodes->at(j)->getPosition();
+                            p_k = pNodes->at(k)->getPosition();
+
+                            // add triangle
+                            if (MathTools::getDistanceOnArc(p_i, p_j) < fThreshold)
+                            {
+                                pGraph->addEdge(i, j);
+                            }
+
+                            if (MathTools::getDistanceOnArc(p_i, p_k) < fThreshold)
+                            {
+                                pGraph->addEdge(i, k);
+                            }
+
+                            if (MathTools::getDistanceOnArc(p_k, p_j) < fThreshold)
+                            {
+                                pGraph->addEdge(k, j);
+                            }
+                        }
+
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+void GraphTriangulation::triangulationQuadratic(CSphericalGraph* pGraph)
+{
+    TEdgeList* pEdges = pGraph->getEdges();
+
+    int nCurrentEdge;
+    int nFaces = 0;
+    int s = 0, t = 0;
+
+    // find two closest neighbours and add edge to triangulation.
+    GraphProcessor::findClosestNeighbours(pGraph, s, t);
+
+    // Create seed edge
+    int nEdgeIndex = pGraph->addEdge(s , t , -1, -1);
+
+    nCurrentEdge = 0;
+
+    while (nCurrentEdge < int(pEdges->size()))
+    {
+        if (pEdges->at(nCurrentEdge)->nLeftFace == -1)
+        {
+            completeFacet(pGraph, nCurrentEdge, nFaces);
+        }
+
+        if (pEdges->at(nCurrentEdge)->nRightFace == -1)
+        {
+            completeFacet(pGraph, nCurrentEdge, nFaces);
+        }
+
+        nCurrentEdge++;
+    }
+}
+
+void GraphTriangulation::completeFacet(CSphericalGraph* pGraph, int nEdgeIndex, int nFaces)
+{
+    TNodeList* pNodes = pGraph->getNodes();
+    TEdgeList* pEdges = pGraph->getEdges();
+    int s, t, u;
+
+    // Cache s and t.
+    if (pEdges->at(nEdgeIndex)->nLeftFace == -1)
+    {
+        s = pEdges->at(nEdgeIndex)->nIndex1;
+        t = pEdges->at(nEdgeIndex)->nIndex2;
+    }
+    else if (pEdges->at(nEdgeIndex)->nRightFace == -1)
+    {
+        s = pEdges->at(nEdgeIndex)->nIndex2;
+        t = pEdges->at(nEdgeIndex)->nIndex1;
+    }
+    else
+    {
+        // Edge already completed.
+        return;
+    }
+
+
+    // Find a point on left of edge.
+    for (u = 0; u < int(pNodes->size()); u++)
+    {
+        if (u == s || u == t)
+        {
+            continue;
+        }
+
+        // check side
+        float fAngle = MathTools::CalculateCrossProductFromDifference(pNodes->at(s)->getPosition(), pNodes->at(t)->getPosition(), pNodes->at(u)->getPosition());
+
+        if (fAngle > 0.0)
+        {
+            break;
+        }
+    }
+
+    // Find best point on left of edge.
+    int nBestPoint = u;
+    float fCp;
+
+    if (nBestPoint < int(pNodes->size()))
+    {
+        TSphereCoord center;
+        float fRadius;
+        GraphProcessor::getCircumcircle(pGraph, s, t, nBestPoint, center, fRadius);
+
+        for (u = nBestPoint + 1; u < int(pNodes->size()); u++)
+        {
+            if (u == s || u == t)
+            {
+                continue;
+            }
+
+            fCp = MathTools::CalculateCrossProductFromDifference(pNodes->at(s)->getPosition(), pNodes->at(t)->getPosition(), pNodes->at(u)->getPosition());
+
+            if (fCp > 0.0)
+            {
+                bool bInside;
+
+                if (GraphProcessor::insideCircumcircle(pGraph, s, t, nBestPoint, u, bInside))
+                {
+                    if (bInside)
+                    {
+                        nBestPoint = u;
+                    }
+                }
+            }
+        }
+    }
+
+    // Add new triangle or update edge info if s-t is on hull.
+    if (nBestPoint < int(pNodes->size()))
+    {
+        // Update face information of edge being completed.
+        updateLeftFace(pGraph, nEdgeIndex, s, t, nFaces);
+        nFaces++;
+
+        // Add new edge or update face info of old edge.
+        nEdgeIndex = GraphProcessor::findEdge(pGraph, nBestPoint, s);
+
+        if (nEdgeIndex == -1)
+        {
+            // New edge.
+            nEdgeIndex = pGraph->addEdge(nBestPoint, s, nFaces, -1);
+        }
+        else
+        {
+            // Old edge.
+            updateLeftFace(pGraph, nEdgeIndex, nBestPoint, s, nFaces);
+        }
+
+        // Add new edge or update face info of old edge.
+        nEdgeIndex = GraphProcessor::findEdge(pGraph, t, nBestPoint);
+
+        if (nEdgeIndex == -1)
+        {
+            // New edge.
+            nEdgeIndex = pGraph->addEdge(t, nBestPoint, nFaces, -1);
+        }
+        else
+        {
+            // Old edge.
+            updateLeftFace(pGraph, nEdgeIndex, t, nBestPoint, nFaces);
+        }
+    }
+    else
+    {
+        updateLeftFace(pGraph, nEdgeIndex, s, t, -2);
+    }
+}
+
+void GraphTriangulation::updateLeftFace(CSphericalGraph* pGraph, int nEdgeIndex, int nIndex1, int nIndex2, int nFace)
+{
+    //  vector<TView*>* pViews = &pGraph->getAspectPool()->m_Views;
+    vector<CSGEdge*>* pEdges = pGraph->getEdges();
+
+    bool bValid = false;
+
+    if ((pEdges->at(nEdgeIndex)->nIndex1 == nIndex1) && (pEdges->at(nEdgeIndex)->nIndex2 == nIndex2))
+    {
+        bValid = true;
+    }
+
+    if ((pEdges->at(nEdgeIndex)->nIndex1 == nIndex2) && (pEdges->at(nEdgeIndex)->nIndex2 == nIndex1))
+    {
+        bValid = true;
+    }
+
+    if (!bValid)
+    {
+        printf("updateLeftFace: adj. matrix and edge table mismatch\n");
+    }
+
+    if ((pEdges->at(nEdgeIndex)->nIndex1 == nIndex1) && (pEdges->at(nEdgeIndex)->nLeftFace == -1))
+    {
+        pEdges->at(nEdgeIndex)->nLeftFace = nFace;
+    }
+    else if ((pEdges->at(nEdgeIndex)->nIndex2 == nIndex1) && (pEdges->at(nEdgeIndex)->nRightFace == -1))
+    {
+        pEdges->at(nEdgeIndex)->nRightFace = nFace;
+    }
+
+}
+
+CSphericalGraph* GraphTriangulation::doubleNodes(CSphericalGraph* pSourceGraph)
+{
+    // list to source views
+    TNodeList* pNodes = pSourceGraph->getNodes();
+    int nNumberSourceNodes = (int) pNodes->size();
+
+    // add views to aspectpool
+    vector<TSphereCoord> coordinates;
+
+
+    for (int i = 0 ; i < nNumberSourceNodes ; i++)
+    {
+        coordinates.push_back(pNodes->at(i)->getPosition());
+    }
+
+    TSphereCoord shiftedCoord;
+
+    for (int i = 0 ; i < nNumberSourceNodes ; i++)
+    {
+        shiftedCoord = pNodes->at(i)->getPosition();
+        shiftedCoord.fTheta += 360.0f;
+        coordinates.push_back(shiftedCoord);
+    }
+
+    /*  TSphereCoord shifted2Coord, shifted3Coord;
+        for(int i = 0 ; i < nNumberSourceNodes ; i++)
+        {
+            shifted2Coord = pNodes->at(i)->getPosition();
+            shifted2Coord.fPhi += 180.0f;
+            coordinates.push_back(shifted2Coord);
+        }
+
+        for(int i = 0 ; i < nNumberSourceNodes ; i++)
+        {
+            shifted3Coord = pNodes->at(i)->getPosition();
+            shifted3Coord.fPhi += 180.0f;
+            shifted3Coord.fTheta += 360.0f;
+            coordinates.push_back(shifted3Coord);
+        }
+    */
+    CSphericalGraph* pTmpGraph = new CSphericalGraph();
+
+    for (int i = 0 ; i < 2 * nNumberSourceNodes ; i++)
+    {
+        CSGNode* pNode = new CSGNode(coordinates.at(i));
+        pTmpGraph->addNode(pNode);
+    }
+
+    return pTmpGraph;
+}
diff --git a/source/RobotAPI/components/EarlyVisionGraph/GraphTriangulation.h b/source/RobotAPI/components/EarlyVisionGraph/GraphTriangulation.h
new file mode 100644
index 000000000..62e3dadc5
--- /dev/null
+++ b/source/RobotAPI/components/EarlyVisionGraph/GraphTriangulation.h
@@ -0,0 +1,52 @@
+// *****************************************************************
+// Filename:    AspectGraphProcessor.h
+// Copyright:   Kai Welke, Chair Prof. Dillmann (IAIM),
+//              Institute for Computer Science and Engineering (CSE),
+//              University of Karlsruhe. All rights reserved.
+// Author:      Kai Welke
+// Date:        12.06.2007
+// *****************************************************************
+
+#ifndef _GRAPH_TRIANGULATION_H_
+#define _GRAPH_TRIANGULATION_H_
+
+// *****************************************************************
+// forward declarations
+// *****************************************************************
+
+// *****************************************************************
+// includes
+// *****************************************************************
+#include "SphericalGraph.h"
+#include "Base/DataStructures/Graph/Convexhull/C3DNode.h"
+#include "Base/DataStructures/Graph/Convexhull/HalfSpace.h"
+#include "Base/DataStructures/Graph/Convexhull/CHGiftWrap.h"
+#include <float.h>
+
+// *****************************************************************
+// namespaces
+// *****************************************************************
+
+// *****************************************************************
+// namespace GraphTriangulation
+// *****************************************************************
+class GraphTriangulation
+{
+public:
+    static void delaunayTriangulationQuadratic(CSphericalGraph* pGraph);
+    // triangulate with O(n^2) spherical
+    static void triangulationQuadraticSpherical(CSphericalGraph* pGraph);
+    // triangulate with O(n^4)
+    static void triangulationQuartic(CSphericalGraph* pGraph, float fThreshold = FLT_MAX);
+    // triangulate with O(n^2)
+    static void triangulationQuadratic(CSphericalGraph* pGraph);
+
+private:
+    static void updateLeftFace(CSphericalGraph* pGraph, int nEdgeIndex, int nIndex1, int nIndex2, int nFace);
+    static void completeFacet(CSphericalGraph* pGraph, int nEdgeIndex, int nFaces);
+
+    static CSphericalGraph* doubleNodes(CSphericalGraph* pSourceGraph);
+
+};
+
+#endif /* _GRAPH_TRIANGULATION_H_ */
diff --git a/source/RobotAPI/components/EarlyVisionGraph/IntensityGraph.cpp b/source/RobotAPI/components/EarlyVisionGraph/IntensityGraph.cpp
new file mode 100644
index 000000000..6d48757d1
--- /dev/null
+++ b/source/RobotAPI/components/EarlyVisionGraph/IntensityGraph.cpp
@@ -0,0 +1,276 @@
+// *****************************************************************
+// Filename:    SensoryEgoSphere.cpp
+// Copyright:   Kai Welke, Chair Prof. Dillmann (IAIM),
+//              Institute for Computer Science and Engineering (CSE),
+//              University of Karlsruhe. All rights reserved.
+// Author:      Kai Welke
+// Date:        21.07.2008
+// *****************************************************************
+
+// *****************************************************************
+// includes
+// *****************************************************************
+#include "IntensityGraph.h"
+//#include "Base/Math/DistributePoints.h"
+//#include "MathTools.h"
+//#include "Base/DataStructures/Graph/GraphProcessor.h"
+
+#include <float.h>
+#include <fstream>
+
+// *****************************************************************
+// implementation of CIntensityNode
+// *****************************************************************
+CIntensityNode::CIntensityNode()
+{
+    setIntensity(0.0f);
+}
+
+CIntensityGraph::CIntensityGraph(const CIntensityGraph& prototype)
+    : CSphericalGraph(prototype)
+{
+}
+
+CIntensityNode::CIntensityNode(TSphereCoord coord)
+    : CSGNode(coord)
+{
+    setIntensity(0.0f);
+}
+
+CIntensityNode::~CIntensityNode()
+{
+}
+
+void CIntensityNode::setIntensity(float fIntensity)
+{
+    m_fIntensity = fIntensity;
+}
+
+float CIntensityNode::getIntensity()
+{
+    return m_fIntensity;
+}
+
+// *****************************************************************
+// implementation of CIntensityGraph
+// *****************************************************************
+// *****************************************************************
+// construction / destruction
+// *****************************************************************
+CIntensityGraph::CIntensityGraph()
+{
+    reset();
+}
+
+//CIntensityGraph::CIntensityGraph(int nNumberNodes)
+//{
+//  // generate points on sphere
+//  points P = generatePoints(nNumberNodes,1000);
+
+//  for(int i = 0 ; i < int(P.V.size()) ; i++)
+//  {
+//      // project point to polar coordinates
+//      Vec3d point;
+//      Math3d::SetVec(point,P.V.at(i).array()[0],P.V.at(i).array()[1],P.V.at(i).array()[2]);
+//      TSphereCoord point_on_sphere;
+//      MathTools::convert(point, point_on_sphere);
+
+//      CIntensityNode* pNode = new CIntensityNode(point_on_sphere);
+
+//      addNode(pNode);
+//  }
+
+//  // initialize
+//  reset();
+//}
+
+CIntensityGraph::CIntensityGraph(string sFilename)
+{
+    printf("Reading intensity graph from: %s\n", sFilename.c_str());
+
+    ifstream infile;
+    infile.open(sFilename.c_str());
+
+    read(infile);
+
+    //printf("Read number nodes: %d\n", getNodes()->size());
+    //printf("Read number edges: %d\n", getEdges()->size());
+}
+
+CIntensityGraph::~CIntensityGraph()
+{
+}
+
+CIntensityGraph& CIntensityGraph::operator= (CIntensityGraph const& rhs)
+{
+    *((CSphericalGraph*) this) = (const CSphericalGraph) rhs;
+    return *this;
+}
+
+// *****************************************************************
+// setting
+// *****************************************************************
+void CIntensityGraph::reset()
+{
+    set(0.0f);
+}
+
+void CIntensityGraph::set(float fIntensity)
+{
+    TNodeList* pNodes = getNodes();
+
+    for (size_t i = 0 ; i < pNodes->size() ; i++)
+    {
+        ((CIntensityNode*) pNodes->at(i))->setIntensity(fIntensity);
+    }
+}
+
+
+// *****************************************************************
+// file io
+// *****************************************************************
+bool CIntensityGraph::read(istream& infile)
+{
+    try
+    {
+        int nNumberNodes;
+
+        // read number of nodes
+        infile >> nNumberNodes;
+
+        // read all nodes
+        for (int n = 0 ; n < nNumberNodes ; n++)
+        {
+            readNode(infile);
+        }
+
+        // read number of edges
+        int nNumberEdges;
+        infile >> nNumberEdges;
+
+        for (int e = 0 ; e < nNumberEdges ; e++)
+        {
+            readEdge(infile);
+        }
+
+    }
+    catch (istream::failure e)
+    {
+        printf("ERROR: failed to write FeatureGraph to file\n");
+        return false;
+    }
+
+    return true;
+}
+
+bool CIntensityGraph::readNode(istream& infile)
+{
+    CIntensityNode* pNewNode = getNewNode();
+
+    int nIndex;
+    TSphereCoord pos;
+    float fIntensity;
+
+    infile >> nIndex;
+    infile >> pos.fPhi;
+    infile >> pos.fTheta;
+    infile >> fIntensity;
+
+    pNewNode->setPosition(pos);
+    pNewNode->setIntensity(fIntensity);
+
+    int nTest = addNode(pNewNode);
+
+    if (nTest != nIndex)
+    {
+        printf("Error input file inconsistent: %d %d\n", nTest, nIndex);
+        return false;
+    }
+
+    return true;
+}
+
+bool CIntensityGraph::readEdge(istream& infile)
+{
+    int nIndex1, nIndex2, nLeftFace, nRightFace;
+
+    infile >> nIndex1;
+    infile >> nIndex2;
+
+    infile >> nLeftFace;
+    infile >> nRightFace;
+
+    addEdge(nIndex1, nIndex2, nLeftFace, nRightFace);
+    return true;
+}
+
+
+bool CIntensityGraph::write(ostream& outfile)
+{
+    try
+    {
+        int nNumberNodes = int(m_Nodes.size());
+        // write number of nodes
+        outfile << nNumberNodes << endl;
+
+        // write all nodes
+        for (int n = 0 ; n < nNumberNodes ; n++)
+        {
+            writeNode(outfile, n);
+        }
+
+        // write number of edges
+        int nNumberEdges = int(m_Edges.size());
+        outfile << nNumberEdges << endl;
+
+        for (int e = 0 ; e < nNumberEdges ; e++)
+        {
+            writeEdge(outfile, e);
+        }
+
+    }
+    catch (ostream::failure e)
+    {
+        printf("ERROR: failed to write FeatureGraph to file\n");
+        return false;
+    }
+
+    return true;
+}
+
+bool CIntensityGraph::writeNode(ostream& outfile, int n)
+{
+    CIntensityNode* pCurrentNode = (CIntensityNode*) m_Nodes.at(n);
+
+    outfile << pCurrentNode->getIndex() << endl;
+    outfile << pCurrentNode->getPosition().fPhi << endl;
+    outfile << pCurrentNode->getPosition().fTheta << endl;
+    outfile << pCurrentNode->getIntensity() << endl;
+
+    outfile << endl;
+    return true;
+}
+
+bool CIntensityGraph::writeEdge(ostream& outfile, int e)
+{
+    CSGEdge* pCurrentEdge = m_Edges.at(e);
+    outfile << pCurrentEdge->nIndex1 << " ";
+    outfile << pCurrentEdge->nIndex2 << " ";
+
+    outfile << pCurrentEdge->nLeftFace << " ";
+    outfile << pCurrentEdge->nRightFace << " ";
+
+    outfile << endl;
+    return true;
+}
+
+void CIntensityGraph::graphToVec(std::vector<float>& vec)
+{
+    TNodeList* nodes = this->getNodes();
+
+    for (size_t i = 0; i < nodes->size(); i++)
+    {
+        CIntensityNode* node = (CIntensityNode*) nodes->at(i);
+        vec.push_back(node->getIntensity());
+    }
+}
diff --git a/source/RobotAPI/components/EarlyVisionGraph/IntensityGraph.h b/source/RobotAPI/components/EarlyVisionGraph/IntensityGraph.h
new file mode 100644
index 000000000..4436704a4
--- /dev/null
+++ b/source/RobotAPI/components/EarlyVisionGraph/IntensityGraph.h
@@ -0,0 +1,97 @@
+// *****************************************************************
+// Filename:    IntensityGraph.h
+// Copyright:   Kai Welke, Chair Prof. Dillmann (IAIM),
+//              Institute for Computer Science and Engineering (CSE),
+//              University of Karlsruhe. All rights reserved.
+// Author:      Kai Welke
+// Date:        12.06.2008
+// *****************************************************************
+
+#ifndef _INTENSITY_GRAPH_H_
+#define _INTENSITY_GRAPH_H_
+
+// *****************************************************************
+// includes
+// *****************************************************************
+#include "SphericalGraph.h"
+#include <string>
+
+using namespace std;
+
+// *****************************************************************
+// namespaces
+// *****************************************************************
+
+// *****************************************************************
+// structures
+// *****************************************************************
+// *****************************************************************
+// definition of nodes
+// *****************************************************************
+class CIntensityNode : public CSGNode
+{
+public:
+    CIntensityNode();
+    CIntensityNode(TSphereCoord coord);
+    ~CIntensityNode();
+
+    void setIntensity(float fIntensity);
+    float getIntensity();
+
+    virtual CSGNode* clone()
+    {
+        CIntensityNode* copy = new CIntensityNode(m_Position);
+        copy->setIndex(m_nIndex);
+        copy->setIntensity(m_fIntensity);
+        return copy;
+    }
+
+private:
+    float   m_fIntensity;
+};
+
+
+// *****************************************************************
+// definition of sensory egosphere
+// *****************************************************************
+class CIntensityGraph : public CSphericalGraph
+{
+public:
+    CIntensityGraph();
+    CIntensityGraph(const CIntensityGraph& prototype);
+    //CIntensityGraph(int nNumberNodes);
+    CIntensityGraph(string sFileName);
+    ~CIntensityGraph();
+
+    void reset();
+    void set(float fIntensity);
+
+
+    void graphToVec(std::vector<float>& vec);
+
+    ///////////////////////////////
+    // file io
+    ///////////////////////////////
+    virtual bool read(istream& infile);
+    virtual bool readNode(istream& infile);
+    virtual bool readEdge(istream& infile);
+
+    virtual bool write(ostream& outfile);
+    virtual bool writeNode(ostream& outfile, int n);
+    virtual bool writeEdge(ostream& outfile, int e);
+
+
+    // inherited
+    virtual CIntensityNode* getNewNode()
+    {
+        return new CIntensityNode();
+    }
+
+    ///////////////////////////////
+    // operators
+    ///////////////////////////////
+    CIntensityGraph& operator= (CIntensityGraph const& rhs);
+
+};
+
+#endif // _INTENSITY_GRAPH_H_ 
diff --git a/source/RobotAPI/components/EarlyVisionGraph/MathTools.cpp b/source/RobotAPI/components/EarlyVisionGraph/MathTools.cpp
new file mode 100644
index 000000000..f43021463
--- /dev/null
+++ b/source/RobotAPI/components/EarlyVisionGraph/MathTools.cpp
@@ -0,0 +1,488 @@
+// *****************************************************************
+// Filename:    AspectGraphProcessor.cpp
+// Copyright:   Kai Welke, Chair Prof. Dillmann (IAIM),
+//              Institute for Computer Science and Engineering (CSE),
+//              University of Karlsruhe. All rights reserved.
+// Author:      Kai Welke
+// Date:        12.06.2007
+// *****************************************************************
+
+// *****************************************************************
+// includes
+// *****************************************************************
+#include "MathTools.h"
+#include <math.h>
+//#include "Base/Tools/DebugMemory.h"
+
+
+// **********************************************************
+// transformation on sphere coordinates and paths
+// **********************************************************
+// returns transformation from p1 -> p2
+TTransform MathTools::determinePathTransformation(TPath* p1, TPath* p2)
+{
+    TSphereCoord start1, start2, end1, end2;
+    start1 = p1->at(0).Position;
+    end1 = p1->at(p1->size() - 1).Position;
+    start2 = p2->at(0).Position;
+    end2 = p2->at(p2->size() - 1).Position;
+
+    return determineTransformation(start1, start2, end1, end2);
+}
+
+TPath* MathTools::transformPath(TTransform transform, TPath* pPath)
+{
+    TPath* pResulting = new TPath();
+
+    if (pPath->size() < 2)
+    {
+        printf("ERROR: path is too short\n");
+        delete pResulting;
+        return NULL;
+    }
+
+    // copy path and transform
+    for (int e = 0 ; e < int(pPath->size()) ; e++)
+    {
+        TPathElement element = pPath->at(e);
+        TSphereCoord res = MathTools::transform(element.Position, transform);
+        element.Position = res;
+
+        pResulting->push_back(element);
+    }
+
+    return pResulting;
+
+}
+
+TPath* MathTools::inverseTransformPath(TTransform transform, TPath* pPath)
+{
+    TPath* pResulting = new TPath();
+
+    if (pPath->size() < 2)
+    {
+        printf("ERROR: path is too short\n");
+        delete pResulting;
+        return NULL;
+    }
+
+    // copy path and transform
+    for (int e = 0 ; e < int(pPath->size()) ; e++)
+    {
+        TPathElement element = pPath->at(e);
+        TSphereCoord res = MathTools::inverseTransform(element.Position, transform);
+        element.Position = res;
+
+        pResulting->push_back(element);
+    }
+
+    return pResulting;
+
+}
+
+TTransform MathTools::determineTransformation(TSphereCoord start1, TSphereCoord start2, TSphereCoord end1, TSphereCoord end2)
+{
+    TTransform result;
+
+    // first determine alpha and beta and beta axis
+    float fAlpha, fBeta;
+    Eigen::Vector3d betaAxis;
+    determineTransformationAlphaBeta(start1, start2, fAlpha, fBeta, betaAxis);
+    result.fAlpha = fAlpha;
+    result.fBeta = fBeta;
+    result.betaAxis = betaAxis;
+
+    // calculate angular for psi rotation
+
+    // apply transform to first path end
+    TSphereCoord end1_transformed = transformAlphaBeta(end1, fAlpha, fBeta, betaAxis);
+
+    Eigen::Vector3d end1_transformed_v, start2_v, end2_v;
+    convert(end1_transformed, end1_transformed_v);
+    convert(start2, start2_v);
+    convert(end2, end2_v);
+
+    // calculate angle between start2 <-> end1_tranformed ; start2 <-> end2
+    Eigen::Vector3d zero = Eigen::Vector3d::Zero();
+
+    Eigen::Vector3d line1 = MathTools::dropAPerpendicular(end1_transformed_v, zero, start2_v);
+    Eigen::Vector3d line2 = MathTools::dropAPerpendicular(end2_v, zero, start2_v);
+    line1 -= end1_transformed_v;
+    line2 -= end2_v;
+
+    float fPsi = MathTools::AngleAndDirection(line1, line2, start2_v) * 180.0 / M_PI;
+
+    result.fPsi = fPsi;
+    result.psiAxis = start2_v;
+
+    return result;
+}
+
+TSphereCoord MathTools::transform(TSphereCoord sc, TTransform transform)
+{
+    // first apply alpha , beta
+    TSphereCoord rotated_ab = transformAlphaBeta(sc, transform.fAlpha, transform.fBeta, transform.betaAxis);
+
+    Eigen::Vector3d rotated_ab_v;
+
+    convert(rotated_ab, rotated_ab_v);
+
+    // now apply final rotation
+    Eigen::AngleAxisd rot(-transform.fPsi * M_PI / 180.0, transform.psiAxis);
+    rotated_ab_v = rot.matrix() * rotated_ab_v;
+
+    TSphereCoord rotated;
+    convert(rotated_ab_v, rotated);
+
+    return rotated;
+}
+
+TSphereCoord MathTools::inverseTransform(TSphereCoord sc, TTransform transform)
+{
+    Eigen::Vector3d sc_v;
+    convert(sc, sc_v);
+
+    // first rotate
+    Eigen::AngleAxisd rot(transform.fPsi * M_PI / 180.0,  transform.psiAxis);
+    sc_v = rot.matrix() * sc_v;
+
+    TSphereCoord rotated;
+    convert(sc_v, rotated);
+
+    return inverseTransformAlphaBeta(rotated, transform.fAlpha, transform.fBeta, transform.betaAxis);
+}
+
+// determine alpha and beta of a transform
+// fAlpha: rotation around the z axis in counterclockwise direction considering the positive z-axis
+// fBeta: rotation around the rotated y axis in counterclockwise direction considering the positive y-axis
+void MathTools::determineTransformationAlphaBeta(TSphereCoord sc1, TSphereCoord sc2, float& fAlpha, float& fBeta, Eigen::Vector3d& betaAxis)
+{
+    Eigen::Vector3d vector1, vector2;
+    convert(sc1, vector1);
+    convert(sc2, vector2);
+
+    // project both vectors to xy plane
+    Eigen::Vector3d vector1_xy, vector2_xy;
+
+    vector1_xy = vector1;
+    vector2_xy = vector2;
+
+    vector1_xy(2) = 0.0;
+    vector2_xy(2) = 0.0;
+
+    // calculate first angle from vec1_projected to vec2_projected with normale z
+    Eigen::Vector3d normal = Eigen::Vector3d::UnitZ();
+
+    if (vector1_xy.norm() == 0.0 || vector2_xy.norm() == 0)
+    {
+        fAlpha = ((sc2.fTheta - sc1.fTheta) / 180.0 * M_PI);
+    }
+    else
+    {
+        fAlpha = MathTools::AngleAndDirection(vector1_xy, vector2_xy, normal);
+    }
+
+    // now rotate first vector with alpha
+    Eigen::Vector3d rotated1, rotated_y;
+
+    // the vector to rotate
+
+    rotated1 = vector1;
+    // set rotation: alpha around z-axis to transform v1 in same plane as v2
+
+    Eigen::AngleAxisd rotation(fAlpha, Eigen::Vector3d::UnitZ());;
+    Eigen::AngleAxisd rotation_yaxis(sc2.fTheta, Eigen::Vector3d::UnitZ());
+
+    // we need normal for angle calculateion, so also rotate x-axis
+    rotated_y << 0.0, 1.0, 0.0;
+
+    // rotate vector and x-axis
+
+
+    rotated1 = rotation.matrix() * rotated1;
+
+    rotated_y =  rotation_yaxis.matrix() * rotated_y;
+
+    betaAxis = rotated_y;
+
+    // calculate angle between both vectors
+    fBeta = MathTools::AngleAndDirection(rotated1, vector2, rotated_y);
+
+    fAlpha *= 180.0 / M_PI;
+    fBeta *= 180.0 / M_PI;
+}
+
+TSphereCoord MathTools::transformAlphaBeta(TSphereCoord sc, float fAlpha, float fBeta, Eigen::Vector3d betaAxis)
+{
+    TSphereCoord result;
+    Eigen::Vector3d vector1, vector1_rotated;
+    convert(sc, vector1);
+
+    // rotate around positive z-axis
+    Eigen::AngleAxisd rotation_alpha(fAlpha  / 180.0 * M_PI, Eigen::Vector3d::UnitZ());
+
+    // rotate vector aroun z axis
+    vector1_rotated = rotation_alpha.matrix() * vector1;
+    // rotate vector with beta around betaAxis
+    Eigen::AngleAxisd rot(-fBeta / 180.0 * M_PI, betaAxis);
+
+    vector1_rotated = rot.matrix() * vector1_rotated;
+
+    convert(vector1_rotated, result);
+
+    return result;
+}
+
+TSphereCoord MathTools::inverseTransformAlphaBeta(TSphereCoord sc, float fAlpha, float fBeta, Eigen::Vector3d betaAxis)
+{
+    Eigen::Vector3d vector1;
+    convert(sc, vector1);
+
+    // do inverse of beta axis rotation
+    Eigen::AngleAxisd rot(fBeta / 180.0 * M_PI, betaAxis);
+    vector1 = rot.matrix() * vector1;
+
+    // do inverse of zaxis rotation
+    Eigen::AngleAxisd rotation_alpha(-fAlpha / 180.0 * M_PI, Eigen::Vector3d::UnitZ());
+
+    // rotate vector aroun z axis
+    vector1 = rotation_alpha * vector1;
+
+    TSphereCoord result;
+    convert(vector1, result);
+
+    return result;
+}
+
+// **********************************************************
+// calculations on sphere coordinates
+// **********************************************************
+float MathTools::CalculateCrossProductFromDifference(TSphereCoord p1, TSphereCoord p2, TSphereCoord p3)
+{
+    float u1, v1, u2, v2;
+
+    u1 =  p2.fPhi - p1.fPhi;
+    v1 =  p2.fTheta - p1.fTheta;
+    u2 =  p3.fPhi - p1.fPhi;
+    v2 =  p3.fTheta - p1.fTheta;
+
+    return u1 * v2 - v1 * u2;
+}
+
+double MathTools::Angle(Eigen::Vector3d vec1, Eigen::Vector3d vec2)
+{
+    double r = vec1.dot(vec2) / (vec1.norm() * vec2.norm());
+    r = std::min(1.0, std::max(-1.0, r));
+    return  std::acos(r);
+}
+
+float MathTools::getDistanceOnArc(TSphereCoord p1, TSphereCoord p2)
+{
+    Eigen::Vector3d vec1, vec2;
+    p1.fDistance = 1.0f;
+    p2.fDistance = 1.0f;
+
+    convert(p1, vec1);
+    convert(p2, vec2);
+
+    float fAngle = (float) MathTools::Angle(vec1, vec2);
+
+    // length of circular arc
+    // not necessary because Math3d::Angle returns a value in radians
+    //float fDist = float( (2 * M_PI * fAngle ) / 360.0f);
+
+    return fAngle;
+}
+
+float MathTools::getDistance(TSphereCoord p1, TSphereCoord p2, float fRadius)
+{
+    // never use this!!!!
+    TSphereCoord diff;
+    diff.fPhi = p1.fPhi - p2.fPhi;
+    diff.fTheta = p1.fTheta - p2.fTheta;
+
+    float fAngle = sqrt(diff.fPhi * diff.fPhi + diff.fTheta * diff.fTheta);
+
+    return fAngle;
+}
+
+// **********************************************************
+// extended 2d Math
+// **********************************************************
+bool MathTools::IntersectLines(Eigen::Vector2d p1, Eigen::Vector2d m1, Eigen::Vector2d p2, Eigen::Vector2d m2, Eigen::Vector2d& res)
+{
+    // calculate perpendicular bisector of sides
+    float dx = float(p1(0) - p2(0));
+    float dy = float(p1(1) - p2(1));
+
+    // now from
+    // g1: g1(x,y) = (p1x,p1y) + (m1x,m1y) * c1
+    // g2: g2(x,y) = (p2x,p2y) + (m2x,m2y) * c2
+    // -->
+    // g1(x,y) = g2(x,y)
+    // -->
+    // (p1x,p1y) + (m1x,m1y) * c1 = (p2x,p2y) + (m2x,m2y) * c2
+    // (p1x,p1y) - (p2x,p2y) = (dx,dy) = (m2x,m2y) * c2 - (m1x,m1y) * c1
+    // -->
+    // dx = m2x * c2 - m1x * c1,  dy = m2y * c2 - m1y * c1
+    // c1 = (m2y * c2 - dy) / m1y
+    // dx = m2x * c2 - m1x * (m2y * c2 - dy) / m1y
+
+    float z = float(dx - (m1(0) * dy) / m1(1));
+    float n = float(m2(0) - (m1(0) * m2(1)) / m1(1));
+
+    float c2;
+
+    if (n == 0)
+    {
+        return false;
+    }
+    else
+    {
+        c2 = z / n;
+    }
+
+    res(0) = p2(0) + c2 * m2(0);
+    res(1) = p2(1) + c2 * m2(1);
+
+    return true;
+}
+
+// **********************************************************
+// extended 3d Math
+// **********************************************************
+// checked and working
+float MathTools::AngleAndDirection(Eigen::Vector3d vector1, Eigen::Vector3d vector2, Eigen::Vector3d normal)
+{
+    double fAngle = MathTools::Angle(vector1, vector2);
+
+    Eigen::Vector3d axis = vector1.cross(vector2);
+
+    // compare axis and normal
+    normal.normalize();
+
+    double c =   normal.dot(vector1);
+
+    axis += vector1;
+    double d = normal.dot(axis) - c;
+
+
+    if (d < 0)
+    {
+        return 2 * M_PI - fAngle;
+    }
+
+    return (float) fAngle;
+}
+
+// checked and working
+Eigen::Vector3d MathTools::dropAPerpendicular(Eigen::Vector3d point, Eigen::Vector3d linepoint, Eigen::Vector3d linevector)
+{
+    // helping plane normal (ax + by + cz + d = 0)
+    Eigen::Vector3d plane_normal = linevector; // (a,b,c)
+    float d = (float) - plane_normal.dot(point);
+
+    // calculate k from plane and line intersection
+    float z = float(- plane_normal(0) * linepoint(0) - plane_normal(1) * linepoint(1) - plane_normal(2) * linepoint(2) - d);
+    float n = float(plane_normal(0) * linevector(0) + plane_normal(1) * linevector(1) + plane_normal(2) * linevector(2));
+
+    float k = z / n;
+
+    // calculate line from line equation
+    linevector = k * linevector;
+    linevector += linepoint;
+
+    return linevector;
+
+}
+
+// **********************************************************
+// conversions
+// **********************************************************
+// checked and working
+void MathTools::convert(TSphereCoord in, Eigen::Vector3d& out)
+{
+    // alpha is azimuth, beta is polar angle
+    in.fPhi *= M_PI / 180.0f;
+    in.fTheta *= M_PI / 180.0f;
+
+    // OLD and wrong??
+    //  out.x = in.fDistance * sin(in.fPhi) * cos(in.fTheta);
+    //  out.y = in.fDistance * sin(in.fPhi) * sin(in.fTheta);
+    //  out.z = in.fDistance * cos(in.fPhi);
+
+    Eigen::Vector3d vector = Eigen::Vector3d::UnitZ();
+    Eigen::AngleAxisd rotation_y(in.fPhi, Eigen::Vector3d::UnitY());
+    Eigen::AngleAxisd rotation_z(in.fTheta, Eigen::Vector3d::UnitZ());
+
+
+    // first rotate around y axis with phi
+    vector = rotation_y.matrix() * vector;
+
+    // second rotate around z with theta
+    vector = rotation_z.matrix() * vector;
+
+    out = vector;
+}
+
+
+void MathTools::convertWithDistance(TSphereCoord in, Eigen::Vector3d& out)
+{
+    convert(in, out);
+    out *= in.fDistance;
+}
+
+void MathTools::convert(TSphereCoord in, Eigen::Vector3f& out)
+{
+    Eigen::Vector3d vec;
+    convert(in, vec);
+    out = vec.cast<float>();
+}
+
+
+// checked and working
+void MathTools::convert(Eigen::Vector3d in, TSphereCoord& out)
+{
+    // alpha is azimuth, beta is polar angle
+    out.fDistance = in.norm();
+
+    float fAngle = in(2) / out.fDistance;
+
+    if (fAngle < -1.0f)
+    {
+        fAngle = -1.0f;
+    }
+
+    if (fAngle > 1.0f)
+    {
+        fAngle = 1.0f;
+    }
+
+    out.fPhi = (float) acos(fAngle);
+
+    out.fTheta = (float) atan2(in(1), in(0));
+
+    // convert to angles and correct interval
+    out.fPhi /= M_PI / 180.0f;
+    out.fTheta /= M_PI / 180.0f;
+
+    // only positive rotations
+    if (out.fTheta < 0.0)
+    {
+        out.fTheta = 360.0f + out.fTheta;
+    }
+
+    // be aware of limit
+    if (out.fPhi > 180.0)
+    {
+        out.fPhi = out.fPhi - 180.0f;
+    }
+}
+
+
+void MathTools::convert(Eigen::Vector3f in, TSphereCoord& out)
+{
+    Eigen::Vector3d vec(in(0), in(1), in(2));
+    convert(vec, out);
+}
+
diff --git a/source/RobotAPI/components/EarlyVisionGraph/MathTools.h b/source/RobotAPI/components/EarlyVisionGraph/MathTools.h
new file mode 100644
index 000000000..336629401
--- /dev/null
+++ b/source/RobotAPI/components/EarlyVisionGraph/MathTools.h
@@ -0,0 +1,72 @@
+// *****************************************************************
+// Filename:    MathTools.h
+// Copyright:   Kai Welke, Chair Prof. Dillmann (IAIM),
+//              Institute for Computer Science and Engineering (CSE),
+//              University of Karlsruhe. All rights reserved.
+// Author:      Kai Welke
+// Date:        12.06.2007
+// *****************************************************************
+
+#ifndef _MATH_TOOLS_H_
+#define _MATH_TOOLS_H_
+
+// *****************************************************************
+// defines
+// *****************************************************************
+#include <math.h>
+#ifndef M_PI
+#define M_PI 3.141592653589793
+#endif
+
+// *****************************************************************
+// includes
+// *****************************************************************
+#include "Structs.h"
+
+#include <Eigen/Core>
+#include <Eigen/Geometry>
+
+// *****************************************************************
+// class MathTools
+// *****************************************************************
+class MathTools
+{
+public:
+    // transformation of coordinates and paths
+    static TTransform determinePathTransformation(TPath* p1, TPath* p2);
+    static TPath* transformPath(TTransform transform, TPath* pPath);
+    static TPath* inverseTransformPath(TTransform transform, TPath* pPath);
+
+    static TTransform determineTransformation(TSphereCoord start1, TSphereCoord start2, TSphereCoord end1, TSphereCoord end2);
+    static TSphereCoord transform(TSphereCoord sc, TTransform transform);
+    static TSphereCoord inverseTransform(TSphereCoord sc, TTransform transform);
+
+    static void determineTransformationAlphaBeta(TSphereCoord sc1, TSphereCoord sc2, float& fAlpha, float& fBeta, Eigen::Vector3d& betaAxis);
+    static TSphereCoord transformAlphaBeta(TSphereCoord sc, float fAlpha, float fBeta, Eigen::Vector3d betaAxis);
+    static TSphereCoord inverseTransformAlphaBeta(TSphereCoord sc, float fAlpha, float fBeta, Eigen::Vector3d betaAxis);
+
+    // calculations on sphere coordimates
+    static float CalculateCrossProductFromDifference(TSphereCoord p1, TSphereCoord p2, TSphereCoord p3);
+    static float getDistanceOnArc(TSphereCoord p1, TSphereCoord p2);
+    static float getDistance(TSphereCoord p1, TSphereCoord p2, float fRadius);
+
+    // extended 2d math
+    static bool IntersectLines(Eigen::Vector2d p1, Eigen::Vector2d m1, Eigen::Vector2d p2, Eigen::Vector2d m2, Eigen::Vector2d& res);
+
+    // extended 3d math
+    static Eigen::Vector3d dropAPerpendicular(Eigen::Vector3d point, Eigen::Vector3d linepoint, Eigen::Vector3d linevector);
+    static float AngleAndDirection(Eigen::Vector3d vector1, Eigen::Vector3d vector2, Eigen::Vector3d normal);
+
+    // coorrdinate conversion
+    static void convert(TSphereCoord in, Eigen::Vector3d& out);
+    static void convert(TSphereCoord in, Eigen::Vector3f& out);
+    static void convert(Eigen::Vector3d in, TSphereCoord& out);
+    static void convert(Eigen::Vector3f in, TSphereCoord& out);
+    static void convertWithDistance(TSphereCoord in, Eigen::Vector3d& out);
+
+    static double Angle(Eigen::Vector3d vec1, Eigen::Vector3d vec2);
+
+
+};
+
+#endif /* _MATH_TOOLS_H_ */
diff --git a/source/RobotAPI/components/EarlyVisionGraph/SphericalGraph.cpp b/source/RobotAPI/components/EarlyVisionGraph/SphericalGraph.cpp
new file mode 100644
index 000000000..31b5b39a4
--- /dev/null
+++ b/source/RobotAPI/components/EarlyVisionGraph/SphericalGraph.cpp
@@ -0,0 +1,314 @@
+// *****************************************************************
+// Filename:    AspectGraph.cpp
+// Copyright:   Kai Welke, Chair Prof. Dillmann (IAIM),
+//              Institute for Computer Science and Engineering (CSE),
+//              University of Karlsruhe. All rights reserved.
+// Author:      Kai Welke
+// Date:        12.06.2007
+// *****************************************************************
+
+
+// *****************************************************************
+// includes
+// *****************************************************************
+#include "SphericalGraph.h"
+//#include "Base/Tools/DebugMemory.h"
+
+// *****************************************************************
+// construction / destruction
+// *****************************************************************
+CSphericalGraph::CSphericalGraph()
+{
+    clear();
+}
+
+CSphericalGraph::CSphericalGraph(const CSphericalGraph& prototype)
+{
+    *this = prototype;
+}
+
+CSphericalGraph::~CSphericalGraph()
+{
+    clear();
+}
+
+CSphericalGraph& CSphericalGraph::operator= (CSphericalGraph const& rhs)
+{
+    clear();
+
+    // copy all nodes
+    const TNodeList* nodes = &rhs.m_Nodes;
+
+    int nNumberNodes = int(nodes->size());
+
+    for (int n = 0 ; n < nNumberNodes ; n++)
+    {
+        addNode(nodes->at(n)->clone());
+    }
+
+    // copy all edges
+    const TEdgeList* edges = &rhs.m_Edges;
+
+    int nNumberEdges = int(edges->size());
+
+    for (int e = 0 ; e < nNumberEdges ; e++)
+    {
+        CSGEdge* edge = edges->at(e);
+        addEdge(edge->nIndex1, edge->nIndex2, edge->nLeftFace, edge->nRightFace);
+    }
+
+    return *this;
+}
+
+
+// *****************************************************************
+// control
+// *****************************************************************
+void CSphericalGraph::clear()
+{
+    // clear edges
+    vector<CSGEdge*>::iterator iter = m_Edges.begin();
+
+    while (iter != m_Edges.end())
+    {
+        delete *iter;
+        iter++;
+    }
+
+    m_Edges.clear();
+
+    // clear nodes
+    vector<CSGNode*>::iterator iter_node = m_Nodes.begin();
+
+    while (iter_node != m_Nodes.end())
+    {
+        delete *iter_node;
+        iter_node++;
+    }
+
+    m_Nodes.clear();
+}
+
+// *****************************************************************
+// graph building
+// *****************************************************************
+// nodes
+int CSphericalGraph::addNode(CSGNode* pNode)
+{
+    m_Nodes.push_back(pNode);
+    pNode->setIndex(int(m_Nodes.size() - 1));
+
+    return pNode->getIndex();
+}
+
+// edges
+int CSphericalGraph::addEdge(int nIndex1, int nIndex2)
+{
+    return addEdge(nIndex1, nIndex2, -1, -1);
+}
+
+int CSphericalGraph::addEdge(int nIndex1, int nIndex2, int nLeftFace, int nRightFace)
+{
+    CSGEdge* pEdge = new CSGEdge;
+    pEdge->nIndex1 = nIndex1;
+    pEdge->nIndex2 = nIndex2;
+    pEdge->nLeftFace = nLeftFace;
+    pEdge->nRightFace = nRightFace;
+
+    //  printf("Adding edge %d --> %d\n",nIndex1,nIndex2);
+
+    // add to list of edges
+    m_Edges.push_back(pEdge);
+
+    // update node adjacency list
+    addNodeAdjacency(nIndex1, nIndex2);
+    addNodeAdjacency(nIndex2, nIndex1);
+
+    return int(m_Edges.size()) - 1;
+}
+
+void CSphericalGraph::addNodeAdjacency(int nNode, int nAdjacency)
+{
+    if (nNode == nAdjacency)
+    {
+        printf("Error: adding node as adjacenca\n");
+    }
+
+    // check if present
+    bool bPresent = false;
+
+    for (int n = 0 ; n < int(m_NodeAdjacency[nNode].size()) ; n++)
+    {
+        if (m_NodeAdjacency[nNode].at(n) == nAdjacency)
+        {
+            bPresent = true;
+        }
+    }
+
+    if (!bPresent)
+    {
+        m_NodeAdjacency[nNode].push_back(nAdjacency);
+    }
+}
+
+// *****************************************************************
+// member access
+// *****************************************************************
+TEdgeList* CSphericalGraph::getEdges()
+{
+    return &m_Edges;
+}
+
+TNodeList* CSphericalGraph::getNodes()
+{
+    return &m_Nodes;
+}
+
+CSGEdge* CSphericalGraph::getEdge(int nEdgeIndex)
+{
+    return m_Edges.at(nEdgeIndex);
+}
+
+CSGNode* CSphericalGraph::getNode(int nIndex)
+{
+    return m_Nodes.at(nIndex);
+}
+
+vector<int>* CSphericalGraph::getNodeAdjacency(int nIndex)
+{
+    return &m_NodeAdjacency[nIndex];
+}
+
+// *****************************************************************
+// file io
+// *****************************************************************
+bool CSphericalGraph::read(istream& infile)
+{
+    try
+    {
+        int nNumberNodes;
+
+        // read number of nodes
+        infile >> nNumberNodes;
+
+        // read all nodes
+        for (int n = 0 ; n < nNumberNodes ; n++)
+        {
+            readNode(infile);
+        }
+
+        // read number of edges
+        int nNumberEdges;
+        infile >> nNumberEdges;
+
+        for (int e = 0 ; e < nNumberEdges ; e++)
+        {
+            readEdge(infile);
+        }
+
+    }
+    catch (istream::failure e)
+    {
+        printf("ERROR: failed to write FeatureGraph to file\n");
+        return false;
+    }
+
+    return true;
+}
+
+bool CSphericalGraph::readNode(istream& infile)
+{
+    CSGNode* pNewNode = (CSGNode*) getNewNode();
+
+    int nIndex;
+    TSphereCoord pos;
+
+    infile >> nIndex;
+    infile >> pos.fPhi;
+    infile >> pos.fTheta;
+
+    pNewNode->setPosition(pos);
+
+    if (addNode(pNewNode) != nIndex)
+    {
+        printf("Error input file inconsistent\n");
+        return false;
+    }
+
+    return true;
+}
+
+
+
+bool CSphericalGraph::readEdge(istream& infile)
+{
+    int nIndex1, nIndex2, nLeftFace, nRightFace;
+
+    infile >> nIndex1;
+    infile >> nIndex2;
+
+    infile >> nLeftFace;
+    infile >> nRightFace;
+
+    addEdge(nIndex1, nIndex2, nLeftFace, nRightFace);
+    return true;
+}
+
+
+bool CSphericalGraph::write(ostream& outfile)
+{
+    try
+    {
+        int nNumberNodes = int(m_Nodes.size());
+        // write number of nodes
+        outfile << nNumberNodes << endl;
+
+        // write all nodes
+        for (int n = 0 ; n < nNumberNodes ; n++)
+        {
+            writeNode(outfile, n);
+        }
+
+        // write number of edges
+        int nNumberEdges = int(m_Edges.size());
+        outfile << nNumberEdges << endl;
+
+        for (int e = 0 ; e < nNumberEdges ; e++)
+        {
+            writeEdge(outfile, e);
+        }
+
+    }
+    catch (ostream::failure e)
+    {
+        printf("ERROR: failed to write FeatureGraph to file\n");
+        return false;
+    }
+
+    return true;
+}
+
+bool CSphericalGraph::writeNode(ostream& outfile, int n)
+{
+    CSGNode* pCurrentNode = m_Nodes.at(n);
+
+    outfile << pCurrentNode->getIndex() << endl;
+    outfile << pCurrentNode->getPosition().fPhi << endl;
+    outfile << pCurrentNode->getPosition().fTheta << endl;
+
+    outfile << endl;
+    return true;
+}
+
+bool CSphericalGraph::writeEdge(ostream& outfile, int e)
+{
+    CSGEdge* pCurrentEdge = m_Edges.at(e);
+    outfile << pCurrentEdge->nIndex1 << " ";
+    outfile << pCurrentEdge->nIndex2 << " ";
+
+    outfile << pCurrentEdge->nLeftFace << " ";
+    outfile << pCurrentEdge->nRightFace << " ";
+
+    outfile << endl;
+    return true;
+}
diff --git a/source/RobotAPI/components/EarlyVisionGraph/SphericalGraph.h b/source/RobotAPI/components/EarlyVisionGraph/SphericalGraph.h
new file mode 100644
index 000000000..fc8ffdbe8
--- /dev/null
+++ b/source/RobotAPI/components/EarlyVisionGraph/SphericalGraph.h
@@ -0,0 +1,165 @@
+// *****************************************************************
+// Filename:    AspectGraph.h
+// Copyright:   Kai Welke, Chair Prof. Dillmann (IAIM),
+//              Institute for Computer Science and Engineering (CSE),
+//              University of Karlsruhe. All rights reserved.
+// Author:      Kai Welke
+// Date:        12.06.2007
+// *****************************************************************
+
+#ifndef _SPHERICAL_GRAPH_H_
+#define _SPHERICAL_GRAPH_H_
+
+// *****************************************************************
+// includes
+// *****************************************************************
+// stl includes
+#include <vector>
+#include <istream>
+#include <ostream>
+
+// local includes
+#include "Structs.h"
+
+// *****************************************************************
+// namespaces
+// *****************************************************************
+using namespace std;
+
+// *****************************************************************
+// defines
+// *****************************************************************
+#define MAX_NODES 100000
+
+// *****************************************************************
+// nodes and edges
+// *****************************************************************
+class CSGEdge
+{
+public:
+    // indices of nodes
+    int             nIndex1;
+    int             nIndex2;
+
+    // indices of faces (needed in triangulation
+    int             nLeftFace;
+    int             nRightFace;
+};
+
+class CSGNode
+{
+public:
+    CSGNode() {}
+    CSGNode(TSphereCoord position)
+    {
+        m_Position = position;
+    }
+    virtual ~CSGNode() {}
+
+    TSphereCoord getPosition()
+    {
+        return m_Position;
+    }
+    void setPosition(TSphereCoord position)
+    {
+        m_Position = position;
+    }
+
+    int getIndex()
+    {
+        return m_nIndex;
+    }
+    void setIndex(int nIndex)
+    {
+        m_nIndex = nIndex;
+    }
+
+    virtual CSGNode* clone()
+    {
+        CSGNode* copy = new CSGNode(m_Position);
+        copy->setIndex(m_nIndex);
+        return copy;
+    }
+
+protected:
+    TSphereCoord    m_Position;
+    int             m_nIndex;
+
+};
+
+// *****************************************************************
+// types
+// *****************************************************************
+typedef vector<CSGEdge*> TEdgeList;
+typedef vector<CSGNode*> TNodeList;
+
+// *****************************************************************
+// definition of class CSphericalGraph
+// *****************************************************************
+class CSphericalGraph
+{
+public:
+    ///////////////////////////////
+    // construction / destruction
+    ///////////////////////////////
+    CSphericalGraph();
+    CSphericalGraph(const CSphericalGraph& prototype);
+
+    virtual ~CSphericalGraph();
+    virtual CSGNode* getNewNode()
+    {
+        return new CSGNode();
+    }
+
+    ///////////////////////////////
+    // aspect graph manipulation
+    ///////////////////////////////
+    // clear graph
+    void clear();
+
+    // add nodes
+    int addNode(CSGNode* pNode);
+
+    // add edges
+    int addEdge(int nIndex1, int nIndex2);
+    int addEdge(int nIndex1, int nIndex2, int nLeftFace, int nRightFace);
+
+    // node adjacency (usually only required by addEdge)
+    void addNodeAdjacency(int nNode, int nAdjacency);
+
+    ///////////////////////////////
+    // member access
+    ///////////////////////////////
+    TEdgeList*          getEdges();
+    TNodeList*          getNodes();
+
+    CSGEdge*            getEdge(int nEdgeIndex);
+    CSGNode*            getNode(int nIndex);
+    vector<int>*            getNodeAdjacency(int nIndex);
+
+    ///////////////////////////////
+    // file io
+    ///////////////////////////////
+    virtual bool read(istream& infile);
+    virtual bool readNode(istream& infile);
+    virtual bool readEdge(istream& infile);
+
+    virtual bool write(ostream& outfile);
+    virtual bool writeNode(ostream& outfile, int n);
+    virtual bool writeEdge(ostream& outfile, int e);
+
+
+
+    ///////////////////////////////
+    // operators
+    ///////////////////////////////
+    CSphericalGraph& operator= (CSphericalGraph const& rhs);
+
+protected:
+    TEdgeList           m_Edges;
+    TNodeList           m_Nodes;
+    vector<int>         m_NodeAdjacency[MAX_NODES];
+
+};
+
+#endif /* _SPHERICAL_GRAPH_H_ */
diff --git a/source/RobotAPI/components/EarlyVisionGraph/Structs.h b/source/RobotAPI/components/EarlyVisionGraph/Structs.h
new file mode 100644
index 000000000..64e071bcd
--- /dev/null
+++ b/source/RobotAPI/components/EarlyVisionGraph/Structs.h
@@ -0,0 +1,85 @@
+// *****************************************************************
+// Filename:    Structs.h
+// Copyright:   Kai Welke, Chair Prof. Dillmann (IAIM),
+//              Institute for Computer Science and Engineering (CSE),
+//              University of Karlsruhe. All rights reserved.
+// Author:      Kai Welke
+// Date:        12.06.2007
+// *****************************************************************
+
+#ifndef _STRUCTS_H_
+#define _STRUCTS_H_
+
+#include <vector>
+#include <Eigen/Core>
+
+using namespace std;
+
+// *****************************************************************
+// structs
+// *****************************************************************
+
+// sphere coordinates with the following convention:
+// phi: rotation from positive z-axis (pointing up) to the vector (p-o) (around the rotated y-axis)
+// theta: rotation from the positive x-axis to the projection of the point in xy plane (around z-axis)
+struct TSphereCoord
+{
+    float fDistance;
+    float fPhi;     // zenith
+    float fTheta;   // azimuth
+};
+
+// transformation from one sphere to another
+// both spheres wiht same radius
+// psi: orientation of the view = rotation around the rotated (by spherical coords) x-axis
+struct TSphereTransform
+{
+    TSphereCoord    fPosition;
+    float           fPsi;       // orientation
+};
+
+// transformation from one sphere to another
+// both spheres wiht same radius
+// fAlpha: rotation around the z axis in counterclockwise direction considering the positive z-axis
+// fBeta: rotation around the rotated y axis in counterclockwise direction considering the positive y-axis
+struct TTransform
+{
+    float fAlpha;
+    float fBeta;
+    Eigen::Vector3d betaAxis;
+    float fPsi;
+    Eigen::Vector3d psiAxis;
+};
+
+// *****************************************************************
+// structs
+// *****************************************************************
+struct TPathElement
+{
+    TSphereCoord    Position;
+    int             nNodeIndex;
+    int             nHits;
+    float           fBestSimilarity;
+};
+
+typedef vector<TPathElement> TPath;
+
+struct THypothesis
+{
+    int             nID;
+    TPath           Path;
+    // path look-a-like rating
+    float           fRating;
+    // visual similarity of last comparison
+    float           fSimilarity;
+    // overall visual similarity
+    float           fAccSimilarity;
+    // overall rating
+    float           fOverallRating;
+    TTransform      Transform;
+    bool            bValidTransform;
+};
+
+
+
+#endif /* _STRUCTS_H_ */
-- 
GitLab