diff --git a/geometry/Building.cpp b/geometry/Building.cpp index 9c778d81de6587ba9211f1c5e66da03692728dea..25e7449986ffd3afccbd0766e104588d010f2df4 100644 --- a/geometry/Building.cpp +++ b/geometry/Building.cpp @@ -379,7 +379,7 @@ bool Building::InitInsideGoals() SubRoom* subRoom = subRoomItr.second.get(); if (subRoom->IsInSubRoom(goal->GetCentroid())){ std::cout << "Goal " << goal->GetId() << " is in subroom " << subRoom->GetUID() << std::endl; - Crossing* crossing = &(goal->GetCentreCrossing()); + Crossing* crossing = goal->GetCentreCrossing(); subRoom->AddCrossing(crossing); crossing->SetRoom1(room); crossing->SetSubRoom1(subRoom); diff --git a/geometry/Goal.cpp b/geometry/Goal.cpp index 8d31a9e532b4563a1994a1e6663ddf31f9382220..0b7530e3a34ed6f45cb990074edf42b2baf60cd8 100644 --- a/geometry/Goal.cpp +++ b/geometry/Goal.cpp @@ -41,7 +41,7 @@ Goal::Goal() _isFinalGoal=0; _walls = vector<Wall > (); _poly = vector<Point > (); -// _crossing = Crossing(); + _crossing = new Crossing(); } Goal::~Goal() @@ -72,7 +72,7 @@ int Goal::GetId() const void Goal::SetId(int id) { _id = id; - _crossing.SetID(id); + _crossing->SetID(id); } const vector<Point>& Goal::GetPolygon() const @@ -236,16 +236,16 @@ bool Goal::ConvertLineToPoly() point1 = tmp + diff * 0.95; point2 = tmp + diff * 0.05; - _crossing.SetPoint1(point1); - _crossing.SetPoint2(point2); + _crossing->SetPoint1(point1); + _crossing->SetPoint2(point2); }else{ - _crossing.SetPoint1(_poly[0]); + _crossing->SetPoint1(_poly[0]); Line line(_poly[_poly.size()/2], _poly[(_poly.size()/2)+1], 0); - _crossing.SetPoint2(line.GetCentre()); + _crossing->SetPoint2(line.GetCentre()); } - std::cout << "Crossing goal: " << _crossing.GetUniqueID() << _crossing.toString() << std::endl; + std::cout << "Crossing goal: " << _crossing->GetUniqueID() << _crossing->toString() << std::endl; return true; } @@ -296,7 +296,7 @@ void Goal::ComputeCentroid() _centroid._y=py; } -Crossing& Goal::GetCentreCrossing() +Crossing* Goal::GetCentreCrossing() { return _crossing; } diff --git a/geometry/Goal.h b/geometry/Goal.h index 4ee4f78551525eac6a4f9dde9b585f7fd4af879b..586cf7264452891e347a8efaaf82f84281969e37 100644 --- a/geometry/Goal.h +++ b/geometry/Goal.h @@ -54,7 +54,7 @@ protected: std::string _caption; std::vector<Wall> _walls; std::vector<Point> _poly; - Crossing _crossing; + Crossing* _crossing; polygon_type _boostPoly; bool _inside; @@ -135,7 +135,7 @@ public: */ std::string Write(); - Crossing& GetCentreCrossing(); + Crossing* GetCentreCrossing(); // bool IsInsideGoal(Pedestrian* ped) const; diff --git a/geometry/WaitingArea.cpp b/geometry/WaitingArea.cpp index 47f15a15d741130775f810c8586132bd03e45d29..d40f040e8c6692b8cfd915e7c73b1732d238f495 100644 --- a/geometry/WaitingArea.cpp +++ b/geometry/WaitingArea.cpp @@ -117,11 +117,18 @@ int WaitingArea::GetNextGoal() void WaitingArea::addPed(int ped) { pedInside.insert(ped); + if (pedInside.size() > maxNumPed){ + open = false; + } } void WaitingArea::removePed(int ped) { pedInside.erase(ped); + if (pedInside.size() <= maxNumPed){ + open = true; + } + } void WaitingArea::startTimer(double time) @@ -150,6 +157,11 @@ bool WaitingArea::isWaiting(double time, const Building* building) return false; } + if ((waitingTime < 0. ) && (trans->IsOpen())){ + std::cout << "Waiting ended" << std::endl; + return false; + } + std::cout << "Waiting ..." << std::endl; return true; } diff --git a/routing/ff_router/ffRouter.cpp b/routing/ff_router/ffRouter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..067c28f0dc292027030ce172b290e751a89b247b --- /dev/null +++ b/routing/ff_router/ffRouter.cpp @@ -0,0 +1,637 @@ +/** + * \file ffRouter.h + * \date Feb 19, 2016 + * \version v0.8 + * \copyright <2016-2022> 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 + * This router is an update of the former Router.{cpp, h} - Global-, Quickest + * Router System. In the __former__ version, a graph was created with doors and + * hlines as nodes and the distances of (doors, hlines), connected with a line- + * of-sight, was used as edge-costs. If there was no line-of-sight, there was no + * connecting edge. On the resulting graph, the Floyd-Warshall algorithm was + * used to find any paths. In the "quickest-___" variants, the edge cost was not + * determined by the distance, but by the distance multiplied by a speed- + * estimate, to find the path with minimum travel times. This whole construct + * worked pretty well, but dependend on hlines to create paths with line-of- + * sights to the next target (hline/door). + * + * In the ffRouter, we want to overcome hlines by using floor fields to + * determine the distances. A line of sight is not required any more. We hope to + * reduce the graph complexity and the preparation-needs for new geometries. + * + * To find a counterpart for the "quickest-____" router, we can either use + * __special__ floor fields, that respect the travel time in the input-speed map, + * or take the distance-floor field and multiply it by a speed-estimate (analog + * to the former construct. + * + * We will derive from the <Router> class to fit the interface. + * + **/ + +#include <cfloat> +#include <algorithm> +#include "ffRouter.h" +//#include "FloorfieldViaFM.h" +//#include "../../geometry/Building.h" + +int FFRouter::_cnt = 0; + +FFRouter::FFRouter() +{ + +} + +FFRouter::FFRouter(int id, RoutingStrategy s, bool hasSpecificGoals, Configuration* config):Router(id,s) { + _config = config; + _building = nullptr; + _hasSpecificGoals = hasSpecificGoals; + _globalFF = nullptr; + _targetWithinSubroom = true; //depending on exit_strat 8 => false, depending on exit_strat 9 => true; + _targetWithinSubroom = (_config->get_exit_strat() == 9); + if (s == ROUTING_FF_QUICKEST) { + _mode = quickest; + _recalc_interval = _config->get_recalc_interval(); + } else if (s == ROUTING_FF_LOCAL_SHORTEST) { + _mode = local_shortest; + _localShortestSafedPeds.clear(); + _localShortestSafedPeds.reserve(500); + } else if (s == ROUTING_FF_GLOBAL_SHORTEST) { + _mode = global_shortest; + } +} + +//FFRouter::FFRouter(const Building* const building) + +FFRouter::~FFRouter() +{ + if (_globalFF) { + delete _globalFF; + } + //delete localffs + std::map<int, UnivFFviaFM*>::reverse_iterator delIter; + for (delIter = _locffviafm.rbegin(); + delIter != _locffviafm.rend(); + ++delIter) { + delete (*delIter).second; + } +} + +bool FFRouter::Init(Building* building) +{ + _building = building; + if (_hasSpecificGoals) { + std::vector<int> goalIDs; + goalIDs.clear(); + //get global field to manage goals (which are not in a subroom) + _globalFF = new FloorfieldViaFM(building, 0.25, 0.25, 0.0, false, true); + for (auto &itrGoal : building->GetAllGoals()) { + _globalFF->createMapEntryInLineToGoalID(itrGoal.first); + goalIDs.emplace_back(itrGoal.first); + } + _goalToLineUIDmap = _globalFF->getGoalToLineUIDmap(); + _goalToLineUIDmap2 = _globalFF->getGoalToLineUIDmap2(); + _goalToLineUIDmap3 = _globalFF->getGoalToLineUIDmap3(); + //_globalFF->writeGoalFF("goal.vtk", goalIDs); + } + //get all door UIDs + _allDoorUIDs.clear(); + _TransByUID.clear(); + _ExitsByUID.clear(); + _CroTrByUID.clear(); + auto& allTrans = building->GetAllTransitions(); + auto& allCross = building->GetAllCrossings(); + std::vector<std::pair<int, int>> roomAndCroTrVector; + roomAndCroTrVector.clear(); + for (auto& pair:allTrans) { + if (pair.second->IsOpen()) { + _allDoorUIDs.emplace_back(pair.second->GetUniqueID()); + _CroTrByUID.insert(std::make_pair(pair.second->GetUniqueID(), pair.second)); + if (pair.second->IsExit()) { + _ExitsByUID.insert(std::make_pair(pair.second->GetUniqueID(), pair.second)); + } + Room* room1 = pair.second->GetRoom1(); + if (room1) roomAndCroTrVector.emplace_back(std::make_pair(room1->GetID(), pair.second->GetUniqueID())); + Room* room2 = pair.second->GetRoom2(); + if (room2) roomAndCroTrVector.emplace_back(std::make_pair(room2->GetID(), pair.second->GetUniqueID())); + } + } + for (auto& pair:allCross) { + if (pair.second->IsOpen()) { + _allDoorUIDs.emplace_back(pair.second->GetUniqueID()); + _CroTrByUID.insert(std::make_pair(pair.second->GetUniqueID(), pair.second)); + Room* room1 = pair.second->GetRoom1(); + if (room1) roomAndCroTrVector.emplace_back(std::make_pair(room1->GetID(), pair.second->GetUniqueID())); + } + } + //make unique + std::sort(_allDoorUIDs.begin(), _allDoorUIDs.end()); + _allDoorUIDs.erase( std::unique(_allDoorUIDs.begin(),_allDoorUIDs.end()), _allDoorUIDs.end()); + + //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 )); + //_subroomMatrix.insert(std::make_pair(key, nullptr)); + } + } + + //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(); + + + 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); + UnivFFviaFM *locffptr = nullptr; + locffptr = new UnivFFviaFM(pairRoomIt->second.get(), building, 0.125, 0.0, false); + + locffptr->setUser(DISTANCE_MEASUREMENTS_ONLY); + locffptr->setMode(CENTERPOINT); + locffptr->setSpeedMode(FF_HOMO_SPEED); + locffptr->addAllTargetsParallel(); + //locffptr->writeFF("UnivFF"+std::to_string(pairRoomIt->first)+".vtk", locffptr->getKnownDoorUIDs()); + Log->Write("INFO: \tAdding distances in Room %d to matrix", (*pairRoomIt).first); +//#pragma omp critical(_locffviafm) + _locffviafm.insert(std::make_pair((*pairRoomIt).first, locffptr)); + } + + + // nowait, because the parallel region ends directly afterwards +//#pragma omp for nowait + //@todo: @ar.graf: it would be easier to browse thru doors of each field directly after "addAllTargetsParallel" as + // we do only want doors of same subroom anyway. BUT the router would have to switch from room-scope + // to subroom-scope. Nevertheless, we could omit the room info (used to acces correct field), if we + // do it like in "ReInit()". + for (unsigned int i = 0; i < roomAndCroTrVector.size(); ++i) { + auto rctIt = roomAndCroTrVector.begin(); + std::advance(rctIt, i); + + ////loop over upper triangular matrice (i,j) and write to (j,i) as well + for (auto otherDoor : roomAndCroTrVector) { + if (otherDoor.first != rctIt->first) continue; // we only want doors with one room in common + if (otherDoor.second <= rctIt->second) continue; // calculate every path only once + // if we exclude otherDoor.second == rctIt->second, the program loops forever + + //if the door is closed, then don't calc distances + //if (!_CroTrByUID.at(*otherDoor)->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 thisUID1 = (_CroTrByUID.at(rctIt->second)->GetSubRoom1()) ? _CroTrByUID.at(rctIt->second)->GetSubRoom1()->GetUID() : -10 ; + int thisUID2 = (_CroTrByUID.at(rctIt->second)->GetSubRoom2()) ? _CroTrByUID.at(rctIt->second)->GetSubRoom2()->GetUID() : -20 ; + int otherUID1 = (_CroTrByUID.at(otherDoor.second)->GetSubRoom1()) ? _CroTrByUID.at(otherDoor.second)->GetSubRoom1()->GetUID() : -30 ; + int otherUID2 = (_CroTrByUID.at(otherDoor.second)->GetSubRoom2()) ? _CroTrByUID.at(otherDoor.second)->GetSubRoom2()->GetUID() : -40 ; + + if ( + (thisUID1 != otherUID1) && + (thisUID1 != otherUID2) && + (thisUID2 != otherUID1) && + (thisUID2 != otherUID2) ) { + continue; + } + + UnivFFviaFM* locffptr = _locffviafm[rctIt->first]; + double tempDistance = locffptr->getDistanceBetweenDoors(rctIt->second, otherDoor.second); + + if (tempDistance < locffptr->getGrid()->Gethx()) { + Log->Write("WARNING:\tIgnoring distance of doors %d and %d because it is too small: %f",rctIt->second, otherDoor.second, tempDistance); + //Log->Write("^^^^^^^^\tIf there are scattered subrooms, which are not connected, this is ok."); + continue; + } +// + std::pair<int, int> key_ij = std::make_pair(otherDoor.second, rctIt->second); + std::pair<int, int> key_ji = std::make_pair(rctIt->second, otherDoor.second); + + +#pragma omp critical(_distMatrix) + if (_distMatrix.at(key_ij) > tempDistance) { + _distMatrix.erase(key_ij); + _distMatrix.erase(key_ji); + _distMatrix.insert(std::make_pair(key_ij, tempDistance)); + _distMatrix.insert(std::make_pair(key_ji, tempDistance)); + } + } // otherDoor + } // roomAndCroTrVector + + if (_config->get_has_directional_escalators()) { + _directionalEscalatorsUID.clear(); + _penaltyList.clear(); + for (auto room : building->GetAllRooms()) { + for (auto subroom : room.second->GetAllSubRooms()) { + if ((subroom.second->GetType() == "escalator_up") || (subroom.second->GetType() == "escalator_down")) { + _directionalEscalatorsUID.emplace_back(subroom.second->GetUID()); + } + } + } + for (int subUID : _directionalEscalatorsUID) { + Escalator* escalator = (Escalator*) building->GetSubRoomByUID(subUID); + std::vector<int> lineUIDs = escalator->GetAllGoalIDs(); + assert(lineUIDs.size() == 2); + if (escalator->IsEscalatorUp()) { + if (_CroTrByUID[lineUIDs[0]]->IsInLineSegment(escalator->GetUp())) { + _penaltyList.emplace_back(std::make_pair(lineUIDs[0], lineUIDs[1])); + } else { + _penaltyList.emplace_back(std::make_pair(lineUIDs[1], lineUIDs[0])); + } + } else { //IsEscalatorDown + if (_CroTrByUID[lineUIDs[0]]->IsInLineSegment(escalator->GetUp())) { + _penaltyList.emplace_back(std::make_pair(lineUIDs[1], lineUIDs[0])); + } else { + _penaltyList.emplace_back(std::make_pair(lineUIDs[0], lineUIDs[1])); + } + } + } + for (auto key : _penaltyList) { + _distMatrix.erase(key); + _distMatrix.insert(std::make_pair(key, DBL_MAX)); + } + } + + FloydWarshall(); + + //debug output in file +// _locffviafm[4]->writeFF("ffTreppe.vtk", _allDoorUIDs); + + //int roomTest = (*(_locffviafm.begin())).first; + //int transTest = (building->GetRoom(roomTest)->GetAllTransitionsIDs())[0]; + //auto test = _CroTrByUID.at(1253); + + if (_config->get_write_VTK_files()) { + for (unsigned int i = 0; i < _locffviafm.size(); ++i) { + auto iter = _locffviafm.begin(); + std::advance(iter, i); + int roomNr = iter->first; + iter->second->writeFF("ffrouterOfRoom" + 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; +} + +bool FFRouter::ReInit() +{ + //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 floorfield : _locffviafm) { + floorfield.second->setSpeedMode(FF_PED_SPEED); + //@todo: ar.graf: create a list of local ped-ptr instead of giving all peds-ptr + floorfield.second->createPedSpeed(_building->GetAllPedestrians().data(), _building->GetAllPedestrians().size(), _mode, 1.); + floorfield.second->recreateAllForQuickest(); + std::vector<int> allDoors(floorfield.second->getKnownDoorUIDs()); + for (auto firstDoor : allDoors) { + for (auto secondDoor : allDoors) { + if (secondDoor <= firstDoor) continue; // calculate every path only once + // 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 thisUID1 = (_CroTrByUID.at(firstDoor)->GetSubRoom1()) ? _CroTrByUID.at(firstDoor)->GetSubRoom1()->GetUID() : -10 ; + int thisUID2 = (_CroTrByUID.at(firstDoor)->GetSubRoom2()) ? _CroTrByUID.at(firstDoor)->GetSubRoom2()->GetUID() : -20 ; + int otherUID1 = (_CroTrByUID.at(secondDoor)->GetSubRoom1()) ? _CroTrByUID.at(secondDoor)->GetSubRoom1()->GetUID() : -30 ; + int otherUID2 = (_CroTrByUID.at(secondDoor)->GetSubRoom2()) ? _CroTrByUID.at(secondDoor)->GetSubRoom2()->GetUID() : -40 ; + + if ( + (thisUID1 != otherUID1) && + (thisUID1 != otherUID2) && + (thisUID2 != otherUID1) && + (thisUID2 != otherUID2) ) { + continue; + } + + //double tempDistance = floorfield.second->getCostToDestination(firstDoor, _CroTrByUID.at(secondDoor)->GetCentre()); + double tempDistance = floorfield.second->getDistanceBetweenDoors(firstDoor, secondDoor); + if (tempDistance < floorfield.second->getGrid()->Gethx()) { + Log->Write("WARNING:\tDistance of doors %d and %d is too small: %f",firstDoor, secondDoor, tempDistance); + //Log->Write("^^^^^^^^\tIf there are scattered subrooms, which are not connected, this is ok."); + continue; + } + std::pair<int, int> key_ij = std::make_pair(secondDoor, firstDoor); + std::pair<int, int> key_ji = std::make_pair(firstDoor, secondDoor); + if (_distMatrix.at(key_ij) > tempDistance) { + _distMatrix.erase(key_ij); + _distMatrix.erase(key_ji); + _distMatrix.insert(std::make_pair(key_ij, tempDistance)); + _distMatrix.insert(std::make_pair(key_ji, tempDistance)); + } + } //secondDoor(s) + } //firstDoor(s) + } //allRooms + + if (_config->get_has_directional_escalators()) { + _directionalEscalatorsUID.clear(); + _penaltyList.clear(); + for (auto room : _building->GetAllRooms()) { + for (auto subroom : room.second->GetAllSubRooms()) { + if ((subroom.second->GetType() == "escalator_up") || (subroom.second->GetType() == "escalator_down")) { + _directionalEscalatorsUID.emplace_back(subroom.second->GetUID()); + } + } + } + for (int subUID : _directionalEscalatorsUID) { + Escalator* escalator = (Escalator*) _building->GetSubRoomByUID(subUID); + std::vector<int> lineUIDs = escalator->GetAllGoalIDs(); + assert(lineUIDs.size() == 2); + if (escalator->IsEscalatorUp()) { + if (_CroTrByUID[lineUIDs[0]]->IsInLineSegment(escalator->GetUp())) { + _penaltyList.emplace_back(std::make_pair(lineUIDs[0], lineUIDs[1])); + } else { + _penaltyList.emplace_back(std::make_pair(lineUIDs[1], lineUIDs[0])); + } + } else { //IsEscalatorDown + if (_CroTrByUID[lineUIDs[0]]->IsInLineSegment(escalator->GetUp())) { + _penaltyList.emplace_back(std::make_pair(lineUIDs[1], lineUIDs[0])); + } else { + _penaltyList.emplace_back(std::make_pair(lineUIDs[0], lineUIDs[1])); + } + } + } + for (auto key : _penaltyList) { + _distMatrix.erase(key); + _distMatrix.insert(std::make_pair(key, DBL_MAX)); + } + } + + FloydWarshall(); + _plzReInit = false; + return true; +} + + + +int FFRouter::FindExit(Pedestrian* p) +{ +// if (_mode == local_shortest) { +// if ((_locffviafm.at(p->GetRoomID())->getGrid()->includesPoint(p->GetPos())) && +// (p->GetSubRoomUID() != _locffviafm.at(p->GetRoomID())->getSubroomUIDAt(p->GetPos()))) { +// //pedestrian is still in the room, but changed subroom +// _localShortestSafedPeds.emplace_back(p->GetID()); +// } +// +// //if needed: quickest-mechanic part 2 of 2 +// if (!(_locffviafm.at(p->GetRoomID())->getGrid()->includesPoint(p->GetPos()))) { +// //pedestrian left the room and therefore changed subroom +// _localShortestSafedPeds.emplace_back(p->GetID()); +// } +// } + if (_mode == quickest) { + if (p->GetGlobalTime() > _recalc_interval && _building->GetRoom(p->GetRoomID())->GetSubRoom(p->GetSubRoomID())->IsInSubRoom(p) + && _locffviafm[p->GetRoomID()]->getCostToDestination(p->GetExitIndex(), p->GetPos()) > 3.0 + && p->GetExitIndex() != -1) { + //delay possible + if ((int) p->GetGlobalTime() % 10 != p->GetID() % 10) { + return p->GetExitIndex(); //stay with old target + } + } + //new version: recalc densityspeed every x seconds + if ((p->GetGlobalTime() > _timeToRecalc) && (p->GetGlobalTime() > Pedestrian::GetMinPremovementTime() + _recalc_interval)) { + _plzReInit = true; + } + } + double minDist = DBL_MAX; + int bestDoor = -1; + + int goalID = p->GetFinalDestination(); + std::vector<int> validFinalDoor; //UIDs of doors + validFinalDoor.clear(); + if (goalID == -1) { + for (auto& pairDoor : _ExitsByUID) { + //we add the all exits, + validFinalDoor.emplace_back(pairDoor.first); //UID + } + } else { //only one specific goal, goalToLineUIDmap gets + //populated in Init() + if ((_goalToLineUIDmap.count(goalID) == 0) || (_goalToLineUIDmap[goalID] == -1)) { + Log->Write("ERROR: \t ffRouter: unknown/unreachable goalID: %d in FindExit(Ped)",goalID); + } else { + validFinalDoor.emplace_back(_goalToLineUIDmap.at(goalID)); + } + } + + std::vector<int> DoorUIDsOfRoom; + DoorUIDsOfRoom.clear(); + if (_building->GetRoom(p->GetRoomID())->GetSubRoom(p->GetSubRoomID())->IsInSubRoom(p->GetPos())) { + //ped is in the subroom, according to its member attribs + } else { + bool located = false; + SubRoom* oldSubRoom = _building->GetRoom(p->GetRoomID())->GetSubRoom(p->GetSubRoomID()); + for (auto& room : _building->GetAllRooms()) { + if (located) {break;} + for (auto& subroom : room.second->GetAllSubRooms()) { + if (subroom.second->IsInSubRoom(p->GetPos()) && subroom.second->IsDirectlyConnectedWith(oldSubRoom)) { + //maybe room on wrong floor + p->SetRoomID(room.second->GetID(), room.second->GetCaption()); + p->SetSubRoomID(subroom.second->GetSubRoomID()); + p->SetSubRoomUID(subroom.second->GetUID()); + located = true; + break; + } + } + } + if (!located) { //ped is outside + return -1; + } + } + DoorUIDsOfRoom.clear(); + if (!_targetWithinSubroom) { + //candidates of current room (ID) (provided by Room) + for (auto transUID : _building->GetRoom(p->GetRoomID())->GetAllTransitionsIDs()) { + if ((_CroTrByUID.count(transUID) != 0) && (_CroTrByUID[transUID]->IsOpen())) { + DoorUIDsOfRoom.emplace_back(transUID); + } + } + for (auto &subIPair : _building->GetRoom(p->GetRoomID())->GetAllSubRooms()) { + for (auto &crossI : subIPair.second->GetAllCrossings()) { + if (crossI->IsOpen()) { + DoorUIDsOfRoom.emplace_back(crossI->GetUniqueID()); + } + } + } + } + else + { + //candidates of current subroom only + for (auto &crossI : _building->GetRoom(p->GetRoomID())->GetSubRoom(p->GetSubRoomID())->GetAllCrossings()) { + if (crossI->IsOpen()) { + DoorUIDsOfRoom.emplace_back(crossI->GetUniqueID()); + } + } + + for (auto &transI : _building->GetRoom(p->GetRoomID())->GetSubRoom(p->GetSubRoomID())->GetAllTransitions()) { + if (transI->IsOpen()) { + DoorUIDsOfRoom.emplace_back(transI->GetUniqueID()); + } + } + } + + int bestFinalDoor = -1; // to silence the compiler + for(int finalDoor : validFinalDoor) { + //with UIDs, we can ask for shortest path + for (int doorUID : DoorUIDsOfRoom) { + //double locDistToDoor = _locffviafm[p->GetRoomID()]->getCostToDestination(doorUID, p->GetPos(), _mode); + double locDistToDoor = 0.; + if (_targetWithinSubroom) { + locDistToDoor = _config->get_dirSubLocal()->GetDistance2Target(p, doorUID); + } else { + locDistToDoor = _config->get_dirLocal()->GetDistance2Target(p, doorUID); + } + + if (locDistToDoor < -J_EPS) { //for old ff: //this can happen, if the point is not reachable and therefore has init val -7 + continue; + } + std::pair<int, int> key = std::make_pair(doorUID, finalDoor); + //auto subroomDoors = _building->GetSubRoomByUID(p->GetSubRoomUID())->GetAllGoalIDs(); + //only consider, if paths exists + if (_pathsMatrix.count(key)==0) { + Log->Write("no key for %d %d", key.first, key.second); + continue; + } + + if ((_distMatrix.count(key)!=0) && (_distMatrix.at(key) != DBL_MAX)) { + if ((_distMatrix.at(key) + locDistToDoor) < minDist) { + minDist = _distMatrix.at(key) + locDistToDoor; + bestDoor = key.first; //doorUID + //if (locDistToDoor == 0.) { + if (true) { + auto subroomDoors = _building->GetSubRoomByUID(p->GetSubRoomUID())->GetAllGoalIDs(); + if (std::find(subroomDoors.begin(), subroomDoors.end(), _pathsMatrix[key]) != subroomDoors.end()) { + bestDoor = _pathsMatrix[key]; //@todo: @ar.graf: check this hack + } + } + bestFinalDoor = key.second; + } + } + } + } + + //at this point, bestDoor is either a crossing or a transition + if ((!_targetWithinSubroom) && (_CroTrByUID.count(bestDoor) != 0)) { + while (!_CroTrByUID[bestDoor]->IsTransition()) { + std::pair<int, int> key = std::make_pair(bestDoor, bestFinalDoor); + bestDoor = _pathsMatrix[key]; + } + } + +//#pragma omp critical(finalDoors) +// _finalDoors.emplace(std::make_pair(p->GetID(), bestFinalDoor)); + + if (_CroTrByUID.count(bestDoor)) { + p->SetExitIndex(bestDoor); + p->SetExitLine(_CroTrByUID.at(bestDoor)); + } + return bestDoor; //-1 if no way was found, doorUID of best, if path found +} + +void FFRouter::FloydWarshall() +{ + bool change = false; + double savedDistance = 0.; + int totalnum = _allDoorUIDs.size(); + for(int k = 0; k<totalnum; ++k) { + for(int i = 0; i<totalnum; ++i) { + for(int j= 0; j<totalnum; ++j) { + std::pair<int, int> key_ij = std::make_pair(_allDoorUIDs[i], _allDoorUIDs[j]); + std::pair<int, int> key_ik = std::make_pair(_allDoorUIDs[i], _allDoorUIDs[k]); + std::pair<int, int> key_kj = std::make_pair(_allDoorUIDs[k], _allDoorUIDs[j]); + if ((_distMatrix[key_ik] < DBL_MAX) && (_distMatrix[key_kj] < DBL_MAX) && + (_distMatrix[key_ik] + _distMatrix[key_kj] < _distMatrix[key_ij])) + { + savedDistance = _distMatrix[key_ij] - _distMatrix[key_ik] - _distMatrix[key_kj]; + _distMatrix.erase(key_ij); + _distMatrix.insert(std::make_pair(key_ij, _distMatrix[key_ik] + _distMatrix[key_kj])); + _pathsMatrix.erase(key_ij); + _pathsMatrix.insert(std::make_pair(key_ij, _pathsMatrix[key_ik])); + change = true; + } + } + } + } + if (change) { + //Log->Write("Floyd nochmal!!! %f", savedDistance); + FloydWarshall(); + } else { + Log->Write("INFO:\t FloydWarshall done!"); + } +} + +void FFRouter::SetMode(std::string s) +{ + if (s == "global_shortest"){ + _mode = global_shortest; + return; + } + + if (s == "quickest") { + _mode = quickest; + return; + } + + _mode = global_shortest; + return; +} + +bool FFRouter::MustReInit() { + return _plzReInit; +} + +void FFRouter::SetRecalc(double t) { + _timeToRecalc = t + _recalc_interval; +} \ No newline at end of file diff --git a/routing/ff_router_trips/FloorfieldViaFMTrips.cpp b/routing/ff_router_trips/FloorfieldViaFMTrips.cpp index 4258289fcf44b0ba4f80dbd070bb1e255d502b0b..73aa9c32a52a8124fb07a4bac1f8e520ec0b6c3d 100644 --- a/routing/ff_router_trips/FloorfieldViaFMTrips.cpp +++ b/routing/ff_router_trips/FloorfieldViaFMTrips.cpp @@ -403,7 +403,7 @@ void FloorfieldViaFMTrips::createMapEntryInLineToGoalID(const int goalID, bool i // UID_of_MIN = 33; // // } - UID_of_MIN = allgoals.at(goalID)->GetCentreCrossing().GetUniqueID(); + UID_of_MIN = allgoals.at(goalID)->GetCentreCrossing()->GetUniqueID(); } else { for (const auto& loctrans : transitions) {