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