From 374ddbf40a93e048b9525da55be0a93870fa6d99 Mon Sep 17 00:00:00 2001
From: Mohcine Chraibi <m.chraibi@fz-juelich.de>
Date: Wed, 5 Jun 2019 23:46:43 +0200
Subject: [PATCH] Add interface to trains. Ready to plot from files..

---
 CMakeLists.txt                    |   1 +
 src/IO/OutputHandler.cpp          |   7 +-
 src/MainWindow.cpp                |  52 ++++++-
 src/SaxParser.cpp                 | 247 ++++++++++++++++++++++++++++++
 src/SaxParser.h                   |  14 ++
 src/SyncData.cpp                  |  15 +-
 src/SyncData.h                    |   8 +-
 src/ThreadVisualisation.cpp       | 143 ++++++++++-------
 src/ThreadVisualisation.h         |   2 +
 src/TimerCallback.cpp             | 205 ++++++++++++++++++++++++-
 src/TimerCallback.h               |   7 +
 src/extern_var.h                  |   8 +-
 src/general/Macros.h              |  15 +-
 src/geometry/Building.cpp         |  29 ++++
 src/geometry/Building.h           |  11 ++
 src/geometry/FacilityGeometry.cpp |   2 +-
 src/geometry/Room.h               |   3 +-
 17 files changed, 684 insertions(+), 85 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2d2fc34..1d3e86a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -159,6 +159,7 @@ set( HDR
   src/IO/TraVisToClient.h
   forms/Settings.h
   src/SaxParser.h
+  src/train.h
   src/Debug.h
   src/Frame.h
   src/InteractorStyle.h
diff --git a/src/IO/OutputHandler.cpp b/src/IO/OutputHandler.cpp
index 064c973..669a15d 100644
--- a/src/IO/OutputHandler.cpp
+++ b/src/IO/OutputHandler.cpp
@@ -57,8 +57,7 @@ int OutputHandler::GetErrors()
 
 void OutputHandler::Write(const string& str)
 {
-     if (this != NULL)
-          cout << str << endl;
+     cout << str << endl;
 }
 
 void OutputHandler::ProgressBar(double TotalPeds, double NowPeds)
@@ -157,10 +156,10 @@ FileHandler::~FileHandler()
 
 void FileHandler::Write(const string& str)
 {
-    if (this != NULL) {
+    // if (this != NULL) {
         _pfp << str << endl;
         _pfp.flush();
-    }
+    // }
 
     if (str.find("ERROR") != string::npos)
     {
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index 5d489c1..a4ab9c2 100755
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -808,8 +808,15 @@ bool MainWindow::addPedestrianGroup(int groupID,QString fileName)
     }
 
     SyncData* dataset=NULL;
+
     extern_trajectories_firstSet.clearFrames();
 
+
+    vtkSmartPointer<vtkSphereSource> org = vtkSphereSource::New();
+    org->SetRadius(10);
+    // extern_mysphere = org;
+
+
     switch(groupID) {
     case 1:
         Debug::Messages("handling first set");
@@ -855,6 +862,8 @@ bool MainWindow::addPedestrianGroup(int groupID,QString fileName)
     else if(fileName.endsWith(".txt",Qt::CaseInsensitive))
     {
          QString source_file= wd + QDir::separator() + SaxParser::extractSourceFileTXT(fileName);
+         QString ttt_file= wd + QDir::separator() + SaxParser::extractTrainTimeTableFileTXT(fileName);
+         QString tt_file= wd + QDir::separator() + SaxParser::extractTrainTypeFileTXT(fileName);
          QString goal_file=wd + QDir::separator() + SaxParser::extractGoalFileTXT(fileName);
          QFileInfo check_file(source_file);
          if( !(check_file.exists() && check_file.isFile()) )
@@ -864,7 +873,7 @@ bool MainWindow::addPedestrianGroup(int groupID,QString fileName)
          else
               Debug::Messages("INFO: MainWindow::addPedestrianGroup: source name: <%s>", source_file.toStdString().c_str());
 
-         check_file = source_file;
+         check_file = goal_file;
          if( !(check_file.exists() && check_file.isFile()) )
         {
              Debug::Messages("WARNING: MainWindow::addPedestrianGroup: goal name: <%s> not found!", goal_file.toStdString().c_str());
@@ -873,6 +882,25 @@ bool MainWindow::addPedestrianGroup(int groupID,QString fileName)
               Debug::Messages("INFO: MainWindow::addPedestrianGroup: goal name: <%s>", goal_file.toStdString().c_str());
 
 
+         check_file = ttt_file;
+         if( !(check_file.exists() && check_file.isFile()) )
+        {
+             Debug::Messages("WARNING: MainWindow::addPedestrianGroup: ttt name: <%s> not found!", ttt_file.toStdString().c_str());
+        }
+         else
+              Debug::Messages("INFO: MainWindow::addPedestrianGroup: ttt name: <%s>", ttt_file.toStdString().c_str());
+
+         check_file = tt_file;
+         if( !(check_file.exists() && check_file.isFile()) )
+        {
+             Debug::Messages("WARNING: MainWindow::addPedestrianGroup: tt name: <%s> not found!", tt_file.toStdString().c_str());
+        }
+         else
+              Debug::Messages("INFO: MainWindow::addPedestrianGroup: tt name: <%s>", tt_file.toStdString().c_str());
+
+
+
+
         // ------ parsing sources
         QFile file(source_file);
         QXmlInputSource source(&file);
@@ -881,14 +909,30 @@ bool MainWindow::addPedestrianGroup(int groupID,QString fileName)
         reader.setContentHandler(&handler);
         reader.parse(source);
         file.close();
+        // -----
+        // // ---- parsing goals
+        // -----
         QFile file2(goal_file);
         QXmlInputSource source2(&file2);
         reader.parse(source2);
         file2.close();
-        // -----
-        // // ---- parsing goals
-        // -----
+        // parsing trains
+        // train type
+        std::map<int, std::shared_ptr<TrainTimeTable> > trainTimeTable;
+        std::map<std::string, std::shared_ptr<TrainType> > trainTypes;
+
+        SaxParser::LoadTrainType(tt_file.toStdString(), trainTypes);
+        extern_trainTypes = trainTypes;
+
+        bool ret = SaxParser::LoadTrainTimetable(ttt_file.toStdString(), trainTimeTable);
+        if(!ret) std::cout << "hmmm\n";
+
+        extern_trainTimeTables = trainTimeTable;
+        for(auto tab: trainTimeTable)
+             std::cout << "tab: " << tab.first << "\n";
 
+        for(auto tab: trainTypes)
+             std::cout << "type: " << tab.first << "\n";
 
         if(false==SaxParser::ParseTxtFormat(fileName, dataset,&frameRate))
             return false;
diff --git a/src/SaxParser.cpp b/src/SaxParser.cpp
index 4bc76de..a0a2ca4 100644
--- a/src/SaxParser.cpp
+++ b/src/SaxParser.cpp
@@ -1199,6 +1199,70 @@ QString SaxParser::extractSourceFileTXT(QString &filename)
      return extracted_source_name;
 }
 
+QString SaxParser::extractTrainTypeFileTXT(QString &filename)
+{
+     QString extracted_tt_name="";
+     QFile file(filename);
+     QString line;
+     if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+          QTextStream in(&file);
+          while (!in.atEnd()) {
+               //look for a line with
+               line = in.readLine();
+               // std::cout << " >> " <<  line.toStdString().c_str() << endl;
+               if(line.split(":").size()==2)
+               {
+                    if(line.split(":")[0].contains("trainType",Qt::CaseInsensitive))
+                    {
+                         extracted_tt_name = line.split(":")[1].simplified().remove(' ');
+                         break;
+                    }
+               }
+          }// while
+     } // if open
+     if(extracted_tt_name=="")
+     {
+          Debug::Warning("Could not extract trainType file!");
+     }
+
+     else
+          Debug::Messages("Extracted trainType from TXT file <%s>", extracted_tt_name.toStdString().c_str());
+     return extracted_tt_name;
+}
+
+QString SaxParser::extractTrainTimeTableFileTXT(QString &filename)
+{
+     QString extracted_ttt_name="";
+     QFile file(filename);
+     QString line;
+     if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+          QTextStream in(&file);
+          while (!in.atEnd()) {
+               //look for a line with
+               line = in.readLine();
+               // std::cout << " >> " <<  line.toStdString().c_str() << endl;
+               if(line.split(":").size()==2)
+               {
+                    if(line.split(":")[0].contains("trainTimeTable",Qt::CaseInsensitive))
+                    {
+                         extracted_ttt_name = line.split(":")[1].simplified().remove(' ');
+                         break;
+                    }
+               }
+          }// while
+     } // if open
+     if(extracted_ttt_name=="")
+     {
+          Debug::Warning("Could not extract trainTimeTable file!");
+     }
+
+     else
+          Debug::Messages("Extracted trainTimeTable from TXT file <%s>", extracted_ttt_name.toStdString().c_str());
+     return extracted_ttt_name;
+}
+
+
+
 QString SaxParser::extractGoalFileTXT(QString &filename)
 {
      QString extracted_goal_name="";
@@ -1687,3 +1751,186 @@ void SaxParser::InitHeader(int major, int minor, int patch)
           exit(0);
      }
 }
+
+
+bool SaxParser::LoadTrainTimetable(std::string Filename, std::map<int, std::shared_ptr<TrainTimeTable> > & trainTimeTables)
+{
+     TiXmlDocument docTTT(Filename);
+     if (!docTTT.LoadFile()) {
+          Debug::Messages("ERROR: \t%s", docTTT.ErrorDesc());
+          Debug::Messages("ERROR: \t could not parse the train timetable file.");
+          return false;
+     }
+     TiXmlElement* xTTT = docTTT.RootElement();
+     if (!xTTT) {
+          Debug::Messages("ERROR:\tRoot element does not exist in TTT file.");
+          return false;
+     }
+     if (xTTT->ValueStr() != "train_time_table") {
+          Debug::Messages("ERROR:\tParsing train timetable file. Root element value is not 'train_time_table'.");
+          return false;
+     }
+     for (TiXmlElement* e = xTTT->FirstChildElement("train"); e;
+                    e = e->NextSiblingElement("train")) {
+          std::shared_ptr<TrainTimeTable> TTT = parseTrainTimeTableNode(e);
+          std::cout << "SI BEFORE" << trainTimeTables.size() << "\n";
+          if (TTT) { // todo: maybe get pointer to train
+               if (trainTimeTables.count(TTT->id)!=0) {
+                    Debug::Messages("WARNING: Duplicate id for train time table found [%d]",TTT->id);
+                    exit(EXIT_FAILURE);
+               }
+               std::cout << "parse " << TTT->id << "\n";
+               trainTimeTables[TTT->id] = TTT;
+          }
+          else {
+          std:cout << "HHH\n" ;
+
+               }
+          std::cout << "SI AFTER" << trainTimeTables.size() << "\n";
+     }
+
+
+     return true;
+}
+
+
+bool   SaxParser::LoadTrainType(std::string Filename, std::map<std::string, std::shared_ptr<TrainType> > & trainTypes)
+{
+
+     TiXmlDocument docTT(Filename);
+     if (!docTT.LoadFile()) {
+          Debug::Messages("ERROR: \t%s", docTT.ErrorDesc());
+          Debug::Messages("ERROR: \t could not parse the train type file.");
+          return false;
+     }
+     TiXmlElement* xTT = docTT.RootElement();
+     if (!xTT) {
+          Debug::Messages("ERROR:\tRoot element does not exist in TT file.");
+          return false;
+     }
+     if (xTT->ValueStr() != "train_type") {
+          Debug::Messages("ERROR:\tParsing train type file. Root element value is not 'train_type'.");
+          return false;
+     }
+     for (TiXmlElement* e = xTT->FirstChildElement("train"); e;
+                    e = e->NextSiblingElement("train")) {
+          std::shared_ptr<TrainType> TT = parseTrainTypeNode(e);
+          if (TT) {
+               if (trainTypes.count(TT->type)!=0) {
+                    Debug::Messages("WARNING: Duplicate type for train found [%s]",TT->type.c_str());
+               }
+               trainTypes[TT->type] = TT;
+          }
+     }
+     return true;
+
+
+}
+
+
+
+std::shared_ptr<TrainTimeTable> SaxParser::parseTrainTimeTableNode(TiXmlElement * e)
+{
+     Debug::Messages("INFO:\tLoading train time table NODE");
+     std::string caption = xmltoa(e->Attribute("caption"), "-1");
+     int id = xmltoi(e->Attribute("id"), -1);
+     std::string type = xmltoa(e->Attribute("type"), "-1");
+     int room_id = xmltoi(e->Attribute("room_id"), -1);
+     int subroom_id = xmltoi(e->Attribute("subroom_id"), -1);
+     int platform_id = xmltoi(e->Attribute("platform_id"), -1);
+     float track_start_x = xmltof(e->Attribute("track_start_x"), -1);
+     float track_start_y = xmltof(e->Attribute("track_start_y"), -1);
+     float track_end_x = xmltof(e->Attribute("track_end_x"), -1);
+     float track_end_y = xmltof(e->Attribute("track_end_y"), -1);
+
+     float train_start_x = xmltof(e->Attribute("train_start_x"),-1);
+     float train_start_y = xmltof(e->Attribute("train_start_y"), -1);
+     float train_end_x = xmltof(e->Attribute("train_end_x"), -1);
+     float train_end_y = xmltof(e->Attribute("train_end_y"), -1);
+
+     float arrival_time = xmltof(e->Attribute("arrival_time"), -1);
+     float departure_time = xmltof(e->Attribute("departure_time"), -1);
+     // @todo: check these values for correctness e.g. arrival < departure
+     Debug::Messages("INFO:\tTrain time table:");
+     Debug::Messages("INFO:\t   id: %d", id);
+     Debug::Messages("INFO:\t   type: %s", type.c_str());
+     Debug::Messages("INFO:\t   room_id: %d", room_id);
+     Debug::Messages("INFO:\t   subroom_id: %d", subroom_id);
+     Debug::Messages("INFO:\t   platform_id: %d", platform_id);
+     Debug::Messages("INFO:\t   track_start: [%.2f, %.2f]", track_start_x, track_start_y);
+     Debug::Messages("INFO:\t   track_end: [%.2f, %.2f]", track_end_x, track_end_y);
+     Debug::Messages("INFO:\t   arrival_time: %.2f", arrival_time);
+     Debug::Messages("INFO:\t   departure_time: %.2f", departure_time);
+     Point track_start(track_start_x, track_start_y);
+     Point track_end(track_end_x, track_end_y);
+     Point train_start(train_start_x, train_start_y);
+     Point train_end(train_end_x, train_end_y);
+     std::shared_ptr<TrainTimeTable> trainTimeTab = std::make_shared<TrainTimeTable>(
+          TrainTimeTable{
+                    id,
+                    type,
+                    room_id,
+                    subroom_id,
+                    arrival_time,
+                    departure_time,
+                    track_start,
+                    track_end,
+                    train_start,
+                    train_end,
+                    platform_id,
+                    false,
+                    false,
+                    });
+
+     return trainTimeTab;
+}
+
+std::shared_ptr<TrainType> SaxParser::parseTrainTypeNode(TiXmlElement * e)
+{
+     Debug::Messages("INFO:\tLoading train type");
+     // int T_id = xmltoi(e->Attribute("id"), -1);
+     std::string type = xmltoa(e->Attribute("type"), "-1");
+     int agents_max = xmltoi(e->Attribute("agents_max"), -1);
+     float length = xmltof(e->Attribute("length"), -1);
+     // std::shared_ptr<Transition> t = new Transition();
+     // std::shared_ptr<Transition> doors;
+     Transition t;
+     std::vector<Transition> doors;
+
+     for (TiXmlElement* xDoor = e->FirstChildElement("door"); xDoor;
+          xDoor = xDoor->NextSiblingElement("door")) {
+          int D_id = xmltoi(xDoor->Attribute("id"), -1);
+          float x1 = xmltof(xDoor->FirstChildElement("vertex")->Attribute("px"), -1);
+          float y1 = xmltof(xDoor->FirstChildElement("vertex")->Attribute("py"), -1);
+          float x2 = xmltof(xDoor->LastChild("vertex")->ToElement()->Attribute("px"), -1);
+          float y2 = xmltof(xDoor->LastChild("vertex")->ToElement()->Attribute("py"), -1);
+          Point start(x1, y1);
+          Point end(x2, y2);
+          float outflow = xmltof(xDoor->Attribute("outflow"), -1);
+          float dn = xmltoi(xDoor->Attribute("dn"), -1);
+          t.SetID(D_id);
+          t.SetCaption(type + std::to_string(D_id));
+          t.SetPoint1(start);
+          t.SetPoint2(end);
+          //t.SetOutflowRate(outflow);
+          //t.SetDN(dn);
+          doors.push_back(t);
+     }
+     Debug::Messages("INFO:\t   type: %s", type.c_str());
+     Debug::Messages("INFO:\t   capacity: %d", agents_max);
+     Debug::Messages("INFO:\t   number of doors: %d", doors.size());
+     for(auto d: doors)
+     {
+          Debug::Messages("INFO\t      door (%d): %s | %s", d.GetID(), d.GetPoint1().toString().c_str(), d.GetPoint2().toString().c_str());
+     }
+
+     std::shared_ptr<TrainType> Type = std::make_shared<TrainType>(
+          TrainType{
+                    type,
+                    agents_max,
+                    length,
+                    doors,
+                    });
+   return Type;
+
+}
diff --git a/src/SaxParser.h b/src/SaxParser.h
index 7e104cb..bcc5e45 100644
--- a/src/SaxParser.h
+++ b/src/SaxParser.h
@@ -35,6 +35,12 @@
 #include <vector>
 #include "SyncData.h"
 #include"geometry/GeometryFactory.h"
+#include "tinyxml/tinyxml.h"
+#include "general/Macros.h"
+
+#include "train.h"
+
+
 
 
 
@@ -90,6 +96,14 @@ public:
 
     /// parse a vtk file
     static bool ParseGradientFieldVTK(QString fileName, GeometryFactory& geoFac);
+     /// Trains
+     static bool LoadTrainTimetable(std::string filename, std::map<int, std::shared_ptr<TrainTimeTable> > & trainTimeTables);
+     static std::shared_ptr<TrainTimeTable> parseTrainTimeTableNode(TiXmlElement * e);
+     static std::shared_ptr<TrainType> parseTrainTypeNode(TiXmlElement * e);
+     static QString extractTrainTypeFileTXT(QString &filename);
+     static QString extractTrainTimeTableFileTXT(QString &filename);
+
+     static bool   LoadTrainType(std::string Filename, std::map<std::string, std::shared_ptr<TrainType> > & trainTypes);
 
 private:
     //clear the mo
diff --git a/src/SyncData.cpp b/src/SyncData.cpp
index 3b6085a..d4af0b4 100644
--- a/src/SyncData.cpp
+++ b/src/SyncData.cpp
@@ -138,6 +138,17 @@ Frame* SyncData::getFrame( int i)
 
 }
 
