Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/guisim/GUITriggeredRerouter.cpp
193874 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-2026 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
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
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
GUITriggeredRerouter::GUIManip_TriggeredRerouter::GUIManip_TriggeredRerouter(
88
GUIMainWindow& app, const std::string& name, GUITriggeredRerouter& o) :
89
GUIManipulator(app, name, 0, 0), myParent(&app),
90
myChosenValue(0), myChosenTarget(myChosenValue, nullptr, MID_OPTION),
91
myUsageProbability(o.getProbability()), myUsageProbabilityTarget(myUsageProbability),
92
myObject(&o) {
93
myChosenTarget.setTarget(this);
94
FXVerticalFrame* f1 =
95
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, 4, 4, 1, 1, 2, 0);
100
{
101
// default
102
FXHorizontalFrame* gf1 =
103
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, 2, 2, 0, 0);
107
}
108
{
109
// free
110
FXHorizontalFrame* gf12 =
111
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, 2, 2, 0, 0);
115
myUsageProbabilityDial =
116
new FXRealSpinner(gf12, 10, this, MID_USER_DEF,
117
LAYOUT_TOP | FRAME_SUNKEN | FRAME_THICK);
118
//myUsageProbabilityDial->setFormatString("%.2f");
119
//myUsageProbabilityDial->setIncrements(.1, .1, .1);
120
myUsageProbabilityDial->setIncrement(.1);
121
myUsageProbabilityDial->setRange(0, 1);
122
myUsageProbabilityDial->setValue(myObject->getUserProbability());
123
}
124
{
125
// off
126
FXHorizontalFrame* gf13 =
127
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, 2, 2, 0, 0);
131
}
132
myChosenValue = myObject->inUserMode()
133
? myObject->getUserProbability() > 0
134
? 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, 4, 4, 1, 1, 2, 0);
140
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
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
}
147
148
149
GUITriggeredRerouter::GUIManip_TriggeredRerouter::~GUIManip_TriggeredRerouter() {}
150
151
152
long
153
GUITriggeredRerouter::GUIManip_TriggeredRerouter::onCmdClose(FXObject*, FXSelector, void*) {
154
destroy();
155
return 1;
156
}
157
158
159
long
160
GUITriggeredRerouter::GUIManip_TriggeredRerouter::onCmdUserDef(FXObject*, FXSelector, void*) {
161
myUsageProbability = (double)(myUsageProbabilityDial->getValue());
162
static_cast<GUITriggeredRerouter*>(myObject)->setUserUsageProbability(myUsageProbability);
163
static_cast<GUITriggeredRerouter*>(myObject)->setUserMode(true);
164
myParent->updateChildren();
165
return 1;
166
}
167
168
169
long
170
GUITriggeredRerouter::GUIManip_TriggeredRerouter::onUpdUserDef(FXObject* sender, FXSelector, void* ptr) {
171
sender->handle(this,
172
myChosenValue != 1 ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
173
ptr);
174
myParent->updateChildren();
175
return 1;
176
}
177
178
179
long
180
GUITriggeredRerouter::GUIManip_TriggeredRerouter::onCmdChangeOption(FXObject*, FXSelector, void*) {
181
static_cast<GUITriggeredRerouter*>(myObject)->setUserUsageProbability(myUsageProbability);
182
switch (myChosenValue) {
183
case 0:
184
static_cast<GUITriggeredRerouter*>(myObject)->setUserMode(false);
185
break;
186
case 1:
187
static_cast<GUITriggeredRerouter*>(myObject)->setUserMode(true);
188
break;
189
case 2:
190
static_cast<GUITriggeredRerouter*>(myObject)->setUserUsageProbability(0);
191
static_cast<GUITriggeredRerouter*>(myObject)->setUserMode(true);
192
break;
193
default:
194
throw 1;
195
}
196
myParent->updateChildren();
197
return 1;
198
}
199
200
long
201
GUITriggeredRerouter::GUIManip_TriggeredRerouter::onCmdShiftProbs(FXObject*, FXSelector, void*) {
202
static_cast<GUITriggeredRerouter*>(myObject)->shiftProbs();
203
myParent->updateChildren();
204
return 1;
205
}
206
207
/* -------------------------------------------------------------------------
208
* GUITriggeredRerouter::GUITriggeredRerouterPopupMenu - methods
209
* ----------------------------------------------------------------------- */
210
211
GUITriggeredRerouter::GUITriggeredRerouterPopupMenu::GUITriggeredRerouterPopupMenu(
212
GUIMainWindow& app, GUISUMOAbstractView& parent, GUIGlObject* o) :
213
GUIGLObjectPopupMenu(app, parent, o) {}
214
215
216
GUITriggeredRerouter::GUITriggeredRerouterPopupMenu::~GUITriggeredRerouterPopupMenu() {}
217
218
219
long
220
GUITriggeredRerouter::GUITriggeredRerouterPopupMenu::onCmdOpenManip(FXObject*,
221
FXSelector,
222
void*) {
223
static_cast<GUITriggeredRerouter*>(myObject)->openManipulator(
224
*myApplication, *myParent);
225
return 1;
226
}
227
228
// -------------------------------------------------------------------------
229
// GUITriggeredRerouter - methods
230
// -------------------------------------------------------------------------
231
232
GUITriggeredRerouter::GUITriggeredRerouter(const std::string& id, const MSEdgeVector& edges, double prob,
233
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
myShiftProbDistIndex(0) {
237
// add visualisation objects for edges which trigger the rerouter
238
for (MSEdgeVector::const_iterator it = edges.begin(); it != edges.end(); ++it) {
239
myEdgeVisualizations.push_back(new GUITriggeredRerouterEdge(dynamic_cast<GUIEdge*>(*it), this, REROUTER_TRIGGER_EDGE, -1, pos, radius));
240
rtree.addAdditionalGLObject(myEdgeVisualizations.back());
241
myBoundary.add(myEdgeVisualizations.back()->getCenteringBoundary());
242
if (pos != Position::INVALID && radius != std::numeric_limits<double>::max()) {
243
break;
244
}
245
}
246
}
247
248
249
GUITriggeredRerouter::~GUITriggeredRerouter() {
250
for (std::vector<GUITriggeredRerouterEdge*>::iterator it = myEdgeVisualizations.begin(); it != myEdgeVisualizations.end(); ++it) {
251
delete *it;
252
}
253
myEdgeVisualizations.clear();
254
}
255
256
257
void
258
GUITriggeredRerouter::myEndElement(int element) {
259
MSTriggeredRerouter::myEndElement(element);
260
if (element == SUMO_TAG_INTERVAL) {
261
// add visualisation objects for closed edges
262
const RerouteInterval& ri = myIntervals.back();
263
for (auto item : ri.getClosed()) {
264
const GUIEdge* edge = dynamic_cast<const GUIEdge*>(item.first);
265
myEdgeVisualizations.push_back(new GUITriggeredRerouterEdge(const_cast<GUIEdge*>(edge), this, REROUTER_CLOSED_EDGE));
266
dynamic_cast<GUINet*>(GUINet::getInstance())->getVisualisationSpeedUp().addAdditionalGLObject(myEdgeVisualizations.back());
267
myBoundary.add(myEdgeVisualizations.back()->getCenteringBoundary());
268
}
269
// add visualisation objects for switches
270
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
for (int i = 0; i < (int)route0->getEdges().size(); i++) {
276
const MSEdge* cand = route0->getEdges()[i];
277
for (ConstMSRoutePtr route : ri.routeProbs.getVals()) {
278
const MSEdge* nextEdge = i < (int)route->getEdges().size() ? route->getEdges()[i] : nullptr;
279
if (nextEdge != cand) {
280
cand = nullptr;
281
}
282
}
283
if (cand != nullptr) {
284
lastEdge = cand;
285
} else {
286
nextIndex = i;
287
break;
288
}
289
}
290
if (lastEdge != nullptr) {
291
double maxProb = ri.routeProbs.getProbs()[myShiftProbDistIndex];
292
for (int i = 0; i < (int)ri.routeProbs.getVals().size(); i++) {
293
const ConstMSEdgeVector& edges = ri.routeProbs.getVals()[i]->getEdges();
294
if (nextIndex < (int)edges.size()) {
295
GUIEdge* edge = dynamic_cast<GUIEdge*>(const_cast<MSEdge*>(edges[nextIndex]));
296
myEdgeVisualizations.push_back(new GUITriggeredRerouterEdge(edge, this, REROUTER_SWITCH_EDGE, i));
297
dynamic_cast<GUINet*>(GUINet::getInstance())->getVisualisationSpeedUp().addAdditionalGLObject(myEdgeVisualizations.back());
298
myBoundary.add(myEdgeVisualizations.back()->getCenteringBoundary());
299
}
300
double prob = ri.routeProbs.getProbs()[i];
301
if (prob > maxProb) {
302
maxProb = prob;
303
myShiftProbDistIndex = i;
304
}
305
}
306
}
307
}
308
}
309
}
310
311
312
GUIGLObjectPopupMenu*
313
GUITriggeredRerouter::getPopUpMenu(GUIMainWindow& app, GUISUMOAbstractView& parent) {
314
GUIGLObjectPopupMenu* ret = new GUITriggeredRerouterPopupMenu(app, parent, this);
315
buildPopupHeader(ret, app);
316
buildCenterPopupEntry(ret);
317
buildShowManipulatorPopupEntry(ret, false);
318
buildNameCopyPopupEntry(ret);
319
buildSelectionPopupEntry(ret);
320
buildPositionCopyEntry(ret, app);
321
return ret;
322
}
323
324
325
GUIParameterTableWindow*
326
GUITriggeredRerouter::getParameterWindow(GUIMainWindow&,
327
GUISUMOAbstractView&) {
328
return nullptr;
329
}
330
331
332
void
333
GUITriggeredRerouter::drawGL(const GUIVisualizationSettings& s) const {
334
UNUSED_PARAMETER(s);
335
}
336
337
338
Boundary
339
GUITriggeredRerouter::getCenteringBoundary() const {
340
Boundary b(myBoundary);
341
b.grow(20);
342
return b;
343
}
344
345
346
double
347
GUITriggeredRerouter::getExaggeration(const GUIVisualizationSettings& s) const {
348
return s.addSize.getExaggeration(s, this);
349
}
350
351
352
GUIManipulator*
353
GUITriggeredRerouter::openManipulator(GUIMainWindow& app,
354
GUISUMOAbstractView&) {
355
GUIManip_TriggeredRerouter* gui = new GUIManip_TriggeredRerouter(app, getFullName(), *this);
356
gui->create();
357
gui->show(PLACEMENT_SCREEN);
358
return gui;
359
}
360
361
362
void
363
GUITriggeredRerouter::shiftProbs() {
364
const RerouteInterval* const ri = getCurrentReroute(MSNet::getInstance()->getCurrentTimeStep());
365
if (ri != nullptr && ri->routeProbs.getProbs().size() > 1) {
366
auto& rp = const_cast<RandomDistributor<ConstMSRoutePtr>&>(ri->routeProbs);
367
double prob = rp.getProbs()[myShiftProbDistIndex];
368
rp.add(rp.getVals()[myShiftProbDistIndex], -prob);
369
myShiftProbDistIndex = (myShiftProbDistIndex + 1) % rp.getProbs().size();
370
rp.add(rp.getVals()[myShiftProbDistIndex], prob);
371
// notify vehicles currently on a trigger edge
372
for (auto rrEdge : myEdgeVisualizations) {
373
if (rrEdge->getRerouterEdgeType() == REROUTER_TRIGGER_EDGE) {
374
if (!MSGlobals::gUseMesoSim) {
375
for (MSLane* lane : rrEdge->getEdge()->getLanes()) {
376
for (const MSVehicle* veh : lane->getVehiclesSecure()) {
377
const_cast<MSVehicle*>(veh)->addReminder(this);
378
}
379
lane->releaseVehicles();
380
}
381
}
382
}
383
}
384
}
385
}
386
387
388
/* -------------------------------------------------------------------------
389
* GUITriggeredRerouterEdge - methods
390
* ----------------------------------------------------------------------- */
391
GUITriggeredRerouter::GUITriggeredRerouterEdge::GUITriggeredRerouterEdge(GUIEdge* edge, GUITriggeredRerouter* parent, RerouterEdgeType edgeType, int distIndex,
392
const Position& pos, const double radius) :
393
GUIGlObject(GLO_REROUTER_EDGE, parent->getID() + ":" + edge->getID(), GUIIconSubSys::getIcon(GUIIcon::REROUTER)),
394
myParent(parent),
395
myEdge(edge),
396
myEdgeType(edgeType),
397
myDistIndex(distIndex) {
398
const std::vector<MSLane*>& lanes = edge->getLanes();
399
if (pos == Position::INVALID || radius == std::numeric_limits<double>::max()) {
400
for (const MSLane* lane : lanes) {
401
if ((lane->getPermissions() & ~SVC_PEDESTRIAN) == 0) {
402
continue;
403
}
404
const PositionVector& v = lane->getShape();
405
double lanePos;
406
double centerPos;
407
switch (edgeType) {
408
case REROUTER_TRIGGER_EDGE:
409
// U sign at end of edge
410
// (note: symbol is drawn downstream of lanePos and extends 6m)
411
lanePos = MAX2(0.0, v.length() - 10);
412
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
default:
420
// closing sign on start of edge
421
lanePos = MIN2(v.length(), 3.0);
422
centerPos = MIN2(lanePos + 3, v.length());
423
}
424
myFGPositions.push_back(v.positionAtOffset(lanePos));
425
myFGRotations.push_back(-v.rotationDegreeAtOffset(lanePos));
426
myBoundary.add(v.positionAtOffset(centerPos));
427
myHalfWidths.push_back(lane->getWidth() * 0.5 * 0.875);
428
}
429
} else {
430
myFGPositions.push_back(pos);
431
const PositionVector& v = lanes.front()->getShape();
432
myFGRotations.push_back(-v.rotationDegreeAtOffset(lanes.front()->getLength()));
433
myBoundary.add(myFGPositions.back());
434
myHalfWidths.push_back(SUMO_const_halfLaneWidth * 0.875);
435
}
436
}
437
438
439
GUITriggeredRerouter::GUITriggeredRerouterEdge::~GUITriggeredRerouterEdge() {}
440
441
442
GUIGLObjectPopupMenu*
443
GUITriggeredRerouter::GUITriggeredRerouterEdge::getPopUpMenu(GUIMainWindow& app,
444
GUISUMOAbstractView& parent) {
445
return myParent->getPopUpMenu(app, parent);
446
}
447
448
449
GUIParameterTableWindow*
450
GUITriggeredRerouter::GUITriggeredRerouterEdge::getParameterWindow(GUIMainWindow&,
451
GUISUMOAbstractView&) {
452
return nullptr;
453
}
454
455
456
void
457
GUITriggeredRerouter::GUITriggeredRerouterEdge::drawGL(const GUIVisualizationSettings& s) const {
458
const double exaggeration = getExaggeration(s);
459
if (s.scale * exaggeration >= 3) {
460
GLHelper::pushName(getGlID());
461
const double prob = myParent->getProbability();
462
if (myEdgeType == REROUTER_CLOSED_EDGE) {
463
// draw closing symbol onto all lanes
464
const RerouteInterval* const ri =
465
myParent->getCurrentReroute(MSNet::getInstance()->getCurrentTimeStep());
466
if (ri != nullptr && prob > 0) {
467
// draw only if the edge is closed at this time
468
const auto& closedEdges = ri->getClosed();
469
if (closedEdges.find(myEdge) != closedEdges.end()) {
470
const int noLanes = (int)myFGPositions.size();
471
for (int j = 0; j < noLanes; ++j) {
472
Position pos = myFGPositions[j];
473
double rot = myFGRotations[j];
474
GLHelper::pushMatrix();
475
glTranslated(pos.x(), pos.y(), 0);
476
glRotated(rot, 0, 0, 1);
477
glTranslated(0, -1.5, 0);
478
int noPoints = 9;
479
if (s.scale > 25) {
480
noPoints = (int)(9.0 + s.scale / 10.0);
481
if (noPoints > 36) {
482
noPoints = 36;
483
}
484
}
485
glTranslated(0, 0, getType());
486
glScaled(exaggeration, exaggeration, 1);
487
glColor3d(0.7, 0, 0);
488
GLHelper::drawFilledCircle((double) 1.3, noPoints);
489
glTranslated(0, 0, .1);
490
glColor3d(1, 0, 0);
491
GLHelper::drawFilledCircle((double) 1.3, noPoints, 0, prob * 360);
492
glTranslated(0, 0, .1);
493
glColor3d(1, 1, 1);
494
glRotated(-90, 0, 0, 1);
495
glBegin(GL_TRIANGLES);
496
glVertex2d(0 - .3, -1.);
497
glVertex2d(0 - .3, 1.);
498
glVertex2d(0 + .3, 1.);
499
glVertex2d(0 + .3, -1.);
500
glVertex2d(0 - .3, -1.);
501
glVertex2d(0 + .3, 1.);
502
glEnd();
503
GLHelper::popMatrix();
504
}
505
}
506
}
507
508
} else if (myEdgeType == REROUTER_TRIGGER_EDGE) {
509
// draw rerouter symbol onto all lanes
510
for (int i = 0; i < (int)myFGPositions.size(); ++i) {
511
const Position& pos = myFGPositions[i];
512
double rot = myFGRotations[i];
513
const double w = myHalfWidths[i];
514
GLHelper::pushMatrix();
515
glTranslated(pos.x(), pos.y(), 0);
516
glRotated(rot, 0, 0, 1);
517
// draw the symbol downstream of pos (without touching the older drawing code)
518
glTranslated(0, -6, 0);
519
glTranslated(0, 0, getType());
520
glScaled(exaggeration, exaggeration, 1);
521
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
522
523
glBegin(GL_TRIANGLES);
524
glColor3d(1, .8f, 0);
525
// base
526
glVertex2d(0 - w, 0);
527
glVertex2d(0 - w, 6);
528
glVertex2d(0 + w, 6);
529
glVertex2d(0 + w, 0);
530
glVertex2d(0 - w, 0);
531
glVertex2d(0 + w, 6);
532
glEnd();
533
534
// draw "U"
535
GLHelper::drawText("U", Position(0, 2), .1, 3 * (w / 1.4), RGBColor::BLACK, 180);
536
537
// draw Probability
538
GLHelper::drawText((toString((int)(prob * 100)) + "%").c_str(), Position(0, 4), .1, 0.7, RGBColor::BLACK, 180);
539
540
GLHelper::popMatrix();
541
}
542
} else if (myEdgeType == REROUTER_SWITCH_EDGE) {
543
const RerouteInterval* const ri =
544
myParent->getCurrentReroute(MSNet::getInstance()->getCurrentTimeStep());
545
const double routeProb = ri != nullptr && prob > 0 ? ri->routeProbs.getProbs()[myDistIndex] / ri->routeProbs.getOverallProb() : 0;
546
if (routeProb > 0) {
547
for (int i = 0; i < (int)myFGPositions.size(); ++i) {
548
const Position& pos = myFGPositions[i];
549
double rot = myFGRotations[i];
550
const double w = myHalfWidths[i];
551
GLHelper::pushMatrix();
552
glTranslated(pos.x(), pos.y(), 0);
553
glRotated(rot, 0, 0, 1);
554
glTranslated(0, 0, getType());
555
glScaled(exaggeration, exaggeration, 1);
556
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
557
558
glBegin(GL_TRIANGLES);
559
glColor3d(0, 1, 1);
560
// base
561
glVertex2d(0 - 0.0, 0);
562
glVertex2d(0 - w, 6);
563
glVertex2d(0 + w, 6);
564
glVertex2d(0 + 0.0, 0);
565
glVertex2d(0 + w, 6);
566
glEnd();
567
568
// draw "P"
569
GLHelper::drawText("P", Position(0, 3.5), .1, 2, RGBColor::BLACK, 180);
570
571
// draw Probability for this target edge
572
GLHelper::drawText((toString((int)(routeProb * 100)) + "%").c_str(), Position(0, 5), .1, 0.7, RGBColor::BLACK, 180);
573
574
GLHelper::popMatrix();
575
}
576
}
577
}
578
GLHelper::popName();
579
}
580
if (myEdgeType == REROUTER_TRIGGER_EDGE && s.addName.show(myParent)) {
581
GLHelper::drawTextSettings(s.addName, myParent->getMicrosimID(), myFGPositions.back(), s.scale, s.angle);
582
}
583
}
584
585
586
double
587
GUITriggeredRerouter::GUITriggeredRerouterEdge::getExaggeration(const GUIVisualizationSettings& s) const {
588
return s.addSize.getExaggeration(s, this);
589
}
590
591
592
Boundary
593
GUITriggeredRerouter::GUITriggeredRerouterEdge::getCenteringBoundary() const {
594
Boundary b(myBoundary);
595
b.grow(20);
596
return b;
597
}
598
599
600
void
601
GUITriggeredRerouter::GUITriggeredRerouterEdge::onLeftBtnPress(void* /*data*/) {
602
myParent->shiftProbs();
603
}
604
605
606
/****************************************************************************/
607
608