@@ -542,6 +542,10 @@ const std::vector<ScenarioConnectionTraversal>& cachedTraversalsForZone(
542542 return it == cache.traversableConnectionsByZone .end () ? empty : it->second ;
543543}
544544
545+ std::string agentCollisionFloorId (const EvacuationRoute& route) {
546+ return route.displayFloorId .empty () ? route.currentFloorId : route.displayFloorId ;
547+ }
548+
545549std::string zoneAt (const ScenarioLayoutCacheResource& cache, const Point2D& point, const std::string& floorId) {
546550 const auto & floorLayout = cachedLayoutForFloor (cache, floorId);
547551 for (const auto & zone : floorLayout.zones ) {
@@ -728,15 +732,19 @@ AgentSpatialIndex buildAgentSpatialIndex(
728732 double cellSize) {
729733 AgentSpatialIndex index;
730734 index.cellSize = cellSize;
731- index.cells .reserve (entities. size () * 2 );
735+ index.cellsByFloor .reserve (4 );
732736
733737 for (const auto entity : entities) {
734738 const auto & status = query.get <EvacuationStatus>(entity);
735739 if (status.evacuated ) {
736740 continue ;
737741 }
738742 const auto & position = query.get <Position>(entity);
739- index.cells [spatialKey (spatialCellFor (position.value , cellSize))].push_back (entity);
743+ const auto floorId = query.contains <EvacuationRoute>(entity)
744+ ? agentCollisionFloorId (query.get <EvacuationRoute>(entity))
745+ : std::string{};
746+ auto & floorCells = index.cellsByFloor [floorId];
747+ floorCells[spatialKey (spatialCellFor (position.value , cellSize))].push_back (entity);
740748 }
741749 return index;
742750}
@@ -745,14 +753,20 @@ std::vector<engine::Entity> nearbyAgents(
745753 engine::WorldQuery& query,
746754 const AgentSpatialIndex& index,
747755 const Point2D& point,
756+ const std::string& floorId,
748757 double radius) {
749758 std::vector<engine::Entity> candidates;
759+ const auto floorIt = index.cellsByFloor .find (floorId);
760+ if (floorIt == index.cellsByFloor .end ()) {
761+ return candidates;
762+ }
763+
750764 const auto center = spatialCellFor (point, index.cellSize );
751765 const auto range = std::max (1 , static_cast <int >(std::ceil (radius / index.cellSize )));
752766 for (int dy = -range; dy <= range; ++dy) {
753767 for (int dx = -range; dx <= range; ++dx) {
754- const auto it = index. cells .find (spatialKey ({.x = center.x + dx, .y = center.y + dy}));
755- if (it == index. cells .end ()) {
768+ const auto it = floorIt-> second .find (spatialKey ({.x = center.x + dx, .y = center.y + dy}));
769+ if (it == floorIt-> second .end ()) {
756770 continue ;
757771 }
758772 for (const auto entity : it->second ) {
@@ -766,6 +780,14 @@ std::vector<engine::Entity> nearbyAgents(
766780 return candidates;
767781}
768782
783+ std::vector<engine::Entity> nearbyAgents (
784+ engine::WorldQuery& query,
785+ const AgentSpatialIndex& index,
786+ const Point2D& point,
787+ double radius) {
788+ return nearbyAgents (query, index, point, std::string{}, radius);
789+ }
790+
769791Point2D deterministicFallbackDirection (engine::Entity entity) {
770792 const auto seed = static_cast <double >((entity.index % 17U ) + 1U );
771793 return normalizedOr ({.x = std::cos (seed * 1.37 ), .y = std::sin (seed * 1.37 )}, {.x = 1.0 , .y = 0.0 });
@@ -817,6 +839,10 @@ Point2D forwardPreservingAgentAvoidanceVelocity(
817839 }
818840 const auto & otherPosition = query.get <Position>(other);
819841 const auto & otherAgent = query.get <Agent>(other);
842+ const auto & otherRoute = query.get <EvacuationRoute>(other);
843+ if (agentCollisionFloorId (otherRoute) != agentCollisionFloorId (route)) {
844+ continue ;
845+ }
820846 const auto offsetToOther = otherPosition.value - position.value ;
821847 const auto distance = lengthOf (offsetToOther);
822848 const auto desiredDistance = static_cast <double >(agent.radius + otherAgent.radius ) + kPersonalSpaceBuffer ;
@@ -825,7 +851,6 @@ Point2D forwardPreservingAgentAvoidanceVelocity(
825851
826852 bool headOn = false ;
827853 if (route.nextWaypointIndex < route.waypoints .size () && distance <= kHeadOnLookAheadDistance ) {
828- const auto & otherRoute = query.get <EvacuationRoute>(other);
829854 if (otherRoute.currentFloorId == route.currentFloorId
830855 && otherRoute.nextWaypointIndex < otherRoute.waypoints .size ()) {
831856 const auto otherTarget = routeWaypointTarget (otherRoute, otherPosition.value );
0 commit comments