+vtkSmartPointer<vtkSphereSource> SyncData::getTTT()
+{
+     return _ttt;
+}
+
+void SyncData::setTTT(vtkSmartPointer<vtkSphereSource> s)
+{
+     _ttt = s;
+}
+
+
 Frame* SyncData::getNextFrame()
 {
 
@@ -193,8 +204,8 @@ Frame* SyncData::getNextFrame()
 /***
 * This method is for convenience only.
 * The normal way to get the previous frame is:
-* 		1. either set the variable extern_update_step to a negative value;
-* 		2. using the function getFrame(int frameNumber). one may first get
+*               1. either set the variable extern_update_step to a negative value;
+*               2. using the function getFrame(int frameNumber). one may first get
 * the current framecursor position using getFrameCursor()
 */
 //Frame* SyncData::getPreviousFrame()
diff --git a/src/SyncData.h b/src/SyncData.h
index 05ba080..488109d 100644
--- a/src/SyncData.h
+++ b/src/SyncData.h
@@ -42,7 +42,8 @@
 #include <memory>
 #include <vector>
 #include <map>
-
+#include <vtkSmartPointer.h>
+#include <vtkSphereSource.h>
 
 class QObject;
 class QStringList;
@@ -84,6 +85,9 @@ public:
 
     /// return the frame at position i
     Frame* getFrame(int i);
+     vtkSmartPointer<vtkSphereSource> getTTT();
+     void setTTT(vtkSmartPointer<vtkSphereSource> s);
+
 
     /// return a pointer to the next frame
     Frame* getNextFrame();
@@ -166,6 +170,8 @@ private:
     //std::vector<Frame*> _frames;
     std::map <int, Frame*> _frames;
     //std::map<int, std::unique_ptr<Frame> > _frames;
+     vtkSmartPointer<vtkSphereSource> _ttt;
+
 };
 
 #endif /* SYNCDATA_H_ */
