diff --git a/Simulation.cpp b/Simulation.cpp index 68d06b9345fa0e0b3223e39a57af46ff252aaa3c..7ecb3979d1882a5fc207bff0df6958f27c8914de 100644 --- a/Simulation.cpp +++ b/Simulation.cpp @@ -476,8 +476,6 @@ double Simulation::RunBody(double maxSimTime) ProcessAgentsQueue(); if (t>Pedestrian::GetMinPremovementTime()) { - //@todo: @ar.graf: here we could place router-tasks (calc new maps) that can use multiple cores AND we have 't' - //update the linked cells _building->UpdateGrid(); @@ -487,8 +485,15 @@ double Simulation::RunBody(double maxSimTime) //update the events _em->ProcessEvent(); - //update doorticks - //UpdateDoorticks(); + //here we could place router-tasks (calc new maps) that can use multiple cores AND we have 't' + //update quickestRouter + if (_routingEngine.get()->GetRouter(ROUTING_FF_QUICKEST)) { + FFRouter* ffrouter = dynamic_cast<FFRouter*>(_routingEngine.get()->GetRouter(ROUTING_FF_QUICKEST)); + if (ffrouter->MustReInit()) { + ffrouter->ReInit(); + ffrouter->SetRecalc(t); + } + } //update the routes and locations UpdateRoutesAndLocations(); diff --git a/general/Macros.h b/general/Macros.h index 8891dfeae3522ed3d614a88464bac7da485858d2..dab0622fa67c574602b143ce0c6720110fe7f3e8 100644 --- a/general/Macros.h +++ b/general/Macros.h @@ -187,6 +187,7 @@ enum FloorfieldMode { FF_FULL_LINE, FF_WALL_AVOID, FF_HOMO_SPEED, + FF_PED_SPEED, FF_ROOM_SCALE, FF_SUBROOM_SCALE }; diff --git a/geometry/Building.cpp b/geometry/Building.cpp index 6fec58b11a0777bd25fa688f44950925b65c40d7..085cf8df182526738c18d49b537925e9b98c81b5 100644 --- a/geometry/Building.cpp +++ b/geometry/Building.cpp @@ -706,12 +706,9 @@ std::vector<Point> Building::GetBoundaryVertices() const bool Building::SanityCheck() { - Log->Write("INFO: \tChecking the geometry for artifacts"); + Log->Write("INFO: \tChecking the geometry for artifacts: (Ignore Warnings, if ff_[...] router is used!)"); bool status = true; - //only for ffRouter - return status; - for(auto&& itr_room: _rooms) { for(auto&& itr_subroom: itr_room.second->GetAllSubRooms()) diff --git a/pedestrian/Pedestrian.cpp b/pedestrian/Pedestrian.cpp index 9bdc9594dc99ff3d5c2856f49c8e0a6e8c98c1be..b493e77180e017e5eec54c54fd01e4c2c184354d 100644 --- a/pedestrian/Pedestrian.cpp +++ b/pedestrian/Pedestrian.cpp @@ -981,7 +981,7 @@ Router* Pedestrian::GetRouter() const int Pedestrian::FindRoute() { if( ! _router) { - Log->Write("ERROR:\t one or more routers does not exit! Check your router_ids"); + Log->Write("ERROR:\t one or more routers does not exist! Check your router_ids"); return -1; } //bool isinsub = (_building->GetAllRooms().at(this->GetRoomID())->GetSubRoom(this->GetSubRoomID())->IsInSubRoom(this)); diff --git a/routing/RoutingEngine.cpp b/routing/RoutingEngine.cpp index d00252fc60675682ed689933551380b4edf98ed3..10001c9331adefd22879fd99139e5aecdad67395 100644 --- a/routing/RoutingEngine.cpp +++ b/routing/RoutingEngine.cpp @@ -95,7 +95,7 @@ Router* RoutingEngine::GetRouter(RoutingStrategy strategy) const if(router->GetStrategy()==strategy) return router; } - Log->Write("ERROR: \t Could not Find any router with Strategy: [%d].",strategy); + //Log->Write("ERROR: \t Could not Find any router with Strategy: [%d].",strategy); return /*(Router*)*/ nullptr; } diff --git a/routing/ff_router/UnivFFviaFM.cpp b/routing/ff_router/UnivFFviaFM.cpp index 1cf2643271e5c7ddd9b7b328b4c891f24597e7e7..8aa46d0745fc24d84b5e0aae0b83b7ba1d43dcff 100644 --- a/routing/ff_router/UnivFFviaFM.cpp +++ b/routing/ff_router/UnivFFviaFM.cpp @@ -8,12 +8,13 @@ #include "../../geometry/Building.h" #include "../../geometry/Room.h" #include "../../geometry/SubRoom.h" +#include "../../pedestrian/Pedestrian.h" #include "mesh/RectGrid.h" UnivFFviaFM::~UnivFFviaFM() { if (_grid) delete _grid; - size_t speedsize = _speedFieldSelector.size(); + //size_t speedsize = _speedFieldSelector.size(); for (auto speedPtr : _speedFieldSelector) { if (speedPtr) delete[] speedPtr; } @@ -78,15 +79,24 @@ UnivFFviaFM::UnivFFviaFM(Room* roomArg, Configuration* const confArg, double hx, const std::vector<Transition*> tmpTrans = subRoomPtr->GetAllTransitions(); int uidNotConst = 0; + bool isOpen = false; for (auto& cross : tmpCross) { uidNotConst = cross->GetUniqueID(); - if (tmpDoors.count(uidNotConst) == 0) { + isOpen = cross->IsOpen(); + if (!isOpen) { + //will be added twice! is it a problem? + lines.emplace_back((Line)*cross); + } else if ((tmpDoors.count(uidNotConst) == 0)) { tmpDoors.emplace(std::make_pair(uidNotConst, (Line) *cross)); } } for (auto& trans : tmpTrans) { uidNotConst = trans->GetUniqueID(); - if (tmpDoors.count(uidNotConst) == 0) { + isOpen = trans->IsOpen(); + if (!isOpen) { + //will be added twice! is it a problem? + lines.emplace_back((Line)*trans); + } else if (tmpDoors.count(uidNotConst) == 0) { tmpDoors.emplace(std::make_pair(uidNotConst, (Line) *trans)); } } @@ -129,13 +139,24 @@ UnivFFviaFM::UnivFFviaFM(SubRoom* subRoomArg, Configuration* const confArg, doub const std::vector<Transition*> tmpTrans = subRoomArg->GetAllTransitions(); int uidNotConst = 0; + bool isOpen = false; for (auto& cross : tmpCross) { uidNotConst = cross->GetUniqueID(); - tmpDoors.emplace(std::make_pair(uidNotConst, (Line) *cross)); + isOpen = cross->IsOpen(); + if (!isOpen) { + lines.emplace_back((Line)*cross); + } else { + tmpDoors.emplace(std::make_pair(uidNotConst, (Line) *cross)); + } } for (auto& trans : tmpTrans) { uidNotConst = trans->GetUniqueID(); - tmpDoors.emplace(std::make_pair(uidNotConst, (Line) *trans)); + isOpen = trans->IsOpen(); + if (!isOpen) { + lines.emplace_back((Line)*trans); + } else { + tmpDoors.emplace(std::make_pair(uidNotConst, (Line) *trans)); + } } //this will interpret "useWallDistances" as best as possible. Users should clearify with "setSpeedMode" before calling "AddTarget" @@ -163,8 +184,11 @@ void UnivFFviaFM::create(std::vector<Line>& walls, std::map<int, Line>& doors, s _speedFieldSelector.emplace(_speedFieldSelector.begin()+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) || (useWallDistances)) { + _speedFieldSelector.emplace(_speedFieldSelector.begin()+REDU_WALL_SPEED, nullptr); + _speedFieldSelector.emplace(_speedFieldSelector.begin()+PED_SPEED, nullptr); + + //allocate _modifiedSpeed + if ((_speedmode == FF_WALL_AVOID) || (useWallDistances)) { double* cost_alias_walldistance = new double[_nPoints]; _costFieldWithKey[0] = cost_alias_walldistance; Point* gradient_alias_walldirection = new Point[_nPoints]; @@ -184,7 +208,7 @@ void UnivFFviaFM::create(std::vector<Line>& walls, std::map<int, Line>& doors, s //_uids.emplace_back(0); double* temp_reduWallSpeed = new double[_nPoints]; - if (_speedFieldSelector.size() > 1) { //free memory before overwriting + if (_speedFieldSelector[REDU_WALL_SPEED]) { //free memory before overwriting delete[] _speedFieldSelector[REDU_WALL_SPEED]; } _speedFieldSelector[REDU_WALL_SPEED] = temp_reduWallSpeed; @@ -193,14 +217,10 @@ void UnivFFviaFM::create(std::vector<Line>& walls, std::map<int, Line>& doors, s createReduWallSpeed(temp_reduWallSpeed); } - //the memory will be allocated in "addTarget". for parallel processing, we might change it to allocate before the - //parallel region and call a fct "addTarget(int, [ptr_to_preallocated mem])" - for (auto targetUID : targetUIDs ) { - addTarget(targetUID); - } //loop over targets - - - + // parallel call + if (!targetUIDs.empty()) { + addTargetsParallel(targetUIDs); + } } void UnivFFviaFM::createRectGrid(std::vector<Line>& walls, std::map<int, Line>& doors, double spacing) { @@ -301,8 +321,8 @@ void UnivFFviaFM::markSubroom(const Point& insidePoint, SubRoom* const value) { wavefront.erase(current); _gridCode[current] = INSIDE; - directNeighbor _neigh = _grid->getNeighbors(current); - long aux = _neigh.key[0]; + _neigh = _grid->getNeighbors(current); + aux = _neigh.key[0]; if ((aux != -2) && (_gridCode[aux] == INSIDE || _gridCode[aux] == OUTSIDE) && _subrooms[aux] == nullptr) { wavefront.insert(aux); _subrooms[aux] = value; @@ -338,6 +358,106 @@ void UnivFFviaFM::createReduWallSpeed(double* reduWallSpeed){ } } } + +void UnivFFviaFM::recreateAllForQuickest() { + //allocate if neccessary (should not be!) + for (int doorUID : _uids) { + if (!_costFieldWithKey[doorUID]) { + _costFieldWithKey[doorUID] = new double[_nPoints]; + } + if (_user == DISTANCE_MEASUREMENTS_ONLY) { + if (_directionFieldWithKey.count(doorUID) != 0 && _directionFieldWithKey[doorUID]){ + delete[] _directionFieldWithKey[doorUID]; + } + _directionFieldWithKey[doorUID] = nullptr; + } + if (_user == DISTANCE_AND_DIRECTIONS_USED) { + //check if not in map OR (in map but) nullptr) + if ((_directionFieldWithKey.count(doorUID) == 0) || (!_directionFieldWithKey[doorUID])) { + _directionFieldWithKey[doorUID] = new Point[_nPoints]; + } + } + } + + //parallel region +#pragma omp parallel + { +#pragma omp for + for (unsigned int i = 0; i < _doors.size(); ++i) { + auto doorPair = _doors.begin(); + std::advance(doorPair, i); + addTarget(doorPair->first, _costFieldWithKey[doorPair->first], _directionFieldWithKey[doorPair->first]); + } + }; +} + +void UnivFFviaFM::createPedSpeed(Pedestrian *const *pedsArg, int nsize, int modechoice, double radius) { + long int delta = radius / _grid->Gethx(); + long int posIndex = 0; + long int pos_i = 0; + long int pos_j = 0; + long int i_start = 0; + long int j_start = 0; + long int i_end = 0; + long int j_end = 0; + long int iStride = _grid->GetiMax(); + double indexDistance = 0.0; + +// if (nsize == 0) { +// Log->Write("WARNING: \tcreatePedSpeed: nsize is ZERO"); +// } else { +// Log->Write("INFO: \t\tNumber of Peds used in createPedSpeed: %d",nsize); +// } + + if ((modechoice == quickest) && (!_speedFieldSelector[PED_SPEED])) { + _speedFieldSelector[PED_SPEED] = new double[_grid->GetnPoints()]; + } + + //we assume, that this function is only used by router and is not using REDU_WALL_SPEED + for (long int i = 0; i < _grid->GetnPoints(); ++i) { + _speedFieldSelector[PED_SPEED][i] = _speedFieldSelector[INITIAL_SPEED][i]; + } + + for (int i = 0; i < nsize; ++i) { + //the following check is not 3D proof, we require the caller of this function to provide a list with "valid" + //pedestrian-pointer + if (!_grid->includesPoint(pedsArg[i]->GetPos())) { + continue; + } + /*this value defines the jam-speed threshold*/ +// if (pedsArg[i]->GetEllipse().GetV().Norm() > 0.8*pedsArg[i]->GetEllipse().GetV0()) { +// continue; +// } + posIndex = _grid->getKeyAtPoint(pedsArg[i]->GetPos()); + pos_i = _grid->get_i_fromKey(posIndex); + pos_j = _grid->get_j_fromKey(posIndex); + + i_start = ((pos_i - delta) < 0) ? 0 : (pos_i - delta); + i_end = ((pos_i + delta) >= iStride) ? iStride-1 : (pos_i + delta); + + j_start = ((pos_j - delta) < 0) ? 0 : (pos_j - delta); + j_end = ((pos_j + delta) >= _grid->GetjMax()) ? _grid->GetjMax()-1 : (pos_j + delta); + + for (long int curr_i = i_start; curr_i < i_end; ++curr_i) { + for (long int curr_j = j_start; curr_j < j_end; ++curr_j) { + //indexDistance holds the square + indexDistance = ( (curr_i - pos_i)*(curr_i - pos_i) + (curr_j - pos_j)*(curr_j - pos_j) ); + //now using indexDistance to store the (speed) reduction value + //indexDistance = (delta*delta) - (indexDistance); + //if (indexDistance < 0) { indexDistance = 0.;} + //scale to [0 .. 1] + //indexDistance = indexDistance/(delta*delta); + + //densityspeed[curr_j*grid->GetiMax() + curr_i] = (indexDistance > (delta*delta)) ? densityspeed[curr_j*grid->GetiMax() + curr_i] : .001; + if (indexDistance < (delta*delta)) { + //std::cout << "c h a n g i n g "; + _speedFieldSelector[PED_SPEED][curr_j*iStride + curr_i] = 0.2; + } + } + } + } +} + void UnivFFviaFM::drawLinesOnGrid(std::map<int, Line>& doors, int *const grid) { for (auto&& doorPair : doors) { int tempUID = doorPair.first; @@ -957,18 +1077,20 @@ void UnivFFviaFM::addTarget(const int uid, double* costarrayDBL, Point* gradarra } Line tempTargetLine = Line(_doors[uid]); Point tempCenterPoint = Point(tempTargetLine.GetCentre()); - if (tempTargetLine.GetLength() > 0.6) { //shorten line from both Points to avoid targeting edges of real door - const Point& p1 = tempTargetLine.GetPoint1(); - const Point& p2 = tempTargetLine.GetPoint2(); - double length = tempTargetLine.GetLength(); - double u = 0.2/length; - tempTargetLine = Line(p1 + (p2-p1)*u, p1 + (p2-p1)*(1-u), 0); - } else if (tempTargetLine.GetLength() > 0.2) { - const Point& p1 = tempTargetLine.GetPoint1(); - const Point& p2 = tempTargetLine.GetPoint2(); - double length = tempTargetLine.GetLength(); - double u = 0.05/length; - tempTargetLine = Line(p1 + (p2-p1)*u, p1 + (p2-p1)*(1-u), 0); + if (_mode == LINESEGMENT) { + if (tempTargetLine.GetLength() > 0.6) { //shorten line from both Points to avoid targeting edges of real door + const Point &p1 = tempTargetLine.GetPoint1(); + const Point &p2 = tempTargetLine.GetPoint2(); + double length = tempTargetLine.GetLength(); + double u = 0.2 / length; + tempTargetLine = Line(p1 + (p2 - p1) * u, p1 + (p2 - p1) * (1 - u), 0); + } else if (tempTargetLine.GetLength() > 0.2) { + const Point &p1 = tempTargetLine.GetPoint1(); + const Point &p2 = tempTargetLine.GetPoint2(); + double length = tempTargetLine.GetLength(); + double u = 0.05 / length; + tempTargetLine = Line(p1 + (p2 - p1) * u, p1 + (p2 - p1) * (1 - u), 0); + } } //this allocation must be on shared heap! to be accessible by any thread later (should be shared in openmp) @@ -1008,6 +1130,8 @@ void UnivFFviaFM::addTarget(const int uid, double* costarrayDBL, Point* gradarra calcFF(newArrayDBL, newArrayPt, _speedFieldSelector[REDU_WALL_SPEED]); } else if (_speedmode == FF_HOMO_SPEED) { calcFF(newArrayDBL, newArrayPt, _speedFieldSelector[INITIAL_SPEED]); + } else if (_speedmode == FF_PED_SPEED) { + calcFF(newArrayDBL, newArrayPt, _speedFieldSelector[PED_SPEED]); } #pragma omp critical(_uids) _uids.emplace_back(uid); @@ -1027,6 +1151,9 @@ void UnivFFviaFM::addAllTargets() { } void UnivFFviaFM::addAllTargetsParallel() { + //Reason: freeing and reallocating takes time. We do not use already allocated memory, because we do not know if it + // is shared memory. Maybe this is not neccessary - maybe reconsider. This way, it is safe. If this function + // is called from a parallel region, we all go to hell. //free old memory for (auto memoryDBL : _costFieldWithKey) { if (memoryDBL.first == 0) continue; //do not free distancemap @@ -1059,6 +1186,39 @@ void UnivFFviaFM::addAllTargetsParallel() { }; } +void UnivFFviaFM::addTargetsParallel(std::vector<int> wantedDoors) { + //free old memory (but not the distancemap with key == 0) + for (int targetUID : wantedDoors) { + if ((targetUID != 0) && _costFieldWithKey.count(targetUID) && _costFieldWithKey[targetUID]) { + delete[] _costFieldWithKey[targetUID]; + } + if ((targetUID != 0) && _directionFieldWithKey.count(targetUID) && _directionFieldWithKey[targetUID]) { + delete[] _directionFieldWithKey[targetUID]; + } + } + //allocate new memory + for (int targetUID : wantedDoors) { + _costFieldWithKey[targetUID] = new double[_nPoints]; + if (_user == DISTANCE_MEASUREMENTS_ONLY) { + _directionFieldWithKey[targetUID] = nullptr; + } + if (_user == DISTANCE_AND_DIRECTIONS_USED) { + _directionFieldWithKey[targetUID] = new Point[_nPoints]; + } + } + + //parallel region +#pragma omp parallel + { +#pragma omp for + for (unsigned int i = 0; i < wantedDoors.size(); ++i) { + auto doorUID = wantedDoors.begin(); + std::advance(doorUID, i); + addTarget(*doorUID, _costFieldWithKey[*doorUID], _directionFieldWithKey[*doorUID]); + } + }; +} + SubRoom** UnivFFviaFM::getSubRoomFF(){ return _subrooms; } @@ -1085,6 +1245,9 @@ void UnivFFviaFM::setMode(int modeArg) { void UnivFFviaFM::setSpeedMode(int speedModeArg) { _speedmode = speedModeArg; + if (_speedmode == FF_PED_SPEED && !_speedFieldSelector[PED_SPEED]) { + _speedFieldSelector[PED_SPEED] = new double[_nPoints]; + } } diff --git a/routing/ff_router/UnivFFviaFM.h b/routing/ff_router/UnivFFviaFM.h index 8bcb80a8f5d6cec405c3f524d58da9ac585a6492..f4424f9a797403eceee66c1c2b208d8488207f11 100644 --- a/routing/ff_router/UnivFFviaFM.h +++ b/routing/ff_router/UnivFFviaFM.h @@ -42,6 +42,7 @@ #include <float.h> #include "../../general/Macros.h" +class Pedestrian; class Room; class SubRoom; class Building; @@ -87,6 +88,7 @@ public: UnivFFviaFM(SubRoom* subRoomArg, Configuration* const confArg, double hx, double wallAvoid, bool useWallDistances, std::vector<int> wantedDoors); void create(std::vector<Line>& walls, std::map<int, Line>& doors, std::vector<int> targetUIDs, int mode, double spacing, double wallAvoidDist, bool useWallDistances); + void recreateAllForQuickest(); UnivFFviaFM() {}; UnivFFviaFM(UnivFFviaFM&){}; virtual ~UnivFFviaFM(); @@ -95,6 +97,7 @@ public: void addTarget(const int uid, double* costarray = nullptr, Point* gradarray = nullptr); void addAllTargets(); void addAllTargetsParallel(); + void addTargetsParallel(std::vector<int> wantedDoors); std::vector<int> getKnownDoorUIDs(); void setUser(int userArg); void setMode(int modeArg); @@ -118,6 +121,7 @@ public: void processGeometry(std::vector<Line>&walls, std::map<int, Line>& doors); void markSubroom(const Point& insidePoint, SubRoom* const value); void createReduWallSpeed(double* reduWallSpeed); + void createPedSpeed(Pedestrian* const * pedsArg, int nsize, int modechoice, double radius); void drawLinesOnGrid(std::map<int, Line>& doors, int *const grid); template <typename T> diff --git a/routing/ff_router/ffRouter.cpp b/routing/ff_router/ffRouter.cpp index 4249c21d115a2ce3f41b72cbe7c4ebbe19ab432b..46e4c66c3bbc1c7d22af422c8b24d39a2d693049 100644 --- a/routing/ff_router/ffRouter.cpp +++ b/routing/ff_router/ffRouter.cpp @@ -185,7 +185,7 @@ bool FFRouter::Init(Building* building) // } else { // locffptr = new LocalFloorfieldViaFM(pairRoomIt->second.get(), building, 0.125, 0.125, 0.0, false); // } - locffptr->setUser(DISTANCE_AND_DIRECTIONS_USED); + locffptr->setUser(DISTANCE_MEASUREMENTS_ONLY); locffptr->setMode(CENTERPOINT); locffptr->setSpeedMode(FF_HOMO_SPEED); locffptr->addAllTargetsParallel(); @@ -198,6 +198,10 @@ bool FFRouter::Init(Building* building) // 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); @@ -337,7 +341,68 @@ bool FFRouter::Init(Building* building) bool FFRouter::ReInit() { - return false; + //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)); + } + } + + 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() : -1 ; + int thisUID2 = (_CroTrByUID.at(firstDoor)->GetSubRoom2()) ? _CroTrByUID.at(firstDoor)->GetSubRoom2()->GetUID() : -2 ; + int otherUID1 = (_CroTrByUID.at(secondDoor)->GetSubRoom1()) ? _CroTrByUID.at(secondDoor)->GetSubRoom1()->GetUID() : -3 ; + int otherUID2 = (_CroTrByUID.at(secondDoor)->GetSubRoom2()) ? _CroTrByUID.at(secondDoor)->GetSubRoom2()->GetUID() : -4 ; + + if ( + (thisUID1 != otherUID1) && + (thisUID1 != otherUID2) && + (thisUID2 != otherUID1) && + (thisUID2 != otherUID2) ) { + continue; + } + + double tempDistance = floorfield.second->getCostToDestination(firstDoor, _CroTrByUID.at(secondDoor)->GetCentre()); + if (tempDistance < floorfield.second->getGrid()->Gethx()) { + //Log->Write("WARNING:\tDistance of doors %d and %d is too small: %f",*otherDoor, *innerPtr, 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 + FloydWarshall(); + _plzReInit = false; + return true; } @@ -359,13 +424,8 @@ int FFRouter::FindExit(Pedestrian* p) // } if (_mode == quickest) { //new version: recalc densityspeed every x seconds - if (p->GetGlobalTime() > _timeToRecalc) { - _timeToRecalc += _recalc_interval; //@todo: ar.graf: change "5" to value of config file/classmember -// for (auto localfield : _locffviafm) { //@todo: ar.graf: create a list of local ped-ptr instead of giving all peds-ptr -// localfield.second->setSpeedThruPeds(_building->GetAllPedestrians().data(), _building->GetAllPedestrians().size(), _mode, 1.); -// localfield.second->deleteAllFFs(); -// } - ReInit(); + if ((p->GetGlobalTime() > _timeToRecalc) && (p->GetGlobalTime() > Pedestrian::GetMinPremovementTime() + _recalc_interval)) { + _plzReInit = true; } } double minDist = DBL_MAX; @@ -649,4 +709,12 @@ void FFRouter::SetMode(std::string s) _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/ffRouter.h b/routing/ff_router/ffRouter.h index b0b866460286e89819ada94c38aa2f168dba07dc..cc875752c880f98476ade6bc5cfae6f5f14f3d75 100644 --- a/routing/ff_router/ffRouter.h +++ b/routing/ff_router/ffRouter.h @@ -137,12 +137,11 @@ public: virtual bool Init(Building* building); /*! - * \brief ReInit the router (must be called after each event (open/close change) + * \brief ReInit the router if quickest router is used. Current position of agents is considered. * * ReInit() will reconstruct the graph (nodes = doors, edges = costs) and * find shortest paths via Floyd-Warshall. It will reconstruct the floorfield to - * evaluate the best doors to certain goals as they could change. Further on it - * will take the information of former floorfields, if useful. + * evaluate the best doors to certain goals as they could change. * * * \param[in] [name of input parameter] [its description] @@ -181,6 +180,8 @@ public: * \brief set mode (shortest, quickest, ...) */ void SetMode(std::string s); + bool MustReInit(); + void SetRecalc(double t); private: @@ -206,6 +207,7 @@ protected: int _mode; double _timeToRecalc = 0.; double _recalc_interval; + bool _plzReInit = false; bool _hasSpecificGoals; bool _targetWithinSubroom; // If we use CentrePointDistance (i.e. CentrePointLocalFFViaFM), some algorithms can maybe be simplified