diff --git a/CMakeLists.txt b/CMakeLists.txt
index 110c8646371b40c9f8ef8f7da89d152c7521211f..82538f685b5b0abca6071c23a5cd0e0c45462c0e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -290,6 +290,7 @@ set(source_files
         routing/ff_router/LocalFloorfieldViaFM.cpp
         routing/ff_router/FloorfieldViaFM.cpp
         #routing/ff_router/FFKit.cpp
+        routing/ff_router/UnivFFviaFM.cpp
 
         #global_shortest
         routing/global_shortest/AccessPoint.cpp
@@ -355,6 +356,7 @@ set(header_files
         routing/ff_router/LocalFloorfieldViaFM.h
         routing/ff_router/FloorfieldViaFM.h
         #routing/ff_router/FFKit.h
+        routing/ff_router/UnivFFviaFM.h
 
         #general
         routing/DirectionStrategy.h
diff --git a/Simulation.cpp b/Simulation.cpp
index 5ee11ed830986ef4d4856f084071562f565f6be8..66d6da09bb02426c1f42a8eb186a51de7c6f23fb 100644
--- a/Simulation.cpp
+++ b/Simulation.cpp
@@ -249,10 +249,6 @@ bool Simulation::InitArgs()
     // This should be done after the initialization of the operationalModel
     // because then, invalid pedestrians have been deleted and FindExit()
     // has been called.
-    Log->Write("INFO:\t PreSim of DirectionStrategy starting ...");
-    if (!_operationalModel->GetDirection()->PreSim(_building.get()))
-        return false;
-    Log->Write("INFO:\t PreSim of DirectionStrategy done");
 
     //other initializations
     for (auto&& ped: _building->GetAllPedestrians()) {
@@ -509,11 +505,11 @@ double Simulation::RunBody(double maxSimTime)
         if (0==frameNr%writeInterval) {
             _iod->WriteFrame(frameNr/writeInterval, _building.get());
         }
-        if(!_gotSources && !_periodic /*&& _printPB*/) // @todo: option for print progressbar
-              // Log->ProgressBar(initialnPeds, initialnPeds-_nPeds, t);
-              //bar->Progressed(initialnPeds-_nPeds);
-        else
-             printf("time: %.2f | %.2f\n",  t , maxSimTime);
+//        if(!_gotSources && !_periodic /*&& _printPB*/) // @todo: option for print progressbar
+//              // Log->ProgressBar(initialnPeds, initialnPeds-_nPeds, t);
+//              bar->Progressed(initialnPeds-_nPeds);
+//        else
+//             printf("time: %.2f | %.2f\n",  t , maxSimTime);
 
         // needed to control the execution time PART 2
         // time(&endtime);
diff --git a/general/Macros.h b/general/Macros.h
index 954e8154141e9ef48c9b763a4075722796c2aa5f..d7b28e052c3ed11020ab1c6b64e61127b838677a 100644
--- a/general/Macros.h
+++ b/general/Macros.h
@@ -162,13 +162,14 @@ enum FFRouterMode {
 };
 
 enum GridCode { //used in floor fields
-    WALL = 0,
-    INSIDE,
-    OUTSIDE,
-    OPEN_CROSSING,
-    OPEN_TRANSITION,
-    CLOSED_CROSSING,     //closed crossings and transitions are marked as walls in "parseBuilding"
-    CLOSED_TRANSITION
+    WALL = -10,
+    INSIDE = -11,
+    OUTSIDE = -12,
+    //instead of constants, GridCode stores UID of doors
+    OPEN_CROSSING = -13,
+    OPEN_TRANSITION = -14,
+    CLOSED_CROSSING = -15,     //closed crossings and transitions are marked as walls in "parseBuilding"
+    CLOSED_TRANSITION = -16
 };
 
 enum FastMarchingFlags {
@@ -181,6 +182,37 @@ enum FastMarchingFlags {
      FM_OUTSIDE = -7
 };
 
+enum FloorfieldMode {
+     FF_CENTRALPOINT,
+     FF_FULL_LINE,
+     FF_WALL_AVOID,
+     FF_HOMO_SPEED
+};
+
+enum MagicNumbers{
+     UNKNOWN_DISTANCE,
+     UNKNOWN_COST,
+     WALL_ON_COSTARRAY,
+     TARGET_REGION
+};
+
+constexpr double magicnum(int i) {
+     return (i == UNKNOWN_DISTANCE) ? -3.0 : (i == UNKNOWN_COST) ? -2.0 : (i == WALL_ON_COSTARRAY) ? -7.0 : (i == TARGET_REGION) ? 0.0 : NAN;
+//     switch (i) {
+//          case UNKNOWN_DISTANCE:
+//               return -3.0;
+//          case UNKNOWN_COST:
+//               return -2.0;
+//          case WALL_ON_COSTARRAY:
+//               return -7.0;
+//          case TARGET_REGION:
+//               return 0.0;
+//          default:
+//               std::cerr << "ERROR: \tunknown magic number " << i << std::endl;
+//               return NAN;
+//     }
+}
+
 //global functions for convenience
 
 inline char xmltob(const char * t, char v = 0)
diff --git a/pedestrian/Pedestrian.cpp b/pedestrian/Pedestrian.cpp
index 072a018335e073ee5908af2f7c119b761b382c90..fce31355371b4181ea9593e04ed90e3420be47b3 100644
--- a/pedestrian/Pedestrian.cpp
+++ b/pedestrian/Pedestrian.cpp
@@ -147,7 +147,6 @@ Pedestrian::Pedestrian(const StartDistribution& agentsParameters, Building& buil
      _tmpFirstOrientation = true;
      _turninAngle = 0.0;
      _ellipse = JEllipse();
-     //_navLine = new NavLine(); //FIXME? argraf : rather nullptr and Setter includes correct uid (done below)
      _navLine = nullptr;
      _router = NULL;
      _building = NULL;
@@ -254,16 +253,11 @@ void Pedestrian::SetExitIndex(int i)
 
 void Pedestrian::SetExitLine(const NavLine* l) //FIXME? argraf : _navLine = new NavLine(*l); this would have a navLine with consistent uid (done below)
 {
-     //_navLine = l;
-     //_navLine->SetPoint1(l->GetPoint1());
-     //_navLine->SetPoint2(l->GetPoint2());
-     if(l) {
-          _navLine = std::unique_ptr<NavLine>(new NavLine(*l));
-     }
-     /*else if(l && _navLine && *l != *_navLine && l->GetUniqueID() != _navLine->GetUniqueID()){
+     if(_navLine)
           delete _navLine;
+     if(l) {
           _navLine = new NavLine(*l);
-     }*/
+     }
 }
 
 void Pedestrian::SetPos(const Point& pos, bool initial)
@@ -392,7 +386,7 @@ int Pedestrian::GetExitIndex() const
 
 NavLine* Pedestrian::GetExitLine() const
 {
-     return _navLine.get();
+     return _navLine;
 }
 
 const vector<int>& Pedestrian::GetTrip() const
diff --git a/pedestrian/Pedestrian.h b/pedestrian/Pedestrian.h
index 3ac426f25fe676dd9c9d0a81ee2e1b7623aba3dc..e8e7538c6f7e6b333039f755aae1548fd8940262 100644
--- a/pedestrian/Pedestrian.h
+++ b/pedestrian/Pedestrian.h
@@ -91,7 +91,7 @@ private:
      int _oldSubRoomID;
      Point _lastE0;
 
-     std::unique_ptr<NavLine> _navLine; // current exit line
+     NavLine* _navLine; // current exit line
      std::map<int, int>_mentalMap; // map the actual room to a destination
      std::vector<int> _destHistory;
      std::vector<int> _trip;
diff --git a/routing/DirectionStrategy.cpp b/routing/DirectionStrategy.cpp
index 4bdf38282ac328e397d39d287fa012f000988759..e51586b1a01f1fa04be2f2d54f5d91d446a6f921 100644
--- a/routing/DirectionStrategy.cpp
+++ b/routing/DirectionStrategy.cpp
@@ -410,48 +410,7 @@ void DirectionLocalFloorfield::Init(Building* buildingArg, double stepsize,
      _initDone = true;
 }
 
-bool DirectionLocalFloorfield::PreSim(Building* building) {
-     std::map<int, std::vector<int>> doorsInRoom;
-     doorsInRoom.clear();
-     Log->Write("INFO: \tDirectionLocalFloorfield::PreSim");
-
-     std::set<std::pair<int, int>> roomsDoorsSet;
-     roomsDoorsSet.clear();
-     auto allPeds = building->GetAllPedestrians();
-#pragma omp parallel
-     {
-#pragma omp for
-          for (size_t i = 0; i < allPeds.size(); ++i) {
-               auto ped = allPeds.begin();
-               std::advance(ped, i);
-               if (auto router = dynamic_cast<FFRouter*>((*ped)->GetRouter())) {
-                    auto pedSubroomsDoorSet = router->GetPresumableExitRoute(*ped);
-#pragma omp critical(roomsDoorsSet)
-                    for (auto it : pedSubroomsDoorSet) {
-                         roomsDoorsSet.insert(std::make_pair(it.first->GetRoomID(), it.second));
-                    }
-               }
-          }
-
-#pragma omp for
-          for (size_t i = 0; i < roomsDoorsSet.size(); ++i) {
-               auto rdIt = roomsDoorsSet.begin();
-               // suboptimal, because a set doesn't provide random-access iterators
-               std::advance(rdIt, i);
-               CalcFloorfield(rdIt->first, rdIt->second);
-#pragma omp critical(doorsInRoom)
-               doorsInRoom[rdIt->first].push_back(rdIt->second);
-          }
-     }
 
-     for (size_t i = 0; i < doorsInRoom.size(); ++i) {
-          auto roomIt = doorsInRoom.begin();
-          std::advance(roomIt, i);
-          //@todo: ar.graf: plz make switch in ini file and dependand on ini write yes/no (issue 208)
-          //writeFF(roomIt->first, roomIt->second);
-     }
-     return true;
-}
 
 void DirectionLocalFloorfield::CalcFloorfield(int room, int destUID) {
      Point dummy;
diff --git a/routing/DirectionStrategy.h b/routing/DirectionStrategy.h
index a25698bd8499aa9159e619b05473bf409e7bd79c..fb3a5d09bf17aec80627c0e0b8e86c265933cef4 100644
--- a/routing/DirectionStrategy.h
+++ b/routing/DirectionStrategy.h
@@ -46,41 +46,33 @@ public:
      DirectionStrategy();
      virtual ~DirectionStrategy();
 
-     // Allow the DirectionStrategy to perform some pre-simulation calculation, with all pedestrians
-     // already set and a valid _exitIndex. Returns true if the initialization was successful.
-     virtual bool PreSim(Building* building) = 0;
 
      virtual Point GetTarget(Room* room, Pedestrian* ped) const = 0;
 };
 
 class DirectionMiddlePoint : public DirectionStrategy {
 public:
-     virtual bool PreSim(Building* building) {(void) building; return true;};
      virtual Point GetTarget(Room* room, Pedestrian* ped) const;
 };
 
 class DirectionMinSeperation : public DirectionStrategy {
 public:
-     virtual bool PreSim(Building* building) {(void) building; return true;};
      virtual Point GetTarget(Room* room, Pedestrian* ped) const;
 };
 
 class DirectionMinSeperationShorterLine : public DirectionStrategy {
 public:
-     virtual bool PreSim(Building* building) {(void) building; return true;};
      virtual Point GetTarget(Room* room, Pedestrian* ped) const;
 };
 
 class DirectionInRangeBottleneck : public DirectionStrategy {
 public:
-     virtual bool PreSim(Building* building) {(void) building; return true;};
      virtual Point GetTarget(Room* room, Pedestrian* ped) const;
 };
 
 
 class DirectionGeneral : public DirectionStrategy {
 public:
-     virtual bool PreSim(Building* building) {(void) building; return true;};
      virtual Point GetTarget(Room* room, Pedestrian* ped) const;
 };
 
@@ -88,7 +80,6 @@ class DirectionFloorfield : public DirectionStrategy {
 public:
     DirectionFloorfield();
     void Init(Building* building, double stepsize, double threshold, bool useDistancMap);
-    virtual bool PreSim(Building* building) {(void) building; return true;};
     ~DirectionFloorfield();
     //void Init();
     virtual Point GetTarget(Room* room, Pedestrian* ped) const;
@@ -105,7 +96,6 @@ public:
      DirectionLocalFloorfield();
      void Init(Building* building, double stepsize, double threshold,
                bool useDistancMap);
-     virtual bool PreSim(Building* building);
      ~DirectionLocalFloorfield();
      //void Init();
      virtual Point GetTarget(Room* room, Pedestrian* ped) const;
@@ -132,7 +122,6 @@ public:
      DirectionSubLocalFloorfield();
      void Init(Building* building, double stepsize, double threshold,
            bool useDistancMap);
-     virtual bool PreSim(Building* building) {(void) building; return true;};
      ~DirectionSubLocalFloorfield();
      //void Init();
      virtual Point GetTarget(Room* room, Pedestrian* ped) const;
diff --git a/routing/ff_router/UnivFFviaFM.cpp b/routing/ff_router/UnivFFviaFM.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..222c2cbcf429f98925b53555f69459f7c4832d3b
--- /dev/null
+++ b/routing/ff_router/UnivFFviaFM.cpp
@@ -0,0 +1,624 @@
+//
+// Created by arne on 5/9/17.
+//
+
+#include "UnivFFviaFM.h"
+#include "../../geometry/Line.h"
+#include "../../geometry/Building.h"
+#include "../../geometry/Room.h"
+#include "../../geometry/SubRoom.h"
+#include "mesh/RectGrid.h"
+
+
+UnivFFviaFM::UnivFFviaFM(Room* a, Building* b, double hx, double hy, double wallAvoid, bool useWallAvoid) {
+     _building = b;
+     const Configuration* conf = b->GetConfig();
+     UnivFFviaFM(a, conf, hx, hy, wallAvoid, useWallAvoid);
+}
+
+UnivFFviaFM::UnivFFviaFM(SubRoom* a, Building* b, double hx, double hy, double wallAvoid, bool useWallAvoid) {
+     _building = b;
+     const Configuration* conf = b->GetConfig();
+     UnivFFviaFM(a, conf, hx, hy, wallAvoid, useWallAvoid);
+}
+
+UnivFFviaFM::UnivFFviaFM(Room *a, const Configuration *b, double hx, double hy, double wallAvoid, bool useWallAvoid) {
+     //build the vector with walls(wall or obstacle), the map with <UID, Door(Cross or Trans)>, the vector with targets(UIDs)
+     //then call other constructor including the mode
+     _wallAvoidDistance = wallAvoid;
+     _useWallAvoidance = useWallAvoid;
+
+     std::vector<Line> lines;
+     std::map<int, Line> tmpDoors;
+
+     for (auto& subroomMap : a->GetAllSubRooms()) {
+          SubRoom* subRoomPtr = subroomMap.second.get();
+          std::vector<Wall> walls = std::vector<Wall>(subRoomPtr->GetAllWalls());
+          for (auto& wall : walls) {
+               lines.emplace_back((Line)wall);
+          }
+
+          std::vector<Obstacle*> tmpObsPtrVec = subRoomPtr->GetAllObstacles();
+          for (Obstacle* ptrObs : tmpObsPtrVec) {
+               const std::vector<Wall> obsWalls = ptrObs->GetAllWalls();
+               for (auto& owall : obsWalls) {
+                    lines.emplace_back((Line)owall);
+               }
+          }
+
+          const std::vector<Crossing*> tmpCross = subRoomPtr->GetAllCrossings();
+          const std::vector<Transition*> tmpTrans = subRoomPtr->GetAllTransitions();
+
+          for (auto& cross : tmpCross) {
+               tmpDoors.emplace(std::make_pair(cross->GetUniqueID(), (Line) *cross));
+          }
+          for (auto& trans : tmpTrans) {
+               tmpDoors.emplace(std::make_pair(trans->GetUniqueID(), (Line) *trans));
+          }
+     }
+
+     std::vector<int> noDoors;
+     UnivFFviaFM(lines, tmpDoors, noDoors, FF_HOMO_SPEED, hx);
+}
+
+UnivFFviaFM::UnivFFviaFM(SubRoom* a, const Configuration* b, double hx, double hy, double wallAvoid, bool useWallAvoid) {
+     //build the vector with walls(wall or obstacle), the map with <UID, Door(Cross or Trans)>, the vector with targets(UIDs)
+     //then call other constructor including the mode
+     _wallAvoidDistance = wallAvoid;
+     _useWallAvoidance = useWallAvoid;
+
+     std::vector<Wall> walls = std::vector<Wall> (a->GetAllWalls());
+     std::vector<Line> lines;
+     for (auto& wall : walls) {
+          lines.emplace_back((Line)wall);
+     }
+
+     std::vector<Obstacle*> tmpObsPtrVec = a->GetAllObstacles();
+     for (Obstacle* ptrObs : tmpObsPtrVec) {
+          const std::vector<Wall> obsWalls = ptrObs->GetAllWalls();
+          for (auto& owall : obsWalls) {
+               lines.emplace_back((Line)owall);
+          }
+     }
+
+     std::map<int, Line> tmpDoors;
+     const std::vector<Crossing*> tmpCross = a->GetAllCrossings();
+     const std::vector<Transition*> tmpTrans = a->GetAllTransitions();
+
+     for (auto& cross : tmpCross) {
+          tmpDoors.emplace(std::make_pair(cross->GetUniqueID(), (Line) *cross));
+     }
+     for (auto& trans : tmpTrans) {
+          tmpDoors.emplace(std::make_pair(trans->GetUniqueID(), (Line) *trans));
+     }
+
+     std::vector<int> noDoors;
+     UnivFFviaFM(lines, tmpDoors, noDoors, FF_HOMO_SPEED, hx);
+}
+
+UnivFFviaFM::UnivFFviaFM(std::vector<Line>& walls, std::map<int, Line>& doors, std::vector<int> targetUIDs, int mode, double spacing) {
+     //find circumscribing rectangle (x_min/max, y_min/max) //create RectGrid
+     createRectGrid(walls, doors, spacing);
+     _nPoints = _grid->GetnPoints();
+
+     //allocate _gridCode and  _speedFieldSelector and initialize them ("draw" walls and doors)
+     _gridCode = new int[_nPoints];
+     processGeometry(walls, doors);
+
+     _speedFieldSelector[INITIAL_SPEED] = new double[_nPoints];
+     std::fill(_speedFieldSelector[INITIAL_SPEED], _speedFieldSelector[INITIAL_SPEED]+_nPoints, 1.0);
+
+     //allocate _initalSpeed and maybe _modifiedSpeed
+     if (mode == FF_WALL_AVOID) {
+          double* cost_alias_walldistance = new double[_nPoints];
+          _costFieldWithKey[0] = cost_alias_walldistance;
+          Point* gradient_alias_walldirection = new Point[_nPoints];
+          _directionFieldWithKey[0] = gradient_alias_walldirection;
+
+          //create wall distance field
+          drawLinesOnGrid(walls, cost_alias_walldistance, magicnum(TARGET_REGION));
+          calcFF(cost_alias_walldistance, gradient_alias_walldirection, _speedFieldSelector[INITIAL_SPEED]);
+
+          double* temp_reduWallSpeed = new double[_nPoints];
+          if (_speedFieldSelector[REDU_WALL_SPEED]) { //free memory before overwriting
+               delete[] _speedFieldSelector[REDU_WALL_SPEED];
+          }
+          _speedFieldSelector[REDU_WALL_SPEED] = temp_reduWallSpeed;
+          //init _reducedWallSpeed by using distance field
+          //@todo: @ar.graf @newFF
+     }
+
+     for (auto targetUID : targetUIDs ) {
+          Line tempTargetLine = Line(doors[targetUID]);
+          Point tempCenterPoint = Point(tempTargetLine.GetCentre());
+
+          //this allocation must be on shared heap! to be accessable by any thread later (head should be shared in openmp)
+          double* newArrayDBL = new double[_nPoints];
+          Point* newArrayPt = nullptr;
+          if (_user == DISTANCE_AND_DIRECTIONS_USED) {
+               newArrayPt = new Point[_nPoints];
+          }
+
+          if (_costFieldWithKey[targetUID])
+               delete[] _costFieldWithKey[targetUID];
+          _costFieldWithKey[targetUID] = newArrayDBL;
+
+          //init costarray
+          for (int i = 0; i < _nPoints; ++i) {
+               if (_gridCode[i] == WALL) {
+                    newArrayDBL[i] = magicnum(WALL_ON_COSTARRAY);
+               } else {
+                    newArrayDBL[i] = magicnum(UNKNOWN_COST);
+               }
+          }
+
+          if (_directionFieldWithKey[targetUID])
+               delete[] _directionFieldWithKey[targetUID];
+          _directionFieldWithKey[targetUID] = newArrayPt;
+
+          //initialize start area
+          if (_mode == LINESEGMENT) {
+               drawLinesOnGrid(tempTargetLine, newArrayDBL, magicnum(TARGET_REGION));
+          }
+          if (_mode == CENTERPOINT) {
+               newArrayDBL[_grid->getKeyAtPoint(tempCenterPoint)] = magicnum(TARGET_REGION);
+          }
+
+          if (mode == FF_WALL_AVOID) {
+               calcFF(newArrayDBL, newArrayPt, _speedFieldSelector[REDU_WALL_SPEED]);
+          } else if (mode == FF_HOMO_SPEED) {
+               calcFF(newArrayDBL, newArrayPt, _speedFieldSelector[INITIAL_SPEED]);
+          }
+          _uids.emplace_back(targetUID);
+     }    //loop over targets
+
+
+
+}
+
+void UnivFFviaFM::createRectGrid(std::vector<Line>& walls, std::map<int, Line>& doors, double spacing) {
+     double x_min = DBL_MAX;  double x_max = DBL_MIN;
+     double y_min = DBL_MAX;  double y_max = DBL_MIN;
+
+     for(auto& wall : walls) {
+          if (wall.GetPoint1()._x < x_min) x_min = wall.GetPoint1()._x;
+          if (wall.GetPoint1()._y < y_min) y_min = wall.GetPoint1()._y;
+          if (wall.GetPoint2()._x < x_min) x_min = wall.GetPoint2()._x;
+          if (wall.GetPoint2()._y < y_min) y_min = wall.GetPoint2()._y;
+
+          if (wall.GetPoint1()._x > x_max) x_max = wall.GetPoint1()._x;
+          if (wall.GetPoint1()._y > y_max) y_max = wall.GetPoint1()._y;
+          if (wall.GetPoint2()._x > x_max) x_max = wall.GetPoint2()._x;
+          if (wall.GetPoint2()._y > y_max) y_max = wall.GetPoint2()._y;
+     }
+
+     for(auto& doorPair:doors) {
+          Line& door = doorPair.second;
+          if (door.GetPoint1()._x < x_min) x_min = door.GetPoint1()._x;
+          if (door.GetPoint1()._y < y_min) y_min = door.GetPoint1()._y;
+          if (door.GetPoint2()._x < x_min) x_min = door.GetPoint2()._x;
+          if (door.GetPoint2()._y < y_min) y_min = door.GetPoint2()._y;
+
+          if (door.GetPoint1()._x > x_max) x_max = door.GetPoint1()._x;
+          if (door.GetPoint1()._y > y_max) y_max = door.GetPoint1()._y;
+          if (door.GetPoint2()._x > x_max) x_max = door.GetPoint2()._x;
+          if (door.GetPoint2()._y > y_max) y_max = door.GetPoint2()._y;
+     }
+
+     //create Rect Grid
+     _grid = new RectGrid();
+     _grid->setBoundaries(x_min, y_min, x_max, y_max);
+     _grid->setSpacing(spacing, spacing);
+     _grid->createGrid();
+}
+
+void UnivFFviaFM::processGeometry(std::vector<Line>&walls, std::map<int, Line>& doors) {
+     for (int i = 0; i < _nPoints; ++i) {
+          _gridCode[i] = OUTSIDE;
+     }
+
+     _doors = doors;
+
+     drawLinesOnGrid<int>(walls, _gridCode, WALL);
+     drawLinesOnGrid(doors, _gridCode); //UIDs of doors will be drawn on _gridCode
+}
+
+void UnivFFviaFM::drawLinesOnGrid(std::map<int, Line>& doors, int *const grid) {
+     for (auto&& doorPair : doors) {
+          int tempUID = doorPair.first;
+          Line tempDoorLine = Line(doorPair.second);
+          drawLinesOnGrid(tempDoorLine, grid, tempUID);
+     }
+}
+
+template <typename T>
+void UnivFFviaFM::drawLinesOnGrid(std::vector<Line>& wallArg, T* const target, const T value) { //no init, plz init elsewhere
+
+     for (auto& line : wallArg) {
+          drawLinesOnGrid(line, target, value);
+     } //loop over all walls
+
+} //drawLinesOnGrid
+
+template <typename T>
+void UnivFFviaFM::drawLinesOnGrid(Line& line, T* const target, const T value) { //no init, plz init elsewhere
+// i~x; j~y;
+//http://stackoverflow.com/questions/10060046/drawing-lines-with-bresenhams-line-algorithm
+//src in answer of "Avi"; adapted to fit this application
+
+     //grid handeling local vars:
+     long int iMax  = _grid->GetiMax();
+
+     long int iStart, iEnd;
+     long int jStart, jEnd;
+     long int iDot, jDot;
+     long int key;
+     long int deltaX, deltaY, deltaX1, deltaY1, px, py, xe, ye, i; //Bresenham Algorithm
+
+
+     key = _grid->getKeyAtPoint(line.GetPoint1());
+     iStart = (long) _grid->get_i_fromKey(key);
+     jStart = (long) _grid->get_j_fromKey(key);
+
+     key = _grid->getKeyAtPoint(line.GetPoint2());
+     iEnd = (long) _grid->get_i_fromKey(key);
+     jEnd = (long) _grid->get_j_fromKey(key);
+
+     deltaX = (int) (iEnd - iStart);
+     deltaY = (int) (jEnd - jStart);
+     deltaX1 = abs( (int) (iEnd - iStart));
+     deltaY1 = abs( (int) (jEnd - jStart));
+
+     px = 2*deltaY1 - deltaX1;
+     py = 2*deltaX1 - deltaY1;
+
+     if(deltaY1<=deltaX1) {
+          if(deltaX>=0) {
+               iDot = iStart;
+               jDot = jStart;
+               xe = iEnd;
+          } else {
+               iDot = iEnd;
+               jDot = jEnd;
+               xe = iStart;
+          }
+          if ((_gridCode[jDot*iMax + iDot] != WALL) && (_gridCode[jDot*iMax + iDot] != CLOSED_CROSSING) && (_gridCode[jDot*iMax + iDot] != CLOSED_TRANSITION)) {
+               target[jDot * iMax + iDot] = value;
+          }
+          for (i=0; iDot < xe; ++i) {
+               ++iDot;
+               if(px<0) {
+                    px+=2*deltaY1;
+               } else {
+                    if((deltaX<0 && deltaY<0) || (deltaX>0 && deltaY>0)) {
+                         ++jDot;
+                    } else {
+                         --jDot;
+                    }
+                    px+=2*(deltaY1-deltaX1);
+               }
+               if ((_gridCode[jDot*iMax + iDot] != WALL) && (_gridCode[jDot*iMax + iDot] != CLOSED_CROSSING) && (_gridCode[jDot*iMax + iDot] != CLOSED_TRANSITION)) {
+                    target[jDot * iMax + iDot] = value;
+               }
+          }
+     } else {
+          if(deltaY>=0) {
+               iDot = iStart;
+               jDot = jStart;
+               ye = jEnd;
+          } else {
+               iDot = iEnd;
+               jDot = jEnd;
+               ye = jStart;
+          }
+          if ((_gridCode[jDot*iMax + iDot] != WALL) && (_gridCode[jDot*iMax + iDot] != CLOSED_CROSSING) && (_gridCode[jDot*iMax + iDot] != CLOSED_TRANSITION)) {
+               target[jDot * iMax + iDot] = value;
+          }
+          for(i=0; jDot<ye; ++i) {
+               ++jDot;
+               if (py<=0) {
+                    py+=2*deltaX1;
+               } else {
+                    if((deltaX<0 && deltaY<0) || (deltaX>0 && deltaY>0)) {
+                         ++iDot;
+                    } else {
+                         --iDot;
+                    }
+                    py+=2*(deltaX1-deltaY1);
+               }
+               if ((_gridCode[jDot*iMax + iDot] != WALL) && (_gridCode[jDot*iMax + iDot] != CLOSED_CROSSING) && (_gridCode[jDot*iMax + iDot] != CLOSED_TRANSITION)) {
+                    target[jDot * iMax + iDot] = value;
+               }
+          }
+     }
+} //drawLinesOnGrid
+
+void UnivFFviaFM::calcFF(double* costOutput, Point* directionOutput, const double *const speed) {
+     CompareCost comp = CompareCost(costOutput);
+     std::priority_queue<long int, std::vector<long int>, CompareCost> trialfield(costOutput); //pass the argument for the constr of CompareCost
+     std::priority_queue<long int, std::vector<long int>, CompareCost> trialfield2(comp);      //pass the CompareCost object directly
+
+     directNeighbor local_neighbor = _grid->getNeighbors(0);
+     long int aux = 0;
+     //init trial field
+     for (long int i = 0; i < _nPoints; ++i) {
+          if (costOutput[i] == 0.0) {
+               //check for negative neighbours, calc that ones and add to queue trialfield
+               local_neighbor = _grid->getNeighbors(i);
+
+               //check for valid neigh
+               aux = local_neighbor.key[0];
+               if ((aux != -2) && (_gridCode[aux] != WALL) && (costOutput[aux] < 0.0)) {
+                    calcCost(aux, costOutput, directionOutput, speed);
+                    trialfield.emplace(aux);
+                    trialfield2.emplace(aux);
+               }
+               aux = local_neighbor.key[1];
+               if ((aux != -2) && (_gridCode[aux] != WALL) && (costOutput[aux] < 0.0)) {
+                    calcCost(aux, costOutput, directionOutput, speed);
+                    trialfield.emplace(aux);
+                    trialfield2.emplace(aux);
+               }
+               aux = local_neighbor.key[2];
+               if ((aux != -2) && (_gridCode[aux] != WALL) && (costOutput[aux] < 0.0)) {
+                    calcCost(aux, costOutput, directionOutput, speed);
+                    trialfield.emplace(aux);
+                    trialfield2.emplace(aux);
+               }
+               aux = local_neighbor.key[3];
+               if ((aux != -2) && (_gridCode[aux] != WALL) && (costOutput[aux] < 0.0)) {
+                    calcCost(aux, costOutput, directionOutput, speed);
+                    trialfield.emplace(aux);
+                    trialfield2.emplace(aux);
+               }
+          }
+     }
+
+     while(!trialfield.empty()) {
+          local_neighbor = _grid->getNeighbors(trialfield.top());
+          trialfield.pop();
+
+          //check for valid neigh
+          aux = local_neighbor.key[0];
+          if ((aux != -2) && (_gridCode[aux] != WALL) && (costOutput[aux] < 0.0)) {
+               calcCost(aux, costOutput, directionOutput, speed);
+               trialfield.emplace(aux);
+               trialfield2.emplace(aux);
+          }
+          aux = local_neighbor.key[1];
+          if ((aux != -2) && (_gridCode[aux] != WALL) && (costOutput[aux] < 0.0)) {
+               calcCost(aux, costOutput, directionOutput, speed);
+               trialfield.emplace(aux);
+               trialfield2.emplace(aux);
+          }
+          aux = local_neighbor.key[2];
+          if ((aux != -2) && (_gridCode[aux] != WALL) && (costOutput[aux] < 0.0)) {
+               calcCost(aux, costOutput, directionOutput, speed);
+               trialfield.emplace(aux);
+               trialfield2.emplace(aux);
+          }
+          aux = local_neighbor.key[3];
+          if ((aux != -2) && (_gridCode[aux] != WALL) && (costOutput[aux] < 0.0)) {
+               calcCost(aux, costOutput, directionOutput, speed);
+               trialfield.emplace(aux);
+               trialfield2.emplace(aux);
+          }
+     }
+}
+
+void UnivFFviaFM::calcCost(const long int key, double* cost, Point* dir, const double* const speed) {
+     //adapt from calcFloorfield
+     double row = DBL_MAX;
+     double col = DBL_MAX;
+     long int aux = -1; //will be set below
+     bool pointsUp = false;
+     bool pointsRight = false;
+
+     directNeighbor dNeigh = _grid->getNeighbors(key);
+
+     aux = dNeigh.key[0];
+     //hint: trialfield[i].cost = dist2Wall + i; <<< set in resetGoalAndCosts
+     if  ((aux != -2) &&                                                                         //neighbor is a gridpoint
+          (cost[aux] != magicnum(UNKNOWN_COST)) && (cost[aux] != magicnum(UNKNOWN_DISTANCE)) &&  //gridpoint holds a calculated value
+          (_gridCode[aux] != WALL))                                                              //gridpoint holds a calculated value
+     {
+          row = cost[aux];
+          pointsRight = true;
+          if (row < 0) {
+               std::cerr << "hier ist was schief " << row << " " << aux << " " <<  std::endl;
+               row = DBL_MAX;
+          }
+     }
+     aux = dNeigh.key[2];
+     if  ((aux != -2) &&                                                         //neighbor is a gridpoint
+          (cost[aux] != magicnum(UNKNOWN_COST)) && (cost[aux] != magicnum(UNKNOWN_DISTANCE)) &&  //gridpoint holds a calculated value
+          (_gridCode[aux] != WALL) &&
+          (cost[aux] < row))                                       //calculated value promises smaller cost
+     {
+          row = cost[aux];
+          pointsRight = false;
+     }
+
+     aux = dNeigh.key[1];
+     //hint: trialfield[i].cost = dist2Wall + i; <<< set in parseBuilding after linescan call
+     if  ((aux != -2) &&                                                         //neighbor is a gridpoint
+          (cost[aux] != magicnum(UNKNOWN_COST)) && (cost[aux] != magicnum(UNKNOWN_DISTANCE)) &&  //gridpoint holds a calculated value
+          (_gridCode[aux] != WALL))
+     {
+          col = cost[aux];
+          pointsUp = true;
+          if (col < 0) {
+               std::cerr << "hier ist was schief " << col << " " << aux << " "  << std::endl;
+               col = DBL_MAX;
+          }
+     }
+     aux = dNeigh.key[3];
+     if  ((aux != -2) &&                                                         //neighbor is a gridpoint
+          (cost[aux] != magicnum(UNKNOWN_COST)) && (cost[aux] != magicnum(UNKNOWN_DISTANCE)) &&  //gridpoint holds a calculated value
+          (_gridCode[aux] != WALL) &&
+          (cost[aux] < col))                                       //calculated value promises smaller cost
+     {
+          col = cost[aux];
+          pointsUp = false;
+     }
+     if (col == DBL_MAX) { //one sided update with row
+          cost[key] = onesidedCalc(row, _grid->Gethx()/speed[key]);
+          //flag[key] = FM_SINGLE;
+          if (pointsRight) {
+               dir[key]._x = (-(cost[key+1]-cost[key])/_grid->Gethx());
+               dir[key]._y = (0.);
+          } else {
+               dir[key]._x = (-(cost[key]-cost[key-1])/_grid->Gethx());
+               dir[key]._y = (0.);
+          }
+          dir[key] = dir[key].Normalized(); //@todo: ar.graf: what yields better performance? scale every point here or scale each read value? more points or more calls to any element of dir2Wall
+          return;
+     }
+
+     if (row == DBL_MAX) { //one sided update with col
+          cost[key] = onesidedCalc(col, _grid->Gethy()/speed[key]);
+          //flag[key] = FM_SINGLE;
+          if (pointsUp) {
+               dir[key]._x = (0.);
+               dir[key]._y = (-(cost[key+(_grid->GetiMax())]-cost[key])/_grid->Gethy());
+          } else {
+               dir[key]._x = (0.);
+               dir[key]._y = (-(cost[key]-cost[key-(_grid->GetiMax())])/_grid->Gethy());
+          }
+          dir[key] = dir[key].Normalized();
+          return;
+     }
+
+     //two sided update
+     double precheck = twosidedCalc(row, col, _grid->Gethx()/speed[key]);
+     if (precheck >= 0) {
+          cost[key] = precheck;
+          //flag[key] = FM_DOUBLE;
+          if (pointsUp && pointsRight) {
+               dir[key]._x = (-(cost[key+1]-cost[key])/_grid->Gethx());
+               dir[key]._y = (-(cost[key+(_grid->GetiMax())]-cost[key])/_grid->Gethy());
+          }
+          if (pointsUp && !pointsRight) {
+               dir[key]._x = (-(cost[key]-cost[key-1])/_grid->Gethx());
+               dir[key]._y = (-(cost[key+(_grid->GetiMax())]-cost[key])/_grid->Gethy());
+          }
+          if (!pointsUp && pointsRight) {
+               dir[key]._x = (-(cost[key+1]-cost[key])/_grid->Gethx());
+               dir[key]._y = (-(cost[key]-cost[key-(_grid->GetiMax())])/_grid->Gethy());
+          }
+          if (!pointsUp && !pointsRight) {
+               dir[key]._x = (-(cost[key]-cost[key-1])/_grid->Gethx());
+               dir[key]._y = (-(cost[key]-cost[key-(_grid->GetiMax())])/_grid->Gethy());
+          }
+     } else {
+          std::cerr << "else in twosided Dist " << std::endl;
+     }
+     dir[key] = dir[key].Normalized();
+}
+
+inline double UnivFFviaFM::onesidedCalc(double xy, double hDivF) {
+     //if ( (xy+hDivF) > 10000) std::cerr << "error in onesided " << xy << std::endl;
+     return xy + hDivF;
+}
+
+inline double UnivFFviaFM::twosidedCalc(double x, double y, double hDivF) { //on error return -2
+     double determinante = (2*hDivF*hDivF - (x-y)*(x-y));
+     if (determinante >= 0) {
+          return (x + y + sqrt(determinante))/2;
+     } else {
+          return (x < y) ? (x + hDivF) : (y + hDivF);
+     }
+     std::cerr << "error in two-sided 2!!!!!!!!!!!!!!!!!!!!!!! o_O??" << std::endl;
+     return -2.; //this line should never execute
+} //twosidedCalc
+
+void UnivFFviaFM::addTarget(const int uid, Line* door) {
+
+
+}
+std::vector<int> UnivFFviaFM::getKnownDoorUIDs(){
+     return _uids;
+}
+
+void UnivFFviaFM::writeFF(const std::string& filename, std::vector<int> targetID) {
+    Log->Write("INFO: \tWrite Floorfield to file");
+    Log->Write(filename);
+    std::ofstream file;
+
+    Log->Write("FloorfieldViaFM::writeFF(): writing to file %s: There are %d targets.", filename.c_str(), targetID.size());
+
+    int numX = (int) ((_grid->GetxMax()-_grid->GetxMin())/_grid->Gethx());
+    int numY = (int) ((_grid->GetyMax()-_grid->GetyMin())/_grid->Gethy());
+    int numTotal = numX * numY;
+    //std::cerr << numTotal << " numTotal" << std::endl;
+    //std::cerr << grid->GetnPoints() << " grid" << std::endl;
+    file.open(filename);
+
+    file << "# vtk DataFile Version 3.0" << std::endl;
+    file << "Testdata: Fast Marching: Test: " << std::endl;
+    file << "ASCII" << std::endl;
+    file << "DATASET STRUCTURED_POINTS" << std::endl;
+    file << "DIMENSIONS " <<
+                                std::to_string(_grid->GetiMax()) <<
+                                " " <<
+                                std::to_string(_grid->GetjMax()) <<
+                                " 1" << std::endl;
+    file << "ORIGIN " << _grid->GetxMin() << " " << _grid->GetyMin() << " 0" << std::endl;
+    file << "SPACING " << std::to_string(_grid->Gethx()) << " " << std::to_string(_grid->Gethy()) << " 1" << std::endl;
+    file << "POINT_DATA " << std::to_string(numTotal) << std::endl;
+    file << "SCALARS GCode float 1" << std::endl;
+    file << "LOOKUP_TABLE default" << std::endl;
+    for (long int i = 0; i < _grid->GetnPoints(); ++i) {
+         file << _gridCode[i] << std::endl;
+    }
+
+    if (_directionFieldWithKey[0]) {
+         file << "VECTORS Dir2Wall float" << std::endl;
+         for (long int i = 0; i < _grid->GetnPoints(); ++i) {
+              file << _directionFieldWithKey[0][i]._x << " " << _directionFieldWithKey[0][i]._y << " 0.0" << std::endl;
+         }
+
+         file << "SCALARS Dist2Wall float 1" << std::endl;
+         file << "LOOKUP_TABLE default" << std::endl;
+         for (long int i = 0; i < _grid->GetnPoints(); ++i) {
+              file << _costFieldWithKey[0][i] << std::endl; //@todo: change target to all dist2wall
+         }
+    }
+
+//    file << "SCALARS SubroomPtr float 1" << std::endl;
+//    file << "LOOKUP_TABLE default" << std::endl;
+//    for (long int i = 0; i < _grid->GetnPoints(); ++i) {
+//        if (_subrooms[i]) {
+//            file << _subrooms[i]->GetUID() << std::endl;
+//        } else {
+//            file << 0.0 << std::endl;
+//        }
+//    }
+
+    for (unsigned int iTarget = 0; iTarget < targetID.size(); ++iTarget) {
+        Log->Write("%s: target number %d: UID %d", filename.c_str(), iTarget, targetID[iTarget]);
+        if (_directionFieldWithKey.count(targetID[iTarget]) == 0) {
+            continue;
+        }
+
+        Point *gradarray = _directionFieldWithKey[targetID[iTarget]];
+        if (gradarray == nullptr) {
+            continue;
+        }
+
+        std::string name = _building->GetTransOrCrossByUID(targetID[iTarget])->GetCaption() + "-" + std::to_string(targetID[iTarget]);
+        std::replace(name.begin(), name.end(), ' ', '_');
+        file << "VECTORS GradientTarget" << name << " float" << std::endl;
+        for (int i = 0; i < _grid->GetnPoints(); ++i) {
+            file << gradarray[i]._x << " " << gradarray[i]._y << " 0.0" << std::endl;
+        }
+
+        double *costarray = _costFieldWithKey[targetID[iTarget]];
+        file << "SCALARS CostTarget" << name << " float 1" << std::endl;
+        file << "LOOKUP_TABLE default" << std::endl;
+        for (long int i = 0; i < _grid->GetnPoints(); ++i) {
+            file << costarray[i] << std::endl;
+        }
+    }
+    file.close();
+}
\ No newline at end of file
diff --git a/routing/ff_router/UnivFFviaFM.h b/routing/ff_router/UnivFFviaFM.h
new file mode 100644
index 0000000000000000000000000000000000000000..4f046d2d4e09d45392e9b30335d1f074fb1a18d8
--- /dev/null
+++ b/routing/ff_router/UnivFFviaFM.h
@@ -0,0 +1,136 @@
+//
+// Created by arne on 5/9/17.
+//
+/**
+ * \file        UnivFFviaFM.h
+ * \date        May 09, 2017
+ * \version     N/A (v0.8.x)
+ * \copyright   <2017-2020> Forschungszentrum Jülich GmbH. All rights reserved.
+ *
+ * \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 Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * JuPedSim 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 Lesser General Public License
+ * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * \section Description
+ * Implementation of classes for a reworked floorfield. A floorfield in general
+ * yields a cost field to a specific goal and a correlated vectorfield for the
+ * optimal path in terms of the cost value.
+ *
+ * Rework focused on a cleaner structure and less inheritance (no diamond) and
+ * less workarounds.
+ *
+ *
+ **/
+#ifndef JPSCORE_UNIVFFVIAFM_H
+#define JPSCORE_UNIVFFVIAFM_H
+
+#include <string>
+#include <vector>
+#include <map>
+#include <float.h>
+
+class Room;
+class SubRoom;
+class Building;
+class Configuration;
+class Point;
+class RectGrid;
+class Line;
+
+enum SPEEDFIELD {        //this enum is used as index in _speedFieldSelector
+     INITIAL_SPEED=0,    //homogen speed in walkable area, nealy zero in walls
+     REDU_WALL_SPEED=1,   //reduced wall speed
+     PED_SPEED=2         //standing agents reduce speed, so that jams will be considered in ff
+};
+
+enum TARGETMODE {
+     LINESEGMENT=0,
+     CENTERPOINT
+};
+
+enum USERMODE {
+     DISTANCE_MEASUREMENTS_ONLY,
+     DISTANCE_AND_DIRECTIONS_USED
+};
+
+class CompareCost {      //this class is used in std::priority_queue in UnivFFviaFM::calcFF
+public:
+     CompareCost(double* costarray) : _costarray(costarray) {}
+     bool operator() (const int a, const int b) const {
+          return _costarray[a] > _costarray[b];
+     }
+
+private:
+     double* _costarray = nullptr;
+};
+
+class UnivFFviaFM {
+public:
+     UnivFFviaFM(Room* a, Building* b, double c, double d, double e, bool f);
+     UnivFFviaFM(SubRoom* a, Building* b, double c, double d, double e, bool f);
+     UnivFFviaFM(Room *a, const Configuration *b, double c, double d, double e, bool f);
+     UnivFFviaFM(SubRoom *a, const Configuration *b, double c, double d, double e, bool f);
+     UnivFFviaFM(std::vector<Line>& walls, std::map<int, Line>& doors, std::vector<int> targetUIDs, int mode, double spacing);
+     UnivFFviaFM() {};
+     UnivFFviaFM(UnivFFviaFM&){};
+     ~UnivFFviaFM(){};
+
+     void addTarget(const int uid, Line* door);
+     std::vector<int> getKnownDoorUIDs();
+
+     double getCostToDestination(const int destID, const Point& position, int mode) {return 0.;};
+     double getCostToDestination(const int destID, const Point& position) {return 0.;};
+     RectGrid* getGrid(){return nullptr;};
+     virtual void getDirectionToUID(int destID, const long int key, Point& direction, int mode){};
+     void getDirectionToUID(int destID, const long int key, Point& direction){};
+     void writeFF(const std::string&, std::vector<int> targetID);
+
+     void createRectGrid(std::vector<Line>& walls, std::map<int, Line>& doors, double spacing);
+     void processGeometry(std::vector<Line>&walls, std::map<int, Line>& doors);
+
+     void drawLinesOnGrid(std::map<int, Line>& doors, int *const grid);
+     template <typename T>
+     void drawLinesOnGrid(std::vector<Line>& wallArg, T* const target, const T value);
+     template <typename T>
+     void drawLinesOnGrid(Line& line, T* const target, const T value);
+
+     void calcFF(double*, Point*, const double* const);
+     void calcCost(const long int key, double* cost, Point* dir, const double* const speed);
+     inline double onesidedCalc(double xy, double hDivF);
+     inline double twosidedCalc(double x, double y, double hDivF);
+
+private:
+     Building* _building = nullptr;
+     Configuration* _configuration = nullptr;
+     int _mode = LINESEGMENT;                     //default
+     int _user = DISTANCE_AND_DIRECTIONS_USED;    //default
+     RectGrid* _grid = nullptr;
+     long int _nPoints = 0;
+     std::vector<double*> _speedFieldSelector;
+     int* _gridCode = nullptr;
+
+     double _wallAvoidDistance = 0.;
+     bool _useWallAvoidance = false;
+
+     //the following maps are responsible for dealloc the arrays
+     std::map<int, double*> _costFieldWithKey;
+     std::map<int, Point*> _directionFieldWithKey;
+     std::vector<int> _uids;
+     std::map<int, Line> _doors;
+
+};
+
+
+#endif //JPSCORE_UNIVFFVIAFM_H
diff --git a/routing/ff_router/ffRouter.cpp b/routing/ff_router/ffRouter.cpp
index 8b3c27138ef38fdb342d60d11e854d778b487cb0..6d6c5f3d645f70c4c04ea23cc75801e2771685bf 100644
--- a/routing/ff_router/ffRouter.cpp
+++ b/routing/ff_router/ffRouter.cpp
@@ -87,7 +87,7 @@ FFRouter::~FFRouter()
           delete _globalFF;
      }
      //delete localffs
-     std::map<int, LocalFloorfieldViaFM*>::reverse_iterator delIter;
+     std::map<int, UnivFFviaFM*>::reverse_iterator delIter;
      for (delIter = _locffviafm.rbegin();
           delIter != _locffviafm.rend();
           ++delIter) {
@@ -142,8 +142,8 @@ bool FFRouter::Init(Building* building)
                if (room1) roomAndCroTrVector.emplace_back(std::make_pair(room1->GetID(), pair.second->GetUniqueID()));
           }
      }
-     //make unique // because of the way how this vector is constructed, the entries are already unique. Besides, std::unique would need a sorted vector.
-     //_allDoorUIDs.erase( std::unique(_allDoorUIDs.begin(),_allDoorUIDs.end()), _allDoorUIDs.end());
+     //make unique
+     _allDoorUIDs.erase( std::unique(_allDoorUIDs.begin(),_allDoorUIDs.end()), _allDoorUIDs.end());
 
      //cleanse maps
      _distMatrix.clear();
@@ -179,13 +179,14 @@ bool FFRouter::Init(Building* building)
 
                auto pairRoomIt = allRooms.begin();
                std::advance(pairRoomIt, i);
-               LocalFloorfieldViaFM *locffptr = nullptr;
-               Log->Write("INFO: \tusing %s in ffRouter::Init", _useCentrePointDistance ? "CentrePointLocalFFViaFm" : "LocalFloorfieldViaFM");
-               if (_useCentrePointDistance) {
-                    locffptr = new CentrePointLocalFFViaFM(pairRoomIt->second.get(), building, 0.125, 0.125, 0.0, false);
-               } else {
-                    locffptr = new LocalFloorfieldViaFM(pairRoomIt->second.get(), building, 0.125, 0.125, 0.0, false);
-               }
+               UnivFFviaFM *locffptr = nullptr;
+               locffptr = new UnivFFviaFM(pairRoomIt->second.get(), building, 0.125, 0.125, 0.0, false);
+//               Log->Write("INFO: \tusing %s in ffRouter::Init", _useCentrePointDistance ? "CentrePointLocalFFViaFm" : "LocalFloorfieldViaFM");
+//               if (_useCentrePointDistance) {
+//                    locffptr = new CentrePointLocalFFViaFM(pairRoomIt->second.get(), building, 0.125, 0.125, 0.0, false);
+//               } else {
+//                    locffptr = new LocalFloorfieldViaFM(pairRoomIt->second.get(), building, 0.125, 0.125, 0.0, false);
+//               }
 
                Log->Write("INFO: \tAdding distances in Room %d to matrix", (*pairRoomIt).first);
 #pragma omp critical(_locffviafm)
@@ -236,7 +237,7 @@ bool FFRouter::Init(Building* building)
                     //question: if (a to c) > (a to b) + (b to c), then FloyedWarshall will favour intermediate goal b
                     //          as a precessor to c. This might be very important, if there are edges among lines, that
                     //          are not adjacent.
-                    LocalFloorfieldViaFM* locffptr = _locffviafm[rctIt->first];
+                    UnivFFviaFM* locffptr = _locffviafm[rctIt->first];
                     double tempDistance = locffptr->getCostToDestination(rctIt->second,
                                                                          _CroTrByUID.at(otherDoor.second)->GetCentre());
 
@@ -310,7 +311,6 @@ bool FFRouter::Init(Building* building)
      } // omp parallel
 
      FloydWarshall();
-     AvoidDoorHopping();
 
      //debug output in file
 //     _locffviafm[4]->writeFF("ffTreppe.vtk", _allDoorUIDs);
@@ -346,229 +346,215 @@ bool FFRouter::Init(Building* building)
 
 bool FFRouter::ReInit()
 {
-     if (_hasSpecificGoals) {
-          //get global field to manage goals (which are not in a subroom)
-          if (_globalFF) delete _globalFF;
-          _globalFF = new FloorfieldViaFM(_building, 0.25, 0.25, 0.0, false, true);
-          for (auto &itrGoal : _building->GetAllGoals()) {
-               _globalFF->createMapEntryInLineToGoalID(itrGoal.first);
-          }
-          _goalToLineUIDmap = _globalFF->getGoalToLineUIDmap(); //@todo: ar.graf: will this create mem-leak?
-          _goalToLineUIDmap2 = _globalFF->getGoalToLineUIDmap2();
-          _goalToLineUIDmap3 = _globalFF->getGoalToLineUIDmap3();
-     }
-     //get all door UIDs
-     _allDoorUIDs.clear();
-     _TransByUID.clear();
-     _ExitsByUID.clear();
-     _CroTrByUID.clear();
-     auto& allTrans = _building->GetAllTransitions();
-     auto& allCross = _building->GetAllCrossings();
-     for (auto& pair:allTrans) {
-          if (pair.second->IsOpen()) {
-               _allDoorUIDs.emplace_back(pair.second->GetUniqueID());
-               _CroTrByUID.insert(std::make_pair(pair.second->GetUniqueID(), (Crossing *) pair.second));
-               if (pair.second->IsExit()) {
-                    _ExitsByUID.insert(std::make_pair(pair.second->GetUniqueID(), pair.second));
-               }
-          }
-     }
-     for (auto& pair:allCross) {
-          if (pair.second->IsOpen()) {
-               _allDoorUIDs.emplace_back(pair.second->GetUniqueID());
-               _CroTrByUID.insert(std::make_pair(pair.second->GetUniqueID(), pair.second));
-          }
-     }
-     //make unique
-     _allDoorUIDs.erase( std::unique(_allDoorUIDs.begin(),_allDoorUIDs.end()), _allDoorUIDs.end());
-
-     std::map< std::pair<int, int> , double > tmpdistMatrix;
-     std::map< std::pair<int, int> , int >    tmppathsMatrix;
-
-     tmpdistMatrix.clear();
-     tmppathsMatrix.clear();
-     tmpdistMatrix = std::move(_distMatrix);
-     tmppathsMatrix = std::move(_pathsMatrix);
-
-     //cleanse maps
-     _distMatrix.clear();
-     _pathsMatrix.clear();
-
-     //init, yet no distances, only create map entries
-     for(auto& id1 : _allDoorUIDs) {
-          for(auto& id2 : _allDoorUIDs){
-               std::pair<int, int> key   = std::make_pair(id1, id2);
-               double              value = (id1 == id2)? 0.0 : DBL_MAX;
-               //distMatrix[i][j] = 0,   if i==j
-               //distMatrix[i][j] = max, else
-               _distMatrix.insert(std::make_pair( key , value));
-               //pathsMatrix[i][j] = i or j ? (follow wiki:path_reconstruction, it should be j)
-               _pathsMatrix.insert(std::make_pair( key , id2 ));
-          }
-     }
-
-     for (auto ptr : _locffviafm) {
-          delete ptr.second;
-     }
-     //prepare all room-floor-fields-objects (one room = one instance)
-     _locffviafm.clear();
-     //type of allRooms: const std::map<int, std::unique_ptr<Room> >&
-     const std::map<int, std::shared_ptr<Room> >& allRooms = _building->GetAllRooms();
-#pragma omp parallel for
-     //for (auto &pairRoom : allRooms) {
-     for (unsigned int i = 0; i < allRooms.size(); ++i) {
-
-#ifdef DEBUG
-          std::cerr << "Creating Floorfield for Room: " << pair.first << std::endl;
-#endif
-          auto pairRoomIt = allRooms.begin();
-          std::advance(pairRoomIt, i);
-          LocalFloorfieldViaFM* ptrToNew = nullptr;
-          double tempDistance = 0.;
-          if (_useCentrePointDistance) {
-               ptrToNew = new CentrePointLocalFFViaFM((*pairRoomIt).second.get(), _building, 0.125, 0.125, 0.0, false);
-          } else {
-               ptrToNew = new LocalFloorfieldViaFM((*pairRoomIt).second.get(), _building, 0.125, 0.125, 0.0, false);
-          }
-          //for (long int i = 0; i < ptrToNew)
-          //Log->Write("INFO: \tAdding distances in Room %d to matrix", (*pairRoomIt).first);
-#pragma omp critical(_locffviafm)
-          _locffviafm.insert(std::make_pair((*pairRoomIt).first, ptrToNew));
-
-          if (_mode == quickest) {
-               ptrToNew->setSpeedThruPeds(_building->GetAllPedestrians().data(), _building->GetAllPedestrians().size(), _mode, 0.5);
-          }
-          //SetDistances
-          vector<int> doorUIDs;
-          doorUIDs.clear();
-          for (int transI: (*pairRoomIt).second->GetAllTransitionsIDs()) {
-               if ( (_CroTrByUID.count(transI) != 0) && (_CroTrByUID[transI]->IsOpen()) ) {
-                    doorUIDs.emplace_back(transI);
-                    //Log->Write("Door UID: %d", transI);
-                    //Log->Write(_CroTrByUID[transI]->GetDescription());
-               }
-          }
-
-          for (auto &subI : (*pairRoomIt).second->GetAllSubRooms()) {
-               for (auto &crossI : subI.second->GetAllCrossings()) { //if clause checks so that only new doors get added
-                    if ((crossI->IsOpen()) &&
-                        (std::find(doorUIDs.begin(), doorUIDs.end(), crossI->GetUniqueID()) == doorUIDs.end())) {
-                         doorUIDs.emplace_back(crossI->GetUniqueID());
-                         //Log->Write("Crossing: %d", crossI->GetUniqueID());
-                         //Log->Write(crossI->GetDescription());
-                    }
-               }
-          }
-          //loop over upper triangular matrice (i,j) and write to (j,i) as well
-          std::vector<int>::const_iterator outerPtr;
-          std::vector<int>::const_iterator innerPtr;
-          //Log->Write("INFO: \tFound %d Doors (Cross + Trans) in room %d", doorUIDs.size(), (*pairRoomIt).first);
-          for (outerPtr = doorUIDs.begin(); outerPtr != doorUIDs.end(); ++outerPtr) {
-               //if the door is closed, then dont calc distances
-               if (!_CroTrByUID.at(*outerPtr)->IsOpen()) {
-                    continue;
-               }
-               // @todo: ar.graf: this following loop and the one directly wrapping this "for (outerPtr = ...)" could be
-               // moved out of the parallel for loop into a follow up part. There we could parallelize the most inner loop
-               // to achieve a better load balancing. You can have a look at DirectionStrategy.cpp at the DirectionLocalFloorfield::Init
-               // and take that scheme.
-               for (innerPtr = outerPtr; innerPtr != doorUIDs.end(); ++innerPtr) {
-                    //if outerdoor == innerdoor or the inner door is closed
-                    if ((*outerPtr == *innerPtr) || (!_CroTrByUID.at(*innerPtr)->IsOpen())) {
-                         continue;
-                    }
-
-                    //if the two doors are not within the same subroom, do not consider (ar.graf)
-                    //should fix problems of oscillation caused by doorgaps in the distancegraph
-                    int innerUID1 = (_CroTrByUID.at(*innerPtr)->GetSubRoom1()) ? _CroTrByUID.at(*innerPtr)->GetSubRoom1()->GetUID() : -1 ;
-                    int innerUID2 = (_CroTrByUID.at(*innerPtr)->GetSubRoom2()) ? _CroTrByUID.at(*innerPtr)->GetSubRoom2()->GetUID() : -2 ;
-                    int outerUID1 = (_CroTrByUID.at(*outerPtr)->GetSubRoom1()) ? _CroTrByUID.at(*outerPtr)->GetSubRoom1()->GetUID() : -3 ;
-                    int outerUID2 = (_CroTrByUID.at(*outerPtr)->GetSubRoom2()) ? _CroTrByUID.at(*outerPtr)->GetSubRoom2()->GetUID() : -4 ;
-
-                    if (
-                              (innerUID1 != outerUID1) &&
-                              (innerUID1 != outerUID2) &&
-                              (innerUID2 != outerUID1) &&
-                              (innerUID2 != outerUID2)      ) {
-                         continue;
-                    }
-
-                    //The distance is checked by reading the timecost of a wave starting at the line(!) to reach a point(!)
-                    //That will have the following implications:
-                    //distance (a to b) can be different than distance (b ta a)
-                    //     for this reason, we calc only (a to b) and set (b to a) to the same value
-                    //distance (line to center) can be larger than (line to endpoint). to get closer to the min-distance
-                    //we did take the minimum of three shots: center, and a point close to each endpoint BUT not anymore
-                    //
-                    //note: we can not assume: (a to c) = (a to b) + (b to c) for the reasons above.
-                    //question: if (a to c) > (a to b) + (b to c), then FloyedWarshall will favour intermediate goal b
-                    //          as a precessor to c. This might be very important, if there are edges among lines, that
-                    //          are not adjacent.
-                    std::pair<int, int> key_ij = std::make_pair(*outerPtr, *innerPtr);
-                    std::pair<int, int> key_ji = std::make_pair(*innerPtr, *outerPtr);
-                    if ((!(_mode == quickest)) && (tmpdistMatrix.count(key_ij) > 0)) { //only take old value if ffields do not change during sim (quickest do change)
-                         tempDistance = tmpdistMatrix.at(key_ij);
-                    } else {
-                         tempDistance = ptrToNew->getCostToDestination(*outerPtr,
-                                                                       _CroTrByUID.at(*innerPtr)->GetCentre(), _mode);
-                    }
-
-                    if (tempDistance < ptrToNew->getGrid()->Gethx()) {
-                         //Log->Write("WARNING:\tDistance of doors %d and %d is too small: %f",*outerPtr, *innerPtr, tempDistance);
-                         //Log->Write("^^^^^^^^\tIf there are scattered subrooms, which are not connected, this is ok.");
-                         continue;
-                    }
-//                    tempDistance = ptrToNew->getCostToDestination(*outerPtr, _CroTrByUID[*innerPtr]->GetCentre());
-                    _distMatrix.erase(key_ij);
-                    _distMatrix.erase(key_ji);
-                    _distMatrix.insert(std::make_pair(key_ij, tempDistance));
-                    _distMatrix.insert(std::make_pair(key_ji, tempDistance));
-               }
-          }
-     }
-     FloydWarshall();
-
-     //debug output in file
-     std::string ffname = "MasterFF" + std::to_string(++_cnt) + ".vtk";
-     //_locffviafm[0]->writeFF(ffname, _allDoorUIDs);
-
-     //int roomTest = (*(_locffviafm.begin())).first;
-     //int transTest = (building->GetRoom(roomTest)->GetAllTransitionsIDs())[0];
-//     for (unsigned int i = 0; i < _locffviafm.size(); ++i) {
-//          auto iter = _locffviafm.begin();
-//          std::advance(iter, i);
-//          int roomNr = iter->first;
-//          iter->second->writeFF("testFF" + std::to_string(roomNr) + ".vtk", _allDoorUIDs);
+//     if (_hasSpecificGoals) {
+//          //get global field to manage goals (which are not in a subroom)
+//          if (_globalFF) delete _globalFF;
+//          _globalFF = new FloorfieldViaFM(_building, 0.25, 0.25, 0.0, false, true);
+//          for (auto &itrGoal : _building->GetAllGoals()) {
+//               _globalFF->createMapEntryInLineToGoalID(itrGoal.first);
+//          }
+//          _goalToLineUIDmap = _globalFF->getGoalToLineUIDmap(); //@todo: ar.graf: will this create mem-leak?
+//          _goalToLineUIDmap2 = _globalFF->getGoalToLineUIDmap2();
+//          _goalToLineUIDmap3 = _globalFF->getGoalToLineUIDmap3();
+//     }
+//     //get all door UIDs
+//     _allDoorUIDs.clear();
+//     _TransByUID.clear();
+//     _ExitsByUID.clear();
+//     _CroTrByUID.clear();
+//     auto& allTrans = _building->GetAllTransitions();
+//     auto& allCross = _building->GetAllCrossings();
+//     for (auto& pair:allTrans) {
+//          if (pair.second->IsOpen()) {
+//               _allDoorUIDs.emplace_back(pair.second->GetUniqueID());
+//               _CroTrByUID.insert(std::make_pair(pair.second->GetUniqueID(), (Crossing *) pair.second));
+//               if (pair.second->IsExit()) {
+//                    _ExitsByUID.insert(std::make_pair(pair.second->GetUniqueID(), pair.second));
+//               }
+//          }
 //     }
+//     for (auto& pair:allCross) {
+//          if (pair.second->IsOpen()) {
+//               _allDoorUIDs.emplace_back(pair.second->GetUniqueID());
+//               _CroTrByUID.insert(std::make_pair(pair.second->GetUniqueID(), pair.second));
+//          }
+//     }
+//     //make unique
+//     _allDoorUIDs.erase( std::unique(_allDoorUIDs.begin(),_allDoorUIDs.end()), _allDoorUIDs.end());
 //
-     std::ofstream matrixfile;
-     matrixfile.open("Matrix.txt");
-
-     for (auto mapItem : _distMatrix) {
-          matrixfile << mapItem.first.first << " to " << mapItem.first.second << " : " << mapItem.second << "\t via \t" << _pathsMatrix[mapItem.first];
-          matrixfile << "\t" << _CroTrByUID.at(mapItem.first.first)->GetID() << " to " << _CroTrByUID.at(mapItem.first.second)->GetID() << "\t via \t";
-          matrixfile << _CroTrByUID.at(_pathsMatrix[mapItem.first])->GetID() << std::endl;
-     }
-     matrixfile.close();
-     Log->Write("INFO: \tFF Router Init done.");
-     return true;
+//     std::map< std::pair<int, int> , double > tmpdistMatrix;
+//     std::map< std::pair<int, int> , int >    tmppathsMatrix;
+//
+//     tmpdistMatrix.clear();
+//     tmppathsMatrix.clear();
+//     tmpdistMatrix = std::move(_distMatrix);
+//     tmppathsMatrix = std::move(_pathsMatrix);
+//
+//     //cleanse maps
+//     _distMatrix.clear();
+//     _pathsMatrix.clear();
+//
+//     //init, yet no distances, only create map entries
+//     for(auto& id1 : _allDoorUIDs) {
+//          for(auto& id2 : _allDoorUIDs){
+//               std::pair<int, int> key   = std::make_pair(id1, id2);
+//               double              value = (id1 == id2)? 0.0 : DBL_MAX;
+//               //distMatrix[i][j] = 0,   if i==j
+//               //distMatrix[i][j] = max, else
+//               _distMatrix.insert(std::make_pair( key , value));
+//               //pathsMatrix[i][j] = i or j ? (follow wiki:path_reconstruction, it should be j)
+//               _pathsMatrix.insert(std::make_pair( key , id2 ));
+//          }
+//     }
+//
+//     for (auto ptr : _locffviafm) {
+//          delete ptr.second;
+//     }
+//     //prepare all room-floor-fields-objects (one room = one instance)
+//     _locffviafm.clear();
+//     //type of allRooms: const std::map<int, std::unique_ptr<Room> >&
+//     const std::map<int, std::shared_ptr<Room> >& allRooms = _building->GetAllRooms();
+//#pragma omp parallel for
+//     //for (auto &pairRoom : allRooms) {
+//     for (unsigned int i = 0; i < allRooms.size(); ++i) {
+//
+//#ifdef DEBUG
+//          std::cerr << "Creating Floorfield for Room: " << pair.first << std::endl;
+//#endif
+//          auto pairRoomIt = allRooms.begin();
+//          std::advance(pairRoomIt, i);
+//          LocalFloorfieldViaFM* ptrToNew = nullptr;
+//          double tempDistance = 0.;
+//          if (_useCentrePointDistance) {
+//               ptrToNew = new CentrePointLocalFFViaFM((*pairRoomIt).second.get(), _building, 0.125, 0.125, 0.0, false);
+//          } else {
+//               ptrToNew = new LocalFloorfieldViaFM((*pairRoomIt).second.get(), _building, 0.125, 0.125, 0.0, false);
+//          }
+//          //for (long int i = 0; i < ptrToNew)
+//          //Log->Write("INFO: \tAdding distances in Room %d to matrix", (*pairRoomIt).first);
+//#pragma omp critical(_locffviafm)
+//          _locffviafm.insert(std::make_pair((*pairRoomIt).first, ptrToNew));
+//
+//          if (_mode == quickest) {
+//               ptrToNew->setSpeedThruPeds(_building->GetAllPedestrians().data(), _building->GetAllPedestrians().size(), _mode, 0.5);
+//          }
+//          //SetDistances
+//          vector<int> doorUIDs;
+//          doorUIDs.clear();
+//          for (int transI: (*pairRoomIt).second->GetAllTransitionsIDs()) {
+//               if ( (_CroTrByUID.count(transI) != 0) && (_CroTrByUID[transI]->IsOpen()) ) {
+//                    doorUIDs.emplace_back(transI);
+//                    //Log->Write("Door UID: %d", transI);
+//                    //Log->Write(_CroTrByUID[transI]->GetDescription());
+//               }
+//          }
+//
+//          for (auto &subI : (*pairRoomIt).second->GetAllSubRooms()) {
+//               for (auto &crossI : subI.second->GetAllCrossings()) { //if clause checks so that only new doors get added
+//                    if ((crossI->IsOpen()) &&
+//                        (std::find(doorUIDs.begin(), doorUIDs.end(), crossI->GetUniqueID()) == doorUIDs.end())) {
+//                         doorUIDs.emplace_back(crossI->GetUniqueID());
+//                         //Log->Write("Crossing: %d", crossI->GetUniqueID());
+//                         //Log->Write(crossI->GetDescription());
+//                    }
+//               }
+//          }
+//          //loop over upper triangular matrice (i,j) and write to (j,i) as well
+//          std::vector<int>::const_iterator outerPtr;
+//          std::vector<int>::const_iterator innerPtr;
+//          //Log->Write("INFO: \tFound %d Doors (Cross + Trans) in room %d", doorUIDs.size(), (*pairRoomIt).first);
+//          for (outerPtr = doorUIDs.begin(); outerPtr != doorUIDs.end(); ++outerPtr) {
+//               //if the door is closed, then dont calc distances
+//               if (!_CroTrByUID.at(*outerPtr)->IsOpen()) {
+//                    continue;
+//               }
+//               // @todo: ar.graf: this following loop and the one directly wrapping this "for (outerPtr = ...)" could be
+//               // moved out of the parallel for loop into a follow up part. There we could parallelize the most inner loop
+//               // to achieve a better load balancing. You can have a look at DirectionStrategy.cpp at the DirectionLocalFloorfield::Init
+//               // and take that scheme.
+//               for (innerPtr = outerPtr; innerPtr != doorUIDs.end(); ++innerPtr) {
+//                    //if outerdoor == innerdoor or the inner door is closed
+//                    if ((*outerPtr == *innerPtr) || (!_CroTrByUID.at(*innerPtr)->IsOpen())) {
+//                         continue;
+//                    }
+//
+//                    //if the two doors are not within the same subroom, do not consider (ar.graf)
+//                    //should fix problems of oscillation caused by doorgaps in the distancegraph
+//                    int innerUID1 = (_CroTrByUID.at(*innerPtr)->GetSubRoom1()) ? _CroTrByUID.at(*innerPtr)->GetSubRoom1()->GetUID() : -1 ;
+//                    int innerUID2 = (_CroTrByUID.at(*innerPtr)->GetSubRoom2()) ? _CroTrByUID.at(*innerPtr)->GetSubRoom2()->GetUID() : -2 ;
+//                    int outerUID1 = (_CroTrByUID.at(*outerPtr)->GetSubRoom1()) ? _CroTrByUID.at(*outerPtr)->GetSubRoom1()->GetUID() : -3 ;
+//                    int outerUID2 = (_CroTrByUID.at(*outerPtr)->GetSubRoom2()) ? _CroTrByUID.at(*outerPtr)->GetSubRoom2()->GetUID() : -4 ;
+//
+//                    if (
+//                              (innerUID1 != outerUID1) &&
+//                              (innerUID1 != outerUID2) &&
+//                              (innerUID2 != outerUID1) &&
+//                              (innerUID2 != outerUID2)      ) {
+//                         continue;
+//                    }
+//
+//                    //The distance is checked by reading the timecost of a wave starting at the line(!) to reach a point(!)
+//                    //That will have the following implications:
+//                    //distance (a to b) can be different than distance (b ta a)
+//                    //     for this reason, we calc only (a to b) and set (b to a) to the same value
+//                    //distance (line to center) can be larger than (line to endpoint). to get closer to the min-distance
+//                    //we did take the minimum of three shots: center, and a point close to each endpoint BUT not anymore
+//                    //
+//                    //note: we can not assume: (a to c) = (a to b) + (b to c) for the reasons above.
+//                    //question: if (a to c) > (a to b) + (b to c), then FloyedWarshall will favour intermediate goal b
+//                    //          as a precessor to c. This might be very important, if there are edges among lines, that
+//                    //          are not adjacent.
+//                    std::pair<int, int> key_ij = std::make_pair(*outerPtr, *innerPtr);
+//                    std::pair<int, int> key_ji = std::make_pair(*innerPtr, *outerPtr);
+//                    if ((!(_mode == quickest)) && (tmpdistMatrix.count(key_ij) > 0)) { //only take old value if ffields do not change during sim (quickest do change)
+//                         tempDistance = tmpdistMatrix.at(key_ij);
+//                    } else {
+//                         tempDistance = ptrToNew->getCostToDestination(*outerPtr,
+//                                                                       _CroTrByUID.at(*innerPtr)->GetCentre(), _mode);
+//                    }
+//
+//                    if (tempDistance < ptrToNew->getGrid()->Gethx()) {
+//                         //Log->Write("WARNING:\tDistance of doors %d and %d is too small: %f",*outerPtr, *innerPtr, tempDistance);
+//                         //Log->Write("^^^^^^^^\tIf there are scattered subrooms, which are not connected, this is ok.");
+//                         continue;
+//                    }
+////                    tempDistance = ptrToNew->getCostToDestination(*outerPtr, _CroTrByUID[*innerPtr]->GetCentre());
+//                    _distMatrix.erase(key_ij);
+//                    _distMatrix.erase(key_ji);
+//                    _distMatrix.insert(std::make_pair(key_ij, tempDistance));
+//                    _distMatrix.insert(std::make_pair(key_ji, tempDistance));
+//               }
+//          }
+//     }
+//     FloydWarshall();
+//
+//     //debug output in file
+//     std::string ffname = "MasterFF" + std::to_string(++_cnt) + ".vtk";
+//     //_locffviafm[0]->writeFF(ffname, _allDoorUIDs);
+//
+//     //int roomTest = (*(_locffviafm.begin())).first;
+//     //int transTest = (building->GetRoom(roomTest)->GetAllTransitionsIDs())[0];
+////     for (unsigned int i = 0; i < _locffviafm.size(); ++i) {
+////          auto iter = _locffviafm.begin();
+////          std::advance(iter, i);
+////          int roomNr = iter->first;
+////          iter->second->writeFF("testFF" + std::to_string(roomNr) + ".vtk", _allDoorUIDs);
+////     }
+////
+//     std::ofstream matrixfile;
+//     matrixfile.open("Matrix.txt");
+//
+//     for (auto mapItem : _distMatrix) {
+//          matrixfile << mapItem.first.first << " to " << mapItem.first.second << " : " << mapItem.second << "\t via \t" << _pathsMatrix[mapItem.first];
+//          matrixfile << "\t" << _CroTrByUID.at(mapItem.first.first)->GetID() << " to " << _CroTrByUID.at(mapItem.first.second)->GetID() << "\t via \t";
+//          matrixfile << _CroTrByUID.at(_pathsMatrix[mapItem.first])->GetID() << std::endl;
+//     }
+//     matrixfile.close();
+//     Log->Write("INFO: \tFF Router Init done.");
+//     return true;
 }
 
-std::set<std::pair<SubRoom*, int>> FFRouter::GetPresumableExitRoute(Pedestrian* p) {
-    std::set<std::pair<SubRoom*, int>> subroomsDoorsSet;
-    subroomsDoorsSet.clear();
-    int finalDoor = _finalDoors.at(p->GetID());
-    SubRoom* subroom = _building->GetRoom(p->GetRoomID())->GetSubRoom(p->GetSubRoomID());
-    int doorUID = p->GetNextDestination();
-
-    while (doorUID != finalDoor) {
-        subroomsDoorsSet.insert(std::make_pair(subroom, doorUID));
-        subroom = _CroTrByUID[doorUID]->GetOtherSubRoom(subroom->GetRoomID(), subroom->GetSubRoomID());
-        doorUID = _pathsMatrix.at(std::make_pair(doorUID, finalDoor));
-    }
-    subroomsDoorsSet.insert(std::make_pair(subroom, doorUID));
-    return subroomsDoorsSet;
-}
+
 
 int FFRouter::FindExit(Pedestrian* p)
 {
@@ -782,19 +768,6 @@ int FFRouter::FindExit(Pedestrian* p)
      return bestDoor; //-1 if no way was found, doorUID of best, if path found
 }
 
-void FFRouter::Reset()
-{
-     for(auto& pair : _distMatrix) {
-          //distMatrix[i][j] = 0,   if i==j
-          //distMatrix[i][j] = max, else
-          pair.second = (pair.second == 0.0) ? 0.0 : DBL_MAX;
-     }
-     for(auto& pair : _pathsMatrix) {
-          //pathsMatrix[i][j] = i
-          pair.second = pair.first.first;
-     }
-}
-
 void FFRouter::FloydWarshall()
 {
      int totalnum = _allDoorUIDs.size();
diff --git a/routing/ff_router/ffRouter.h b/routing/ff_router/ffRouter.h
index c7878eb4c9b3b09ff4d859a4b77ee10bbf1f40bc..b0b866460286e89819ada94c38aa2f168dba07dc 100644
--- a/routing/ff_router/ffRouter.h
+++ b/routing/ff_router/ffRouter.h
@@ -64,6 +64,7 @@
 #include "../../general/Macros.h"
 #include "../../geometry/Building.h"
 #include "LocalFloorfieldViaFM.h"
+#include "UnivFFviaFM.h"
 
 class Building;
 class Pedestrian;
@@ -181,13 +182,6 @@ public:
       */
       void SetMode(std::string s);
 
-     /*!
-      * \brief Get the route the pedestrian p wants to take (according to _pathsMatrix)
-      * @param p The pedestrian in question
-      * @return A set containing (subroom*, doorUID) pairs. The floorfields needed are inside the subroom, originating from the door.
-      */
-     std::set<std::pair<SubRoom*, int>> GetPresumableExitRoute(Pedestrian* p);
-
 private:
 
 protected:
@@ -198,7 +192,7 @@ protected:
      std::vector<int>                         _allDoorUIDs;
      std::vector<int>                         _localShortestSafedPeds;
      const Building*                          _building;
-     std::map<int, LocalFloorfieldViaFM*>     _locffviafm; // the actual type might be CentrePointLocalFFViaFM
+     std::map<int, UnivFFviaFM*>     _locffviafm; // the actual type might be CentrePointLocalFFViaFM
      FloorfieldViaFM*                         _globalFF;
      std::map<int, Transition*>               _TransByUID;
      std::map<int, Transition*>               _ExitsByUID;