diff --git a/src/ThreadVisualisation.cpp b/src/ThreadVisualisation.cpp
index ef079cf..4efc0ce 100644
--- a/src/ThreadVisualisation.cpp
+++ b/src/ThreadVisualisation.cpp
@@ -76,7 +76,7 @@
 #include <vtkWindowToImageFilter.h>
 #include <vtkActor.h>
 #include <vtkLightKit.h>
-
+#include <vtkPolyLine.h>
 
 #include "geometry/FacilityGeometry.h"
 #include "geometry/GeometryFactory.h"
@@ -140,7 +140,7 @@ void ThreadVisualisation::slotSetFrameRate(float fps)
 
 void ThreadVisualisation::run()
 {
-//     std::cout << "RUN " << _runningTime << "\n";
+     std::cout << "RUN " << _runningTime << "\n";
     //deactivate the output windows
     vtkObject::GlobalWarningDisplayOff();
 
@@ -180,59 +180,83 @@ void ThreadVisualisation::run()
     //renderer->AddActor(axis);
 
     //add big circle at null point
-    {
-        vtkSphereSource* org = vtkSphereSource::New();
-        org->SetRadius(300);
-
-        vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
-        mapper->SetInputConnection(org->GetOutputPort());
-        org->Delete();
-
-        // create actor
-        vtkActor* actor = vtkActor::New();
-        actor->SetMapper(mapper);
-        mapper->Delete();
-        actor->GetProperty()->SetColor(.90,.90,0.0);
-        actor->Delete();
-        //renderer->AddActor(actor);
-    }
-    //add another big circle at null point
-    {
-        vtkSphereSource* org = vtkSphereSource::New();
-        org->SetRadius(300);
-        //org->SetCenter(50,80,0);
-
-        vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
-        mapper->SetInputConnection(org->GetOutputPort());
-        org->Delete();
-
-        // create actor
-        vtkActor* actor = vtkActor::New();
-        actor->SetMapper(mapper);
-        mapper->Delete();
-        actor->GetProperty()->SetColor(.90,.90,0.0);
-        actor->SetPosition(5000,8000,0);
-        actor->Delete();
-        //renderer->AddActor(actor);
-    }
-
-
-    // Create a real circle, not a sphere
-    {
-        VTK_CREATE(vtkRegularPolygonSource, polygonSource);
-        polygonSource->GeneratePolygonOff();
-        polygonSource->SetNumberOfSides(50);
-        polygonSource->SetRadius(1000);
-        polygonSource->SetCenter(0,0,0);
-        polygonSource->Update();
-
-        VTK_CREATE(vtkPolyDataMapper,mapper);
-        mapper->SetInputConnection(polygonSource->GetOutputPort());
-        VTK_CREATE(vtkActor,actor);
-        actor->GetProperty()->SetColor(180.0/255,180.0/255.0,180.0/255.0);
-        actor->SetMapper(mapper);
-        //renderer->AddActor(actor);
-    }
+    // {
+    //      vtkSphereSource* org = vtkSphereSource::New();
+    //     org->SetRadius(10);
+    //     vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
+    //     mapper->SetInputConnection(org->GetOutputPort());
+    //     org->Delete();
+    //     //------
+    //     // create actor
+    //     vtkActor* actor = vtkActor::New();
+    //     actor->SetMapper(mapper);
+    //     mapper->Delete();
+    //     actor->GetProperty()->SetColor(.1,.10,0.0);
+    //     _renderer->AddActor(actor);
+    //     actor->Delete();
+    //      mysphere;
+    //     //
+    // }
+    // {
+    //     vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
+    //     mapper->SetInputConnection(extern_mysphere->GetOutputPort());
+    //     //------
+    //     // create actor
+    //     vtkActor* actor = vtkActor::New();
+    //     actor->SetMapper(mapper);
+    //     mapper->Delete();
+    //     actor->GetProperty()->SetColor(.1,.10,0.0);
+    //     _renderer->AddActor(actor);
+    //     actor->Delete();
+    //     //
+    // }
+
+    // {
+    //      // Train
+    //      double p0[3] = {1.0*100, 4.0*100, 0.0};
+    //      double p1[3] = {3.0*100, 4.0*100, 0.0};
+    //      double p2[3] = {3.0*100, 5.0*100, 0.0};
+    //      double p3[3] = {1.0*100, 5.0*100, 0.0};
+    //      double p4[3] = {1.0*100, 4.0*100, 0.0};
+    //      // Create a vtkPoints object and store the points in it
+    //      VTK_CREATE(vtkPoints, points);
+
+    //      points->InsertNextPoint(p0);
+    //      points->InsertNextPoint(p1);
+    //      points->InsertNextPoint(p2);
+    //      points->InsertNextPoint(p3);
+    //      points->InsertNextPoint(p4);
+
+    //      VTK_CREATE(vtkPolyLine, polyLine);
+
+    //      polyLine->GetPointIds()->SetNumberOfIds(5);
+    //      for(unsigned int i = 0; i < 5; i++)
+    //      {
+    //           polyLine->GetPointIds()->SetId(i,i);
+    //      }
+
+    //      // Create a cell array to store the lines in and add the lines to it
+    //      VTK_CREATE(vtkCellArray, cells);
+    //      cells->InsertNextCell(polyLine);
+
+    //      // Create a polydata to store everything in
+    //      VTK_CREATE(vtkPolyData, polyData);
+
+    //      // Add the points to the dataset
+    //      polyData->SetPoints(points);
+
+    //      // Add the lines to the dataset
+    //      polyData->SetLines(cells);
+
+    //      VTK_CREATE(vtkPolyDataMapper, mapper);
+    //      mapper->SetInputData(polyData);
+
+
+    //      VTK_CREATE(vtkActor, actor);
+    //      actor->SetMapper(mapper);
+    //      actor->GetProperty()->SetColor(.1,.10,0.0);
+    //     _renderer->AddActor(actor);
+    // }
 
     // Create the render window
     _renderWindow = vtkRenderWindow::New();
@@ -302,6 +326,10 @@ void ThreadVisualisation::run()
     renderingTimer->setTextActor(_runningTime);
     _renderWinInteractor->AddObserver(vtkCommand::TimerEvent,renderingTimer);
 
+
+
+
+
     //create the necessary connections
     QObject::connect(renderingTimer, SIGNAL(signalRunningTime(unsigned long )),
                      this->parent(), SLOT(slotRunningTime(unsigned long )));
@@ -311,8 +339,7 @@ void ThreadVisualisation::run()
 
     QObject::connect(renderingTimer, SIGNAL(signalRenderingTime(int)),
                      this->parent(), SLOT(slotRenderingTime(int)));
-//    std::cout << "timer " << timer << "\n";
-
+   std::cout << "timer " << timer << "\n";
     // Create my interactor style
     InteractorStyle* style = InteractorStyle::New();
     _renderWinInteractor->SetInteractorStyle( style );
@@ -586,7 +613,7 @@ void ThreadVisualisation::initGlyphs3D()
         //importer->GetRenderWindow()->GetInteractor()->Start();
 
         ////collect all the elements from the 3ds
-        vtkActorCollection* collection=importer->GetRenderer()->GetActors();
+        vtkActorCollection* collection=importer->GetRenderer()x->GetActors();
         vtkActor *actorCharlie= collection->GetLastActor();
         actorCharlie->InitPathTraversal();
         vtkMapper *mapperCharlie=actorCharlie->GetMapper();
diff --git a/src/ThreadVisualisation.h b/src/ThreadVisualisation.h
index efe0288..32560b5 100644
--- a/src/ThreadVisualisation.h
+++ b/src/ThreadVisualisation.h
@@ -74,6 +74,8 @@ extern  vtkActor* extern_glyphs_pedestrians_actor_2D;
 extern  vtkActor* extern_glyphs_pedestrians_actor_3D;
 
 extern SyncData extern_trajectories_firstSet;
+// extern vtkSmartPointer<vtkSphereSource> extern_mysphere;
+
 
 class ThreadVisualisation :public QThread {
     Q_OBJECT
diff --git a/src/TimerCallback.cpp b/src/TimerCallback.cpp
index 416ed69..ace0694 100644
--- a/src/TimerCallback.cpp
+++ b/src/TimerCallback.cpp
@@ -77,8 +77,12 @@
 #include <vtkLabeledDataMapper.h>
 #include <vtkMath.h>
 
-
-
+#include <vtkPolyLine.h>
+#include <vtkTextProperty.h>
+#include <vtkProperty.h>
+#include <vtkLineSource.h>
+#include <vtkVectorText.h>
+#include <vtkFollower.h>
 
 #include "geometry/FacilityGeometry.h"
 #include "geometry/Point.h"
@@ -126,6 +130,10 @@ void TimerCallback::Execute(vtkObject *caller, unsigned long eventId,
             vtkRenderWindow  *renderWindow = iren->GetRenderWindow();
             vtkRenderer *renderer =renderWindow->GetRenderers()->GetFirstRenderer();
 
+
+
+
+
             if (iren && renderWindow && renderer) {
 
                 //first pedestrian group
@@ -145,8 +153,118 @@ void TimerCallback::Execute(vtkObject *caller, unsigned long eventId,
                         frame = extern_trajectories_firstSet.getNextFrame();
                     }
 
+
                         frameNumber=extern_trajectories_firstSet.getFrameCursor();
 
+
+                        double now = frameNumber*iren->GetTimerDuration(tid)/1000;
+                        VTK_CREATE(vtkActor, trainActor);
+                        VTK_CREATE(vtkActor, doorActor);
+                        VTK_CREATE(vtkActor, doorActor22);
+                        // std::cout << "HH " <<extern_trainTypes["RE"]->nmax << "\n";
+                        // std::cout << "Tab " <<extern_trainTimeTables[1]->id << "\n";
+                        auto polyData = train(0.8, 4.1, 5.2, 4.5);
+                        auto doorData = door(1, 4.1, 3.0, 4.1);
+                        auto doorData2 = door(3.5, 4.1, 5.0, 4.1);
+                        if ( now >= 5 && now < 10){
+                             trainActor->GetProperty()->SetColor(.1,.10,0.0);
+                             trainActor->GetProperty()->SetLineWidth(5);
+                             VTK_CREATE(vtkPolyDataMapper, mapper);
+                             mapper->SetInputData(polyData);
+                             trainActor->SetMapper(mapper);
+                             // door
+                             doorActor->GetProperty()->SetColor(renderer->GetBackground());
+                             doorActor->GetProperty()->SetLineWidth(5);
+                             VTK_CREATE(vtkPolyDataMapper, doorMapper);
+                             doorMapper->SetInputConnection(doorData->GetOutputPort());
+                             doorActor->SetMapper(doorMapper);
+
+                             doorActor22->GetProperty()->SetColor(renderer->GetBackground());
+                             doorActor22->GetProperty()->SetLineWidth(5);
+                             VTK_CREATE(vtkPolyDataMapper, doorMapper2);
+                             doorMapper2->SetInputConnection(doorData2->GetOutputPort());
+                             doorActor22->SetMapper(doorMapper2);
+
+                             // text
+                             VTK_CREATE(vtkTextActor, textActor);
+                             textActor->SetInput ( "RE" );
+                             textActor->SetPosition ( 300, 600 );
+                             textActor->GetTextProperty()->SetFontSize ( 24 );
+                             textActor->GetTextProperty()->SetColor ( 1.0, 0.0, 0.0 );
+                             // add renderer
+                             renderer->AddActor(trainActor);
+                             renderer->AddActor(doorActor);
+                             renderer->AddActor(doorActor22);
+                             renderer->AddActor(textActor);
+                        }
+                        else
+                        {
+                             trainActor->GetProperty()->SetColor(renderer->GetBackground());
+                             trainActor->GetProperty()->SetLineWidth(5);
+                             VTK_CREATE(vtkPolyDataMapper, mapper);
+                             mapper->SetInputData(polyData);
+                             trainActor->SetMapper(mapper);
+                             VTK_CREATE(vtkTextActor, textActor);
+                             textActor->SetInput ( "RE" );
+                             textActor->SetPosition ( 300, 600 );
+                             textActor->GetTextProperty()->SetFontSize ( 24 );
+                             textActor->GetTextProperty()->SetColor(renderer->GetBackground());
+                             renderer->AddActor(textActor);
+                             renderer->AddActor(trainActor);
+                        }
+                        // ICE
+                        auto polyData2 = train(6.3, 4.1, 9.7, 4.5);
+                        auto doorData22 = door(6.5, 4.1, 9.5, 4.1);
+                        VTK_CREATE(vtkActor, trainActor2);
+                        VTK_CREATE(vtkActor, doorActor2);
+                        if ( now >= 15 && now < 35){
+                             trainActor2->GetProperty()->SetColor(1,.5,1);
+                             trainActor2->GetProperty()->SetLineWidth(5);
+                             VTK_CREATE(vtkPolyDataMapper, mapper);
+                             mapper->SetInputData(polyData2);
+                             trainActor2->SetMapper(mapper);
+                             // door
+                             doorActor2->GetProperty()->SetColor(renderer->GetBackground());
+                             doorActor2->GetProperty()->SetLineWidth(5);
+                             VTK_CREATE(vtkPolyDataMapper, doorMapper);
+                             doorMapper->SetInputConnection(doorData22->GetOutputPort());
+                             doorActor2->SetMapper(doorMapper);
+                             // text
+                             VTK_CREATE(vtkTextActor, textActor);
+                             textActor->SetInput ( "ICE" );
+                             textActor->SetPosition ( 700, 600 );
+                             textActor->GetTextProperty()->SetFontSize ( 24 );
+                             textActor->GetTextProperty()->SetColor ( 1.0, 0.0, 0.0 );
+
+                             // renderer
+                             renderer->AddActor(trainActor2);
+                             renderer->AddActor(doorActor2);
+                             renderer->AddActor(textActor);
+                        }
+                        else
+                        {
+                             trainActor2->GetProperty()->SetColor(renderer->GetBackground());
+                             trainActor2->GetProperty()->SetLineWidth(5);
+                             VTK_CREATE(vtkPolyDataMapper, mapper);
+                             mapper->SetInputData(polyData2);
+                             trainActor2->SetMapper(mapper);
+                             // text
+                             VTK_CREATE(vtkTextActor, textActor);
+                             textActor->SetInput ( "ICE" );
+                             textActor->SetPosition ( 700, 600 );
+                             textActor->GetTextProperty()->SetFontSize ( 24 );
+                             textActor->GetTextProperty()->SetColor (renderer->GetBackground());
+
+                             renderer->AddActor(trainActor2);
+                             renderer->AddActor(textActor);
+                        }
+
+
+
+                        // std::cout << "   TimerCallback::Execute " << frameNumber <<  " " << frameNumber*iren->GetTimerDuration(tid)/1000<< "\n";
+
+
+
                     if(frame==NULL)
                     {
 
@@ -205,7 +323,7 @@ void TimerCallback::Execute(vtkObject *caller, unsigned long eventId,
                 int* winSize=renderWindow->GetSize();
                 static int  lastWinX=winSize[0]+1; // +1 to trigger a first change
                 static int lastWinY=winSize[1];
-
+                // HHHHHH
                 sprintf(runningTimeText,"Pedestrians: %d      Time: %ld Sec",nPeds,frameNumber*iren->GetTimerDuration(tid)/1000);
                 runningTime->SetInput(runningTimeText);
                 runningTime->Modified();
@@ -252,6 +370,7 @@ void TimerCallback::Execute(vtkObject *caller, unsigned long eventId,
                     emit signalFrameNumber(frameNumber, minFrame);
                     emit signalRunningTime(frameNumber*iren->GetTimerDuration(tid));
                     emit signalRenderingTime(effectivefps);
+
                 }
 
 #ifdef TRAVISTO_FFMPEG
@@ -542,3 +661,83 @@ void TimerCallback::setTextActor(vtkTextActor* ra)
 {
     runningTime=ra;
 }
+
+vtkSmartPointer<vtkPolyData> TimerCallback::train(double x1, double y1, double x2, double y2)
+{
+     // Train
+     double p0[3] = {x1*100, y1*100, 0.0};
+     double p1[3] = {x2*100, y1*100, 0.0};
+     double p2[3] = {x2*100, y2*100, 0.0};
+     double p3[3] = {x1*100, y2*100, 0.0};
+     double p4[3] = {x1*100, y1*100, 0.0};
+     // Create a vtkPoints object and store the points in it
+
+     VTK_CREATE(vtkPoints, points);
+
+     points->InsertNextPoint(p0);
+     points->InsertNextPoint(p1);
+     points->InsertNextPoint(p2);
+     points->InsertNextPoint(p3);
+     points->InsertNextPoint(p4);
+
+     VTK_CREATE(vtkPolyLine, polyLine);
+
+     polyLine->GetPointIds()->SetNumberOfIds(5);
+     for(unsigned int i = 0; i < 5; i++)
+     {
+          polyLine->GetPointIds()->SetId(i,i);
+     }
+
+     // Create a cell array to store the lines in and add the lines to it
+     VTK_CREATE(vtkCellArray, cells);
+     cells->InsertNextCell(polyLine);
+
+     // Create a polydata to store everything in
+     VTK_CREATE(vtkPolyData, polyData);
+
+     // Add the points to the dataset
+     polyData->SetPoints(points);
+
+     // Add the lines to the dataset
+     polyData->SetLines(cells);
+     return polyData;
+
+
+}
+
+vtkSmartPointer<vtkLineSource> TimerCallback::door(double x1, double y1, double x2, double y2)
+{
+     // Train
+     double p0[3] = {x1*100, y1*100, 0.0};
+     double p1[3] = {x2*100, y2*100, 0.0};
+     // Create a vtkPoints object and store the points in it
+
+     VTK_CREATE(vtkPoints, points);
+
+     points->InsertNextPoint(p0);
+     points->InsertNextPoint(p1);
+
+     VTK_CREATE(vtkLineSource, lineSource);
+     lineSource->SetPoint1(p0);
+     lineSource->SetPoint2(p1);
+     lineSource->Update();
+     // polyLine->GetPointIds()->SetNumberOfIds(5);
+     // for(unsigned int i = 0; i < 5; i++)
+     // {
+     //      polyLine->GetPointIds()->SetId(i,i);
+     // }
+
+     // Create a cell array to store the lines in and add the lines to it
+     // VTK_CREATE(vtkCellArray, cells);
+     // cells->InsertNextCell(polyLine);
+
+     // Create a polydata to store everything in
+     // VTK_CREATE(vtkPolyData, polyData);
+
+     // Add the points to the dataset
+     // polyData->SetPoints(points);
+
+     // Add the lines to the dataset
+     // polyData->SetLines(cells);
+     return lineSource;
+}
diff --git a/src/TimerCallback.h b/src/TimerCallback.h
index 836aa13..1b2b7e8 100644
--- a/src/TimerCallback.h
+++ b/src/TimerCallback.h
@@ -52,6 +52,8 @@ class vtkFFMPEGWriter;
 #include <vtkTensorGlyph.h>
 #include <vtkSmartPointer.h>
 #include <vtkPolyDataMapper.h>
+#include <vtkLineSource.h>
+#include "train.h"
 
 class SyncData;
 class QObject;
@@ -89,6 +91,9 @@ extern PointPlotter* extern_trail_plotter;
 
 extern SyncData extern_trajectories_firstSet;
 
+extern SyncData mysphere;
+extern std::map<std::string, std::shared_ptr<TrainType> > extern_trainTypes;
+extern std::map<int, std::shared_ptr<TrainTimeTable> > extern_trainTimeTables;
 //states if the datasets are loaded.
 extern bool extern_first_dataset_loaded;
 
@@ -126,6 +131,8 @@ public:
     void SetRenderTimerId(int tid);
 
     void setTextActor(vtkTextActor* runningTime);
+     vtkSmartPointer<vtkPolyData> train(double x1, double y1, double x2, double y2);
+     vtkSmartPointer<vtkLineSource> door(double x1, double y1, double x2, double y2);
 
 private:
     ///updates system global changes, like fullscreen, ffw and soone
diff --git a/src/extern_var.h b/src/extern_var.h
index 99bab85..2d9f1ea 100644
--- a/src/extern_var.h
+++ b/src/extern_var.h
@@ -46,10 +46,9 @@
 #include <vtkSmartPointer.h>
 #include <vtkPolyDataMapper.h>
 
-
-
+#include "train.h"
 #define VTK_CREATE(type, name) \
-		vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
+                vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
 
 //external variables
 /// define the speed/rate/pace at which  the trajectories are displayed.
@@ -84,6 +83,9 @@ double extern_scale_pedestrian=0.1;
 // At most three pedestrians groups can be loaded
 ///The first pedestrian group
 Pedestrian** extern_pedestrians_firstSet=NULL;
+vtkSmartPointer<vtkSphereSource> extern_mysphere=nullptr;
+std::map<std::string, std::shared_ptr<TrainType> > extern_trainTypes;
+std::map<int, std::shared_ptr<TrainTimeTable> > extern_trainTimeTables;
 
 
 //vtkSmartPointer<vtkTensorGlyph> extern_glyphs_pedestrians=NULL;
diff --git a/src/general/Macros.h b/src/general/Macros.h
index 92bbd4a..3f6e326 100644
--- a/src/general/Macros.h
+++ b/src/general/Macros.h
@@ -25,7 +25,7 @@
  *
  *
  **/
- 
+
 
 #ifndef _MACROS_H
 #define _MACROS_H
@@ -39,9 +39,15 @@
 #include <iostream>
 
 
+enum RoomState {
+     ROOM_CLEAN=0,
+     ROOM_SMOKED=1
+};
+
+
 #ifndef M_PI
 #define M_PI 3.14159265358979323846
-#endif 
+#endif
 
 //fix for osx/linux/win
 #define  _isnan(x) std::isnan(x)
@@ -89,11 +95,6 @@
 #define LIST_EMPTY  -1
 
 
-enum RoomState {
-     ROOM_CLEAN=0,
-     ROOM_SMOKED=1
-};
-
 enum AgentType {
      MALE=0,
      FEMALE,
diff --git a/src/geometry/Building.cpp b/src/geometry/Building.cpp
index 482384d..8b1433f 100644
--- a/src/geometry/Building.cpp
+++ b/src/geometry/Building.cpp
@@ -82,6 +82,35 @@ Building::Building(const std::string& filename, const std::string& rootDir, Rout
 }
 #endif
 
+// bool Building::AddTrainType(std::shared_ptr<TrainType> TT)
+// {
+//       if (_trainTypes.count(TT->type)!=0) {
+//             // Log->Write("WARNING: Duplicate type for train found [%s]",TT->type);
+//       }
+//       _trainTypes[TT->type] = TT;
+//       return true;
+// }
+
+// bool Building::AddTrainTimeTable(std::shared_ptr<TrainTimeTable> TTT)
+// {
+//       if (_trainTimeTables.count(TTT->id)!=0) {
+//             Log->Write("WARNING: Duplicate id for train time table found [%d]",TTT->id);
+//             exit(EXIT_FAILURE);
+//       }
+//       _trainTimeTables[TTT->id] = TTT;
+//       return true;
+// }
+// const std::map<std::string, std::shared_ptr<TrainType> >& Building::GetTrainTypes() const
+// {
+//       return _trainTypes;
+// }
+
+// const std::map<int, std::shared_ptr<TrainTimeTable> >& Building::GetTrainTimeTables() const
+// {
+//       return _trainTimeTables;
+// }
+
+
 Building::~Building()
 {
      //
diff --git a/src/geometry/Building.h b/src/geometry/Building.h
index 7497f78..4c4db41 100644
--- a/src/geometry/Building.h
+++ b/src/geometry/Building.h
@@ -43,6 +43,12 @@
 #include "Obstacle.h"
 #include "Goal.h"
 #include "../tinyxml/tinyxml.h"
+
+// train schedules: Trains get deleted and added.
+
+
+
+
 class RoutingEngine;
 class Pedestrian;
 class Transition;
@@ -67,6 +73,8 @@ private:
      std::map<int, Hline*> _hLines;
      std::map<int, Goal*>_goals;
 
+
+
      /// pedestrians pathway
      bool _savePathway;
      std::ofstream _pathWayStream;
@@ -101,6 +109,9 @@ public:
      Transition* GetTransition(int id) ;
      Transition* ParseTransitionNode(TiXmlElement * xTrans);
 
+
+
+
      /**
       * Not implemented
       */
diff --git a/src/geometry/FacilityGeometry.cpp b/src/geometry/FacilityGeometry.cpp
index 3fbfd5b..4249d9f 100644
--- a/src/geometry/FacilityGeometry.cpp
+++ b/src/geometry/FacilityGeometry.cpp
@@ -578,7 +578,7 @@ void FacilityGeometry::addObstacles(vtkPolyData* polygonPolyData )
 void FacilityGeometry::addRectangle(double x1, double y1, double x2, double y2, double z, double color1, double color2, string text)
 {
     //if(z!=1)return;
-     const double cellSize=40; //cm
+     const double cellSize=10; //cm
     //	const int dimX=(x2-x1)/cellSize+1;
     //	const int dimY=(y2-y1)/cellSize+1;
 
diff --git a/src/geometry/Room.h b/src/geometry/Room.h
index 7abe606..176f86e 100644
--- a/src/geometry/Room.h
+++ b/src/geometry/Room.h
@@ -23,7 +23,7 @@
  *
  *
  **/
- 
+
 
 #ifndef _ROOM_H
 #define _ROOM_H
@@ -165,4 +165,3 @@ public:
 };
 
 #endif  /* _ROOM_H */
-
-- 
GitLab