Line data Source code
1 : #include <spdlog/spdlog.h>
2 :
3 : #include <stdexcept>
4 :
5 : #include "Dynamic/Env/Edge.hpp"
6 : #include "Static/Solution.hpp"
7 : #include "Static/supply/Network.hpp"
8 : #include "data/SUMO/Network.hpp"
9 : #include "data/SUMO/Routes.hpp"
10 : #include "utils/stringify.hpp"
11 :
12 : using namespace std;
13 : using namespace SUMO;
14 :
15 : using utils::stringify::stringify;
16 :
17 : // clang-format off
18 0 : Routes Routes::Loader<
19 : const Static::Network &,
20 : const Static::Solution &,
21 : const Static::SUMOAdapter &
22 : >::load(
23 : const Static::Network &network,
24 : const Static::Solution &x,
25 : const Static::SUMOAdapter &adapter
26 : ) {
27 : // clang-format on
28 0 : Routes ret;
29 :
30 0 : const Static::Solution::Routes &routes = x.getRoutes();
31 :
32 0 : map<pair<SUMO::TAZ::ID, SUMO::TAZ::ID>, vector<pair<Static::Flow, SUMO::Route>>> allRoutes;
33 :
34 0 : size_t numberFlows = 0;
35 0 : Static::Flow maxFlow = 0.0;
36 :
37 0 : for(const auto &[path, flow]: routes) {
38 0 : SUMO::Route route;
39 0 : for(const Static::Network::Edge::ID &eid: path) {
40 0 : if(adapter.isSumoEdge(eid))
41 0 : route.push_back(adapter.toSumoEdge(eid));
42 : }
43 0 : const SUMO::TAZ::ID &fromTaz = adapter.toSumoTAZ(network.getEdge(*path.begin()).u);
44 0 : const SUMO::TAZ::ID &toTaz = adapter.toSumoTAZ(network.getEdge(*path.rbegin()).v);
45 :
46 0 : allRoutes[{fromTaz, toTaz}].push_back({flow, route});
47 0 : ++numberFlows;
48 0 : maxFlow = max(maxFlow, flow);
49 : }
50 :
51 0 : size_t flowID = 0;
52 0 : for(const auto &[fromTo, fromToRoutes]: allRoutes) {
53 0 : const auto &[fromTaz, toTaz] = fromTo;
54 :
55 0 : const float MIN_INTENSITY = 0.5;
56 0 : const float MAX_INTENSITY = 1.5;
57 0 : const float DEFAULT_INTENSITY = 1.0;
58 :
59 0 : for(size_t i = 0; i < fromToRoutes.size(); ++i) {
60 0 : const auto &[f, route] = fromToRoutes[i];
61 :
62 0 : float intensity = (fromToRoutes.size() <= 1 ? DEFAULT_INTENSITY : MIN_INTENSITY + (MAX_INTENSITY - MIN_INTENSITY) * float(i) / float(fromToRoutes.size() - 1));
63 :
64 0 : float h = 360.0f * float(flowID) / float(numberFlows);
65 0 : float v = 100.0f * min(intensity, 1.0f);
66 0 : float s = 100.0f * (1.0f - max(intensity - 1.0f, 0.0f));
67 :
68 0 : color::hsv<float> colorHSV({h, s, v});
69 0 : color::rgb<float> colorRGB;
70 0 : colorRGB = colorHSV;
71 :
72 0 : Flow &flow = ret.createFlow(
73 0 : stringify<size_t>::toString(flowID++),
74 : route,
75 : 0, 3600,
76 0 : shared_ptr<Flow::Policy>(
77 0 : new Flow::PolicyVehsPerHour(f * 60.0 * 60.0)
78 : )
79 0 : );
80 0 : flow.setColor(colorRGB);
81 0 : flow.setFromTaz(fromTaz);
82 0 : flow.setToTaz(toTaz);
83 0 : flow.setDepartPos({.e = Flow::DepartPos::Enum::RANDOM_FREE});
84 0 : flow.setDepartSpeed({.e = Flow::DepartSpeed::Enum::RANDOM});
85 : }
86 : }
87 :
88 0 : return ret;
89 : }
90 :
91 : // clang-format off
92 0 : Routes Routes::Loader<
93 : const list<reference_wrapper<const Dynamic::Env::Vehicle>> &,
94 : const SUMO::TAZs &,
95 : const Dynamic::SUMOAdapter &
96 : >::load(
97 : const list<reference_wrapper<const Dynamic::Env::Vehicle>> &vehs,
98 : const SUMO::TAZs &tazs,
99 : const Dynamic::SUMOAdapter &adapter
100 : ) {
101 : // clang-format on
102 0 : Routes ret;
103 :
104 0 : size_t i = 0;
105 :
106 0 : unordered_map<SUMO::Network::Edge::ID, SUMO::TAZ::ID> edge2tazSource;
107 0 : unordered_map<SUMO::Network::Edge::ID, SUMO::TAZ::ID> edge2tazSink;
108 0 : for(const auto &[_, taz]: tazs) {
109 0 : for(const SUMO::TAZ::Source &source: taz.sources) {
110 0 : if(edge2tazSource.count(source.id)) {
111 : // clang-format off
112 0 : spdlog::warn(
113 : "Routes::Loader<>::load: Source edge {} already assigned to TAZ {}, cannot be assigned to TAZ {} as well",
114 0 : source.id,
115 0 : edge2tazSource[source.id],
116 0 : taz.id
117 : );
118 : // clang-format on
119 : }
120 0 : edge2tazSource[source.id] = taz.id;
121 : }
122 0 : for(const SUMO::TAZ::Sink &sink: taz.sinks) {
123 0 : if(edge2tazSink.count(sink.id)) {
124 : // clang-format off
125 0 : spdlog::warn(
126 : "Routes::Loader<>::load: Sink edge {} already assigned to TAZ {}, cannot be assigned to TAZ {} as well",
127 0 : sink.id,
128 0 : edge2tazSink[sink.id],
129 0 : taz.id
130 : );
131 : // clang-format on
132 : }
133 0 : edge2tazSink[sink.id] = taz.id;
134 : }
135 : }
136 :
137 0 : for(const Dynamic::Env::Vehicle &vehicle: vehs) {
138 0 : Route route;
139 0 : for(const auto &[t, lane]: vehicle.path) {
140 0 : SUMO::Network::Edge::ID edgeID = adapter.toSumoEdge(lane.get().edge.id);
141 :
142 0 : if(!route.empty() && route.back() == edgeID)
143 0 : continue;
144 :
145 0 : route.push_back(edgeID);
146 : }
147 :
148 0 : Vehicle &veh = ret.createVehicle(
149 0 : to_string(vehicle.id),
150 : route,
151 0 : vehicle.depart
152 0 : );
153 :
154 0 : float h = 360.0f * float(i) / float(vehs.size());
155 0 : float v = 100.0f;
156 0 : float s = 100.0f;
157 :
158 0 : color::hsv<float> colorHSV({h, s, v});
159 0 : color::rgb<float> colorRGB;
160 0 : colorRGB = colorHSV;
161 :
162 0 : veh.setColor(colorRGB);
163 0 : veh.setFromTaz(to_string(vehicle.fromTAZ.id));
164 0 : veh.setToTaz(to_string(vehicle.toTAZ.id));
165 :
166 0 : ++i;
167 : }
168 :
169 0 : return ret;
170 : }
|