Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2025 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 : * GUITriggeredRerouter::GUITriggeredRerouterPopupMenu - methods
209 : * ----------------------------------------------------------------------- */
210 :
211 0 : GUITriggeredRerouter::GUITriggeredRerouterPopupMenu::GUITriggeredRerouterPopupMenu(
212 0 : GUIMainWindow& app, GUISUMOAbstractView& parent, GUIGlObject* o) :
213 0 : GUIGLObjectPopupMenu(app, parent, o) {}
214 :
215 :
216 0 : GUITriggeredRerouter::GUITriggeredRerouterPopupMenu::~GUITriggeredRerouterPopupMenu() {}
217 :
218 :
219 : long
220 0 : GUITriggeredRerouter::GUITriggeredRerouterPopupMenu::onCmdOpenManip(FXObject*,
221 : FXSelector,
222 : void*) {
223 0 : static_cast<GUITriggeredRerouter*>(myObject)->openManipulator(
224 0 : *myApplication, *myParent);
225 0 : return 1;
226 : }
227 :
228 : // -------------------------------------------------------------------------
229 : // GUITriggeredRerouter - methods
230 : // -------------------------------------------------------------------------
231 :
232 703 : GUITriggeredRerouter::GUITriggeredRerouter(const std::string& id, const MSEdgeVector& edges, double prob,
233 703 : bool off, bool optional, SUMOTime timeThreshold, const std::string& vTypes, const Position& pos, const double radius, SUMORTree& rtree) :
234 : MSTriggeredRerouter(id, edges, prob, off, optional, timeThreshold, vTypes, pos, radius),
235 : GUIGlObject_AbstractAdd(GLO_REROUTER, id, GUIIconSubSys::getIcon(GUIIcon::REROUTER)),
236 703 : myShiftProbDistIndex(0) {
237 : // add visualisation objects for edges which trigger the rerouter
238 1602 : for (MSEdgeVector::const_iterator it = edges.begin(); it != edges.end(); ++it) {
239 899 : myEdgeVisualizations.push_back(new GUITriggeredRerouterEdge(dynamic_cast<GUIEdge*>(*it), this, REROUTER_TRIGGER_EDGE, -1, pos, radius));
240 899 : rtree.addAdditionalGLObject(myEdgeVisualizations.back());
241 899 : myBoundary.add(myEdgeVisualizations.back()->getCenteringBoundary());
242 18 : if (pos != Position::INVALID && radius != std::numeric_limits<double>::max()) {
243 : break;
244 : }
245 : }
246 703 : }
247 :
248 :
249 1406 : GUITriggeredRerouter::~GUITriggeredRerouter() {
250 1841 : for (std::vector<GUITriggeredRerouterEdge*>::iterator it = myEdgeVisualizations.begin(); it != myEdgeVisualizations.end(); ++it) {
251 1138 : delete *it;
252 : }
253 : myEdgeVisualizations.clear();
254 1406 : }
255 :
256 :
257 : void
258 4487 : GUITriggeredRerouter::myEndElement(int element) {
259 4487 : MSTriggeredRerouter::myEndElement(element);
260 4487 : if (element == SUMO_TAG_INTERVAL) {
261 : // add visualisation objects for closed edges
262 : const RerouteInterval& ri = myIntervals.back();
263 919 : for (auto item : ri.getClosed()) {
264 214 : const GUIEdge* edge = dynamic_cast<const GUIEdge*>(item.first);
265 214 : myEdgeVisualizations.push_back(new GUITriggeredRerouterEdge(const_cast<GUIEdge*>(edge), this, REROUTER_CLOSED_EDGE));
266 214 : dynamic_cast<GUINet*>(GUINet::getInstance())->getVisualisationSpeedUp().addAdditionalGLObject(myEdgeVisualizations.back());
267 214 : myBoundary.add(myEdgeVisualizations.back()->getCenteringBoundary());
268 : }
269 : // add visualisation objects for switches
270 705 : if (ri.routeProbs.getProbs().size() > 1) {
271 : // find last common edge of all routes
272 : ConstMSRoutePtr route0 = ri.routeProbs.getVals()[0];
273 : const MSEdge* lastEdge = nullptr;
274 : int nextIndex = 0;
275 20 : for (int i = 0; i < (int)route0->getEdges().size(); i++) {
276 20 : const MSEdge* cand = route0->getEdges()[i];
277 74 : for (ConstMSRoutePtr route : ri.routeProbs.getVals()) {
278 54 : const MSEdge* nextEdge = i < (int)route->getEdges().size() ? route->getEdges()[i] : nullptr;
279 54 : if (nextEdge != cand) {
280 : cand = nullptr;
281 : }
282 : }
283 20 : if (cand != nullptr) {
284 : lastEdge = cand;
285 : } else {
286 : nextIndex = i;
287 : break;
288 : }
289 : }
290 9 : if (lastEdge != nullptr) {
291 9 : double maxProb = ri.routeProbs.getProbs()[myShiftProbDistIndex];
292 34 : for (int i = 0; i < (int)ri.routeProbs.getVals().size(); i++) {
293 25 : const ConstMSEdgeVector& edges = ri.routeProbs.getVals()[i]->getEdges();
294 25 : if (nextIndex < (int)edges.size()) {
295 25 : GUIEdge* edge = dynamic_cast<GUIEdge*>(const_cast<MSEdge*>(edges[nextIndex]));
296 25 : myEdgeVisualizations.push_back(new GUITriggeredRerouterEdge(edge, this, REROUTER_SWITCH_EDGE, i));
297 25 : dynamic_cast<GUINet*>(GUINet::getInstance())->getVisualisationSpeedUp().addAdditionalGLObject(myEdgeVisualizations.back());
298 25 : myBoundary.add(myEdgeVisualizations.back()->getCenteringBoundary());
299 : }
300 25 : double prob = ri.routeProbs.getProbs()[i];
301 25 : if (prob > maxProb) {
302 : maxProb = prob;
303 1 : myShiftProbDistIndex = i;
304 : }
305 : }
306 : }
307 : }
308 : }
309 4487 : }
310 :
311 :
312 : GUIGLObjectPopupMenu*
313 0 : GUITriggeredRerouter::getPopUpMenu(GUIMainWindow& app, GUISUMOAbstractView& parent) {
314 0 : GUIGLObjectPopupMenu* ret = new GUITriggeredRerouterPopupMenu(app, parent, this);
315 0 : buildPopupHeader(ret, app);
316 0 : buildCenterPopupEntry(ret);
317 0 : buildShowManipulatorPopupEntry(ret, false);
318 0 : buildNameCopyPopupEntry(ret);
319 0 : buildSelectionPopupEntry(ret);
320 0 : buildPositionCopyEntry(ret, app);
321 0 : return ret;
322 : }
323 :
324 :
325 : GUIParameterTableWindow*
326 0 : GUITriggeredRerouter::getParameterWindow(GUIMainWindow&,
327 : GUISUMOAbstractView&) {
328 0 : return nullptr;
329 : }
330 :
331 :
332 : void
333 0 : GUITriggeredRerouter::drawGL(const GUIVisualizationSettings& s) const {
334 : UNUSED_PARAMETER(s);
335 0 : }
336 :
337 :
338 : Boundary
339 0 : GUITriggeredRerouter::getCenteringBoundary() const {
340 : Boundary b(myBoundary);
341 0 : b.grow(20);
342 0 : return b;
343 : }
344 :
345 :
346 : double
347 0 : GUITriggeredRerouter::getExaggeration(const GUIVisualizationSettings& s) const {
348 0 : return s.addSize.getExaggeration(s, this);
349 : }
350 :
351 :
352 : GUIManipulator*
353 0 : GUITriggeredRerouter::openManipulator(GUIMainWindow& app,
354 : GUISUMOAbstractView&) {
355 0 : GUIManip_TriggeredRerouter* gui = new GUIManip_TriggeredRerouter(app, getFullName(), *this);
356 0 : gui->create();
357 0 : gui->show(PLACEMENT_SCREEN);
358 0 : return gui;
359 : }
360 :
361 :
362 : void
363 0 : GUITriggeredRerouter::shiftProbs() {
364 0 : const RerouteInterval* const ri = getCurrentReroute(MSNet::getInstance()->getCurrentTimeStep());
365 0 : if (ri != nullptr && ri->routeProbs.getProbs().size() > 1) {
366 0 : auto& rp = const_cast<RandomDistributor<ConstMSRoutePtr>&>(ri->routeProbs);
367 0 : double prob = rp.getProbs()[myShiftProbDistIndex];
368 0 : rp.add(rp.getVals()[myShiftProbDistIndex], -prob);
369 0 : myShiftProbDistIndex = (myShiftProbDistIndex + 1) % rp.getProbs().size();
370 0 : rp.add(rp.getVals()[myShiftProbDistIndex], prob);
371 : // notify vehicles currently on a trigger edge
372 0 : for (auto rrEdge : myEdgeVisualizations) {
373 0 : if (rrEdge->getRerouterEdgeType() == REROUTER_TRIGGER_EDGE) {
374 0 : if (!MSGlobals::gUseMesoSim) {
375 0 : for (MSLane* lane : rrEdge->getEdge()->getLanes()) {
376 0 : for (const MSVehicle* veh : lane->getVehiclesSecure()) {
377 0 : const_cast<MSVehicle*>(veh)->addReminder(this);
378 : }
379 0 : lane->releaseVehicles();
380 : }
381 : }
382 : }
383 : }
384 : }
385 0 : }
386 :
387 :
388 : /* -------------------------------------------------------------------------
389 : * GUITriggeredRerouterEdge - methods
390 : * ----------------------------------------------------------------------- */
391 1138 : GUITriggeredRerouter::GUITriggeredRerouterEdge::GUITriggeredRerouterEdge(GUIEdge* edge, GUITriggeredRerouter* parent, RerouterEdgeType edgeType, int distIndex,
392 1138 : const Position& pos, const double radius) :
393 1138 : GUIGlObject(GLO_REROUTER_EDGE, parent->getID() + ":" + edge->getID(), GUIIconSubSys::getIcon(GUIIcon::REROUTER)),
394 1138 : myParent(parent),
395 1138 : myEdge(edge),
396 1138 : myEdgeType(edgeType),
397 3414 : myDistIndex(distIndex) {
398 : const std::vector<MSLane*>& lanes = edge->getLanes();
399 18 : if (pos == Position::INVALID || radius == std::numeric_limits<double>::max()) {
400 2382 : for (const MSLane* lane : lanes) {
401 1244 : if ((lane->getPermissions() & ~SVC_PEDESTRIAN) == 0) {
402 29 : continue;
403 : }
404 : const PositionVector& v = lane->getShape();
405 : double lanePos;
406 : double centerPos;
407 1215 : switch (edgeType) {
408 974 : case REROUTER_TRIGGER_EDGE:
409 : // U sign at end of edge
410 : // (note: symbol is drawn downstream of lanePos and extends 6m)
411 974 : lanePos = MAX2(0.0, v.length() - 10);
412 974 : centerPos = MIN2(lanePos + 3, v.length());
413 : break;
414 : case REROUTER_SWITCH_EDGE:
415 : // triangle with switch probability
416 : lanePos = 0;
417 : centerPos = lanePos;
418 : break;
419 216 : default:
420 : // closing sign on start of edge
421 216 : lanePos = MIN2(v.length(), 3.0);
422 216 : centerPos = MIN2(lanePos + 3, v.length());
423 : }
424 1215 : myFGPositions.push_back(v.positionAtOffset(lanePos));
425 1215 : myFGRotations.push_back(-v.rotationDegreeAtOffset(lanePos));
426 1215 : myBoundary.add(v.positionAtOffset(centerPos));
427 1215 : myHalfWidths.push_back(lane->getWidth() * 0.5 * 0.875);
428 : }
429 : } else {
430 0 : myFGPositions.push_back(pos);
431 0 : const PositionVector& v = lanes.front()->getShape();
432 0 : myFGRotations.push_back(-v.rotationDegreeAtOffset(lanes.front()->getLength()));
433 0 : myBoundary.add(myFGPositions.back());
434 0 : myHalfWidths.push_back(SUMO_const_halfLaneWidth * 0.875);
435 : }
436 1138 : }
437 :
438 :
439 2276 : GUITriggeredRerouter::GUITriggeredRerouterEdge::~GUITriggeredRerouterEdge() {}
440 :
441 :
442 : GUIGLObjectPopupMenu*
443 0 : GUITriggeredRerouter::GUITriggeredRerouterEdge::getPopUpMenu(GUIMainWindow& app,
444 : GUISUMOAbstractView& parent) {
445 0 : return myParent->getPopUpMenu(app, parent);
446 : }
447 :
448 :
449 : GUIParameterTableWindow*
450 0 : GUITriggeredRerouter::GUITriggeredRerouterEdge::getParameterWindow(GUIMainWindow&,
451 : GUISUMOAbstractView&) {
452 0 : return nullptr;
453 : }
454 :
455 :
456 : void
457 201673 : GUITriggeredRerouter::GUITriggeredRerouterEdge::drawGL(const GUIVisualizationSettings& s) const {
458 201673 : const double exaggeration = getExaggeration(s);
459 201673 : if (s.scale * exaggeration >= 3) {
460 5375 : GLHelper::pushName(getGlID());
461 5375 : const double prob = myParent->getProbability();
462 5375 : if (myEdgeType == REROUTER_CLOSED_EDGE) {
463 : // draw closing symbol onto all lanes
464 : const RerouteInterval* const ri =
465 42 : myParent->getCurrentReroute(MSNet::getInstance()->getCurrentTimeStep());
466 42 : if (ri != nullptr && prob > 0) {
467 : // draw only if the edge is closed at this time
468 17 : const auto& closedEdges = ri->getClosed();
469 17 : if (closedEdges.find(myEdge) != closedEdges.end()) {
470 17 : const int noLanes = (int)myFGPositions.size();
471 34 : for (int j = 0; j < noLanes; ++j) {
472 17 : Position pos = myFGPositions[j];
473 17 : double rot = myFGRotations[j];
474 17 : GLHelper::pushMatrix();
475 17 : glTranslated(pos.x(), pos.y(), 0);
476 17 : glRotated(rot, 0, 0, 1);
477 17 : glTranslated(0, -1.5, 0);
478 : int noPoints = 9;
479 17 : if (s.scale > 25) {
480 0 : noPoints = (int)(9.0 + s.scale / 10.0);
481 0 : if (noPoints > 36) {
482 : noPoints = 36;
483 : }
484 : }
485 17 : glTranslated(0, 0, getType());
486 : //glScaled(exaggeration, exaggeration, 1);
487 17 : glColor3d(0.7, 0, 0);
488 17 : GLHelper::drawFilledCircle((double) 1.3, noPoints);
489 17 : glTranslated(0, 0, .1);
490 17 : glColor3d(1, 0, 0);
491 17 : GLHelper::drawFilledCircle((double) 1.3, noPoints, 0, prob * 360);
492 17 : glTranslated(0, 0, .1);
493 17 : glColor3d(1, 1, 1);
494 17 : glRotated(-90, 0, 0, 1);
495 17 : glBegin(GL_TRIANGLES);
496 17 : glVertex2d(0 - .3, -1.);
497 17 : glVertex2d(0 - .3, 1.);
498 17 : glVertex2d(0 + .3, 1.);
499 17 : glVertex2d(0 + .3, -1.);
500 17 : glVertex2d(0 - .3, -1.);
501 17 : glVertex2d(0 + .3, 1.);
502 17 : glEnd();
503 17 : GLHelper::popMatrix();
504 : }
505 : }
506 : }
507 :
508 5333 : } else if (myEdgeType == REROUTER_TRIGGER_EDGE) {
509 : // draw rerouter symbol onto all lanes
510 11397 : for (int i = 0; i < (int)myFGPositions.size(); ++i) {
511 6532 : const Position& pos = myFGPositions[i];
512 6532 : double rot = myFGRotations[i];
513 6532 : const double w = myHalfWidths[i];
514 6532 : GLHelper::pushMatrix();
515 6532 : glTranslated(pos.x(), pos.y(), 0);
516 6532 : glRotated(rot, 0, 0, 1);
517 : // draw the symbol downstream of pos (without touching the older drawing code)
518 6532 : glTranslated(0, -6, 0);
519 6532 : glTranslated(0, 0, getType());
520 6532 : glScaled(exaggeration, exaggeration, 1);
521 6532 : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
522 :
523 6532 : glBegin(GL_TRIANGLES);
524 6532 : glColor3d(1, .8f, 0);
525 : // base
526 6532 : glVertex2d(0 - w, 0);
527 6532 : glVertex2d(0 - w, 6);
528 6532 : glVertex2d(0 + w, 6);
529 6532 : glVertex2d(0 + w, 0);
530 6532 : glVertex2d(0 - w, 0);
531 6532 : glVertex2d(0 + w, 6);
532 6532 : glEnd();
533 :
534 : // draw "U"
535 13064 : GLHelper::drawText("U", Position(0, 2), .1, 3 * (w / 1.4), RGBColor::BLACK, 180);
536 :
537 : // draw Probability
538 13064 : GLHelper::drawText((toString((int)(prob * 100)) + "%").c_str(), Position(0, 4), .1, 0.7, RGBColor::BLACK, 180);
539 :
540 6532 : GLHelper::popMatrix();
541 : }
542 468 : } else if (myEdgeType == REROUTER_SWITCH_EDGE) {
543 : const RerouteInterval* const ri =
544 468 : myParent->getCurrentReroute(MSNet::getInstance()->getCurrentTimeStep());
545 468 : const double routeProb = ri != nullptr && prob > 0 ? ri->routeProbs.getProbs()[myDistIndex] / ri->routeProbs.getOverallProb() : 0;
546 468 : if (routeProb > 0) {
547 924 : for (int i = 0; i < (int)myFGPositions.size(); ++i) {
548 462 : const Position& pos = myFGPositions[i];
549 462 : double rot = myFGRotations[i];
550 462 : const double w = myHalfWidths[i];
551 462 : GLHelper::pushMatrix();
552 462 : glTranslated(pos.x(), pos.y(), 0);
553 462 : glRotated(rot, 0, 0, 1);
554 462 : glTranslated(0, 0, getType());
555 462 : glScaled(exaggeration, exaggeration, 1);
556 462 : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
557 :
558 462 : glBegin(GL_TRIANGLES);
559 462 : glColor3d(0, 1, 1);
560 : // base
561 462 : glVertex2d(0 - 0.0, 0);
562 462 : glVertex2d(0 - w, 6);
563 462 : glVertex2d(0 + w, 6);
564 462 : glVertex2d(0 + 0.0, 0);
565 462 : glVertex2d(0 + w, 6);
566 462 : glEnd();
567 :
568 : // draw "P"
569 924 : GLHelper::drawText("P", Position(0, 3.5), .1, 2, RGBColor::BLACK, 180);
570 :
571 : // draw Probability for this target edge
572 924 : GLHelper::drawText((toString((int)(routeProb * 100)) + "%").c_str(), Position(0, 5), .1, 0.7, RGBColor::BLACK, 180);
573 :
574 462 : GLHelper::popMatrix();
575 : }
576 : }
577 : }
578 5375 : GLHelper::popName();
579 : }
580 201673 : if (myEdgeType == REROUTER_TRIGGER_EDGE && s.addName.show(myParent)) {
581 0 : GLHelper::drawTextSettings(s.addName, myParent->getMicrosimID(), myFGPositions.back(), s.scale, s.angle);
582 : }
583 201673 : }
584 :
585 :
586 : double
587 201673 : GUITriggeredRerouter::GUITriggeredRerouterEdge::getExaggeration(const GUIVisualizationSettings& s) const {
588 201673 : return s.addSize.getExaggeration(s, this);
589 : }
590 :
591 :
592 : Boundary
593 2276 : GUITriggeredRerouter::GUITriggeredRerouterEdge::getCenteringBoundary() const {
594 : Boundary b(myBoundary);
595 2276 : b.grow(20);
596 2276 : return b;
597 : }
598 :
599 :
600 : void
601 0 : GUITriggeredRerouter::GUITriggeredRerouterEdge::onLeftBtnPress(void* /*data*/) {
602 0 : myParent->shiftProbs();
603 0 : }
604 :
605 :
606 : /****************************************************************************/
|