Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/guisim/GUIContainer.cpp
169666 views
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 GUIContainer.cpp
15
/// @author Melanie Weber
16
/// @author Andreas Kendziorra
17
/// @date Wed, 01.08.2014
18
///
19
// A MSContainer extended by some values for usage within the gui
20
/****************************************************************************/
21
#include <config.h>
22
23
#include <cmath>
24
#include <vector>
25
#include <string>
26
#include <microsim/logging/CastingFunctionBinding.h>
27
#include <microsim/logging/FunctionBinding.h>
28
#include <microsim/MSLane.h>
29
#include <microsim/MSVehicleControl.h>
30
#include <microsim/lcmodels/MSAbstractLaneChangeModel.h>
31
#include <microsim/devices/MSDevice_Vehroutes.h>
32
#include <utils/common/MsgHandler.h>
33
#include <utils/common/StringUtils.h>
34
#include <utils/vehicle/SUMOVehicleParameter.h>
35
#include <utils/geom/GeomHelper.h>
36
#include <utils/gui/images/GUITexturesHelper.h>
37
#include <utils/gui/windows/GUISUMOAbstractView.h>
38
#include <utils/gui/windows/GUIAppEnum.h>
39
#include <utils/gui/div/GUIParameterTableWindow.h>
40
#include <utils/gui/div/GUIGlobalSelection.h>
41
#include <utils/gui/div/GLHelper.h>
42
#include <utils/gui/div/GLObjectValuePassConnector.h>
43
#include <utils/geom/PositionVector.h>
44
#include <gui/GUIApplicationWindow.h>
45
#include <gui/GUIGlobals.h>
46
#include <utils/gui/globjects/GLIncludes.h>
47
#include <utils/gui/div/GUIDesigns.h>
48
49
#include "GUIContainer.h"
50
#include "GUINet.h"
51
#include "GUIEdge.h"
52
53
//#define GUIContainer_DEBUG_DRAW_WALKING_AREA_SHAPE
54
55
// ===========================================================================
56
// FOX callback mapping
57
// ===========================================================================
58
FXDEFMAP(GUIContainer::GUIContainerPopupMenu) GUIContainerPopupMenuMap[] = {
59
FXMAPFUNC(SEL_COMMAND, MID_START_TRACK, GUIContainer::GUIContainerPopupMenu::onCmdStartTrack),
60
FXMAPFUNC(SEL_COMMAND, MID_STOP_TRACK, GUIContainer::GUIContainerPopupMenu::onCmdStopTrack),
61
FXMAPFUNC(SEL_COMMAND, MID_SHOWPLAN, GUIContainer::GUIContainerPopupMenu::onCmdShowPlan),
62
};
63
64
// Object implementation
65
FXIMPLEMENT(GUIContainer::GUIContainerPopupMenu, GUIGLObjectPopupMenu, GUIContainerPopupMenuMap, ARRAYNUMBER(GUIContainerPopupMenuMap))
66
67
#define WATER_WAY_OFFSET 6.0
68
69
// ===========================================================================
70
// method definitions
71
// ===========================================================================
72
/* -------------------------------------------------------------------------
73
* GUIContainer::GUIContainerPopupMenu - methods
74
* ----------------------------------------------------------------------- */
75
GUIContainer::GUIContainerPopupMenu::GUIContainerPopupMenu(
76
GUIMainWindow& app, GUISUMOAbstractView& parent, GUIGlObject* o) :
77
GUIGLObjectPopupMenu(app, parent, o) {
78
}
79
80
81
GUIContainer::GUIContainerPopupMenu::~GUIContainerPopupMenu() {}
82
83
84
long
85
GUIContainer::GUIContainerPopupMenu::onCmdShowPlan(FXObject*, FXSelector, void*) {
86
GUIContainer* p = dynamic_cast<GUIContainer*>(myObject);
87
if (p == nullptr) {
88
return 1;
89
}
90
GUIParameterTableWindow* ret = new GUIParameterTableWindow(*myApplication, *p);
91
// add items
92
for (int stage = 1; stage < p->getNumStages(); stage++) {
93
ret->mkItem(toString(stage).c_str(), false, p->getStageSummary(stage));
94
}
95
// close building (use an object that is not Parameterised as argument)
96
Parameterised dummy;
97
ret->closeBuilding(&dummy);
98
return 1;
99
}
100
101
102
long
103
GUIContainer::GUIContainerPopupMenu::onCmdStartTrack(FXObject*, FXSelector, void*) {
104
assert(myObject->getType() == GLO_PERSON);
105
if (myParent->getTrackedID() != static_cast<GUIContainer*>(myObject)->getGlID()) {
106
myParent->startTrack(static_cast<GUIContainer*>(myObject)->getGlID());
107
}
108
return 1;
109
}
110
111
long
112
GUIContainer::GUIContainerPopupMenu::onCmdStopTrack(FXObject*, FXSelector, void*) {
113
assert(myObject->getType() == GLO_PERSON);
114
myParent->stopTrack();
115
return 1;
116
}
117
118
119
120
121
/* -------------------------------------------------------------------------
122
* GUIContainer - methods
123
* ----------------------------------------------------------------------- */
124
GUIContainer::GUIContainer(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan) :
125
MSTransportable(pars, vtype, plan, false),
126
GUIGlObject(GLO_CONTAINER, pars->id, GUIIconSubSys::getIcon(GUIIcon::CONTAINER)) {
127
}
128
129
130
GUIContainer::~GUIContainer() {
131
}
132
133
134
GUIGLObjectPopupMenu*
135
GUIContainer::getPopUpMenu(GUIMainWindow& app,
136
GUISUMOAbstractView& parent) {
137
GUIGLObjectPopupMenu* ret = new GUIContainerPopupMenu(app, parent, this);
138
buildPopupHeader(ret, app);
139
buildCenterPopupEntry(ret);
140
buildNameCopyPopupEntry(ret);
141
buildSelectionPopupEntry(ret);
142
new FXMenuSeparator(ret);
143
if (parent.getTrackedID() != getGlID()) {
144
GUIDesigns::buildFXMenuCommand(ret, "Start Tracking", nullptr, ret, MID_START_TRACK);
145
} else {
146
GUIDesigns::buildFXMenuCommand(ret, "Stop Tracking", nullptr, ret, MID_STOP_TRACK);
147
}
148
//
149
150
buildShowParamsPopupEntry(ret);
151
buildShowTypeParamsPopupEntry(ret);
152
GUIDesigns::buildFXMenuCommand(ret, "Show Plan", GUIIconSubSys::getIcon(GUIIcon::APP_TABLE), ret, MID_SHOWPLAN);
153
new FXMenuSeparator(ret);
154
buildPositionCopyEntry(ret, app);
155
return ret;
156
}
157
158
159
GUIParameterTableWindow*
160
GUIContainer::getParameterWindow(GUIMainWindow& app,
161
GUISUMOAbstractView&) {
162
GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
163
// add items
164
ret->mkItem(TL("stage"), false, getCurrentStageDescription());
165
// there is always the "start" stage which we do not count here because it is not strictly part of the plan
166
ret->mkItem(TL("stage index"), false, toString(getCurrentStageIndex()) + " of " + toString(getNumStages() - 1));
167
ret->mkItem(TL("start edge [id]"), false, getFromEdge()->getID());
168
ret->mkItem(TL("dest edge [id]"), false, getDestination()->getID());
169
ret->mkItem(TL("arrivalPos [m]"), false, toString(getCurrentStage()->getArrivalPos()));
170
ret->mkItem(TL("edge [id]"), false, getEdge()->getID());
171
ret->mkItem(TL("position [m]"), true, new FunctionBinding<GUIContainer, double>(this, &GUIContainer::getEdgePos));
172
ret->mkItem(TL("speed [m/s]"), true, new FunctionBinding<GUIContainer, double>(this, &GUIContainer::getSpeed));
173
ret->mkItem(TL("speed factor"), false, getChosenSpeedFactor());
174
ret->mkItem(TL("angle [degree]"), true, new FunctionBinding<GUIContainer, double>(this, &GUIContainer::getAngle));
175
ret->mkItem(TL("waiting time [s]"), true, new FunctionBinding<GUIContainer, double>(this, &GUIContainer::getWaitingSeconds));
176
ret->mkItem(TL("desired depart [s]"), false, time2string(getParameter().depart));
177
// close building
178
ret->closeBuilding(&getParameter());
179
return ret;
180
}
181
182
183
GUIParameterTableWindow*
184
GUIContainer::getTypeParameterWindow(GUIMainWindow& app, GUISUMOAbstractView&) {
185
GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this, "vType:" + myVType->getID());
186
ret->mkItem(TL("length"), false, myVType->getLength());
187
ret->mkItem(TL("width"), false, myVType->getWidth());
188
ret->mkItem(TL("height"), false, myVType->getHeight());
189
ret->mkItem(TL("minGap"), false, myVType->getMinGap());
190
ret->mkItem(TL("mass [kg]"), false, myVType->getMass());
191
ret->mkItem(TL("maximum speed [m/s]"), false, myVType->getMaxSpeed());
192
ret->closeBuilding(&(myVType->getParameter()));
193
return ret;
194
}
195
196
197
double
198
GUIContainer::getExaggeration(const GUIVisualizationSettings& s) const {
199
return s.containerSize.getExaggeration(s, this);
200
}
201
202
203
Boundary
204
GUIContainer::getCenteringBoundary() const {
205
Boundary b;
206
// ensure that the vehicle is drawn, otherwise myPositionInVehicle will not be updated
207
b.add(getPosition());
208
b.grow(20);
209
return b;
210
}
211
212
213
void
214
GUIContainer::drawGL(const GUIVisualizationSettings& s) const {
215
GLHelper::pushName(getGlID());
216
GLHelper::pushMatrix();
217
Position p1 = getPosition();
218
double angle = getAngle();
219
if (getCurrentStageType() == MSStageType::DRIVING && !isWaiting4Vehicle()) {
220
p1 = myPositionInVehicle.pos;
221
angle = myPositionInVehicle.angle;
222
}
223
glTranslated(p1.x(), p1.y(), getType());
224
glRotated(RAD2DEG(angle), 0, 0, 1);
225
// set container color
226
setColor(s);
227
// scale
228
const double upscale = getExaggeration(s);
229
glScaled(upscale, upscale, 1);
230
switch (s.containerQuality) {
231
case 0:
232
case 1:
233
case 2:
234
drawAction_drawAsPoly(s);
235
break;
236
case 3:
237
default:
238
drawAction_drawAsImage(s);
239
break;
240
}
241
GLHelper::popMatrix();
242
243
drawName(p1, s.scale, s.containerName, s.angle);
244
GLHelper::popName();
245
}
246
247
248
void
249
GUIContainer::drawGLAdditional(GUISUMOAbstractView* const /* parent */, const GUIVisualizationSettings& /* s */) const {
250
GLHelper::pushName(getGlID());
251
GLHelper::pushMatrix();
252
/*
253
glTranslated(0, 0, getType() - .1); // don't draw on top of other cars
254
if (hasActiveAddVisualisation(parent, VO_SHOW_BEST_LANES)) {
255
drawBestLanes();
256
}
257
if (hasActiveAddVisualisation(parent, VO_SHOW_ROUTE)) {
258
drawRoute(s, 0, 0.25);
259
}
260
if (hasActiveAddVisualisation(parent, VO_SHOW_ALL_ROUTES)) {
261
if (getNumberReroutes() > 0) {
262
const int noReroutePlus1 = getNumberReroutes() + 1;
263
for (int i = noReroutePlus1 - 1; i >= 0; i--) {
264
double darken = double(0.4) / double(noReroutePlus1) * double(i);
265
drawRoute(s, i, darken);
266
}
267
} else {
268
drawRoute(s, 0, 0.25);
269
}
270
}
271
if (hasActiveAddVisualisation(parent, VO_SHOW_LFLINKITEMS)) {
272
for (DriveItemVector::const_iterator i = myLFLinkLanes.begin(); i != myLFLinkLanes.end(); ++i) {
273
if((*i).myLink==0) {
274
continue;
275
}
276
MSLink* link = (*i).myLink;
277
MSLane *via = link->getViaLane();
278
if (via == 0) {
279
via = link->getLane();
280
}
281
if (via != 0) {
282
Position p = via->getShape()[0];
283
if((*i).mySetRequest) {
284
glColor3f(0, 1, 0);
285
} else {
286
glColor3f(1, 0, 0);
287
}
288
glTranslated(p.x(), p.y(), -.1);
289
GLHelper::drawFilledCircle(1);
290
glTranslated(-p.x(), -p.y(), .1);
291
}
292
}
293
}
294
*/
295
GLHelper::popMatrix();
296
GLHelper::popName();
297
}
298
299
300
301
302
void
303
GUIContainer::setColor(const GUIVisualizationSettings& s) const {
304
const GUIColorer& c = s.containerColorer;
305
if (!setFunctionalColor(c.getActive())) {
306
GLHelper::setColor(c.getScheme().getColor(getColorValue(s, c.getActive())));
307
}
308
}
309
310
311
bool
312
GUIContainer::setFunctionalColor(int activeScheme) const {
313
switch (activeScheme) {
314
case 0: {
315
if (getParameter().wasSet(VEHPARS_COLOR_SET)) {
316
GLHelper::setColor(getParameter().color);
317
return true;
318
}
319
if (getVehicleType().wasSet(VTYPEPARS_COLOR_SET)) {
320
GLHelper::setColor(getVehicleType().getColor());
321
return true;
322
}
323
return false;
324
}
325
case 2: {
326
if (getParameter().wasSet(VEHPARS_COLOR_SET)) {
327
GLHelper::setColor(getParameter().color);
328
return true;
329
}
330
return false;
331
}
332
case 3: {
333
if (getVehicleType().wasSet(VTYPEPARS_COLOR_SET)) {
334
GLHelper::setColor(getVehicleType().getColor());
335
return true;
336
}
337
return false;
338
}
339
case 8: { // color by angle
340
double hue = GeomHelper::naviDegree(getAngle());
341
GLHelper::setColor(RGBColor::fromHSV(hue, 1., 1.));
342
return true;
343
}
344
case 9: { // color randomly (by pointer)
345
const double hue = (double)((long long int)this % 360); // [0-360]
346
const double sat = (double)(((long long int)this / 360) % 67) / 100. + 0.33; // [0.33-1]
347
GLHelper::setColor(RGBColor::fromHSV(hue, sat, 1.));
348
return true;
349
}
350
default:
351
return false;
352
}
353
}
354
355
356
double
357
GUIContainer::getColorValue(const GUIVisualizationSettings& /* s */, int activeScheme) const {
358
switch (activeScheme) {
359
case 4:
360
return getSpeed();
361
case 5:
362
if (isWaiting4Vehicle()) {
363
return 5;
364
} else {
365
return (double)getCurrentStageType();
366
}
367
case 6:
368
return getWaitingSeconds();
369
case 7:
370
return gSelected.isSelected(GLO_CONTAINER, getGlID());
371
}
372
return 0;
373
}
374
375
376
double
377
GUIContainer::getEdgePos() const {
378
FXMutexLock locker(myLock);
379
return MSTransportable::getEdgePos();
380
}
381
382
int
383
GUIContainer::getDirection() const {
384
FXMutexLock locker(myLock);
385
return MSTransportable::getDirection();
386
}
387
388
389
Position
390
GUIContainer::getPosition() const {
391
FXMutexLock locker(myLock);
392
if (getCurrentStageType() == MSStageType::WAITING && getEdge()->getPermissions() == SVC_SHIP) {
393
MSLane* lane = getEdge()->getLanes().front(); //the most right lane of the water way
394
PositionVector laneShape = lane->getShape();
395
return laneShape.positionAtOffset2D(getEdgePos(), WATER_WAY_OFFSET);
396
}
397
return MSTransportable::getPosition();
398
}
399
400
401
double
402
GUIContainer::getAngle() const {
403
FXMutexLock locker(myLock);
404
return MSTransportable::getAngle();
405
}
406
407
408
double
409
GUIContainer::getWaitingSeconds() const {
410
FXMutexLock locker(myLock);
411
return MSTransportable::getWaitingSeconds();
412
}
413
414
415
double
416
GUIContainer::getSpeed() const {
417
FXMutexLock locker(myLock);
418
return MSTransportable::getSpeed();
419
}
420
421
422
void
423
GUIContainer::drawAction_drawAsPoly(const GUIVisualizationSettings& /* s */) const {
424
// draw pedestrian shape
425
glScaled(getVehicleType().getLength(), getVehicleType().getWidth(), 1);
426
glBegin(GL_QUADS);
427
glVertex2d(0, 0.5);
428
glVertex2d(0, -0.5);
429
glVertex2d(-1, -0.5);
430
glVertex2d(-1, 0.5);
431
glEnd();
432
GLHelper::setColor(GLHelper::getColor().changedBrightness(-30));
433
glTranslated(0, 0, .045);
434
glBegin(GL_QUADS);
435
glVertex2d(-0.1, 0.4);
436
glVertex2d(-0.1, -0.4);
437
glVertex2d(-0.9, -0.4);
438
glVertex2d(-0.9, 0.4);
439
glEnd();
440
}
441
442
443
void
444
GUIContainer::drawAction_drawAsImage(const GUIVisualizationSettings& s) const {
445
const std::string& file = getVehicleType().getImgFile();
446
if (file != "") {
447
// @todo invent an option for controlling whether images should be rotated or not
448
//if (getVehicleType().getGuiShape() == SVS_CONTAINER) {
449
// glRotated(RAD2DEG(getAngle() + M_PI / 2.), 0, 0, 1);
450
//}
451
int textureID = GUITexturesHelper::getTextureID(file);
452
if (textureID > 0) {
453
const double exaggeration = s.personSize.getExaggeration(s, this);
454
const double halfLength = getVehicleType().getLength() / 2.0 * exaggeration;
455
const double halfWidth = getVehicleType().getWidth() / 2.0 * exaggeration;
456
GUITexturesHelper::drawTexturedBox(textureID, -halfWidth, -halfLength, halfWidth, halfLength);
457
}
458
} else {
459
// fallback if no image is defined
460
drawAction_drawAsPoly(s);
461
}
462
}
463
464
bool
465
GUIContainer::isSelected() const {
466
return gSelected.isSelected(GLO_CONTAINER, getGlID());
467
}
468
469
/****************************************************************************/
470
471