@@ -489,43 +489,66 @@ namespace dsm {
489489 Id nodeId,
490490 std::optional<Id> streetId) {
491491 auto possibleMoves = this ->graph ().adjacencyMatrix ().getRow (nodeId);
492+
493+ std::set<Id> forbiddenStreetIds;
494+ if (streetId.has_value ()) {
495+ auto const & pStreet{this ->graph ().edge (*streetId)};
496+ forbiddenStreetIds = pStreet->forbiddenTurns ();
497+ // Avoid U-TURNS, if possible
498+ if (!(this ->graph ().node (nodeId)->isRoundabout ()) &&
499+ (possibleMoves.size () > forbiddenStreetIds.size () + 1 )) {
500+ auto const & pOppositeStreet{this ->graph ().oppositeStreet (*streetId)};
501+ if (pOppositeStreet) {
502+ forbiddenStreetIds.insert (pOppositeStreet->get ()->id ());
503+ }
504+ }
505+ }
506+ // Exclude FORBIDDEN turns
507+ for (auto const & forbiddenStreetId : forbiddenStreetIds) {
508+ auto const & pForbiddenStreet{this ->graph ().edge (forbiddenStreetId)};
509+ // if possible moves contains the forbidden street, remove it
510+ auto it = std::find (
511+ possibleMoves.begin (), possibleMoves.end (), pForbiddenStreet->target ());
512+ if (it != possibleMoves.end ()) {
513+ possibleMoves.erase (it);
514+ }
515+ }
516+
492517 if (!pAgent->isRandom ()) {
518+ std::vector<Id> newPossibleMoves;
493519 std::uniform_real_distribution<double > uniformDist{0 ., 1 .};
494520 if (!(this ->itineraries ().empty ())) {
495521 if (!(m_errorProbability.has_value () &&
496522 uniformDist (this ->m_generator ) < m_errorProbability)) {
497523 const auto & it = this ->itineraries ().at (pAgent->itineraryId ());
498524 if (it->destination () != nodeId) {
499- possibleMoves = it->path ()->getRow (nodeId);
525+ newPossibleMoves = it->path ()->getRow (nodeId);
500526 }
501527 }
528+ for (auto const & forbiddenStreetId : forbiddenStreetIds) {
529+ auto const & pForbiddenStreet{this ->graph ().edge (forbiddenStreetId)};
530+ // if possible moves contains the forbidden street, remove it
531+ auto it = std::find (newPossibleMoves.begin (),
532+ newPossibleMoves.end (),
533+ pForbiddenStreet->target ());
534+ if (it != newPossibleMoves.end ()) {
535+ newPossibleMoves.erase (it);
536+ }
537+ }
538+ if (!newPossibleMoves.empty ()) {
539+ possibleMoves = newPossibleMoves;
540+ }
502541 }
503542 }
543+
504544 assert (!possibleMoves.empty ());
505- if (streetId.has_value ()) {
506- auto const & pStreet{this ->graph ().edge (*streetId)};
507- for (auto const & foirbiddenStreetId : pStreet->forbiddenTurns ()) {
508- auto const & pForbiddenStreet{this ->graph ().edge (foirbiddenStreetId)};
509- // if possible moves contains the forbidden street, remove it
510- auto it = std::find (
511- possibleMoves.begin (), possibleMoves.end (), pForbiddenStreet->target ());
512- if (it != possibleMoves.end ()) {
513- possibleMoves.erase (it);
514- }
515- }
545+
546+ if (possibleMoves.size () == 1 ) {
547+ return nodeId * this ->graph ().nNodes () + possibleMoves[0 ];
516548 }
517549 std::uniform_int_distribution<Size> moveDist{
518550 0 , static_cast <Size>(possibleMoves.size () - 1 )};
519- // while loop to avoid U turns in non-roundabout junctions
520- Id nextStreetId;
521- do {
522- nextStreetId =
523- nodeId * this ->graph ().nNodes () + possibleMoves[moveDist (this ->m_generator )];
524- } while (!this ->graph ().node (nodeId)->isRoundabout () && streetId.has_value () &&
525- (this ->graph ().edge (nextStreetId)->target () ==
526- this ->graph ().edge (streetId.value ())->source ()) &&
527- (possibleMoves.size () > 1 ));
528- return nextStreetId;
551+ return nodeId * this ->graph ().nNodes () + possibleMoves[moveDist (this ->m_generator )];
529552 }
530553
531554 template <typename delay_t >
0 commit comments