From bfd79571c5a9ed43cab6c38c7968ac7fe23e7a2b Mon Sep 17 00:00:00 2001
From: Ulrich Kemloh <kemlohulrich@gmail.com>
Date: Fri, 9 Jan 2015 16:34:12 +0100
Subject: [PATCH] massive  performance improvement for the distributor.

---
 IO/TraVisToClient.h           |  24 ++---
 geometry/Building.cpp         |   6 +-
 math/GompertzModel.cpp        |   2 +-
 mpi/LCGrid.cpp                |   2 +-
 pedestrian/PedDistributor.cpp | 183 +++++++++++++++++++---------------
 pedestrian/PedDistributor.h   |   5 +-
 routing/GlobalRouter.cpp      |   3 +
 routing/NavMesh.cpp           |  20 ++--
 routing/RoutingEngine.cpp     |   1 -
 9 files changed, 137 insertions(+), 109 deletions(-)

diff --git a/IO/TraVisToClient.h b/IO/TraVisToClient.h
index 1ad6279e..cf93ad0f 100644
--- a/IO/TraVisToClient.h
+++ b/IO/TraVisToClient.h
@@ -51,18 +51,18 @@
 
 // #ifdef TRACE_LOGGING
 
-// /******** macro definitions ******************************************/
-// #define dtrace(...)                         \
-//     (_printDebugLine(__FILE__, __LINE__),   \
-//     fprintf(stderr, __VA_ARGS__),           \
-//     (void) fprintf(stderr, "\n"))
-
-// #define derror(...)                         \
-//     (_printDebugLine(__FILE__, __LINE__),   \
-//     fprintf(stderr, "ERROR: "),             \
-//     fprintf(stderr, __VA_ARGS__),           \
-//     _printErrorMessage())
-
+/*
+ #define dtrace(...)                         \
+     (_printDebugLine(__FILE__, __LINE__),   \
+     fprintf(stderr, __VA_ARGS__),           \
+     (void) fprintf(stderr, "\n"))
+
+ #define derror(...)                         \
+     (_printDebugLine(__FILE__, __LINE__),   \
+     fprintf(stderr, "ERROR: "),             \
+     fprintf(stderr, __VA_ARGS__),           \
+     _printErrorMessage())
+*/
 
 
 // // #define dtrace(...)   _printDebugLine(__FILE__, __LINE__, false, __VA_ARGS__)
diff --git a/geometry/Building.cpp b/geometry/Building.cpp
index e66c581f..b3eae583 100644
--- a/geometry/Building.cpp
+++ b/geometry/Building.cpp
@@ -71,6 +71,8 @@ Building::Building(const std::string& filename, const std::string& rootDir, Rout
      _caption = "no_caption";
      _rooms = vector<Room*>();
      _savePathway = false;
+
+     //todo: what happens if any of these  methods failed (return false)? throw exception ?
      this->LoadGeometry();
      this->LoadRoutingInfo(filename);
      this->AddSurroundingRoom();
@@ -178,12 +180,12 @@ Room* Building::GetRoom(int index) const
      } else {
           Log->Write("ERROR: Wrong 'index' in CBuiling::GetRoom() Room ID: %d size: %d",index, _rooms.size());
           Log->Write("\tControl your rooms ID and make sure they are in the order 0, 1, 2,.. ");
-          exit(EXIT_FAILURE);
+          //exit(EXIT_FAILURE);
+          return NULL;
      }
 }
 
 
