Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file GUITriggeredRerouter.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date Mon, 25.07.2005
19 : ///
20 : // Reroutes vehicles passing an edge (gui version)
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <string>
25 : #include <utils/common/MsgHandler.h>
26 : #include <utils/geom/PositionVector.h>
27 : #include <utils/geom/Boundary.h>
28 : #include <utils/gui/div/GLHelper.h>
29 : #include <utils/common/ToString.h>
30 : #include <utils/common/Command.h>
31 : #include <microsim/MSNet.h>
32 : #include <microsim/MSLane.h>
33 : #include <microsim/MSEdge.h>
34 : #include <microsim/MSRoute.h>
35 : #include <microsim/MSVehicle.h>
36 : #include <guisim/GUINet.h>
37 : #include <guisim/GUIEdge.h>
38 : #include "GUITriggeredRerouter.h"
39 : #include <utils/gui/globjects/GUIGLObjectPopupMenu.h>
40 : #include <utils/gui/windows/GUIAppEnum.h>
41 : #include <gui/GUIGlobals.h>
42 : #include <utils/gui/div/GUIParameterTableWindow.h>
43 : #include <gui/GUIApplicationWindow.h>
44 : #include <microsim/logging/FunctionBinding.h>
45 : #include <utils/gui/div/GUIGlobalSelection.h>
46 : #include <utils/gui/globjects/GLIncludes.h>
47 : #include <utils/gui/globjects/GLIncludes.h>
48 : #include <utils/gui/div/GUIDesigns.h>
49 :
50 :
51 : // ===========================================================================
52 : // FOX callback mapping
53 : // ===========================================================================
54 : /* -------------------------------------------------------------------------
55 : * GUITriggeredRerouter::GUITriggeredRerouterPopupMenu - mapping
56 : * ----------------------------------------------------------------------- */
57 : FXDEFMAP(GUITriggeredRerouter::GUITriggeredRerouterPopupMenu)
58 : GUITriggeredRerouterPopupMenuMap[] = {
59 : FXMAPFUNC(SEL_COMMAND, MID_MANIP, GUITriggeredRerouter::GUITriggeredRerouterPopupMenu::onCmdOpenManip),
60 :
61 : };
62 :
63 : // Object implementation
64 0 : FXIMPLEMENT(GUITriggeredRerouter::GUITriggeredRerouterPopupMenu, GUIGLObjectPopupMenu, GUITriggeredRerouterPopupMenuMap, ARRAYNUMBER(GUITriggeredRerouterPopupMenuMap))
65 :
66 :
67 : /* -------------------------------------------------------------------------
68 : * GUITriggeredRerouter::GUIManip_TriggeredRerouter - mapping
69 : * ----------------------------------------------------------------------- */
70 : FXDEFMAP(GUITriggeredRerouter::GUIManip_TriggeredRerouter) GUIManip_TriggeredRerouterMap[] = {
71 : FXMAPFUNC(SEL_COMMAND, GUITriggeredRerouter::GUIManip_TriggeredRerouter::MID_USER_DEF, GUITriggeredRerouter::GUIManip_TriggeredRerouter::onCmdUserDef),
72 : FXMAPFUNC(SEL_UPDATE, GUITriggeredRerouter::GUIManip_TriggeredRerouter::MID_USER_DEF, GUITriggeredRerouter::GUIManip_TriggeredRerouter::onUpdUserDef),
73 : FXMAPFUNC(SEL_COMMAND, GUITriggeredRerouter::GUIManip_TriggeredRerouter::MID_OPTION, GUITriggeredRerouter::GUIManip_TriggeredRerouter::onCmdChangeOption),
74 : FXMAPFUNC(SEL_COMMAND, GUITriggeredRerouter::GUIManip_TriggeredRerouter::MID_SHIFT_PROBS, GUITriggeredRerouter::GUIManip_TriggeredRerouter::onCmdShiftProbs),
75 : FXMAPFUNC(SEL_COMMAND, GUITriggeredRerouter::GUIManip_TriggeredRerouter::MID_CLOSE, GUITriggeredRerouter::GUIManip_TriggeredRerouter::onCmdClose),
76 : };
77 :
78 0 : FXIMPLEMENT(GUITriggeredRerouter::GUIManip_TriggeredRerouter, GUIManipulator, GUIManip_TriggeredRerouterMap, ARRAYNUMBER(GUIManip_TriggeredRerouterMap))
79 :
80 :
81 : // ===========================================================================
82 : // method definitions
83 : // ===========================================================================
84 : /* -------------------------------------------------------------------------
85 : * GUITriggeredRerouter::GUIManip_TriggeredRerouter - methods
86 : * ----------------------------------------------------------------------- */
87 0 : GUITriggeredRerouter::GUIManip_TriggeredRerouter::GUIManip_TriggeredRerouter(
88 0 : GUIMainWindow& app, const std::string& name, GUITriggeredRerouter& o) :
89 0 : GUIManipulator(app, name, 0, 0), myParent(&app),
90 0 : myChosenValue(0), myChosenTarget(myChosenValue, nullptr, MID_OPTION),
91 0 : myUsageProbability(o.getProbability()), myUsageProbabilityTarget(myUsageProbability),
92 0 : myObject(&o) {
93 0 : myChosenTarget.setTarget(this);
94 : FXVerticalFrame* f1 =
95 0 : new FXVerticalFrame(this, LAYOUT_FILL_X | LAYOUT_FILL_Y, 0, 0, 0, 0, 0, 0, 0, 0);
96 :
97 : FXGroupBox* gp = new FXGroupBox(f1, "Change Trigger Probability",
98 : GROUPBOX_TITLE_LEFT | FRAME_SUNKEN | FRAME_RIDGE,
99 0 : 0, 0, 0, 0, 4, 4, 1, 1, 2, 0);
100 : {
101 : // default
102 : FXHorizontalFrame* gf1 =
103 0 : new FXHorizontalFrame(gp, LAYOUT_TOP | LAYOUT_LEFT, 0, 0, 0, 0, 10, 10, 5, 5);
104 : new FXRadioButton(gf1, "Default", &myChosenTarget, FXDataTarget::ID_OPTION + 0,
105 : ICON_BEFORE_TEXT | LAYOUT_SIDE_TOP,
106 0 : 0, 0, 0, 0, 2, 2, 0, 0);
107 : }
108 : {
109 : // free
110 : FXHorizontalFrame* gf12 =
111 0 : new FXHorizontalFrame(gp, LAYOUT_TOP | LAYOUT_LEFT, 0, 0, 0, 0, 10, 10, 5, 5);
112 : new FXRadioButton(gf12, "User Given: ", &myChosenTarget, FXDataTarget::ID_OPTION + 1,
113 : ICON_BEFORE_TEXT | LAYOUT_SIDE_TOP | LAYOUT_CENTER_Y,
114 0 : 0, 0, 0, 0, 2, 2, 0, 0);
115 0 : myUsageProbabilityDial =
116 : new FXRealSpinner(gf12, 10, this, MID_USER_DEF,
117 0 : LAYOUT_TOP | FRAME_SUNKEN | FRAME_THICK);
118 : //myUsageProbabilityDial->setFormatString("%.2f");
119 : //myUsageProbabilityDial->setIncrements(.1, .1, .1);
120 0 : myUsageProbabilityDial->setIncrement(.1);
121 0 : myUsageProbabilityDial->setRange(0, 1);
122 0 : myUsageProbabilityDial->setValue(myObject->getUserProbability());
123 : }
124 : {
125 : // off
126 : FXHorizontalFrame* gf13 =
127 0 : new FXHorizontalFrame(gp, LAYOUT_TOP | LAYOUT_LEFT, 0, 0, 0, 0, 10, 10, 5, 5);
128 : new FXRadioButton(gf13, "Off", &myChosenTarget, FXDataTarget::ID_OPTION + 2,
129 : ICON_BEFORE_TEXT | LAYOUT_SIDE_TOP,
130 0 : 0, 0, 0, 0, 2, 2, 0, 0);
131 : }
132 0 : myChosenValue = myObject->inUserMode()
133 0 : ? myObject->getUserProbability() > 0
134 0 : ? 1 : 2
135 : : 0;
136 :
137 : FXGroupBox* gp2 = new FXGroupBox(f1, "Change Route Probability",
138 : GROUPBOX_TITLE_LEFT | FRAME_SUNKEN | FRAME_RIDGE,
139 0 : 0, 0, 0, 0, 4, 4, 1, 1, 2, 0);
140 0 : GUIDesigns::buildFXButton(gp2, "Shift", "", "", nullptr, this, MID_SHIFT_PROBS,
141 : BUTTON_INITIAL | BUTTON_DEFAULT | FRAME_RAISED | FRAME_THICK | LAYOUT_TOP | LAYOUT_LEFT | LAYOUT_CENTER_X, 0, 0, 0, 0, 30, 30, 4, 4);
142 :
143 0 : GUIDesigns::buildFXButton(f1, "Close", "", "", nullptr, this, MID_CLOSE,
144 : BUTTON_INITIAL | BUTTON_DEFAULT | FRAME_RAISED | FRAME_THICK | LAYOUT_TOP | LAYOUT_LEFT | LAYOUT_CENTER_X, 0, 0, 0, 0, 30, 30, 4, 4);
145 :
146 0 : }
147 :
148 :
149 0 : GUITriggeredRerouter::GUIManip_TriggeredRerouter::~GUIManip_TriggeredRerouter() {}
150 :
151 :
152 : long
153 0 : GUITriggeredRerouter::GUIManip_TriggeredRerouter::onCmdClose(FXObject*, FXSelector, void*) {
154 0 : destroy();
155 0 : return 1;
156 : }
157 :
158 :
159 : long
160 0 : GUITriggeredRerouter::GUIManip_TriggeredRerouter::onCmdUserDef(FXObject*, FXSelector, void*) {
161 0 : myUsageProbability = (double)(myUsageProbabilityDial->getValue());
162 0 : static_cast<GUITriggeredRerouter*>(myObject)->setUserUsageProbability(myUsageProbability);
163 0 : static_cast<GUITriggeredRerouter*>(myObject)->setUserMode(true);
164 0 : myParent->updateChildren();
165 0 : return 1;
166 : }
167 :
168 :
169 : long
170 0 : GUITriggeredRerouter::GUIManip_TriggeredRerouter::onUpdUserDef(FXObject* sender, FXSelector, void* ptr) {
171 0 : sender->handle(this,
172 0 : myChosenValue != 1 ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
173 : ptr);
174 0 : myParent->updateChildren();
175 0 : return 1;
176 : }
177 :
178 :
179 : long
180 0 : GUITriggeredRerouter::GUIManip_TriggeredRerouter::onCmdChangeOption(FXObject*, FXSelector, void*) {
181 0 : static_cast<GUITriggeredRerouter*>(myObject)->setUserUsageProbability(myUsageProbability);
182 0 : switch (myChosenValue) {
183 0 : case 0:
184 0 : static_cast<GUITriggeredRerouter*>(myObject)->setUserMode(false);
185 0 : break;
186 0 : case 1:
187 0 : static_cast<GUITriggeredRerouter*>(myObject)->setUserMode(true);
188 0 : break;
189 0 : case 2:
190 0 : static_cast<GUITriggeredRerouter*>(myObject)->setUserUsageProbability(0);
191 0 : static_cast<GUITriggeredRerouter*>(myObject)->setUserMode(true);
192 0 : break;
193 0 : default:
194 0 : throw 1;
195 : }
196 0 : myParent->updateChildren();
197 0 : return 1;
198 : }
199 :
200 : long
201 0 : GUITriggeredRerouter::GUIManip_TriggeredRerouter::onCmdShiftProbs(FXObject*, FXSelector, void*) {
202 0 : static_cast<GUITriggeredRerouter*>(myObject)->shiftProbs();
203 0 : myParent->updateChildren();
204 0 : return 1;
205 : }
206 :
207 :
208 :
209 : /* -------------------------------------------------------------------------
210 : * GUITriggeredRerouter::GUITriggeredRerouterPopupMenu - methods
211 : * ----------------------------------------------------------------------- */
212 0 : GUITriggeredRerouter::GUITriggeredRerouterPopupMenu::GUITriggeredRerouterPopupMenu(
213 : GUIMainWindow& app, GUISUMOAbstractView& parent,
214 0 : GUIGlObject& o)
215 0 : : GUIGLObjectPopupMenu(app, parent, o) {}
216 :
217 :
218 0 : GUITriggeredRerouter::GUITriggeredRerouterPopupMenu::~GUITriggeredRerouterPopupMenu() {}
219 :
220 :
221 : long
222 0 : GUITriggeredRerouter::GUITriggeredRerouterPopupMenu::onCmdOpenManip(FXObject*,
223 : FXSelector,
224 : void*) {
225 0 : static_cast<GUITriggeredRerouter*>(myObject)->openManipulator(
226 0 : *myApplication, *myParent);
227 0 : return 1;
228 : }
229 :
230 : // -------------------------------------------------------------------------
231 : // GUITriggeredRerouter - methods
232 : // -------------------------------------------------------------------------
233 :
234 662 : GUITriggeredRerouter::GUITriggeredRerouter(const std::string& id, const MSEdgeVector& edges, double prob,
235 662 : bool off, bool optional, SUMOTime timeThreshold, const std::string& vTypes, const Position& pos, SUMORTree& rtree) :
236 : MSTriggeredRerouter(id, edges, prob, off, optional, timeThreshold, vTypes, pos),
237 : GUIGlObject_AbstractAdd(GLO_REROUTER, id, GUIIconSubSys::getIcon(GUIIcon::REROUTER)),
238 662 : myShiftProbDistIndex(0) {
239 : // add visualisation objects for edges which trigger the rerouter
240 1516 : for (MSEdgeVector::const_iterator it = edges.begin(); it != edges.end(); ++it) {
241 854 : myEdgeVisualizations.push_back(new GUITriggeredRerouterEdge(dynamic_cast<GUIEdge*>(*it), this, REROUTER_TRIGGER_EDGE));
242 854 : rtree.addAdditionalGLObject(myEdgeVisualizations.back());
243 854 : myBoundary.add(myEdgeVisualizations.back()->getCenteringBoundary());
244 : }
245 662 : }
246 :
247 :
248 1324 : GUITriggeredRerouter::~GUITriggeredRerouter() {
249 1749 : for (std::vector<GUITriggeredRerouterEdge*>::iterator it = myEdgeVisualizations.begin(); it != myEdgeVisualizations.end(); ++it) {
250 1087 : delete *it;
251 : }
252 : myEdgeVisualizations.clear();
253 1324 : }
254 :
255 :
256 : void
257 4235 : GUITriggeredRerouter::myEndElement(int element) {
258 4235 : MSTriggeredRerouter::myEndElement(element);
259 4235 : if (element == SUMO_TAG_INTERVAL) {
260 : // add visualisation objects for closed edges
261 : const RerouteInterval& ri = myIntervals.back();
262 872 : for (MSEdgeVector::const_iterator it = ri.closed.begin(); it != ri.closed.end(); ++it) {
263 208 : myEdgeVisualizations.push_back(new GUITriggeredRerouterEdge(dynamic_cast<GUIEdge*>(*it), this, REROUTER_CLOSED_EDGE));
264 208 : dynamic_cast<GUINet*>(GUINet::getInstance())->getVisualisationSpeedUp().addAdditionalGLObject(myEdgeVisualizations.back());
265 208 : myBoundary.add(myEdgeVisualizations.back()->getCenteringBoundary());
266 : }
267 : // add visualisation objects for switches
268 664 : if (ri.routeProbs.getProbs().size() > 1) {
269 : // find last common edge of all routes
270 : ConstMSRoutePtr route0 = ri.routeProbs.getVals()[0];
271 : const MSEdge* lastEdge = nullptr;
272 : int nextIndex = 0;
273 20 : for (int i = 0; i < (int)route0->getEdges().size(); i++) {
274 20 : const MSEdge* cand = route0->getEdges()[i];
275 74 : for (ConstMSRoutePtr route : ri.routeProbs.getVals()) {
276 54 : const MSEdge* nextEdge = i < (int)route->getEdges().size() ? route->getEdges()[i] : nullptr;
277 54 : if (nextEdge != cand) {
278 : cand = nullptr;
279 : }
280 : }
281 20 : if (cand != nullptr) {
282 : lastEdge = cand;
283 : } else {
284 : nextIndex = i;
285 : break;
286 : }
287 : }
288 9 : if (lastEdge != nullptr) {
289 34 : for (int i = 0; i < (int)ri.routeProbs.getVals().size(); i++) {
290 25 : const ConstMSEdgeVector& edges = ri.routeProbs.getVals()[i]->getEdges();
291 25 : if (nextIndex < (int)edges.size()) {
292 25 : GUIEdge* edge = dynamic_cast<GUIEdge*>(const_cast<MSEdge*>(edges[nextIndex]));
293 25 : myEdgeVisualizations.push_back(new GUITriggeredRerouterEdge(edge, this, REROUTER_SWITCH_EDGE, i));
294 25 : dynamic_cast<GUINet*>(GUINet::getInstance())->getVisualisationSpeedUp().addAdditionalGLObject(myEdgeVisualizations.back());
295 25 : myBoundary.add(myEdgeVisualizations.back()->getCenteringBoundary());
296 : }
297 : }
298 : }
299 : }
300 : }
301 4235 : }
302 :
303 :
304 : GUIGLObjectPopupMenu*
305 0 : GUITriggeredRerouter::getPopUpMenu(GUIMainWindow& app,
306 : GUISUMOAbstractView& parent) {
307 0 : GUIGLObjectPopupMenu* ret = new GUITriggeredRerouterPopupMenu(app, parent, *this);
308 0 : buildPopupHeader(ret, app);
309 0 : buildCenterPopupEntry(ret);
310 0 : buildShowManipulatorPopupEntry(ret, false);
311 0 : buildNameCopyPopupEntry(ret);
312 0 : buildSelectionPopupEntry(ret);
313 0 : buildPositionCopyEntry(ret, app);
314 0 : return ret;
315 : }
316 :
317 :
318 : GUIParameterTableWindow*
319 0 : GUITriggeredRerouter::getParameterWindow(GUIMainWindow&,
320 : GUISUMOAbstractView&) {
321 0 : return nullptr;
322 : }
323 :
324 :
325 : void
326 0 : GUITriggeredRerouter::drawGL(const GUIVisualizationSettings& s) const {
327 : UNUSED_PARAMETER(s);
328 0 : }
329 :
330 :
331 : Boundary
332 0 : GUITriggeredRerouter::getCenteringBoundary() const {
333 : Boundary b(myBoundary);
334 0 : b.grow(20);
335 0 : return b;
336 0 : }
337 :
338 :
339 : double
340 0 : GUITriggeredRerouter::getExaggeration(const GUIVisualizationSettings& s) const {
341 0 : return s.addSize.getExaggeration(s, this);
342 : }
343 :
344 :
345 : GUIManipulator*
346 0 : GUITriggeredRerouter::openManipulator(GUIMainWindow& app,
347 : GUISUMOAbstractView&) {
348 0 : GUIManip_TriggeredRerouter* gui = new GUIManip_TriggeredRerouter(app, getFullName(), *this);
349 0 : gui->create();
350 0 : gui->show(PLACEMENT_SCREEN);
351 0 : return gui;
352 : }
353 :
354 :
355 : void
356 0 : GUITriggeredRerouter::shiftProbs() {
357 0 : const RerouteInterval* const ri = getCurrentReroute(MSNet::getInstance()->getCurrentTimeStep());
358 0 : if (ri != nullptr && ri->routeProbs.getProbs().size() > 1) {
359 0 : auto& rp = const_cast<RandomDistributor<ConstMSRoutePtr>&>(ri->routeProbs);
360 0 : myShiftProbDistIndex = myShiftProbDistIndex % rp.getProbs().size();
361 0 : double prob = rp.getProbs()[myShiftProbDistIndex];
362 0 : rp.add(rp.getVals()[myShiftProbDistIndex], -prob);
363 0 : myShiftProbDistIndex = (myShiftProbDistIndex + 1) % rp.getProbs().size();
364 0 : rp.add(rp.getVals()[myShiftProbDistIndex], prob);
365 : // notify vehicles currently on a trigger edge
366 0 : for (auto rrEdge : myEdgeVisualizations) {
367 0 : if (rrEdge->getRerouterEdgeType() == REROUTER_TRIGGER_EDGE) {
368 0 : if (!MSGlobals::gUseMesoSim) {
369 0 : for (MSLane* lane : rrEdge->getEdge()->getLanes()) {
370 0 : for (const MSVehicle* veh : lane->getVehiclesSecure()) {
371 0 : const_cast<MSVehicle*>(veh)->addReminder(this);
372 : }
373 0 : lane->releaseVehicles();
374 : }
375 : }
376 : }
377 : }
378 : }
379 0 : }
380 :
381 :
382 : /* -------------------------------------------------------------------------
383 : * GUITriggeredRerouterEdge - methods
384 : * ----------------------------------------------------------------------- */
385 1087 : GUITriggeredRerouter::GUITriggeredRerouterEdge::GUITriggeredRerouterEdge(GUIEdge* edge, GUITriggeredRerouter* parent, RerouterEdgeType edgeType, int distIndex) :
386 1087 : GUIGlObject(GLO_REROUTER_EDGE, parent->getID() + ":" + edge->getID(), GUIIconSubSys::getIcon(GUIIcon::REROUTER)),
387 1087 : myParent(parent),
388 1087 : myEdge(edge),
389 1087 : myEdgeType(edgeType),
390 3261 : myDistIndex(distIndex) {
391 : const std::vector<MSLane*>& lanes = edge->getLanes();
392 1087 : myFGPositions.reserve(lanes.size());
393 1087 : myFGRotations.reserve(lanes.size());
394 2272 : for (const MSLane* lane : lanes) {
395 1185 : if ((lane->getPermissions() & ~SVC_PEDESTRIAN) == 0) {
396 25 : continue;
397 : }
398 : const PositionVector& v = lane->getShape();
399 1160 : const double pos = edgeType == REROUTER_TRIGGER_EDGE ? MAX2(0.0, v.length() - 6) : MIN2(v.length(), 3.0);
400 1160 : myFGPositions.push_back(v.positionAtOffset(pos));
401 1160 : myFGRotations.push_back(-v.rotationDegreeAtOffset(pos));
402 1160 : myBoundary.add(myFGPositions.back());
403 1160 : myHalfWidths.push_back(lane->getWidth() * 0.5 * 0.875);
404 : }
405 1087 : }
406 :
407 :
408 2174 : GUITriggeredRerouter::GUITriggeredRerouterEdge::~GUITriggeredRerouterEdge() {}
409 :
410 :
411 : GUIGLObjectPopupMenu*
412 0 : GUITriggeredRerouter::GUITriggeredRerouterEdge::getPopUpMenu(GUIMainWindow& app,
413 : GUISUMOAbstractView& parent) {
414 0 : return myParent->getPopUpMenu(app, parent);
415 : }
416 :
417 :
418 : GUIParameterTableWindow*
419 0 : GUITriggeredRerouter::GUITriggeredRerouterEdge::getParameterWindow(GUIMainWindow&,
420 : GUISUMOAbstractView&) {
421 0 : return nullptr;
422 : }
423 :
424 :
425 : void
426 163686 : GUITriggeredRerouter::GUITriggeredRerouterEdge::drawGL(const GUIVisualizationSettings& s) const {
427 163686 : const double exaggeration = getExaggeration(s);
428 163686 : if (s.scale * exaggeration >= 3) {
429 5043 : GLHelper::pushName(getGlID());
430 5043 : const double prob = myParent->getProbability();
431 5043 : if (myEdgeType == REROUTER_CLOSED_EDGE) {
432 : // draw closing symbol onto all lanes
433 : const RerouteInterval* const ri =
434 26 : myParent->getCurrentReroute(MSNet::getInstance()->getCurrentTimeStep());
435 26 : if (ri != nullptr && prob > 0) {
436 : // draw only if the edge is closed at this time
437 12 : if (std::find(ri->closed.begin(), ri->closed.end(), myEdge) != ri->closed.end()) {
438 12 : const int noLanes = (int)myFGPositions.size();
439 24 : for (int j = 0; j < noLanes; ++j) {
440 12 : Position pos = myFGPositions[j];
441 12 : double rot = myFGRotations[j];
442 12 : GLHelper::pushMatrix();
443 12 : glTranslated(pos.x(), pos.y(), 0);
444 12 : glRotated(rot, 0, 0, 1);
445 12 : glTranslated(0, -1.5, 0);
446 : int noPoints = 9;
447 12 : if (s.scale > 25) {
448 0 : noPoints = (int)(9.0 + s.scale / 10.0);
449 0 : if (noPoints > 36) {
450 : noPoints = 36;
451 : }
452 : }
453 12 : glTranslated(0, 0, getType());
454 : //glScaled(exaggeration, exaggeration, 1);
455 12 : glColor3d(0.7, 0, 0);
456 12 : GLHelper::drawFilledCircle((double) 1.3, noPoints);
457 12 : glTranslated(0, 0, .1);
458 12 : glColor3d(1, 0, 0);
459 12 : GLHelper::drawFilledCircle((double) 1.3, noPoints, 0, prob * 360);
460 12 : glTranslated(0, 0, .1);
461 12 : glColor3d(1, 1, 1);
462 12 : glRotated(-90, 0, 0, 1);
463 12 : glBegin(GL_TRIANGLES);
464 12 : glVertex2d(0 - .3, -1.);
465 12 : glVertex2d(0 - .3, 1.);
466 12 : glVertex2d(0 + .3, 1.);
467 12 : glVertex2d(0 + .3, -1.);
468 12 : glVertex2d(0 - .3, -1.);
469 12 : glVertex2d(0 + .3, 1.);
470 12 : glEnd();
471 12 : GLHelper::popMatrix();
472 : }
473 : }
474 : }
475 :
476 5017 : } else if (myEdgeType == REROUTER_TRIGGER_EDGE) {
477 : // draw rerouter symbol onto all lanes
478 12011 : for (int i = 0; i < (int)myFGPositions.size(); ++i) {
479 7186 : const Position& pos = myFGPositions[i];
480 7186 : double rot = myFGRotations[i];
481 7186 : const double w = myHalfWidths[i];
482 7186 : GLHelper::pushMatrix();
483 7186 : glTranslated(pos.x(), pos.y(), 0);
484 7186 : glRotated(rot, 0, 0, 1);
485 7186 : glTranslated(0, 0, getType());
486 7186 : glScaled(exaggeration, exaggeration, 1);
487 7186 : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
488 :
489 7186 : glBegin(GL_TRIANGLES);
490 7186 : glColor3d(1, .8f, 0);
491 : // base
492 7186 : glVertex2d(0 - w, 0);
493 7186 : glVertex2d(0 - w, 6);
494 7186 : glVertex2d(0 + w, 6);
495 7186 : glVertex2d(0 + w, 0);
496 7186 : glVertex2d(0 - w, 0);
497 7186 : glVertex2d(0 + w, 6);
498 7186 : glEnd();
499 :
500 : // draw "U"
501 14372 : GLHelper::drawText("U", Position(0, 2), .1, 3 * (w / 1.4), RGBColor::BLACK, 180);
502 :
503 : // draw Probability
504 21558 : GLHelper::drawText((toString((int)(prob * 100)) + "%").c_str(), Position(0, 4), .1, 0.7, RGBColor::BLACK, 180);
505 :
506 7186 : GLHelper::popMatrix();
507 : }
508 192 : } else if (myEdgeType == REROUTER_SWITCH_EDGE) {
509 : const RerouteInterval* const ri =
510 192 : myParent->getCurrentReroute(MSNet::getInstance()->getCurrentTimeStep());
511 192 : const double routeProb = ri != nullptr && prob > 0 ? ri->routeProbs.getProbs()[myDistIndex] / ri->routeProbs.getOverallProb() : 0;
512 192 : if (routeProb > 0) {
513 372 : for (int i = 0; i < (int)myFGPositions.size(); ++i) {
514 186 : const Position& pos = myFGPositions[i];
515 186 : double rot = myFGRotations[i];
516 186 : const double w = myHalfWidths[i];
517 186 : GLHelper::pushMatrix();
518 186 : glTranslated(pos.x(), pos.y(), 0);
519 186 : glRotated(rot, 0, 0, 1);
520 186 : glTranslated(0, 0, getType());
521 186 : glScaled(exaggeration, exaggeration, 1);
522 186 : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
523 :
524 186 : glBegin(GL_TRIANGLES);
525 186 : glColor3d(0, 1, 1);
526 : // base
527 186 : glVertex2d(0 - 0.0, 0);
528 186 : glVertex2d(0 - w, 6);
529 186 : glVertex2d(0 + w, 6);
530 186 : glVertex2d(0 + 0.0, 0);
531 186 : glVertex2d(0 + w, 6);
532 186 : glEnd();
533 :
534 : // draw "P"
535 372 : GLHelper::drawText("P", Position(0, 3.5), .1, 2, RGBColor::BLACK, 180);
536 :
537 : // draw Probability for this target edge
538 558 : GLHelper::drawText((toString((int)(routeProb * 100)) + "%").c_str(), Position(0, 5), .1, 0.7, RGBColor::BLACK, 180);
539 :
540 186 : GLHelper::popMatrix();
541 : }
542 : }
543 : }
544 5043 : GLHelper::popName();
545 : }
546 163686 : }
547 :
548 :
549 : double
550 163686 : GUITriggeredRerouter::GUITriggeredRerouterEdge::getExaggeration(const GUIVisualizationSettings& s) const {
551 163686 : return s.addSize.getExaggeration(s, this);
552 : }
553 :
554 :
555 : Boundary
556 2174 : GUITriggeredRerouter::GUITriggeredRerouterEdge::getCenteringBoundary() const {
557 : Boundary b(myBoundary);
558 2174 : b.grow(20);
559 2174 : return b;
560 0 : }
561 :
562 :
563 : void
564 0 : GUITriggeredRerouter::GUITriggeredRerouterEdge::onLeftBtnPress(void* /*data*/) {
565 0 : myParent->shiftProbs();
566 0 : }
567 :
568 :
569 : /****************************************************************************/
|