| 56 | {"both", Obstacle::Direction::Both}}; |
| 57 | |
| 58 | void ObstacleMap::preProcess(const NodeIDVector &node_ids, const WayNodeIDOffsets &way_node_offsets) |
| 59 | { |
| 60 | util::UnbufferedLog log; |
| 61 | log << "Collecting information on " << osm_obstacles.size() << " obstacles..."; |
| 62 | TIMER_START(preProcess); |
| 63 | |
| 64 | // collect the node IDs of unidirectional obstacles |
| 65 | std::unordered_set<OSMNodeID> directional_obstacle_nodes; |
| 66 | for (const auto &[from_id, to_id, obstacle] : osm_obstacles) |
| 67 | { |
| 68 | if (obstacle.direction == Obstacle::Direction::Forward || |
| 69 | obstacle.direction == Obstacle::Direction::Backward) |
| 70 | { |
| 71 | directional_obstacle_nodes.insert(to_id); |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | if (!directional_obstacle_nodes.empty()) |
| 76 | { |
| 77 | // build a multimap of OSMNodeId to way index, but only for obstacle nodes |
| 78 | std::unordered_multimap<OSMNodeID, size_t> node2start_index; |
| 79 | |
| 80 | for (size_t i = 0, j = 1; j < way_node_offsets.size(); ++i, ++j) |
| 81 | { |
| 82 | for (size_t k = way_node_offsets[i]; k < way_node_offsets[j]; ++k) |
| 83 | { |
| 84 | if (directional_obstacle_nodes.contains(node_ids[k])) |
| 85 | { |
| 86 | node2start_index.emplace(node_ids[k], i); |
| 87 | } |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | // For each unidirectional obstacle, find the node immediately before |
| 92 | // or after the obstacle on each way that crosses it. Collect new |
| 93 | // entries separately to avoid mutating osm_obstacles during iteration. |
| 94 | std::vector<OsmFromToObstacle> new_entries; |
| 95 | |
| 96 | for (const auto &[from_id, to_id, obstacle] : osm_obstacles) |
| 97 | { |
| 98 | if (obstacle.direction == Obstacle::Direction::Forward || |
| 99 | obstacle.direction == Obstacle::Direction::Backward) |
| 100 | { |
| 101 | bool forward = obstacle.direction == Obstacle::Direction::Forward; |
| 102 | auto [wno_begin, wno_end] = node2start_index.equal_range(to_id); |
| 103 | for (auto wno_iter = wno_begin; wno_iter != wno_end; ++wno_iter) |
| 104 | { |
| 105 | using NodeIdIterator = NodeIDVector::const_iterator; |
| 106 | |
| 107 | NodeIdIterator begin = node_ids.cbegin() + way_node_offsets[wno_iter->second]; |
| 108 | NodeIdIterator end = node_ids.cbegin() + way_node_offsets[wno_iter->second + 1]; |
| 109 | if (forward) |
| 110 | ++begin; |
| 111 | else |
| 112 | --end; |
| 113 | |
| 114 | NodeIdIterator node_iter = find(begin, end, to_id); |
| 115 | if (node_iter != end) |
no test coverage detected