-
 LCGrid* Building::GetGrid() const
 {
      return _linkedCellGrid;
diff --git a/math/GompertzModel.cpp b/math/GompertzModel.cpp
index 73c7064a..fed816a1 100644
--- a/math/GompertzModel.cpp
+++ b/math/GompertzModel.cpp
@@ -129,7 +129,7 @@ void GompertzModel::ComputeNextTimeStep(double current, double deltaT, Building*
      partSize = (int) (nSize / nThreads);
 
       //int debugPed = -69;//10;
-      //building->GetGrid()->HighlightNeighborhood(debugPed, building);
+      //building->GetGrid()->HighlightNeighborhood(-9, building);
 
 
       #pragma omp parallel  default(shared) num_threads(nThreads)
diff --git a/mpi/LCGrid.cpp b/mpi/LCGrid.cpp
index 82341e70..b41cafa6 100644
--- a/mpi/LCGrid.cpp
+++ b/mpi/LCGrid.cpp
@@ -50,7 +50,7 @@ LCGrid::LCGrid(double boundaries[4], double cellsize, int nPeds)
      pCellSize=cellsize;
      pNpeds=nPeds;
 
-     // add 1 to ensure that the whole area is covered by cells if not divisable without remainder
+     // add 1 to ensure that the whole area is covered by cells if not divisible without remainder
      pGridSizeX = (int) ((pGrid_xmax - pGrid_xmin) / pCellSize) + 1 + 2; // 1 dummy cell on each side
      pGridSizeY = (int) ((pGrid_ymax - pGrid_ymin) / pCellSize) + 1 + 2; // 1 dummy cell on each side
 
diff --git a/pedestrian/PedDistributor.cpp b/pedestrian/PedDistributor.cpp
index 52c2d5f0..60bdf3c5 100644
--- a/pedestrian/PedDistributor.cpp
+++ b/pedestrian/PedDistributor.cpp
@@ -322,75 +322,97 @@ bool PedDistributor::InitDistributor(const string& fileName, const std::map<int,
      return true;
 }
 
-int PedDistributor::Distribute(Building* building) const
+bool PedDistributor::Distribute(Building* building) const
 {
-
      Log->Write("INFO: \tInit Distribute");
-
      int nPeds = 0;
 
-     //first compute all possible positions in the geometry
-     // @todo that is not necessary, especially when N is small. It is then not worth the work
-     vector< GridPoints > allFreePos = vector< GridPoints >();
-     for (int r = 0; r < building->GetNumberOfRooms(); r++) {
-          // vector< vector<Point > >  allFreePosRoom = vector< vector<Point > > ();
-          GridPoints  allFreePosRoom = GridPoints ();
-          Room* room = building->GetRoom(r);
-          if(room->GetCaption()=="outside") continue;
-          for (int s = 0; s < room->GetNumberOfSubRooms(); s++) {
-               SubRoom* subr = room->GetSubRoom(s);
-               allFreePosRoom.push_back(PedDistributor::PossiblePositions(*subr));
+     // store the position in a map since we are not computing for all rooms/subrooms.
+     std::map <int, std::map <int, vector <Point>>> allFreePos;
+
+     //collect the available positions for that subroom
+     for(const auto& dist: _start_dis_sub)
+     {
+          int roomID = dist->GetRoomId();
+          Room* r = building->GetRoom(roomID);
+          if(!r) return false;
+
+          int subroomID = dist->GetSubroomID();
+          SubRoom* sr = r->GetSubRoom(subroomID);
+          if(!sr) return false;
+
+          auto&  allFreePosRoom=allFreePos[roomID];
+          // the positions were already computed
+          if(allFreePosRoom.count(subroomID)>0)
+               continue;
+
+          allFreePosRoom[subroomID]=PedDistributor::PossiblePositions(*sr);
+     }
+
+     //collect the available positions for that room
+     for(const auto& dist: _start_dis)
+     {
+          int roomID = dist->GetRoomId();
+          Room* r = building->GetRoom(roomID);
+          if(!r) return false;
+
+          //compute all subrooms since no specific one is given
+          for (const auto& sr: r->GetAllSubRooms())
+          {
+               int subroomID=sr->GetSubRoomID();
+               auto&  allFreePosRoom=allFreePos[roomID];
+               // the positions were already computed
+               if(allFreePosRoom.count(subroomID)>0)
+                    continue;
+
+               allFreePosRoom[subroomID]=PedDistributor::PossiblePositions(*sr);
           }
-          allFreePos.push_back(allFreePosRoom);
      }
-  
-     // first perform the distribution according to the  subrooms (if any)
 
-     int  max_rooms_id = allFreePos.size();
-     int  max_subrooms_id;
-     if(max_rooms_id>0)
-          max_subrooms_id = allFreePos[0].size();
+
+     // now proceed to the distribution
      int pid = 1; // the pedID is being increased throughout...
-     for (int i = 0; i < (int) _start_dis_sub.size(); i++) {
 
-          int room_id = _start_dis_sub[i]->GetRoomId();
+     for(const auto& dist: _start_dis_sub)
+     {
+          int room_id = dist->GetRoomId();
           Room* r = building->GetRoom(room_id);
           if(!r) continue;
           int roomID = r->GetID();
-          int subroomID = _start_dis_sub[i]->GetSubroomID();
-          int N = _start_dis_sub[i]->GetAgentsNumber();
+          int subroomID = dist->GetSubroomID();
+          int N = dist->GetAgentsNumber();
+          SubRoom* sr = r->GetSubRoom(subroomID);
+          if(!sr) continue;
 
           if (N < 0) {
                Log->Write("ERROR: \t negative  number of pedestrians!");
-               exit(EXIT_FAILURE);
-          }
-          if(roomID>=max_rooms_id || subroomID>=max_subrooms_id){
-               Log->Write("ERROR: \t max_room_id = %d, Got roomID = %d | max_subroom_id = %d, Got subroomID = %d",max_rooms_id, roomID, max_subrooms_id, subroomID);
-               exit(EXIT_FAILURE);
+               return false;
           }
-          tPoints &allpos = allFreePos[roomID][subroomID];
+
+          auto& allpos = allFreePos[roomID][subroomID];
+
           int max_pos = allpos.size();
-          if (max_pos < N) {
+          if (max_pos < N)
+          {
                Log->Write("ERROR: \tCannot distribute %d agents in Room %d . Maximum allowed: %d\n",
                           N, roomID, allpos.size());
-               exit(EXIT_FAILURE);
+              return false;
           }
 
           // Distributing
           Log->Write("INFO: \tDistributing %d Agents in Room/Subrom [%d/%d]! Maximum allowed: %d", N, roomID, subroomID, max_pos);
-          SubRoom* sr = building->GetRoom(roomID)->GetSubRoom(subroomID);
-          DistributeInSubRoom(sr, N, allpos, &pid,_start_dis_sub[i],building);
+          DistributeInSubRoom(sr, N, allpos, &pid,dist,building);
           Log->Write("\t...Done");
-
           nPeds += N;
      }
 
      // then continue the distribution according to the rooms
-     for (int i = 0; i < (int) _start_dis.size(); i++) {
-          int room_id = _start_dis[i]->GetRoomId();
+     for(const auto& dist: _start_dis)
+     {
+          int room_id = dist->GetRoomId();
           Room* r = building->GetRoom(room_id);
           if(!r) continue;
-          int N = _start_dis[i]->GetAgentsNumber();
+          int N = dist->GetAgentsNumber();
           if (N < 0) {
                Log->Write("ERROR: \t negative or null number of pedestrians! Ignoring");
                continue;
@@ -403,7 +425,7 @@ int PedDistributor::Distribute(Building* building) const
           vector<int> max_anz = vector<int>();
           vector<int> akt_anz = vector<int>();
 
-          GridPoints&  allFreePosInRoom=allFreePos[room_id];
+          auto&  allFreePosInRoom=allFreePos[room_id];
           for (int is = 0; is < r->GetNumberOfSubRooms(); is++) {
                SubRoom* sr = r->GetSubRoom(is);
                double area = sr->GetArea();
@@ -414,8 +436,8 @@ int PedDistributor::Distribute(Building* building) const
           }
           if (max_pos < N) {
                Log->Write("ERROR: \t Distribution of %d pedestrians in Room %d not possible! Maximum allowed: %d\n",
-                          N, r->GetID(), max_pos);
-               exit(EXIT_FAILURE);
+                         N, r->GetID(), max_pos);
+               return false;
           }
           ppm = N / sum_area;
           // Anzahl der Personen pro SubRoom bestimmen
@@ -449,7 +471,7 @@ int PedDistributor::Distribute(Building* building) const
           for (unsigned int is = 0; is < akt_anz.size(); is++) {
                SubRoom* sr = r->GetSubRoom(is);
                if (akt_anz[is] > 0)
-                    DistributeInSubRoom(sr, akt_anz[is], allFreePosInRoom[is], &pid, (StartDistributionSubroom*)_start_dis[i],building);
+                    DistributeInSubRoom(sr, akt_anz[is], allFreePosInRoom[is], &pid, (StartDistributionSubroom*)dist,building);
           }
           nPeds += N;
      }
@@ -485,7 +507,6 @@ vector<Point> PedDistributor::PositionsOnFixX(double min_x, double max_x, double
                     }
                }
 
-
                for(unsigned int c=0; c<r.GetAllCrossings().size(); c++) {
                     if(r.GetCrossing(c)->DistTo(pos)<J_EPS_GOAL) {
                          //too close
@@ -542,7 +563,7 @@ vector<Point>PedDistributor::PositionsOnFixY(double min_x, double max_x, double
      return positions;
 }
 
-vector<Point> PedDistributor::PossiblePositions(const SubRoom& r)
+vector<Point >  PedDistributor::PossiblePositions(const SubRoom& r)
 {
      double uni = 0.7; // wenn ein Raum in x oder y -Richtung schmaler ist als 0.7 wird in der Mitte verteilt
      double bufx = 0.12;
@@ -551,16 +572,14 @@ vector<Point> PedDistributor::PossiblePositions(const SubRoom& r)
      double amin=0.18; // = GetAmin()->GetMean();
      double bmax=0.25; // = GetBmax()->GetMean();
 
-     //TODO:
-     //double dx = GetAmin()->GetMean() + bufx;
-     //double dy = GetBmax()->GetMean() + bufy;
-
      double dx = amin + bufx;
      double dy = bmax + bufy;
 
+     double max_buf=max(bufx, bufy);
+
      vector<double>::iterator min_x, max_x, min_y, max_y;
-     vector<Point> poly = r.GetPolygon();
-     vector<Point> positions;
+     const vector<Point>& poly = r.GetPolygon();
+     vector<Point > all_positions;
      vector<double> xs;
      vector<double> ys;
 
@@ -575,57 +594,63 @@ vector<Point> PedDistributor::PossiblePositions(const SubRoom& r)
      max_y = max_element(ys.begin(), ys.end());
 
      if (*max_y - *min_y < uni) {
-          positions = PositionsOnFixY(*min_x, *max_x, *min_y, *max_y, r, bufx, bufy, dx);
+          all_positions = PositionsOnFixY(*min_x, *max_x, *min_y, *max_y, r, bufx, bufy, dx);
      } else if (*max_x - *min_x < uni) {
-          positions = PositionsOnFixX(*min_x, *max_x, *min_y, *max_y, r, bufx, bufy, dy);
+          all_positions = PositionsOnFixX(*min_x, *max_x, *min_y, *max_y, r, bufx, bufy, dy);
      } else {
           // create the grid
           double x = (*min_x);
-          while (x < *max_x) {
+          while (x < *max_x)
+          {
                double y = (*min_y);
-               while (y < *max_y) {
+               while (y < *max_y)
+               {
                     y += dy;
                     Point pos = Point(x, y);
                     bool tooNear=false;
 
-                    // check the distance to all Wall
-                    for (int k = 0; k < r.GetNumberOfWalls(); k++) {
-                         const Wall& w = r.GetWall(k);
-                         if (w.DistTo(pos) < max(bufx, bufy) || !r.IsInSubRoom(pos)) {
+                    //skip if the position is not in the polygon
+                    if(!r.IsInSubRoom(pos)) continue;
+
+                    // check the distance to all Walls
+                    for (const auto & w : r.GetAllWalls())
+                    {
+                         if (w.DistTo(pos) < max_buf) {
                               tooNear=true;
                               break; // too close
                          }
                     }
 
-                    //check all transitions
+                    //check the distance to all transitions
                     if(tooNear==true) continue;
-                    for(unsigned int t=0; t<r.GetAllTransitions().size(); t++) {
-                         if(r.GetTransition(t)->DistTo(pos)<max(bufx, bufy)) {
+                    for (const auto & t : r.GetAllTransitions())
+                    {
+                         if(t->DistTo(pos)<max_buf) {
                               //too close
                               tooNear=true;
                               break;
                          }
                     }
 
-                    //  and check all crossings
+                    //  and check the distance to all crossings
                     if(tooNear==true) continue;
-                    for(unsigned int c=0; c<r.GetAllCrossings().size(); c++) {
-                         if(r.GetCrossing(c)->DistTo(pos)<max(bufx, bufy)) {
+                    for (const auto & c : r.GetAllCrossings())
+                    {
+                         if(c->DistTo(pos)<max_buf) {
                               //too close
                               tooNear=true;
                               break;
                          }
                     }
 
-                    // and finally all opened obstacles
+                    // and finally the distance to all opened obstacles
                     if(tooNear==true) continue;
 
-                    const vector<Obstacle*>& obstacles = r.GetAllObstacles();
-                    for (unsigned int obs = 0; obs < obstacles.size(); ++obs) {
-                         Obstacle *obst =obstacles[obs];
-                         const vector<Wall>& walls = obst->GetAllWalls();
-                         for (unsigned int i = 0; i < walls.size(); i++) {
-                              if (walls[i].DistTo(pos) < max(bufx, bufy) || !r.IsInSubRoom(pos)) {
+                    for (const auto & obst : r.GetAllObstacles())
+                    {
+                         for (const auto & wall : obst->GetAllWalls())
+                         {
+                              if (wall.DistTo(pos) < max_buf) {
                                    tooNear=true;
                                    break; // too close
                               }
@@ -634,23 +659,21 @@ vector<Point> PedDistributor::PossiblePositions(const SubRoom& r)
                          //only continue if...
                          if(tooNear==true) continue;
 
-                         if((obst->GetClosed()==1) && (obst->Contains(pos)==true)) {
+                         if((obst->GetClosed()==1) && (obst->Contains(pos)==true))
+                         {
                               tooNear=true;
                               break; // too close
                          }
                     }
 
-                    if(tooNear==false) positions.push_back(pos);
+                    if(tooNear==false) all_positions.push_back(pos);
                }
                x += dx;
           }
      }
-     // for (auto i:positions)
-     //      std::cout << "x="<< i.GetX()<<"  y="<< i.GetY() << std::endl
-               ;
-     //shuffle the array
-     std::random_shuffle(positions.begin(), positions.end());
-     return positions;
+
+     std::random_shuffle(all_positions.begin(), all_positions.end());
+     return all_positions;
 }
 /* Verteilt N Fußgänger in SubRoom r
  * Algorithms:
diff --git a/pedestrian/PedDistributor.h b/pedestrian/PedDistributor.h
index 06157907..0eedbc1f 100644
--- a/pedestrian/PedDistributor.h
+++ b/pedestrian/PedDistributor.h
@@ -154,12 +154,11 @@ public:
      virtual ~PedDistributor();
 
      // sonstige Funktionen
-
-     static std::vector<Point> PossiblePositions(const SubRoom& r);
+     static vector<Point >  PossiblePositions(const SubRoom& r);
      void DistributeInSubRoom(SubRoom* r, int N, std::vector<Point>& positions, int* pid, StartDistributionSubroom* parameters,Building* building) const;
 
 
-     int Distribute(Building* building) const;
+     bool Distribute(Building* building) const;
 };
 
 #endif  /* _PEDDISTRIBUTOR_H */
diff --git a/routing/GlobalRouter.cpp b/routing/GlobalRouter.cpp
index aa5d0e93..a830645d 100644
--- a/routing/GlobalRouter.cpp
+++ b/routing/GlobalRouter.cpp
@@ -1317,6 +1317,9 @@ bool GlobalRouter::GenerateNavigationMesh()
      //Navigation mesh implementation
      NavMesh* nv= new NavMesh(_building);
      nv->BuildNavMesh();
+     _building->SaveGeometry("test_geometry.xml");
+     exit(0);
+     //nv->WriteToFileTraVisTo()
 
      const std::vector<NavMesh::JEdge*>& edges = nv->GetEdges();
 
diff --git a/routing/NavMesh.cpp b/routing/NavMesh.cpp
index 20841f77..598808bd 100644
--- a/routing/NavMesh.cpp
+++ b/routing/NavMesh.cpp
@@ -281,6 +281,7 @@ void NavMesh::BuildNavMesh()
      //DumpNode(2341);
      //DumpEdge(9);
      UpdateNodes();
+     return;
      Test();
 
      std::sort(_nodes.begin(), _nodes.end(),JNode());
@@ -666,9 +667,9 @@ void NavMesh::WriteToString(std::string& output)
           JNode* node=_nodes[n];
 
           int node_id=node->id; //cout<<"node id: "<<node_id<<endl;
-          if(nodes_to_plot.size()!=0)
-               if (IsElementInVector(nodes_to_plot, node_id) == false)
-                    continue;
+          //if(nodes_to_plot.size()!=0)
+          //     if (IsElementInVector(nodes_to_plot, node_id) == false)
+          //          continue;
           //              if(problem_nodes.size()!=0)
           //                      if (IsElementInVector(problem_nodes, node_id) == false)
           //                              continue;
@@ -678,7 +679,7 @@ void NavMesh::WriteToString(std::string& output)
           //if(node->IsConvex()==true) continue;
           //if(node->IsClockwise()==true) continue;
 
-          file<<"\t\t<label centerX=\""<<node->pCentroid.GetX()*factor -centre.GetX()<<"\" centerY=\""<<node->pCentroid.GetY()*factor-centre.GetY()<<"\" centerZ=\"0\" text=\""<<node->id <<"\" color=\"100\" />"<<endl;
+          //file<<"\t\t<label centerX=\""<<node->pCentroid.GetX()*factor -centre.GetX()<<"\" centerY=\""<<node->pCentroid.GetY()*factor-centre.GetY()<<"\" centerZ=\"0\" text=\""<<node->id <<"\" color=\"100\" />"<<endl;
           //              cout<<"size: "<< node->pHull.size()<<endl;
           //              std::sort(node->pHull.begin(), node->pHull.end());
           //              node->pHull.erase(std::unique(node->pHull.begin(), node->pHull.end()), node->pHull.end());
@@ -736,7 +737,7 @@ void NavMesh::WriteToString(std::string& output)
                     double x2=edge->pEnd.pPos.GetX()*factor-centre._x;
                     double y2=edge->pEnd.pPos.GetY()*factor-centre._y;
 
-                    file<<"\t\t<label centerX=\""<<0.5*(x1+x2)<<"\" centerY=\""<<0.5*(y1+y2)<<"\" centerZ=\"0\" text=\""<<edge->id<<"\" color=\"20\" />"<<endl;
+                    //file<<"\t\t<label centerX=\""<<0.5*(x1+x2)<<"\" centerY=\""<<0.5*(y1+y2)<<"\" centerZ=\"0\" text=\""<<edge->id<<"\" color=\"20\" />"<<endl;
                     file<<"\t\t<door id = \""<<i<<"\">"<<endl;
                     file<<"\t\t\t<point xPos=\""<<x1<<"\" yPos=\""<<y1<<"\"/>"<<endl;
                     file<<"\t\t\t<point xPos=\""<<x2<<"\" yPos=\""<<y2<<"\"/>"<<endl;
@@ -772,8 +773,8 @@ void NavMesh::WriteToFileTraVisTo(std::string fileName)
 
      //writing the header
      file<<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl
-         <<"<trajectoriesDataset>"<<endl
-         <<"\t<header formatVersion = \"1.0\">"<<endl
+         <<"<trajectories>"<<endl
+         <<"\t<header version = \"0.5\">"<<endl
          <<"\t\t<agents>3</agents>"<<endl
          <<"\t\t<seed>0</seed>"<<endl
          <<"\t\t<frameRate>10</frameRate>"<<endl
@@ -2179,8 +2180,9 @@ void NavMesh::WriteStartPositions()
           if(room->GetCaption()=="outside") continue;
           for (int s = 0; s < room->GetNumberOfSubRooms(); s++) {
                SubRoom* subr = room->GetSubRoom(s);
-               vector<Point > pos = PedDistributor::PossiblePositions(*subr);
-               freePosRoom.insert(freePosRoom.end(),pos.begin(),pos.end());
+               // TODO
+               //vector<Point > pos = PedDistributor::PossiblePositions(*subr);
+               //freePosRoom.insert(freePosRoom.end(),pos.begin(),pos.end());
           }
           availablePos.push_back(freePosRoom);
      }
diff --git a/routing/RoutingEngine.cpp b/routing/RoutingEngine.cpp
index 6885b6ec..c0688cd5 100644
--- a/routing/RoutingEngine.cpp
+++ b/routing/RoutingEngine.cpp
@@ -114,6 +114,5 @@ bool RoutingEngine::Init(Building* building)
           if(_routersCollection[r]->Init(building)==false)
                status=false;
      }
-     Log->Write("bad status" + status);
      return status;
 }
-- 
GitLab