Skip to content
Snippets Groups Projects
Select Git revision
  • master default protected
  • 67-multithreading-is-plattform-dependent
  • cmake_windows
  • v0.8.4
  • v0.8.3
  • v0.8.2
  • v0.8
  • v0.7
  • v0.6
  • v0.5-alpha
  • v0.4
11 results

SaxParser.cpp

Blame
  • SaxParser.cpp 65.10 KiB
    /**
     * @file    SaxParser.cpp
     * @author  Ulrich Kemloh <kemlohulrich@gmail.com>
     * @version 0.1
     * Created on: 6 Sep 2010
     * Copyright (C) <2009-2010>
     *
     * @section LICENSE
     * This file is part of JuPedSim.
     *
     * JuPedSim is free software: you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation, either version 3 of the License, or
     * any later version.
     *
     * OpenPedSim is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     * GNU General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License
     * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>.
     *
     * @section DESCRIPTION
     *
     *
     *
     */
    
    #include "SaxParser.h"
    #include "TrajectoryPoint.h"
    #include "FrameElement.h"
    #include "Frame.h"
    #include "SyncData.h"
    #include "Debug.h"
    
    #include "geometry/JPoint.h"
    #include "geometry/FacilityGeometry.h"
    #include "geometry/Building.h"
    #include "geometry/GeometryFactory.h"
    
    #include "geometry/Wall.h"
    #include "geometry/SubRoom.h"
    
    #include "SystemSettings.h"
    
    #include <QMessageBox>
    #include <QString>
    #include <QProgressDialog>
    #include <QPushButton>
    #include <limits>
    #include <iostream>
    #include <cmath>
    
    #include <vtkVersion.h>
    #include <vtkSmartPointer.h>
    #include <vtkPolygon.h>
    #include <vtkCellArray.h>
    #include <vtkPolyData.h>
    #include <vtkPolyDataMapper.h>
    #include <vtkActor.h>
    #include <vtkRenderWindow.h>
    #include <vtkRenderer.h>
    #include <vtkRenderWindowInteractor.h>
    #include <vtkAssembly.h>
    #include <vtkProperty.h>
    #include <vtkTriangleFilter.h>
    #include <vtkGenericDataObjectReader.h>
    #include <vtkPolyDataReader.h>
    #include <vtkStructuredGridReader.h>
    #include <vtkStructuredPointsReader.h>
    #include <vtkImageDataGeometryFilter.h>
    #include <vtkStripper.h>
    
    
    #define VTK_CREATE(type, name)                                  \
         vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
    
    
    using namespace std;
    
    /**
     * constructor
     *
     * @param geo
     * @param data
     * @param par 0=fps, 1=agents
     * @param roomCaption
     * @return
     */
    SaxParser::SaxParser(GeometryFactory& geoFac, SyncData& dataset, double * fps):_geoFactory(geoFac),_dataset(dataset)
    {
         _para=fps;
         _parsingWalls=false;
         _parsingCrossings=false;
         _color=0.0;
         _dataset.clearFrames();
    
         _geometry = std::shared_ptr<FacilityGeometry>(new FacilityGeometry("No name", "No name", "No name"));
         _geoFactory.AddElement(-1,-1,_geometry);
    
         //default header
         InitHeader(0,0,0);
    }
    
    SaxParser::~SaxParser()
    {
    
    }
    
    bool SaxParser::startElement(const QString & /* namespaceURI */,
                                 const QString & /* localName */, const QString &qName,
                                 const QXmlAttributes &at)
    {
         if (qName == "header") {
              for(int i=0; i<at.length(); i++) {
                   if(at.localName(i)=="version") {
                        QStringList query = at.value(i).split(".");
                        int major=0;
                        int minor=0;
                        int patch=0;
                        switch (query.size() ) {
                        case 1:
                             major=query.at(0).toInt();
                             break;
                        case 2:
                             major=query.at(0).toInt();
                             minor=query.at(1).toInt();
                             break;
                        case 3:
                             major=query.at(0).toInt();
                             minor=query.at(1).toInt();
                             patch=query.at(2).toInt();
                             break;
                        }
                        InitHeader(major,minor,patch);
                        //cout<<"version found:"<<at.value(i).toStdString()<<endl;exit(0);
                   }
              }
         } else if (qName == "file") {
              for(int i=0; i<at.length(); i++) {
                   if(at.localName(i)=="location") {
                        QString fileName=at.value(i);
                        if(!fileName.isEmpty()) {
                             if(fileName.endsWith(".xml",Qt::CaseInsensitive)) {
                                  //SaxParser::parseGeometryJPS(fileName,geometry);
                             } else if (fileName.endsWith(".trav",Qt::CaseInsensitive)) {
                                  SaxParser::parseGeometryTRAV(fileName,_geoFactory);
                             }
                        }
                   }
              }
         }
         else if (qName == "source")
         {
              double xmin, xmax, ymin, ymax;
              double z=0;// @todo read this some when we go 3D
    
              int source_id=-1;
              for(int i=0; i<at.length(); i++) {
                   if(at.localName(i)=="id") {
                        source_id=at.value(i).toInt();
                   } else if(at.localName(i)=="x_min") {
                        xmin=at.value(i).toDouble()*FAKTOR;
                   }
                   else if(at.localName(i)=="x_max") {
                        xmax=at.value(i).toDouble()*FAKTOR;
                   }
                   else if(at.localName(i)=="y_min") {
                        ymin=at.value(i).toDouble()*FAKTOR;
                   }
                   else if(at.localName(i)=="y_max") {
                        ymax=at.value(i).toDouble()*FAKTOR;
                   }
              }
              _geometry->addSource(xmin,ymin,xmax,ymax);
    
              // double CHT[3]= {_color,_height,_thickness};
              // JPoint* pt1= new JPoint(xmin,ymin,z);
              // JPoint* pt2= new JPoint(xmin,ymax,z);
              // JPoint* pt3= new JPoint(xmax,ymin,z);
              // JPoint* pt4= new JPoint(xmax,ymax,z);
              // pt1->setColorHeightThicknes(CHT);
              // pt2->setColorHeightThicknes(CHT);
              // pt3->setColorHeightThicknes(CHT);
              // pt4->setColorHeightThicknes(CHT);
              // _currentPointsList.push_back(pt1);
              // _currentPointsList.push_back(pt2);
              // _currentPointsList.push_back(pt3);
              // _currentPointsList.push_back(pt4);
         } // source
         else if (qName == "floor") {
              double xMin=0,
                   xMax=0,
                   yMin=0,
                   yMax=0;
    
              for(int i=0; i<at.length(); i++) {
                   if(at.localName(i)=="xMin") {
                        xMin=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="xMax") {
                        xMax=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="yMin") {
                        yMin=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="yMax") {
                        yMax=at.value(i).toDouble()*FAKTOR;
                   }
    
              }
              _geometry->addFloor(xMin,yMin,xMax,yMax);
         } else if (qName == "cuboid") {
              double length=0, height=0,
                   width=0, color=0;
              double center[3]= {0,0,0};
    
              for(int i=0; i<at.length(); i++) {
                   if(at.localName(i)=="centerX") {
                        center[0]=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="centerY") {
                        center[1]=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="centerZ") {
                        center[2]=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="length") {
                        length=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="height") {
                        height=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="width") {
                        width=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="color") {
                        color=at.value(i).toDouble()*FAKTOR;
                   }
              }
              _geometry->addObjectBox(center,height,width,length,color);
    
         } else if (qName == "sphere") {
              double radius=0, color=0;
              double center[3]= {0,0,0};
    
              for(int i=0; i<at.length(); i++) {
                   if(at.localName(i)=="centerX") {
                        center[0]=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="centerY") {
                        center[1]=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="centerZ") {
                        center[2]=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="radius") {
                        radius=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="color") {
                        color=at.value(i).toDouble();
                   }
              }
              _geometry->addObjectSphere(center,radius,color);
         } else if (qName == "label") {
              double  color=0;
              double center[3]= {0,0,0};
              QString text;
    
              for(int i=0; i<at.length(); i++) {
                   if(at.localName(i)=="centerX") {
                        center[0]=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="centerY") {
                        center[1]=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="centerZ") {
                        center[2]=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="text") {
                        text=at.value(i);
                   } else if(at.localName(i)=="color") {
                        color=at.value(i).toDouble();
                   }
              }
              _geometry->addObjectLabel(center,center,text.toStdString(),color);
         } else if (qName == "cylinder") {
              double height=0, radius=0, color=0;
              double center[3]= {0,0,0};
              double rotation[3]= {0,0,0};
    
              for(int i=0; i<at.length(); i++) {
                   if(at.localName(i)=="centerX") {
                        center[0]=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="centerY") {
                        center[1]=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="centerZ") {
                        center[2]=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="height") {
                        height=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="radius") {
                        radius=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="color") {
                        color=at.value(i).toDouble();
                   } else if(at.localName(i)=="angleX") {
                        rotation[0]=at.value(i).toDouble();
                   } else if(at.localName(i)=="angleY") {
                        rotation[1]=at.value(i).toDouble();
                   } else if(at.localName(i)=="angleZ") {
                        rotation[2]=at.value(i).toDouble();
                   }
              }
              _geometry->addObjectCylinder(center,radius,height,rotation,color);
         } else if (qName == "agents") {
         } else if (qName == "roomCaption") {
         } else if (qName == "frameRate") {
         } else if (qName == "geometry")
         {
              //cout<<"geo tag found"<<endl;
              //_geometry = std::shared_ptr<FacilityGeometry>(new FacilityGeometry("No name"));
              //_geoFactory.AddElement(0,0,_geometry);
    
         }else if (qName == "gradient_field"){
              for(int i=0; i<at.length(); i++) {
                   if(at.localName(i)=="filename") {
                        ParseGradientFieldVTK(at.value(i),_geoFactory);
                   }
              }
    
         }
         else if (qName == "wall") {
              _parsingWalls=true;
              _thickness=15;
              _height=250;
              _color=0;
              _caption="";
    
              for(int i=0; i<at.length(); i++) {
                   if(at.localName(i)=="thickness") {
                        _thickness=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="height") {
                        _height=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="color") {
                        _color=at.value(i).toDouble();
                   } else if(at.localName(i)=="caption") {
                        _caption=at.value(i);
                   }
              }
    
         } else if (qName == "door") {
              _parsingWalls=false;
              _thickness=15;
              _height=250;
              _color=255;
              _caption="";
    
              for(int i=0; i<at.length(); i++) {
                   if(at.localName(i)=="thickness") {
                        _thickness=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="height") {
                        _height=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="color") {
                        _color=at.value(i).toDouble();
                   } else if(at.localName(i)=="caption") {
                        _caption=at.value(i);
                   }
              }
    
         }
    //FIXME
         else if (qName == "crossing") {
              _parsingWalls=false;
              _parsingCrossings=true;
              _thickness=15;
              _height=250;
              _color=255;
              _caption="";
    
              for(int i=0; i<at.length(); i++) {
                   if(at.localName(i)=="thickness") {
                        _thickness=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="height") {
                        _height=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="color") {
                        _color=at.value(i).toDouble();
                   } else if(at.localName(i)=="caption") {
                        _caption=at.value(i);
                   }
              }
    
         }else if (qName == "hline") {
              _parsingWalls=false;
              _parsingCrossings=true;
              _thickness=15;
              _height=250;
              _color=255;
              _caption="";
              QString room_id, subroom_id;
    
              for(int i=0; i<at.length(); i++) {
                   if(at.localName(i)=="thickness") {
                        _thickness=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="height") {
                        _height=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="color") {
                        _color=at.value(i).toDouble();
                   } else if(at.localName(i)=="caption") {
                        _caption=at.value(i);
                   }else if(at.localName(i)=="room_id") {
                        room_id=at.value(i);
                   }else if(at.localName(i)=="subroom_id") {
                        subroom_id=at.value(i);
                   }
              }
              _caption=room_id+":"+subroom_id+":"+_caption;
    
         }
         else if (qName == "timeFirstFrame") {
              /*unsigned long timeFirstFrame_us=0;
                unsigned long timeFirstFrame_s=0;
    
                for(int i=0; i<at.length(); i++) {
                if(at.localName(i)=="microsec") {
                timeFirstFrame_us=at.value(i).toULong();
                } else if(at.localName(i)=="sec") {
                timeFirstFrame_s=at.value(i).toULong();
                }
                }
                dataset->setDelayAbsolute(timeFirstFrame_s,timeFirstFrame_us);
              */
         } else if (qName == "point") {
              double xPos=0;
              double yPos=0;
              double zPos=0;
    
              for(int i=0; i<at.length(); i++) {
                   if(at.localName(i)=="xPos") {
                        xPos=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="yPos") {
                        yPos=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)=="zPos") {
                        zPos=at.value(i).toDouble()*FAKTOR;
                   }
              }
              double CHT[3]= {_color,_height,_thickness};
              JPoint* pt= new JPoint(xPos,yPos,zPos);
              pt->setColorHeightThicknes(CHT);
              _currentPointsList.push_back(pt);
    
         }
         else if (qName == "frame")
         {
              for(int i=0; i<at.length(); i++) {
                   if(at.localName(i)=="ID") {
                        _currentFrameID=at.value(i).toInt();
                        //cout<<"frame: " <<_currentFrameID<<endl;
                   }
              }
    
         }
         else if (qName == "agent") {
    
              int id=0;
              double xPos=0;
              double yPos=0;
              double zPos=0;
              //double agent_color =std::numeric_limits<double>::quiet_NaN();
              //double xVel=std::numeric_limits<double>::quiet_NaN();
              //double yVel=std::numeric_limits<double>::quiet_NaN();
              //double zVel=std::numeric_limits<double>::quiet_NaN();
              double dia_a=std::numeric_limits<double>::quiet_NaN();
              double dia_b=std::numeric_limits<double>::quiet_NaN();
              double el_angle=std::numeric_limits<double>::quiet_NaN();
              double el_color=std::numeric_limits<double>::quiet_NaN();
              double el_x=std::numeric_limits<double>::quiet_NaN();
              double el_y=std::numeric_limits<double>::quiet_NaN();
              double el_z=std::numeric_limits<double>::quiet_NaN();
    
              for(int i=0; i<at.length(); i++) {
                   if(at.localName(i)=="ID") {
                        id=at.value(i).toInt();
                        //TODO: maybe you should change ur format to take the ID 0 as first valid ID.
                        if (id==0) {
                             //slotErrorOutput("Person with ID=0 detected. ID should start with 1 !");
                             return false;
                        }
                   } else if(at.localName(i)==_jps_xPos) {
                        xPos=at.value(i).toDouble()*FAKTOR;
                        //xPos=at.value(i).toDouble();
                   } else if(at.localName(i)==_jps_yPos) {
                        //yPos=at.value(i).toDouble();
                        yPos=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)==_jps_zPos) {
                        zPos=at.value(i).toDouble()*FAKTOR;
                   }
    
                   else if(at.localName(i)==_jps_radiusA) {
                        dia_a=at.value(i).toDouble()*FAKTOR;
                        //dia_a=at.value(i).toDouble();
                   } else if(at.localName(i)==_jps_radiusB) {
                        dia_b=at.value(i).toDouble()*FAKTOR;
                        //dia_b=at.value(i).toDouble();
                   } else if(at.localName(i)==_jps_ellipseOrientation) {
                        el_angle=at.value(i).toDouble();
                   } else if(at.localName(i)==_jps_ellipseColor) {
                        el_color=at.value(i).toDouble();
                   } else if(at.localName(i)=="agentColor") {
                        //agent_color=at.value(i).toDouble();
                   } else if(at.localName(i)==_jps_xVel) {
                        //xVel=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)==_jps_yVel) {
                        //yVel=at.value(i).toDouble()*FAKTOR;
                   } else if(at.localName(i)==_jps_zVel) {
                        //zVel=at.value(i).toDouble()*FAKTOR;
                   }
    
              }
    //        xml2txt
    //        cout << _currentFrameID << " " << id << " " << xPos << " " << yPos << " " << zPos << "\n";
    
              //coordinates of the ellipse, default to the head of the agent
              //if(std::isnan(el_x)) el_x=xPos;
              //if(std::isnan(el_y)) el_y=yPos;
              //if(std::isnan(el_z)) el_z=zPos;
    
              //double pos[3]={xPos,yPos,zPos};
              //double vel[3]={xVel,yPos,zPos};
              //double ellipse[7]={el_x,el_y,el_z,dia_a,dia_b,el_angle,el_color};
              //double para[2]={agent_color,el_angle};
    
              double pos[3]= {xPos,yPos,zPos};
              double angle[3]= {0,0,el_angle};
              double radius[3]= {dia_a,dia_b,30.0};
    
              FrameElement *element = new FrameElement(id-1);
              element->SetPos(pos);
              element->SetOrientation(angle);
              element->SetRadius(radius);
              element->SetColor(el_color);
              _currentFrame.push_back(element);
    
         } else if (qName == "agentInfo") {
              double height=std::numeric_limits<double>::quiet_NaN();
              double color=std::numeric_limits<double>::quiet_NaN();
              double id=std::numeric_limits<double>::quiet_NaN();
    
              for(int i=0; i<at.length(); i++) {
                   if(at.localName(i)=="ID") {
                        id=at.value(i).toDouble();
                   }
                   if(at.localName(i)=="height") {
                        height=at.value(i).toDouble()*FAKTOR;
                   }
                   if(at.localName(i)=="color") {
                        color=at.value(i).toDouble();
                   }
              }
              if(std::isnan(id)) return true;
    
              if(!std::isnan(height)) {
                   _initialPedestriansHeights.append(QString::number(int(id)));
                   _initialPedestriansHeights.append(QString::number(height));
              }
              if(!std::isnan(color)) {
                   _initialPedestriansColors.append(QString::number(int(id)));
                   _initialPedestriansColors.append(QString::number(int(color)));
              }
         }
         return true;
    }
    
    bool SaxParser::characters(const QString &str)
    {
         _currentText.append(str);
         return true;
    }
    
    bool SaxParser::endElement(const QString & /* namespaceURI */,
                               const QString & /* localName */, const QString &qName)
    {
         if (qName == "header") {
    
         } else if (qName == "agents") {
              _dataset.setNumberOfAgents(_currentText.toInt());
         } else if (qName == "frameRate") {
              _para[0]=_currentText.toFloat();
         } else if (qName == "wall") {
              if(_currentPointsList.size()>1)
                   for(unsigned int i=0; i<_currentPointsList.size()-1; i++) {
                        _geometry->addWall(_currentPointsList[i],_currentPointsList[i+1],_caption.toStdString());
                   }
              clearPoints();
         } else if (qName == "door") {
              for(unsigned int i=0; i<_currentPointsList.size()-1; i++) {
                   _geometry->addDoor(_currentPointsList[i],_currentPointsList[i+1],_caption.toStdString());
              }
              clearPoints();
         } else if (qName == "crossing") {
              if(_currentPointsList.size()>1) //hack
                   for(unsigned int i=0; i<_currentPointsList.size()-1; i++) {
                        _geometry->addNavLine(_currentPointsList[i],_currentPointsList[i+1],_caption.toStdString());
                   }
              clearPoints();
         } else if (qName == "hline") {
              if(_currentPointsList.size()>1)
              {
                   for(unsigned int i=0; i<_currentPointsList.size()-1; i++)
                   {
                        int room_id=-1;
                        int subroom_id=-1;
                        QStringList lst = _caption.split(":");
                        if(lst.length()>2)
                        {
                             room_id=lst[0].toInt();
                             subroom_id=lst[1].toInt();
                             _caption=lst[2];
                        }
                        auto&& geo=_geoFactory.GetElement(room_id,subroom_id);
                        if(geo!=nullptr)
                        {
                             geo->addNavLine(_currentPointsList[i],_currentPointsList[i+1],_caption.toStdString());
                        }
                        else
                        {
                             _geometry->addNavLine(_currentPointsList[i],_currentPointsList[i+1],_caption.toStdString());
                        }
                   }
              }
              clearPoints();
         } else if (qName == "step") {//FIXME
              for(unsigned int i=0; i<_currentPointsList.size()-1; i++) {
                   _geometry->addDoor(_currentPointsList[i],_currentPointsList[i+1],_caption.toStdString());
              }
              clearPoints();
         } else if (qName == "frame") {
              Frame* frame = new Frame(_currentFrameID);
              while(!_currentFrame.empty()) {
                   frame->addElement(_currentFrame.back());
                   _currentFrame.pop_back();
              }
    
              //compute the polydata, might increase the runtime
              frame->ComputePolyData();
    
              _dataset.addFrame(frame);
              //to be on the safe side
              _currentFrame.clear();
    
         } else if (qName == "agent") {
         } else if (qName == "geometry") {
         } else if (qName == "point") {
         } else if (qName == "shape") {
              _dataset.setInitialHeights(_initialPedestriansHeights);
              _dataset.setInitialColors(_initialPedestriansColors);
         } else if (qName == "gradient_field") {
         }
         _currentText.clear();
         return true;
    }
    
    bool SaxParser::fatalError(const QXmlParseException &exception)
    {
         QMessageBox::warning(0, QObject::tr("SAX Handler"), QObject::tr(
                                   "Parse error at line %1, column "
                                   "%2:\n%3.") .arg(exception.lineNumber()) .arg(
                                        exception.columnNumber()) .arg(exception.message()));
         return false;
    }
    
    bool SaxParser::attributeDecl(const QString& eName, const QString& aName,
                                  const QString& type, const QString& valueDefault, const QString& value)
    {
         //cout<<aName.toStdString()<<endl;
    
         QString dummy=eName+aName+type+valueDefault+value;
         return (dummy==dummy);
         //return true;
    }
    
    void SaxParser::clearPoints()
    {
         while (!_currentPointsList.empty()) {
              delete _currentPointsList.back();
              _currentPointsList.pop_back();
         }
         _currentPointsList.clear();
         return;
    }
    
    /// provided for convenience and will be removed in the next version
    bool SaxParser::parseGeometryJPS(QString fileName, GeometryFactory& geoFac)
    {
         Debug::Messages( "Enter SaxParser::parseGeometryJPS with filename <%s>",fileName.toStdString().c_str());
    
         double captionsColor=0;//red
         if(!fileName.endsWith(".xml",Qt::CaseInsensitive)) return false;
         QString wd;
         SystemSettings::getWorkingDirectory(wd);
         fileName=wd + "/" + fileName; //TODO: is this windows compatible?
         // QString = QDir::cleanPath(wd + QDir::separator() + fileName);
         Debug::Messages("filename: <%s)", fileName.toStdString().c_str());
         Debug::Messages("wd: <%s>",wd.toStdString().c_str());
         Debug::Messages("filename2: <%s>",fileName.toStdString().c_str());
         Building* building = new Building();
         string geometrypath = fileName.toStdString();
         // read the geometry
         if(!building->LoadGeometry(geometrypath))
              return false;
         if(!building->InitGeometry())
              return false; // create the polygons
    
         int room_id = -1;
         int subroom_id = -1;
         for(auto&& itr_room: building->GetAllRooms())
         {
              room_id++;
              for(auto&& itr_subroom: itr_room.second->GetAllSubRooms())
              {
                   subroom_id++;
                   string room_caption = itr_room.second->GetCaption() + "_RId_" + QString::number(itr_room.first).toStdString();
                   string subroom_caption = itr_subroom.second->GetCaption()+ "_RId_" + QString::number(itr_room.first).toStdString();
                   auto geometry= shared_ptr<FacilityGeometry>(
                        new FacilityGeometry(itr_subroom.second->GetType(), room_caption, subroom_caption
                             )
                        );
                   int currentFloorPolyID=0;
                   int currentObstPolyID=0;
    
                   // Setup the points
                   VTK_CREATE(vtkPoints,floor_points);
                   VTK_CREATE(vtkPoints,obstacles_points);
                   // Add the polygon to a list of polygons
                   VTK_CREATE(vtkCellArray,floor_polygons);
                   VTK_CREATE(vtkCellArray,obstacles_polygons);
    
                   //string caption = r->GetCaption();
                   SubRoom* sub = itr_subroom.second.get();
    
                   vector<Point> poly = sub->GetPolygon();
                   if(sub->IsClockwise()==true) {
                        std::reverse(poly.begin(),poly.end());
                   }
    
                   // Create the polygon
                   VTK_CREATE(vtkPolygon,polygon);
                   polygon->GetPointIds()->SetNumberOfIds(poly.size());
    
                   for (unsigned int s=0; s<poly.size(); s++) {
                        floor_points->InsertNextPoint(poly[s]._x*FAKTOR,poly[s]._y*FAKTOR,sub->GetElevation(poly[s])*FAKTOR);
                        polygon->GetPointIds()->SetId(s, currentFloorPolyID++);
                   }
                   floor_polygons->InsertNextCell(polygon);
    
                   //plot the walls only for not stairs
                   const vector<Wall>& walls= sub->GetAllWalls();
                   for(unsigned int w=0; w<walls.size(); w++) {
                        Point p1 = walls[w].GetPoint1();
                        Point p2 = walls[w].GetPoint2();
                        double z1= sub->GetElevation(p1);
                        double z2= sub->GetElevation(p2);
    
                        if(sub->GetType()=="stair") {
                             geometry->addStair(p1._x*FAKTOR, p1._y*FAKTOR, z1*FAKTOR, p2._x*FAKTOR, p2._y*FAKTOR,z2*FAKTOR);
                        } else {
                             geometry->addWall(p1._x*FAKTOR, p1._y*FAKTOR, z1*FAKTOR, p2._x*FAKTOR, p2._y*FAKTOR,z2*FAKTOR);
                        }
                   }
    
                   //insert the subroom caption
                   string caption=itr_room.second->GetCaption()+" ( " + QString::number(sub->GetSubRoomID()).toStdString() + " ) ";
                   const Point& p=sub->GetCentroid();
                   double z= sub->GetElevation(p);
                   double pos[3]= {p._x*FAKTOR,p._y*FAKTOR,z*FAKTOR};
                   geometry->addObjectLabel(pos,pos,caption,captionsColor);
    
                   //plot the obstacles
                   for(auto obst:sub->GetAllObstacles())
                   {
                        for(auto wall: obst->GetAllWalls())
                        {
                             Point p1 = wall.GetPoint1();
                             Point p2 = wall.GetPoint2();
                             double z1= sub->GetElevation(p1);
                             double z2= sub->GetElevation(p2);
                             geometry->addWall(p1._x*FAKTOR, p1._y*FAKTOR, z1*FAKTOR, p2._x*FAKTOR, p2._y*FAKTOR,z2*FAKTOR);
                        }
                        //add the obstacle caption
                        const Point& p=obst->GetCentroid();
                        double z= sub->GetElevation(p);
                        double pos[3]= {p._x*FAKTOR,p._y*FAKTOR,z*FAKTOR};
                        geometry->addObjectLabel(pos,pos,obst->GetCaption(),captionsColor);
    
                        //add a special texture to the obstacles
                        auto poly = obst->GetPolygon();
                        //if(obst->IsClockwise()==true) {
                        //  std::reverse(poly.begin(),poly.end());
                        //}
    
                        // Create the polygon
                        VTK_CREATE(vtkPolygon,polygon);
                        polygon->GetPointIds()->SetNumberOfIds(poly.size());
    
                        for (unsigned int s=0; s<poly.size(); s++) {
                             obstacles_points->InsertNextPoint(poly[s]._x*FAKTOR,poly[s]._y*FAKTOR,sub->GetElevation(poly[s])*FAKTOR);
                             polygon->GetPointIds()->SetId(s, currentObstPolyID++);
                        }
                        obstacles_polygons->InsertNextCell(polygon);
                   }
    
                   // Create a PolyData to represent the floor
                   VTK_CREATE(vtkPolyData, floorPolygonPolyData);
                   floorPolygonPolyData->SetPoints(floor_points);
                   floorPolygonPolyData->SetPolys(floor_polygons);
                   geometry->addFloor(floorPolygonPolyData);
    
                   // Create a PolyData to represen the obstacles
                   VTK_CREATE(vtkPolyData, obstPolygonPolyData);
                   obstPolygonPolyData->SetPoints(obstacles_points);
                   obstPolygonPolyData->SetPolys(obstacles_polygons);
                   geometry->addObstacles(obstPolygonPolyData);
    
                   // add the crossings
                   for(auto&& cr: itr_subroom.second->GetAllCrossings())
                   {
                        Point p1 = cr->GetPoint1();
                        Point p2 = cr->GetPoint2();
                        double z1= cr->GetSubRoom1()->GetElevation(p1);
                        double z2= cr->GetSubRoom1()->GetElevation(p2);
                        geometry->addNavLine(p1._x*FAKTOR, p1._y*FAKTOR, z1*FAKTOR, p2._x*FAKTOR, p2._y*FAKTOR,z2*FAKTOR);
    
                        const Point& p =cr->GetCentre();
                        double pos[3]= {p._x*FAKTOR,p._y*FAKTOR,z1*FAKTOR};
                        geometry->addObjectLabel(pos,pos,"nav_"+QString::number(cr->GetID()).toStdString()+"_"+
                                                 QString::number(cr->GetUniqueID()).toStdString()
                                                 ,captionsColor);
                   }
    
                   // add the exits
                   for(auto&& tr: itr_subroom.second->GetAllTransitions())
                   {
                        Point p1 = tr->GetPoint1();
                        Point p2 = tr->GetPoint2();
                        double z1 = 0;
                        double z2 = 0;
    
                        if(tr->GetSubRoom1()) // get elevation for both points
                        {
                             z2 = tr->GetSubRoom1()->GetElevation(p2);
                             z1 = tr->GetSubRoom1()->GetElevation(p1);
                        }
                        else if(! tr->GetSubRoom2())
                        {
                             z2 = tr->GetSubRoom2()->GetElevation(p2);
                             z1 = tr->GetSubRoom2()->GetElevation(p1);
                        }
                        else
                             std::cout << "ERROR: Can not calculate elevations for transition " << tr->GetID() << ", " << tr->GetCaption() << ". Both subrooms are not defined \n";
    
                        geometry->addDoor(p1._x*FAKTOR, p1._y*FAKTOR, z1*FAKTOR, p2._x*FAKTOR, p2._y*FAKTOR,z2*FAKTOR);
    
                        const Point& p =tr->GetCentre();
                        double pos[3]= {p._x*FAKTOR,p._y*FAKTOR,z1*FAKTOR};
                        geometry->addObjectLabel(pos,pos,"door_"+QString::number(tr->GetID()).toStdString()+
                                                 +"_"+ QString::number(tr->GetUniqueID()).toStdString(),captionsColor);
                   }
    
                   geoFac.AddElement(room_id,subroom_id,geometry);
              }
         }
    
    
         // free memory
         delete building;
         return true;
    }
    
    /// provided for convenience and will be removed in the next version
    
    void SaxParser::parseGeometryTRAV(QString content, GeometryFactory& geoFac,QDomNode geo)
    {
    
         cout<<"external geometry found"<<endl;
         //creating am empty document
         // to be filled
         QDomDocument doc("");
         QDomNode geoNode;
         auto geometry= shared_ptr<FacilityGeometry>(new FacilityGeometry("no name", "no name", "no name"));
    
         //first try to open the file
         if(content.endsWith(".trav",Qt::CaseInsensitive) ) {
              QFile file(content);
              if (!file.open(QIODevice::ReadOnly)) {
                   //slotErrorOutput("could not open the File" );
                   cout<<"could not open the File"<<endl;
                   return ;
              }
              QString *errorCode = new QString();
              if (!doc.setContent(&file, errorCode)) {
                   file.close();
                   //slotErrorOutput(*errorCode);
                   cout<<errorCode->toStdString()<<endl;
                   return ;
              }
              file.close();
              geoNode =doc.documentElement().namedItem("geometry");
    
              if (geoNode.isNull()) {
                   cout<<"No geometry information found. <geometry> <geometry/> tag is missing."<<endl;
              }
         } else {
              if(content.isEmpty()) {
                   geoNode=geo;
                   cout <<"parsing the old fashion way"<<endl;
              } else {
                   content = "<travisto>\n" +content+ "\n</travisto>\n";
                   QString errorMsg="";
                   doc.setContent(content,&errorMsg);
    
                   if(!errorMsg.isEmpty()) {
                        Debug::Error("%s", (const char *)errorMsg.toStdString().c_str());
                        return;
                   }
                   geoNode =doc.elementsByTagName("geometry").item(0);
              }
         }
    
         // for the case there is more than just one geometry Node
         while (!geoNode.isNull()) {
              QDomElement e = geoNode.toElement();
              QDomNodeList walls = e.elementsByTagName("wall");
              QDomNodeList doors = e.elementsByTagName("door");
    
              //objects which can be positioned everywhere in the facility
              QDomNodeList spheres = e.elementsByTagName("sphere");
              QDomNodeList cuboids = e.elementsByTagName("cuboid");
              QDomNodeList floors = e.elementsByTagName("floor");
              QDomNodeList cylinders = e.elementsByTagName("cylinder");
              QDomNodeList labels = e.elementsByTagName("label");
    
    
              //parsing the walls
              for (  int i = 0; i < walls.length(); i++) {
                   QDomElement el = walls.item(i).toElement();
    
                   //wall thickness, default to 30 cm
                   double thickness = el.attribute("thickness","15").toDouble()*FAKTOR;
                   //wall height default to 250 cm
                   double height = el.attribute("height","250").toDouble()*FAKTOR;
                   //wall color default to blue
                   double color = el.attribute("color","0").toDouble();
    
                   //get the points defining each wall
                   //not that a wall is not necessarily defined by two points, could be more...
                   QDomNodeList points = el.elementsByTagName("point");
                   for (  int i = 0; i < points.length() - 1; i++) {
    
                        double x1=points.item(i).toElement().attribute("xPos", "0").toDouble()*FAKTOR;
                        double y1=points.item(i).toElement().attribute("yPos", "0").toDouble()*FAKTOR;
                        double z1=points.item(i).toElement().attribute("zPos", "0").toDouble()*FAKTOR;
    
                        double x2=points.item(i+1).toElement().attribute("xPos", "0").toDouble()*FAKTOR;
                        double y2=points.item(i+1).toElement().attribute("yPos", "0").toDouble()*FAKTOR;
                        double z2=points.item(i+1).toElement().attribute("zPos", "0").toDouble()*FAKTOR;
                        geometry->addWall(x1, y1,z1 ,x2, y2,z2,thickness,height,color);
                   }
              }
    
              //parsing the doors
              if(doors.length()>0)
                   for (  int i = 0; i < doors.length(); i++) {
                        QDomElement el = doors.item(i).toElement();
    
                        //door thickness, default to 15 cm
                        double thickness = el.attribute("thickness","15").toDouble()*FAKTOR;
                        //door height default to 250 cm
                        double height = el.attribute("height","250").toDouble()*FAKTOR;
                        //door color default to blue
                        double color = el.attribute("color","255").toDouble();
    
                        //get the points defining each wall
                        //not that a wall is not necesarily defined by two points, could be more...
                        QDomNodeList points = el.elementsByTagName("point");
                        //Debug::Messages("found:  " << points.length() <<" for this wall" <<endl;
                        for (  int i = 0; i < points.length() - 1; i++) {
    
                             double x1=points.item(i).toElement().attribute("xPos", "0").toDouble()*FAKTOR;
                             double y1=points.item(i).toElement().attribute("yPos", "0").toDouble()*FAKTOR;
                             double z1=points.item(i).toElement().attribute("zPos", "0").toDouble()*FAKTOR;
    
                             double x2=points.item(i+1).toElement().attribute("xPos", "0").toDouble()*FAKTOR;
                             double y2=points.item(i+1).toElement().attribute("yPos", "0").toDouble()*FAKTOR;
                             double z2=points.item(i+1).toElement().attribute("zPos", "0").toDouble()*FAKTOR;
                             geometry->addDoor(x1, y1, z1, x2, y2,z2,thickness,height,color);
                        }
                   }
    
              // parsing the objets
              for (  int i = 0; i < spheres.length(); i++) {
    
                   double center[3];
                   center[0] = spheres.item(i).toElement().attribute("centerX", "0").toDouble()*FAKTOR;
                   center[1]= spheres.item(i).toElement().attribute("centerY", "0").toDouble()*FAKTOR;
                   center[2]= spheres.item(i).toElement().attribute("centerZ", "0").toDouble()*FAKTOR;
                   double color= spheres.item(i).toElement().attribute("color", "0").toDouble()*FAKTOR;
                   double radius= spheres.item(i).toElement().attribute("radius", "0").toDouble()*FAKTOR;
                   //double width = spheres.item(i).toElement().attribute("width", "0").toDouble();
                   //double height= spheres.item(i).toElement().attribute("height", "0").toDouble();
    
                   geometry->addObjectSphere(center,radius,color);
              }
              // cubic shapes
              for (  int i = 0; i < cuboids.length(); i++) {
    
                   double center[3];
                   center[0] = cuboids.item(i).toElement().attribute("centerX", "0").toDouble()*FAKTOR;
                   center[1]= cuboids.item(i).toElement().attribute("centerY", "0").toDouble()*FAKTOR;
                   center[2]= cuboids.item(i).toElement().attribute("centerZ", "0").toDouble()*FAKTOR;
                   double color= cuboids.item(i).toElement().attribute("color", "0").toDouble();
                   double length= cuboids.item(i).toElement().attribute("length", "0").toDouble()*FAKTOR;
                   double width = cuboids.item(i).toElement().attribute("width", "0").toDouble()*FAKTOR;
                   double height= cuboids.item(i).toElement().attribute("height", "0").toDouble()*FAKTOR;
                   geometry->addObjectBox(center,height,width,length,color);
                   //		Debug::Error("cuboids: "<<length<<" || " <<width << " || "<<height<<" || "<<color<<endl;
              }
              // floors
              for (  int i = 0; i < floors.length(); i++) {
    
                   double left =floors.item(i).toElement().attribute("xMin","0").toDouble()*FAKTOR;
                   double right =floors.item(i).toElement().attribute("xMax","0").toDouble()*FAKTOR;
                   double up =floors.item(i).toElement().attribute("yMax","0").toDouble()*FAKTOR;
                   double down =floors.item(i).toElement().attribute("yMin","0").toDouble()*FAKTOR;
                   double z =floors.item(i).toElement().attribute("z","0").toDouble()*FAKTOR;
                   geometry->addFloor(left,down,right,up,z);
              }
              // cylinders
              for (  int i = 0; i < cylinders.length(); i++) {
    
                   double center[3], rotation[3];
                   center[0] = cylinders.item(i).toElement().attribute("centerX", "0").toDouble()*FAKTOR;
                   center[1]= cylinders.item(i).toElement().attribute("centerY", "0").toDouble()*FAKTOR;
                   center[2]= cylinders.item(i).toElement().attribute("centerZ", "0").toDouble()*FAKTOR;
                   double color= cylinders.item(i).toElement().attribute("color", "0").toDouble();
                   double radius= cylinders.item(i).toElement().attribute("radius", "0").toDouble()*FAKTOR;
                   double height= cylinders.item(i).toElement().attribute("height", "0").toDouble()*FAKTOR;
                   rotation[0] = cylinders.item(i).toElement().attribute("angleX", "90").toDouble();
                   rotation[1] = cylinders.item(i).toElement().attribute("angleY", "0").toDouble();
                   rotation[2] = cylinders.item(i).toElement().attribute("angleZ", "0").toDouble();
                   geometry->addObjectCylinder(center,radius,height,rotation,color);
              }
    
              //Labels
              for (  int i = 0; i < labels.length(); i++) {
    
                   double center[3];
                   center[0] = labels.item(i).toElement().attribute("centerX", "0").toDouble()*FAKTOR;
                   center[1]= labels.item(i).toElement().attribute("centerY", "0").toDouble()*FAKTOR;
                   center[2]= labels.item(i).toElement().attribute("centerZ", "0").toDouble()*FAKTOR;
                   double color= labels.item(i).toElement().attribute("color", "0").toDouble();
                   string caption= labels.item(i).toElement().attribute("text", "").toStdString();
                   geometry->addObjectLabel(center,center,caption,color);
              }
              // you should normally have only one geometry node, but one never knows...
              geoNode = geoNode.nextSiblingElement("geometry");
         }
    
         geoFac.AddElement(0,0,geometry);
    }
    
    QString SaxParser::extractGeometryFilename(QString &filename)
    {
         QString extracted_geo_name="";
         //first try to look at a string <file location="filename.xml"/>
         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();
                   //cout<<"checking: "<<line.toStdString()<<endl;
                   if(line.contains("location" ,Qt::CaseInsensitive))
                        if(line.contains("<file" ,Qt::CaseInsensitive)) {
                             //try to extract what ever is inside the quotes
    
                             QString begin="\"";
                             QString end="\"";
                             int startIndex = line.indexOf(begin)+begin.length();
                             if(startIndex <= 0)continue; //false alarm
                             int endIndex = line.indexOf(end,startIndex);
                             if(endIndex <= 0)continue; // false alarm
                             extracted_geo_name= line.mid(startIndex,endIndex - startIndex);
                             return extracted_geo_name;
                             //break;// we are done
                        }
                   if(line.contains("<geometry" ,Qt::CaseInsensitive))
                        if(line.contains("version" ,Qt::CaseInsensitive)) {
                             //real geometry file
                             QFileInfo fileInfoGeometry(filename);
                             extracted_geo_name=fileInfoGeometry.fileName();
                             return extracted_geo_name;
                        }
              }
         }
    
         //maybe this is already the geometry file itself ?
         //do a rapid test
         //    FacilityGeometry* geo = new FacilityGeometry();
         //    QFileInfo fileInfoGeometry(filename);
         //    extracted_geo_name=fileInfoGeometry.fileName();
    
         //    //just check if it starts with geometry
         //    //if(parseGeometryJPS(extracted_geo_name,geo)==true)
         //    //{
         //        return extracted_geo_name;
         //    //}
         //    delete geo;
    
         return "";
    }
    
    QString SaxParser::extractGeometryFilenameTXT(QString &filename)
    {
         QString extracted_geo_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 >> endl;
                   if(line.split(":").size()==2)
                   {
                        if(line.split(":")[0] == "#geometry")
                        {
                             extracted_geo_name = line.split(":")[1]
                        }
                   }
              }// while
         } // if open
         cout << ">> geo: " <<   extracted_geo_name << endl;
         return extracted_geo_name;
    }
    
    
    void SaxParser::parseGeometryXMLV04(QString filename, GeometryFactory& geoFac)
    {
         cout << "parsing 04\n" ;
         QDomDocument doc("");
         QFile file(filename);
    
         int size =file.size()/(1024*1024);
    
         //avoid dom parsing a very large dataset
         if(size>500) {
              //cout<<"The file is too large: "<<filename.toStdString()<<endl;
              return;
         }
    
         auto geo= shared_ptr<FacilityGeometry>(new FacilityGeometry("no name", "no name", "no name"));
         //cout<<"filename: "<<filename.toStdString()<<endl;
    
         //TODO: check if you can parse this with the building classes.
         // This should be a fall back option
    
         if (!file.open(QIODevice::ReadOnly)) {
              qDebug()<<"could not open the file: "<<filename<<endl;
              return ;
         }
         QString *errorCode = new QString();
         if (!doc.setContent(&file, errorCode)) {
              file.close();
              qDebug()<<errorCode<<endl;
              return ;
         }
         QDomElement root= doc.documentElement();
    
         //only parsing the geometry node
         if(root.tagName()!="geometry") return;
    
    
         double version =root.attribute("version","-1").toDouble();
    
         string unit=root.attribute("unit","cm").toStdString();
         double xToCmfactor=100;
         if (unit=="cm") xToCmfactor=1;
         if (unit=="m") xToCmfactor=100;
    
         if(version<0.4) {
              QMessageBox::warning(0, QObject::tr("Parsing Error"),
                                   QObject::tr("Only geometry version >= 0.4 supported"));
         }
    
         //parsing the subrooms
         QDomNodeList xSubRoomsNodeList=doc.elementsByTagName("subroom");
         //parsing the walls
         for (  int i = 0; i < xSubRoomsNodeList.length(); i++) {
              QDomElement xPoly = xSubRoomsNodeList.item(i).firstChildElement("polygon");
              double position[3]= {0,0,0};
              double pos_count=1;
              double color=0;
    
              while(!xPoly.isNull()) {
                   //wall thickness, default to 30 cm
                   double thickness = xPoly.attribute("thickness","15").toDouble();
                   //wall height default to 250 cm
                   double height = xPoly.attribute("height","250").toDouble();
                   //wall color default to blue
                   color = xPoly.attribute("color","0").toDouble();
    
                   QDomNodeList xVertices=xPoly.elementsByTagName("vertex");
                   pos_count+=xVertices.count()-1;
    
                   for( int i=0; i<xVertices.count()-1; i++) {
                        //all unit are converted in cm
                        double x1=xVertices.item(i).toElement().attribute("px", "0").toDouble()*xToCmfactor;
                        double y1=xVertices.item(i).toElement().attribute("py", "0").toDouble()*xToCmfactor;
                        double z1=xVertices.item(i).toElement().attribute("pz", "0").toDouble()*xToCmfactor;
                        double x2=xVertices.item(i+1).toElement().attribute("px", "0").toDouble()*xToCmfactor;
                        double y2=xVertices.item(i+1).toElement().attribute("py", "0").toDouble()*xToCmfactor;
                        double z2=xVertices.item(i+1).toElement().attribute("pz", "0").toDouble()*xToCmfactor;
    
                        position[0]+= x1;
                        position[1]+= y1;
                        position[2]+= z1;
    
                        geo->addWall(x1, y1, z1, x2, y2,z2,thickness,height,color);
                   }
                   xPoly = xPoly.nextSiblingElement("polygon");
              }
    
              //add the caption
              string roomCaption = xSubRoomsNodeList.item(i).parentNode().toElement().attribute("caption").toStdString();
              string subroomCaption=xSubRoomsNodeList.item(i).toElement().attribute("id").toStdString();
              string caption=roomCaption+" ( " + subroomCaption + " ) ";
              position[0]/=pos_count;
              position[1]/=pos_count;
              position[2]/=pos_count;
              geo->addObjectLabel(position,position,caption,color);
              geo->SetRoomCaption(roomCaption);
              geo->SetSubRoomCaption(subroomCaption);
              cout<<"position: [" <<position[0]<<", "<<position[1]<<", "<<position[2]<<" ]"<<endl;;
              cout << roomCaption<< "  " << subroomCaption << "\n" ;
         }
    
         QDomNodeList xObstaclesList=doc.elementsByTagName("obstacle");
         for (  int i = 0; i < xObstaclesList.length(); i++) {
              QDomElement xPoly = xObstaclesList.item(i).firstChildElement("polygon");
              while(!xPoly.isNull()) {
                   //wall thickness, default to 30 cm
                   double thickness = xPoly.attribute("thickness","15").toDouble();
                   //wall height default to 250 cm
                   double height = xPoly.attribute("height","250").toDouble();
                   //wall color default to blue
                   double color = xPoly.attribute("color","0").toDouble();
    
                   QDomNodeList xVertices=xPoly.elementsByTagName("vertex");
                   for( int i=0; i<xVertices.count()-1; i++) {
                        double x1=xVertices.item(i).toElement().attribute("px", "0").toDouble()*xToCmfactor;
                        double y1=xVertices.item(i).toElement().attribute("py", "0").toDouble()*xToCmfactor;
                        double z1=xVertices.item(i).toElement().attribute("pz", "0").toDouble()*xToCmfactor;
    
                        double x2=xVertices.item(i+1).toElement().attribute("px", "0").toDouble()*xToCmfactor;
                        double y2=xVertices.item(i+1).toElement().attribute("py", "0").toDouble()*xToCmfactor;
                        double z2=xVertices.item(i+1).toElement().attribute("pz", "0").toDouble()*xToCmfactor;
                        geo->addWall(x1, y1, z1, x2, y2,z2,thickness,height,color);
                   }
                   xPoly = xPoly.nextSiblingElement("polygon");
              }
         }
    
         QDomNodeList xCrossingsList=doc.elementsByTagName("crossing");
    
         for (int i = 0; i < xCrossingsList.length(); i++) {
              QDomElement xCrossing = xCrossingsList.item(i).toElement();
              QDomNodeList xVertices=xCrossing.elementsByTagName("vertex");
    
              ///door thickness, default to 15 cm
              double thickness = xCrossing.attribute("thickness","15").toDouble();
              //door height default to 250 cm
              double height = xCrossing.attribute("height","250").toDouble();
              //door color default to blue
              double color = xCrossing.attribute("color","120").toDouble();
              QString id= xCrossing.attribute("id","-1");
    
              double x1=xVertices.item(0).toElement().attribute("px", "0").toDouble()*xToCmfactor;
              double y1=xVertices.item(0).toElement().attribute("py", "0").toDouble()*xToCmfactor;
              double z1=xVertices.item(0).toElement().attribute("pz", "0").toDouble()*xToCmfactor;
    
              double x2=xVertices.item(1).toElement().attribute("px", "0").toDouble()*xToCmfactor;
              double y2=xVertices.item(1).toElement().attribute("py", "0").toDouble()*xToCmfactor;
              double z2=xVertices.item(1).toElement().attribute("pz", "0").toDouble()*xToCmfactor;
              geo->addNavLine(x1, y1, z1, x2, y2,z2,thickness,height,color);
    
              double center[3]= {(x1+x2)/2.0, (y1+y2)/2.0, (z2+z1)/2.0};
              geo->addObjectLabel(center,center,id.toStdString(),21);
         }
    
         QDomNodeList xTransitionsList=doc.elementsByTagName("transition");
         for (int i = 0; i < xTransitionsList.length(); i++) {
              QDomElement xTransition = xTransitionsList.item(i).toElement();
              QDomNodeList xVertices=xTransition.elementsByTagName("vertex");
    
              ///door thickness, default to 15 cm
              double thickness = xTransition.attribute("thickness","15").toDouble();
              //door height default to 250 cm
              double height = xTransition.attribute("height","250").toDouble();
              //door color default to blue
              double color = xTransition.attribute("color","255").toDouble();
    
              double x1=xVertices.item(0).toElement().attribute("px", "0").toDouble()*xToCmfactor;
              double y1=xVertices.item(0).toElement().attribute("py", "0").toDouble()*xToCmfactor;
              double z1=xVertices.item(0).toElement().attribute("pz", "0").toDouble()*xToCmfactor;
    
              double x2=xVertices.item(1).toElement().attribute("px", "0").toDouble()*xToCmfactor;
              double y2=xVertices.item(1).toElement().attribute("py", "0").toDouble()*xToCmfactor;
              double z2=xVertices.item(1).toElement().attribute("pz", "0").toDouble()*xToCmfactor;
              geo->addDoor(x1, y1, z1, x2, y2,z2,thickness,height,color);
    
              string id= xTransition.attribute("id","-1").toStdString();
              double center[3]= {(x1+x2)/2.0, (y1+y2)/2.0, (z2+z1)/2.0};
              geo->addObjectLabel(center,center,id,21);
         }
    
         //room 0, subroom 0
         geoFac.AddElement(0,0,geo);
    }
    
    bool SaxParser::ParseTxtFormat(const QString &fileName, SyncData* dataset, double * fps)
    {
         //fileName="data/trajectories/1000_1_0_0_1_1.txt";
         //fileName="data/trajectories/50_3_0_1_1_2.txt";
         qDebug()<<"parsing the text file: "<<fileName<<endl;
         QFile inputFile(fileName);
         if (inputFile.open(QIODevice::ReadOnly))
         {
              QTextStream in(&inputFile);
              int lastFrameID=-1;
    
    
              //skip the first line
              in.readLine();
              //the second line contains the framerate
              QString line = in.readLine();
              if(line.split(":").size()==2)
              {
                   bool ok;
                   *fps=line.split(":")[1].toDouble(&ok);
                   if(!ok)
                   {
                        *fps=16;//default value
                        qDebug()<<"WARNING: Could not parse frame rate. Setting to default: "<<*fps<<endl; //exit(0);
                   }
                   else
                        qDebug()<<"INFo: frame rate: "<<*fps<<endl; //exit(0);
              }
              // third line geometry
              line = in.readLine();
              std::string geometry_filename="";
              if(line.split(":").size()==2)
              {
                   bool ok;
                   geometry_filename=line.split(":")[1].toDouble(&ok);
                   if(!ok) {
                        qDebug()<<"WARNING: Could not parse geometry file."<<endl;
                   }
                   else
                        qDebug()<<"INFO: geometry file: "<<geometry_filename<<endl; //exit(0);
              }
              // 4th line max frame
              line = in.readLine();
              int maxFrame=1000;
              if(line.split(":").size()==2)
              {
                   bool ok;
                   maxFrame=line.split(":")[1].toDouble(&ok);
                   if(!ok) {
                        maxFrame=1000;//default value
                        qDebug()<<"WARNING: Could not parse maxFrame. Setting to default: "<<maxFrame<<endl; //exit(0);
                   }
                   else
                        qDebug()<<"INFO: max frame: "<<maxFrame<<endl; //exit(0);
              }
              // skip header
              in.readLine();
    
              //initialize the process dialog
              QProgressDialog progressDialog ("Simulation","Abbrechen",1, maxFrame,NULL);
              progressDialog.setModal(true);
              //_progressDialog->setStyleSheet(stylesheet);
              progressDialog.setWindowFlags(Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
              //_progressDialog->setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowTitleHint|Qt::WindowStaysOnTopHint);
              progressDialog.setFixedSize(400,100);
              progressDialog.setLabelText("<h3>Loading...</h3>");
              QList<QPushButton *> buttons=progressDialog.findChildren<QPushButton *>();
              buttons.at(0)->hide(); // that is the cancel button
              progressDialog.setValue(1);
              progressDialog.show();
    
              double unitFactor=1;// I assume meter
    
              while ( !in.atEnd() )
              {
                   QString line = in.readLine();
                   QStringList pieces = line.split(QRegExp("\\s+"));
    
                   double pos[3];
                   double angle[3]={0,0,30};
                   double radius[3]={0.3,0.3,0.3};
    
                   int agentID=-1 ;
                   int frameID=-1;
                   double color=155 ;
                   switch(pieces.size())
                   {
                   case 5:
                        agentID=pieces[0].toInt();
                        frameID=pieces[1].toInt();
                        pos[0]=pieces[2].toDouble()*unitFactor;
                        pos[1]=pieces[3].toDouble()*unitFactor;
                        pos[2]=pieces[4].toDouble()*unitFactor;
                        break;
    
                   case 9:
                        agentID=pieces[0].toInt();
                        frameID=pieces[1].toInt();
                        color=pieces[8].toDouble();
                        pos[0]=pieces[2].toDouble()*unitFactor;
                        pos[1]=pieces[3].toDouble()*unitFactor;
                        pos[2]=pieces[4].toDouble()*unitFactor;
                        radius[0]=pieces[5].toDouble()*unitFactor;
                        radius[1]=pieces[6].toDouble()*unitFactor;
                        angle[2]=pieces[7].toDouble();
                        break;
    
                   default:
                        //try to scan the line for the unit
                        if(line.contains("centimeter", Qt::CaseInsensitive)||
                           line.contains("centimetre", Qt::CaseInsensitive))
                        {
                             unitFactor=0.01;
                             qDebug()<<"unit centimetre detected";
                        }
                        else
                             if(line.contains("meter", Qt::CaseInsensitive)||
                                line.contains("metre", Qt::CaseInsensitive))
                             {
                                  unitFactor=1;
                                  qDebug()<<"unit metre detected";
                             }
                             else
                             {
                                  qDebug()<<"Ignoring line: "<<line;
                             }
                        continue;//next line
                        break;
                   }
    
                   FrameElement *element = new FrameElement(agentID-1);
                   element->SetPos(pos);
                   element->SetOrientation(angle);
                   element->SetRadius(radius);
                   element->SetColor(color);
    
                   if(dataset->GetFrames().count(frameID)<1)
                   {
                        Frame* frame = new Frame(frameID);
                        frame->addElement(element);
                        dataset->addFrame(frame);
                        //cout<<"adding frame: "<<frameID<<endl;
                   }
                   else
                   {
                        dataset->GetFrames()[frameID]->addElement(element);
                   }
    
                   //a new frame is starting.
                   // not longer necessary if you are using maps and frameid
                   if(frameID!=lastFrameID)
                   {
                        progressDialog.setValue(dataset->getSize());
                        lastFrameID=frameID;
                        QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
                   }
              }
    
              inputFile.close();
              qDebug()<<dataset->GetFrames().size()<<" frames added";
              //construct the polydata
              for( const auto & frame:dataset->GetFrames())
              {
                   frame.second->ComputePolyData();
                   //cout<<"computing polydata"<<endl;
              }
              //dataset->setNumberOfAgents(50);
    
         }
         else
         {
              qDebug()<<"could not open the file: "<<fileName<<endl;
              return false;
         }
    
         return true;
    }
    
    bool SaxParser::ParseGradientFieldVTK(QString fileName, GeometryFactory& geoFac)
    {
         if(QFileInfo(fileName).isRelative())
         {
              QString wd;
              SystemSettings::getWorkingDirectory(wd);
              fileName=wd+"/"+fileName;
         }
    
         qDebug()<<"Opening the gradient field:"<<fileName<<endl;
         // Read the file
         VTK_CREATE(vtkStructuredPointsReader, reader);
         reader->SetFileName(fileName.toStdString().c_str());
         reader->Update();
         reader->SetLookupTableName("LOOKUP_TABLE default");
    
         VTK_CREATE(vtkImageDataGeometryFilter,geometryFilter );
         geometryFilter->SetInputConnection(reader->GetOutputPort());
         geometryFilter->Update();
    
         //try a triangle strip
    //    VTK_CREATE(vtkStripper,stripper);
    //    stripper->SetInputConnection(geometryFilter->GetOutputPort());
    //    VTK_CREATE(vtkTriangleFilter,trianglefilter);
    //    trianglefilter->SetInputConnection(stripper->GetOutputPort());
    
    
         VTK_CREATE(vtkPolyDataMapper,mapper);
         mapper->SetInputConnection(geometryFilter->GetOutputPort());
    
         VTK_CREATE(vtkActor, actor);
         actor->SetMapper(mapper);
         //conversion from m to cm
         actor->SetScale(100);
    
         auto gradient_field= shared_ptr<FacilityGeometry>(new FacilityGeometry("Gradient Field", "no name", "no name"));
         gradient_field->addGradientField(actor);
    
         geoFac.AddElement(-1,-1,gradient_field);
         geoFac.AddElement(-2,-2,gradient_field);
         return true;
    }
    
    void SaxParser::InitHeader(int major, int minor, int patch)
    {
         if ( (minor==6) || (minor==5 && patch==1) ) {
              _jps_xPos=QString("x");
              _jps_yPos=QString("y");
              _jps_zPos=QString("z");
              _jps_xVel=QString("xV");
              _jps_yVel=QString("yV");
              _jps_zVel=QString("zV");
              _jps_radiusA=QString("rA");
              _jps_radiusB=QString("rB");
              _jps_ellipseOrientation=QString("eO");
              _jps_ellipseColor=QString("eC");
         } else {
              _jps_xPos=QString("xPos");
              _jps_yPos=QString("yPos");
              _jps_zPos=QString("zPos");
              _jps_xVel=QString("xVel");
              _jps_yVel=QString("yVel");
              _jps_zVel=QString("zVel");
              _jps_radiusA=QString("radiusA");
              _jps_radiusB=QString("radiusB");
              _jps_ellipseOrientation=QString("ellipseOrientation");
              _jps_ellipseColor=QString("ellipseColor");
         }
         if(major!=0) {
              cout<<"unsupported header version: "<<major<<"."<<minor<<"."<<patch<<endl;
              cout<<"Please use 0.5 0.5.1 or 0.6 "<<endl;
              exit(0);
         }
    }