Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/guisim/GUIBaseVehicle.cpp
193674 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 GUIBaseVehicle.cpp
15
/// @author Daniel Krajzewicz
16
/// @author Jakob Erdmann
17
/// @author Michael Behrisch
18
/// @author Laura Bieker-Walz
19
/// @date Sept 2002
20
///
21
// A MSVehicle extended by some values for usage within the gui
22
/****************************************************************************/
23
#include <config.h>
24
25
#include <cmath>
26
#include <vector>
27
#include <string>
28
#include <functional>
29
#include <utils/common/MsgHandler.h>
30
#include <utils/common/StringUtils.h>
31
#include <utils/common/StringTokenizer.h>
32
#include <utils/geom/GeomHelper.h>
33
#include <utils/vehicle/SUMOVehicleParameter.h>
34
#include <utils/emissions/PollutantsInterface.h>
35
#include <utils/gui/globjects/GLIncludes.h>
36
#include <utils/gui/windows/GUISUMOAbstractView.h>
37
#include <utils/gui/windows/GUIAppEnum.h>
38
#include <utils/gui/images/GUITexturesHelper.h>
39
#include <utils/gui/div/GUIGlobalSelection.h>
40
#include <utils/gui/div/GLHelper.h>
41
#include <utils/gui/div/GUIGlobalSelection.h>
42
#include <utils/gui/div/GUIBaseVehicleHelper.h>
43
#include <mesosim/MEVehicle.h>
44
#include <mesosim/MELoop.h>
45
#include <microsim/MSVehicle.h>
46
#include <microsim/MSLane.h>
47
#include <microsim/logging/CastingFunctionBinding.h>
48
#include <microsim/logging/FunctionBinding.h>
49
#include <microsim/MSVehicleControl.h>
50
#include <microsim/MSStop.h>
51
#include <microsim/MSTrainHelper.h>
52
#include <microsim/lcmodels/MSAbstractLaneChangeModel.h>
53
#include <microsim/devices/MSDevice_Vehroutes.h>
54
#include <microsim/devices/MSDevice_Transportable.h>
55
#include <microsim/devices/MSDevice_BTreceiver.h>
56
#include <microsim/trigger/MSStoppingPlaceRerouter.h>
57
#include <gui/GUIApplicationWindow.h>
58
#include <gui/GUIGlobals.h>
59
#include <utils/gui/div/GUIDesigns.h>
60
61
#include "GUIBaseVehicle.h"
62
#include "GUIChargingStation.h"
63
#include "GUIPerson.h"
64
#include "GUIContainer.h"
65
#include "GUINet.h"
66
#include "GUIEdge.h"
67
#include "GUILane.h"
68
#include "GUIParkingArea.h"
69
70
//#define DRAW_BOUNDING_BOX
71
72
// ===========================================================================
73
// FOX callback mapping
74
// ===========================================================================
75
FXDEFMAP(GUIBaseVehicle::GUIBaseVehiclePopupMenu) GUIBaseVehiclePopupMenuMap[] = {
76
FXMAPFUNC(SEL_COMMAND, MID_SHOW_ALLROUTES, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowAllRoutes),
77
FXMAPFUNC(SEL_COMMAND, MID_HIDE_ALLROUTES, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideAllRoutes),
78
FXMAPFUNC(SEL_COMMAND, MID_SHOW_CURRENTROUTE, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowCurrentRoute),
79
FXMAPFUNC(SEL_COMMAND, MID_HIDE_CURRENTROUTE, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideCurrentRoute),
80
FXMAPFUNC(SEL_COMMAND, MID_SHOW_FUTUREROUTE, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowFutureRoute),
81
FXMAPFUNC(SEL_COMMAND, MID_HIDE_FUTUREROUTE, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideFutureRoute),
82
FXMAPFUNC(SEL_COMMAND, MID_SHOW_ROUTE_NOLOOPS, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowRouteNoLoops),
83
FXMAPFUNC(SEL_COMMAND, MID_HIDE_ROUTE_NOLOOPS, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideRouteNoLoops),
84
FXMAPFUNC(SEL_COMMAND, MID_SHOW_BEST_LANES, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowBestLanes),
85
FXMAPFUNC(SEL_COMMAND, MID_HIDE_BEST_LANES, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideBestLanes),
86
FXMAPFUNC(SEL_COMMAND, MID_START_TRACK, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdStartTrack),
87
FXMAPFUNC(SEL_COMMAND, MID_STOP_TRACK, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdStopTrack),
88
FXMAPFUNC(SEL_COMMAND, MID_SHOW_LFLINKITEMS, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowLFLinkItems),
89
FXMAPFUNC(SEL_COMMAND, MID_HIDE_LFLINKITEMS, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideLFLinkItems),
90
FXMAPFUNC(SEL_COMMAND, MID_SHOW_FOES, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowFoes),
91
FXMAPFUNC(SEL_COMMAND, MID_SELECT_TRANSPORTED, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdSelectTransported),
92
FXMAPFUNC(SEL_COMMAND, MID_REMOVE_OBJECT, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdRemoveObject),
93
FXMAPFUNC(SEL_COMMAND, MID_TOGGLE_STOP, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdToggleStop),
94
};
95
96
// Object implementation
97
FXIMPLEMENT(GUIBaseVehicle::GUIBaseVehiclePopupMenu, GUIGLObjectPopupMenu, GUIBaseVehiclePopupMenuMap, ARRAYNUMBER(GUIBaseVehiclePopupMenuMap))
98
99
// ===========================================================================
100
// method definitions
101
// ===========================================================================
102
/* -------------------------------------------------------------------------
103
* GUIBaseVehicle::GUIBaseVehiclePopupMenu - methods
104
* ----------------------------------------------------------------------- */
105
GUIBaseVehicle::GUIBaseVehiclePopupMenu::GUIBaseVehiclePopupMenu(
106
GUIMainWindow& app, GUISUMOAbstractView& parent, GUIGlObject* o) :
107
GUIGLObjectPopupMenu(app, parent, o) {
108
}
109
110
111
GUIBaseVehicle::GUIBaseVehiclePopupMenu::~GUIBaseVehiclePopupMenu() {}
112
113
114
long
115
GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowAllRoutes(FXObject*, FXSelector, void*) {
116
assert(myObject->getType() == GLO_VEHICLE);
117
if (!static_cast<GUIBaseVehicle*>(myObject)->hasActiveAddVisualisation(myParent, VO_SHOW_ALL_ROUTES)) {
118
static_cast<GUIBaseVehicle*>(myObject)->addActiveAddVisualisation(myParent, VO_SHOW_ALL_ROUTES);
119
}
120
return 1;
121
}
122
123
long
124
GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideAllRoutes(FXObject*, FXSelector, void*) {
125
assert(myObject->getType() == GLO_VEHICLE);
126
static_cast<GUIBaseVehicle*>(myObject)->removeActiveAddVisualisation(myParent, VO_SHOW_ALL_ROUTES);
127
return 1;
128
}
129
130
131
long
132
GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowCurrentRoute(FXObject*, FXSelector, void*) {
133
assert(myObject->getType() == GLO_VEHICLE);
134
if (!static_cast<GUIBaseVehicle*>(myObject)->hasActiveAddVisualisation(myParent, VO_SHOW_ROUTE)) {
135
static_cast<GUIBaseVehicle*>(myObject)->addActiveAddVisualisation(myParent, VO_SHOW_ROUTE);
136
}
137
return 1;
138
}
139
140
long
141
GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideCurrentRoute(FXObject*, FXSelector, void*) {
142
assert(myObject->getType() == GLO_VEHICLE);
143
static_cast<GUIBaseVehicle*>(myObject)->removeActiveAddVisualisation(myParent, VO_SHOW_ROUTE);
144
return 1;
145
}
146
147
148
long
149
GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowFutureRoute(FXObject*, FXSelector, void*) {
150
assert(myObject->getType() == GLO_VEHICLE);
151
if (!static_cast<GUIBaseVehicle*>(myObject)->hasActiveAddVisualisation(myParent, VO_SHOW_FUTURE_ROUTE)) {
152
static_cast<GUIBaseVehicle*>(myObject)->addActiveAddVisualisation(myParent, VO_SHOW_FUTURE_ROUTE);
153
}
154
return 1;
155
}
156
157
long
158
GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideFutureRoute(FXObject*, FXSelector, void*) {
159
assert(myObject->getType() == GLO_VEHICLE);
160
static_cast<GUIBaseVehicle*>(myObject)->removeActiveAddVisualisation(myParent, VO_SHOW_FUTURE_ROUTE);
161
return 1;
162
}
163
164
165
long
166
GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowRouteNoLoops(FXObject*, FXSelector, void*) {
167
assert(myObject->getType() == GLO_VEHICLE);
168
if (!static_cast<GUIBaseVehicle*>(myObject)->hasActiveAddVisualisation(myParent, VO_SHOW_ROUTE_NOLOOP)) {
169
static_cast<GUIBaseVehicle*>(myObject)->addActiveAddVisualisation(myParent, VO_SHOW_ROUTE_NOLOOP);
170
}
171
return 1;
172
}
173
174
long
175
GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideRouteNoLoops(FXObject*, FXSelector, void*) {
176
assert(myObject->getType() == GLO_VEHICLE);
177
static_cast<GUIBaseVehicle*>(myObject)->removeActiveAddVisualisation(myParent, VO_SHOW_ROUTE_NOLOOP);
178
return 1;
179
}
180
181
182
long
183
GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowBestLanes(FXObject*, FXSelector, void*) {
184
assert(myObject->getType() == GLO_VEHICLE);
185
if (!static_cast<GUIBaseVehicle*>(myObject)->hasActiveAddVisualisation(myParent, VO_SHOW_BEST_LANES)) {
186
static_cast<GUIBaseVehicle*>(myObject)->addActiveAddVisualisation(myParent, VO_SHOW_BEST_LANES);
187
}
188
return 1;
189
}
190
191
long
192
GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideBestLanes(FXObject*, FXSelector, void*) {
193
assert(myObject->getType() == GLO_VEHICLE);
194
static_cast<GUIBaseVehicle*>(myObject)->removeActiveAddVisualisation(myParent, VO_SHOW_BEST_LANES);
195
return 1;
196
}
197
198
199
long
200
GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdStartTrack(FXObject*, FXSelector, void*) {
201
assert(myObject->getType() == GLO_VEHICLE);
202
if (myParent->getTrackedID() != static_cast<GUIBaseVehicle*>(myObject)->getGlID()) {
203
myParent->startTrack(static_cast<GUIBaseVehicle*>(myObject)->getGlID());
204
}
205
return 1;
206
}
207
208
long
209
GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdStopTrack(FXObject*, FXSelector, void*) {
210
assert(myObject->getType() == GLO_VEHICLE);
211
myParent->stopTrack();
212
return 1;
213
}
214
215
216
long
217
GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowLFLinkItems(FXObject*, FXSelector, void*) {
218
assert(myObject->getType() == GLO_VEHICLE);
219
if (!static_cast<GUIBaseVehicle*>(myObject)->hasActiveAddVisualisation(myParent, VO_SHOW_LFLINKITEMS)) {
220
static_cast<GUIBaseVehicle*>(myObject)->addActiveAddVisualisation(myParent, VO_SHOW_LFLINKITEMS);
221
}
222
return 1;
223
}
224
225
long
226
GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideLFLinkItems(FXObject*, FXSelector, void*) {
227
assert(myObject->getType() == GLO_VEHICLE);
228
static_cast<GUIBaseVehicle*>(myObject)->removeActiveAddVisualisation(myParent, VO_SHOW_LFLINKITEMS);
229
return 1;
230
}
231
232
long
233
GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowFoes(FXObject*, FXSelector, void*) {
234
assert(myObject->getType() == GLO_VEHICLE);
235
static_cast<GUIBaseVehicle*>(myObject)->selectBlockingFoes();
236
myParent->update();
237
return 1;
238
}
239
240
241
long
242
GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdSelectTransported(FXObject*, FXSelector, void*) {
243
assert(myObject->getType() == GLO_VEHICLE);
244
const MSBaseVehicle& veh = static_cast<GUIBaseVehicle*>(myObject)->getVehicle();
245
for (const MSTransportable* t : veh.getPersons()) {
246
gSelected.select((static_cast<const GUIPerson*>(t))->getGlID());
247
}
248
for (MSTransportable* t : veh.getContainers()) {
249
gSelected.select((static_cast<const GUIContainer*>(t))->getGlID());
250
}
251
myParent->update();
252
return 1;
253
}
254
255
long
256
GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdRemoveObject(FXObject*, FXSelector, void*) {
257
GUIBaseVehicle* baseVeh = static_cast<GUIBaseVehicle*>(myObject);
258
MSVehicle* microVeh = dynamic_cast<MSVehicle*>(&baseVeh->myVehicle);
259
if (microVeh != nullptr) {
260
MSLane* lane = microVeh->getMutableLane();
261
if (lane != nullptr) {
262
lane->getVehiclesSecure();
263
lane->removeVehicle(microVeh, MSMoveReminder::NOTIFICATION_VAPORIZED_GUI);
264
}
265
microVeh->onRemovalFromNet(MSMoveReminder::NOTIFICATION_VAPORIZED_GUI);
266
if (lane != nullptr) {
267
lane->releaseVehicles();
268
}
269
} else {
270
MEVehicle* mesoVeh = dynamic_cast<MEVehicle*>(&baseVeh->myVehicle);
271
MSGlobals::gMesoNet->vaporizeCar(mesoVeh, MSMoveReminder::NOTIFICATION_VAPORIZED_GUI);
272
}
273
MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(&baseVeh->myVehicle);
274
myParent->destroyPopup();
275
myParent->update();
276
return 1;
277
}
278
279
280
long
281
GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdToggleStop(FXObject*, FXSelector, void*) {
282
GUIBaseVehicle* baseVeh = static_cast<GUIBaseVehicle*>(myObject);
283
MSVehicle* microVeh = dynamic_cast<MSVehicle*>(&baseVeh->myVehicle);
284
if (microVeh != nullptr) {
285
if (microVeh->isStopped()) {
286
microVeh->resumeFromStopping();
287
} else {
288
std::string errorOut;
289
const double brakeGap = microVeh->getCarFollowModel().brakeGap(microVeh->getSpeed());
290
std::pair<const MSLane*, double> stopPos = microVeh->getLanePosAfterDist(brakeGap);
291
if (stopPos.first != nullptr) {
292
SUMOVehicleParameter::Stop stop;
293
stop.lane = stopPos.first->getID();
294
stop.startPos = stopPos.second;
295
stop.endPos = stopPos.second + POSITION_EPS;
296
stop.duration = TIME2STEPS(3600);
297
microVeh->addTraciStop(stop, errorOut);
298
if (errorOut != "") {
299
WRITE_WARNING(errorOut);
300
}
301
}
302
}
303
} else {
304
WRITE_WARNING(TL("GUI-triggered stop not implemented for meso"));
305
}
306
myParent->update();
307
return 1;
308
}
309
310
311
/* -------------------------------------------------------------------------
312
* GUIBaseVehicle - methods
313
* ----------------------------------------------------------------------- */
314
315
GUIBaseVehicle::GUIBaseVehicle(MSBaseVehicle& vehicle) :
316
GUIGlObject(GLO_VEHICLE, vehicle.getID(), GUIIconSubSys::getIcon(GUIIcon::VEHICLE)),
317
myVehicle(vehicle),
318
myPopup(nullptr) {
319
// as it is possible to show all vehicle routes, we have to store them... (bug [ 2519761 ])
320
myRoutes = MSDevice_Vehroutes::buildVehicleDevices(myVehicle, myVehicle.myDevices, 5);
321
myVehicle.myMoveReminders.push_back(std::make_pair(myRoutes, 0.));
322
mySeatPositions.push_back(Seat()); // ensure length 1
323
myContainerPositions.push_back(Seat()); // ensure length 1
324
}
325
326
327
GUIBaseVehicle::~GUIBaseVehicle() {
328
myLock.lock();
329
for (std::map<GUISUMOAbstractView*, int>::iterator i = myAdditionalVisualizations.begin(); i != myAdditionalVisualizations.end(); ++i) {
330
if (i->first->getTrackedID() == getGlID()) {
331
i->first->stopTrack();
332
}
333
while (i->first->removeAdditionalGLVisualisation(this));
334
}
335
myLock.unlock();
336
delete myRoutes;
337
if (myPopup != nullptr) {
338
myPopup->getParentView()->destroyPopup();
339
}
340
}
341
342
343
GUIGLObjectPopupMenu*
344
GUIBaseVehicle::getPopUpMenu(GUIMainWindow& app, GUISUMOAbstractView& parent) {
345
GUIGLObjectPopupMenu* ret = new GUIBaseVehiclePopupMenu(app, parent, this);
346
buildPopupHeader(ret, app);
347
buildCenterPopupEntry(ret);
348
buildNameCopyPopupEntry(ret);
349
buildSelectionPopupEntry(ret);
350
//
351
if (hasActiveAddVisualisation(&parent, VO_SHOW_ROUTE)) {
352
GUIDesigns::buildFXMenuCommand(ret, TL("Hide Current Route"), nullptr, ret, MID_HIDE_CURRENTROUTE);
353
} else {
354
GUIDesigns::buildFXMenuCommand(ret, TL("Show Current Route"), nullptr, ret, MID_SHOW_CURRENTROUTE);
355
}
356
if (hasActiveAddVisualisation(&parent, VO_SHOW_FUTURE_ROUTE)) {
357
GUIDesigns::buildFXMenuCommand(ret, TL("Hide Future Route"), nullptr, ret, MID_HIDE_FUTUREROUTE);
358
} else {
359
GUIDesigns::buildFXMenuCommand(ret, TL("Show Future Route"), nullptr, ret, MID_SHOW_FUTUREROUTE);
360
}
361
if (hasActiveAddVisualisation(&parent, VO_SHOW_ALL_ROUTES)) {
362
GUIDesigns::buildFXMenuCommand(ret, TL("Hide All Routes"), nullptr, ret, MID_HIDE_ALLROUTES);
363
} else {
364
GUIDesigns::buildFXMenuCommand(ret, TL("Show All Routes"), nullptr, ret, MID_SHOW_ALLROUTES);
365
}
366
if (hasActiveAddVisualisation(&parent, VO_SHOW_ROUTE_NOLOOP)) {
367
FXMenuCheck* showLoops = new FXMenuCheck(ret, TL("Draw looped routes"), ret, MID_HIDE_ROUTE_NOLOOPS);
368
showLoops->setCheck(false);
369
} else {
370
FXMenuCheck* showLoops = new FXMenuCheck(ret, TL("Draw looped routes"), ret, MID_SHOW_ROUTE_NOLOOPS);
371
showLoops->setCheck(true);
372
}
373
if (hasActiveAddVisualisation(&parent, VO_SHOW_BEST_LANES)) {
374
GUIDesigns::buildFXMenuCommand(ret, TL("Hide Best Lanes"), nullptr, ret, MID_HIDE_BEST_LANES);
375
} else {
376
GUIDesigns::buildFXMenuCommand(ret, TL("Show Best Lanes"), nullptr, ret, MID_SHOW_BEST_LANES);
377
}
378
if (hasActiveAddVisualisation(&parent, VO_SHOW_LFLINKITEMS)) {
379
GUIDesigns::buildFXMenuCommand(ret, TL("Hide Link Items"), nullptr, ret, MID_HIDE_LFLINKITEMS);
380
} else {
381
GUIDesigns::buildFXMenuCommand(ret, TL("Show Link Items"), nullptr, ret, MID_SHOW_LFLINKITEMS);
382
}
383
new FXMenuSeparator(ret);
384
if (parent.getTrackedID() != getGlID()) {
385
GUIDesigns::buildFXMenuCommand(ret, TL("Start Tracking"), nullptr, ret, MID_START_TRACK);
386
} else {
387
GUIDesigns::buildFXMenuCommand(ret, TL("Stop Tracking"), nullptr, ret, MID_STOP_TRACK);
388
}
389
GUIDesigns::buildFXMenuCommand(ret, TL("Select Foes"), nullptr, ret, MID_SHOW_FOES);
390
if (myVehicle.getPersons().size() + myVehicle.getContainers().size() > 0) {
391
GUIDesigns::buildFXMenuCommand(ret, TL("Select transported"), nullptr, ret, MID_SELECT_TRANSPORTED);
392
}
393
GUIDesigns::buildFXMenuCommand(ret, myVehicle.isStopped() ? TL("Abort stop") : TL("Stop"), nullptr, ret, MID_TOGGLE_STOP);
394
GUIDesigns::buildFXMenuCommand(ret, TL("Remove"), nullptr, ret, MID_REMOVE_OBJECT);
395
396
new FXMenuSeparator(ret);
397
//
398
buildShowParamsPopupEntry(ret, false);
399
buildShowTypeParamsPopupEntry(ret);
400
buildPositionCopyEntry(ret, app);
401
myPopup = ret;
402
return ret;
403
}
404
405
406
void
407
GUIBaseVehicle::removedPopupMenu() {
408
myPopup = nullptr;
409
}
410
411
412
double
413
GUIBaseVehicle::getExaggeration(const GUIVisualizationSettings& s) const {
414
return (s.vehicleSize.getExaggeration(s, this) *
415
s.vehicleScaler.getScheme().getColor(getScaleValue(s, s.vehicleScaler.getActive())));
416
}
417
418
419
Boundary
420
GUIBaseVehicle::getCenteringBoundary() const {
421
Boundary b;
422
b.add(getVisualPosition(GUIGlobals::gSecondaryShape));
423
b.grow(myVehicle.getVehicleType().getLength());
424
return b;
425
}
426
427
428
const std::string
429
GUIBaseVehicle::getOptionalName() const {
430
return myVehicle.getParameter().getParameter("name", "");
431
}
432
433
434
void
435
GUIBaseVehicle::drawOnPos(const GUIVisualizationSettings& s, const Position& pos, const double angle) const {
436
GLHelper::pushName(getGlID());
437
GLHelper::pushMatrix();
438
Position p1 = pos;
439
const double degAngle = RAD2DEG(angle + M_PI / 2.);
440
const double length = getVType().getLength();
441
if (s.trueZ) {
442
glTranslated(p1.x(), p1.y(), p1.z() + 1);
443
} else {
444
glTranslated(p1.x(), p1.y(), getType());
445
}
446
glRotated(degAngle, 0, 0, 1);
447
RGBColor col = setColor(s);
448
// scale
449
const double upscale = getExaggeration(s);
450
const bool s2 = s.secondaryShape;
451
452
if (upscale > 1 && s.laneWidthExaggeration > 1 && myVehicle.isOnRoad()) {
453
// optionally shift according to edge exaggeration
454
double offsetFromLeftBorder = myVehicle.getCurrentEdge()->getWidth() - myVehicle.getRightSideOnEdge() - myVehicle.getVehicleType().getWidth() / 2;
455
glTranslated((s.laneWidthExaggeration - 1) * -offsetFromLeftBorder / 2, 0, 0);
456
}
457
458
double upscaleLength = MSTrainHelper::getUpscaleLength(upscale, length, getVType().getWidth(), s.vehicleQuality);
459
glScaled(upscale, upscaleLength, 1);
460
/*
461
MSLaneChangeModel::DK2004 &m2 = static_cast<MSLaneChangeModel::DK2004&>(veh->getLaneChangeModel());
462
if((m2.getState()&LCA_URGENT)!=0) {
463
glColor3d(1, .4, .4);
464
} else if((m2.getState()&LCA_SPEEDGAIN)!=0) {
465
glColor3d(.4, .4, 1);
466
} else {
467
glColor3d(.4, 1, .4);
468
}
469
*/
470
// draw the vehicle
471
bool drawCarriages = false;
472
// do not upscale vehicles on physically impossible geometry factors > 1
473
const double geometryFactor = (s.scaleLength ?
474
MIN2(1.0, (myVehicle.getLane() != nullptr
475
? myVehicle.getLane()->getLengthGeometryFactor(s2)
476
: (myVehicle.getEdge()->getLanes().size() > 0 ? myVehicle.getEdge()->getLanes()[0]->getLengthGeometryFactor(s2) : 1)))
477
: 1);
478
double scaledLength = length * geometryFactor;
479
if (col.alpha() != 0) {
480
switch (s.vehicleQuality) {
481
case 0:
482
GUIBaseVehicleHelper::drawAction_drawVehicleAsTrianglePlus(getVType().getWidth(), scaledLength, drawReversed(s));
483
break;
484
case 1:
485
GUIBaseVehicleHelper::drawAction_drawVehicleAsBoxPlus(getVType().getWidth(), scaledLength, drawReversed(s));
486
break;
487
case 2:
488
drawCarriages = drawAction_drawVehicleAsPolyWithCarriagges(s, scaledLength);
489
// draw flashing blue light for emergency vehicles
490
if (getVType().getGuiShape() == SUMOVehicleShape::EMERGENCY) {
491
glTranslated(0, 0, .1);
492
drawAction_drawVehicleBlueLight();
493
}
494
break;
495
case 3:
496
drawCarriages = drawAction_drawVehicleAsPolyWithCarriagges(s, scaledLength, true);
497
break;
498
case 4: {
499
// do not scale circle radius by lengthGeometryFactor nor length and reduce the effect of width
500
const double w = 1.8 * sqrt(getVType().getWidth() / 1.8);
501
GUIBaseVehicleHelper::drawAction_drawVehicleAsCircle(w, s.scale * upscale);
502
// display text at circle center
503
scaledLength = 0;
504
break;
505
}
506
default:
507
break;
508
}
509
if (s.drawMinGap) {
510
const double minGap = -getVType().getMinGap();
511
glColor3d(0., 1., 0.);
512
glBegin(GL_LINES);
513
glVertex2d(0., 0);
514
glVertex2d(0., minGap);
515
glVertex2d(-.5, minGap);
516
glVertex2d(.5, minGap);
517
glEnd();
518
}
519
if (s.drawBrakeGap && !MSGlobals::gUseMesoSim
520
&& (!s.vehicleSize.constantSizeSelected || myVehicle.isSelected())) {
521
const double brakeGap = -static_cast<MSVehicle&>(myVehicle).getCarFollowModel().brakeGap(myVehicle.getSpeed());
522
glColor3d(1., 0., 0.);
523
glBegin(GL_LINES);
524
glVertex2d(0., 0);
525
glVertex2d(0., brakeGap);
526
glVertex2d(-.5, brakeGap);
527
glVertex2d(.5, brakeGap);
528
glEnd();
529
}
530
if (s.showBTRange) {
531
MSVehicleDevice_BTreceiver* dev = static_cast<MSVehicleDevice_BTreceiver*>(myVehicle.getDevice(typeid(MSVehicleDevice_BTreceiver)));
532
if (dev != nullptr) {
533
glColor3d(1., 0., 0.);
534
GLHelper::drawOutlineCircle(dev->getRange(), dev->getRange() - .2, 32);
535
}
536
}
537
// draw the blinker and brakelights if wished
538
if (s.showBlinker) {
539
glTranslated(0, 0, .1);
540
switch (getVType().getGuiShape()) {
541
case SUMOVehicleShape::PEDESTRIAN:
542
case SUMOVehicleShape::BICYCLE:
543
case SUMOVehicleShape::SCOOTER:
544
case SUMOVehicleShape::ANT:
545
case SUMOVehicleShape::SHIP:
546
case SUMOVehicleShape::RAIL:
547
case SUMOVehicleShape::RAIL_CARGO:
548
case SUMOVehicleShape::RAIL_CAR:
549
case SUMOVehicleShape::AIRCRAFT:
550
break;
551
case SUMOVehicleShape::MOTORCYCLE:
552
case SUMOVehicleShape::MOPED:
553
drawAction_drawVehicleBlinker(scaledLength);
554
drawAction_drawVehicleBrakeLight(scaledLength, true);
555
break;
556
default:
557
// only SUMOVehicleShape::RAIL_CAR has blinkers and brake lights but they are drawn along with the carriages
558
if (!drawCarriages) {
559
drawAction_drawVehicleBlinker(scaledLength);
560
drawAction_drawVehicleBrakeLight(scaledLength);
561
}
562
break;
563
}
564
}
565
// draw the wish to change the lane
566
if (s.drawLaneChangePreference) {
567
/*
568
if(gSelected.isSelected(GLO_VEHICLE, veh->getGlID())) {
569
MSLaneChangeModel::DK2004 &m = static_cast<MSLaneChangeModel::DK2004&>(veh->getLaneChangeModel());
570
glColor3d(.5, .5, 1);
571
glBegin(GL_LINES);
572
glVertex2f(0, 0);
573
glVertex2f(m.getChangeProbability(), .5);
574
glEnd();
575
576
glColor3d(1, 0, 0);
577
glBegin(GL_LINES);
578
glVertex2f(0.1, 0);
579
glVertex2f(0.1, m.myMaxJam1);
580
glEnd();
581
582
glColor3d(0, 1, 0);
583
glBegin(GL_LINES);
584
glVertex2f(-0.1, 0);
585
glVertex2f(-0.1, m.myTDist);
586
glEnd();
587
}
588
*/
589
}
590
}
591
glTranslated(0, MIN2(scaledLength / 2, double(5)), -getType()); // drawing name at GLO_MAX fails unless translating z
592
glScaled(1 / upscale, 1 / upscaleLength, 1);
593
glRotated(-degAngle, 0, 0, 1);
594
drawName(Position(0, 0), s.scale, s.vehicleName, s.angle);
595
if (s.vehicleName.show(this) && myVehicle.getParameter().line != "") {
596
glRotated(-s.angle, 0, 0, 1);
597
glTranslated(0, 0.7 * s.vehicleName.scaledSize(s.scale), 0);
598
glRotated(s.angle, 0, 0, 1);
599
GLHelper::drawTextSettings(s.vehicleName, "line:" + myVehicle.getParameter().line, Position(0, 0), s.scale, s.angle);
600
}
601
if (s.vehicleValue.show(this)) {
602
glRotated(-s.angle, 0, 0, 1);
603
glTranslated(0, 0.7 * s.vehicleName.scaledSize(s.scale), 0);
604
glRotated(s.angle, 0, 0, 1);
605
const double value = getColorValue(s, s.vehicleColorer.getActive());
606
if (value != s.MISSING_DATA) {
607
GLHelper::drawTextSettings(s.vehicleValue, toString(value), Position(0, 0), s.scale, s.angle);
608
}
609
}
610
if (s.vehicleScaleValue.show(this)) {
611
glRotated(-s.angle, 0, 0, 1);
612
glTranslated(0, 0.7 * s.vehicleName.scaledSize(s.scale), 0);
613
glRotated(s.angle, 0, 0, 1);
614
const double value = getScaleValue(s, s.vehicleScaler.getActive());
615
if (value != s.MISSING_DATA) {
616
GLHelper::drawTextSettings(s.vehicleScaleValue, toString(value), Position(0, 0), s.scale, s.angle);
617
}
618
}
619
if (s.vehicleText.show(this)) {
620
std::string error;
621
std::string value = myVehicle.getPrefixedParameter(s.vehicleTextParam, error);
622
if (value != "") {
623
auto lines = StringTokenizer(value, StringTokenizer::NEWLINE).getVector();
624
glRotated(-s.angle, 0, 0, 1);
625
glTranslated(0, 0.7 * s.vehicleText.scaledSize(s.scale) * (double)lines.size(), 0);
626
glRotated(s.angle, 0, 0, 1);
627
for (std::string& line : lines) {
628
GLHelper::drawTextSettings(s.vehicleText, line, Position(0, 0), s.scale, s.angle);
629
glRotated(-s.angle, 0, 0, 1);
630
glTranslated(0, -0.7 * s.vehicleText.scaledSize(s.scale), 0);
631
glRotated(s.angle, 0, 0, 1);
632
}
633
}
634
}
635
if (s.showParkingInfo && myAdditionalVisualizations.size() != 0 && hasActiveAddVisualisation(
636
myAdditionalVisualizations.begin()->first, VO_SHOW_ROUTE | VO_SHOW_FUTURE_ROUTE | VO_SHOW_ALL_ROUTES)) {
637
glRotated(-s.angle, 0, 0, 1);
638
glTranslated(0, 0.7 * s.vehicleName.scaledSize(s.scale), 0);
639
glRotated(s.angle, 0, 0, 1);
640
const double value = myVehicle.getNumberParkingReroutes();
641
GLHelper::drawTextSettings(s.vehicleName, toString(value), Position(0, 0), s.scale, s.angle);
642
}
643
644
if (!drawCarriages) {
645
mySeatPositions.clear();
646
myContainerPositions.clear();
647
int requiredSeats = getNumPassengers();
648
int requiredContainerPositions = getNumContainers();
649
const Position back = (p1 + Position(-scaledLength * upscaleLength, 0)).rotateAround2D(angle, p1);
650
double extraOffset = scaledLength * 0.15;
651
computeSeats(p1, back, SUMO_const_waitingPersonWidth, getVType().getPersonCapacity(), upscale, requiredSeats, mySeatPositions, extraOffset);
652
computeSeats(p1, back, SUMO_const_waitingContainerWidth, getVType().getContainerCapacity(), upscale, requiredContainerPositions, myContainerPositions, extraOffset);
653
}
654
655
GLHelper::popMatrix();
656
GLHelper::popName();
657
drawAction_drawPersonsAndContainers(s);
658
}
659
660
661
void
662
GUIBaseVehicle::drawGL(const GUIVisualizationSettings& s) const {
663
drawOnPos(s, getVisualPosition(s.secondaryShape), getVisualAngle(s.secondaryShape));
664
}
665
666
667
void
668
GUIBaseVehicle::drawGLAdditional(GUISUMOAbstractView* const parent, const GUIVisualizationSettings& s) const {
669
if (!myVehicle.isOnRoad()) {
670
drawGL(s);
671
}
672
GLHelper::pushName(getGlID());
673
GLHelper::pushMatrix();
674
glTranslated(0, 0, getType() - .1); // don't draw on top of other cars
675
if (hasActiveAddVisualisation(parent, VO_SHOW_BEST_LANES)) {
676
drawBestLanes();
677
}
678
bool noLoop = hasActiveAddVisualisation(parent, VO_SHOW_ROUTE_NOLOOP);
679
if (hasActiveAddVisualisation(parent, VO_SHOW_ROUTE)) {
680
drawRoute(s, 0, 0.25, false, noLoop);
681
}
682
if (hasActiveAddVisualisation(parent, VO_SHOW_FUTURE_ROUTE)) {
683
drawRoute(s, 0, 0.25, true, noLoop);
684
}
685
if (hasActiveAddVisualisation(parent, VO_SHOW_ALL_ROUTES)) {
686
if (myVehicle.getNumberReroutes() > 0) {
687
const int noReroutePlus1 = myVehicle.getNumberReroutes() + 1;
688
for (int i = noReroutePlus1 - 1; i >= 0; i--) {
689
double darken = double(0.4) / double(noReroutePlus1) * double(i);
690
drawRoute(s, i, darken);
691
}
692
} else {
693
drawRoute(s, 0, 0.25, false, noLoop);
694
}
695
}
696
if (hasActiveAddVisualisation(parent, VO_SHOW_LFLINKITEMS)) {
697
drawAction_drawLinkItems(s);
698
}
699
GLHelper::popMatrix();
700
GLHelper::popName();
701
}
702
703
704
void
705
GUIBaseVehicle::drawLinkItem(const Position& pos, SUMOTime arrivalTime, SUMOTime leaveTime, double exagerate) {
706
glTranslated(pos.x(), pos.y(), -.1);
707
GLHelper::drawFilledCircle(1);
708
std::string times = toString(STEPS2TIME(arrivalTime)) + "/" + toString(STEPS2TIME(leaveTime));
709
GLHelper::drawText(times.c_str(), Position(), .1, 1.6 * exagerate, RGBColor::GREEN, 0);
710
glTranslated(-pos.x(), -pos.y(), .1);
711
}
712
713
714
RGBColor
715
GUIBaseVehicle::setColor(const GUIVisualizationSettings& s) const {
716
RGBColor col;
717
const GUIColorer& c = s.vehicleColorer;
718
if (!setFunctionalColor(c.getActive(), &myVehicle, col)) {
719
col = c.getScheme().getColor(getColorValue(s, c.getActive()));
720
}
721
GLHelper::setColor(col);
722
return col;
723
}
724
725
726
bool
727
GUIBaseVehicle::setFunctionalColor(int activeScheme, const MSBaseVehicle* veh, RGBColor& col) {
728
switch (activeScheme) {
729
case 0: {
730
//test for emergency vehicle
731
if (veh->getVehicleType().getGuiShape() == SUMOVehicleShape::EMERGENCY) {
732
col = RGBColor::WHITE;
733
return true;
734
}
735
//test for firebrigade
736
if (veh->getVehicleType().getGuiShape() == SUMOVehicleShape::FIREBRIGADE) {
737
col = RGBColor::RED;
738
return true;
739
}
740
//test for police car
741
if (veh->getVehicleType().getGuiShape() == SUMOVehicleShape::POLICE) {
742
col = RGBColor::BLUE;
743
return true;
744
}
745
if (veh->getParameter().wasSet(VEHPARS_COLOR_SET)) {
746
col = veh->getParameter().color;
747
return true;
748
}
749
if (veh->getVehicleType().wasSet(VTYPEPARS_COLOR_SET)) {
750
col = veh->getVehicleType().getColor();
751
return true;
752
}
753
if (&(veh->getRoute().getColor()) != &RGBColor::DEFAULT_COLOR) {
754
col = veh->getRoute().getColor();
755
return true;
756
}
757
return false;
758
}
759
case 2: {
760
if (veh->getParameter().wasSet(VEHPARS_COLOR_SET)) {
761
col = veh->getParameter().color;
762
return true;
763
}
764
return false;
765
}
766
case 3: {
767
if (veh->getVehicleType().wasSet(VTYPEPARS_COLOR_SET)) {
768
col = veh->getVehicleType().getColor();
769
return true;
770
}
771
return false;
772
}
773
case 4: {
774
if (&(veh->getRoute().getColor()) != &RGBColor::DEFAULT_COLOR) {
775
col = veh->getRoute().getColor();
776
return true;
777
}
778
return false;
779
}
780
case 5: {
781
Position p = veh->getRoute().getEdges()[0]->getLanes()[0]->getShape()[0];
782
const Boundary& b = ((GUINet*) MSNet::getInstance())->getBoundary();
783
Position center = b.getCenter();
784
double hue = 180. + atan2(center.x() - p.x(), center.y() - p.y()) * 180. / M_PI;
785
double sat = p.distanceTo(center) / center.distanceTo(Position(b.xmin(), b.ymin()));
786
col = RGBColor::fromHSV(hue, sat, 1.);
787
return true;
788
}
789
case 6: {
790
Position p = veh->getRoute().getEdges().back()->getLanes()[0]->getShape()[-1];
791
const Boundary& b = ((GUINet*) MSNet::getInstance())->getBoundary();
792
Position center = b.getCenter();
793
double hue = 180. + atan2(center.x() - p.x(), center.y() - p.y()) * 180. / M_PI;
794
double sat = p.distanceTo(center) / center.distanceTo(Position(b.xmin(), b.ymin()));
795
col = RGBColor::fromHSV(hue, sat, 1.);
796
return true;
797
}
798
case 7: {
799
Position pb = veh->getRoute().getEdges()[0]->getLanes()[0]->getShape()[0];
800
Position pe = veh->getRoute().getEdges().back()->getLanes()[0]->getShape()[-1];
801
const Boundary& b = ((GUINet*) MSNet::getInstance())->getBoundary();
802
double hue = 180. + atan2(pb.x() - pe.x(), pb.y() - pe.y()) * 180. / M_PI;
803
Position minp(b.xmin(), b.ymin());
804
Position maxp(b.xmax(), b.ymax());
805
double sat = pb.distanceTo(pe) / minp.distanceTo(maxp);
806
col = RGBColor::fromHSV(hue, sat, 1.);
807
return true;
808
}
809
case 35: { // color randomly (by pointer hash)
810
std::hash<const MSBaseVehicle*> ptr_hash;
811
const double hue = (double)(ptr_hash(veh) % 360); // [0-360]
812
const double sat = (double)((ptr_hash(veh) / 360) % 67) / 100.0 + 0.33; // [0.33-1]
813
col = RGBColor::fromHSV(hue, sat, 1.);
814
return true;
815
}
816
case 36: { // color by angle
817
double hue = GeomHelper::naviDegree(veh->getAngle());
818
col = RGBColor::fromHSV(hue, 1., 1.);
819
return true;
820
}
821
}
822
return false;
823
}
824
825
826
double
827
GUIBaseVehicle::getScaleValue(const GUIVisualizationSettings& s, int activeScheme) const {
828
switch (activeScheme) {
829
case 0: // uniform
830
return 0;
831
case 1: // selection
832
return myVehicle.isSelected();
833
case 2: // by speed
834
if (myVehicle.isStopped()) {
835
return myVehicle.isParking() ? -2 : -1;
836
}
837
return myVehicle.getSpeed();
838
case 3:
839
return myVehicle.getWaitingSeconds();
840
case 4: {
841
MSVehicle* microVeh = dynamic_cast<MSVehicle*>(&myVehicle);
842
return (microVeh != nullptr ? microVeh->getAccumulatedWaitingSeconds() : 0);
843
}
844
case 5: {
845
MSVehicle* microVeh = dynamic_cast<MSVehicle*>(&myVehicle);
846
return (microVeh != nullptr ? microVeh->getLane()->getVehicleMaxSpeed(microVeh) : myVehicle.getEdge()->getVehicleMaxSpeed(&myVehicle));
847
}
848
case 6:
849
return myVehicle.getNumberReroutes();
850
case 7: {
851
MSVehicle* microVeh = dynamic_cast<MSVehicle*>(&myVehicle);
852
return (microVeh != nullptr
853
? (microVeh->getLaneChangeModel().isOpposite() ? -100 : microVeh->getBestLaneOffset())
854
: 0);
855
}
856
case 8:
857
return myVehicle.getAcceleration();
858
case 9: {
859
MSVehicle* microVeh = dynamic_cast<MSVehicle*>(&myVehicle);
860
return (microVeh != nullptr ? microVeh->getTimeGapOnLane() : 0);
861
}
862
case 10:
863
return STEPS2TIME(myVehicle.getDepartDelay());
864
case 11:
865
return myVehicle.getTimeLossSeconds();
866
case 12:
867
return myVehicle.getStopDelay();
868
case 13:
869
return myVehicle.getStopArrivalDelay();
870
case 14: // by numerical param value
871
std::string error;
872
std::string val = myVehicle.getPrefixedParameter(s.vehicleScaleParam, error);
873
try {
874
if (val == "") {
875
return 0;
876
} else {
877
return StringUtils::toDouble(val);
878
}
879
} catch (NumberFormatException&) {
880
try {
881
return StringUtils::toBool(val);
882
} catch (BoolFormatException&) {
883
WRITE_WARNINGF(TL("Vehicle parameter '%' key '%' is not a number for vehicle '%'."),
884
myVehicle.getParameter().getParameter(s.vehicleScaleParam, "0"), s.vehicleScaleParam, myVehicle.getID());
885
return -1;
886
}
887
}
888
}
889
return 0;
890
}
891
892
893
// ------------ Additional visualisations
894
bool
895
GUIBaseVehicle::hasActiveAddVisualisation(GUISUMOAbstractView* const parent, int which) const {
896
return myAdditionalVisualizations.find(parent) != myAdditionalVisualizations.end() && (myAdditionalVisualizations.find(parent)->second & which) != 0;
897
}
898
899
900
void
901
GUIBaseVehicle::addActiveAddVisualisation(GUISUMOAbstractView* const parent, int which) {
902
if (myAdditionalVisualizations.find(parent) == myAdditionalVisualizations.end()) {
903
myAdditionalVisualizations[parent] = 0;
904
}
905
myAdditionalVisualizations[parent] |= which;
906
if (which != VO_TRACK) {
907
parent->addAdditionalGLVisualisation(this);
908
}
909
}
910
911
912
void
913
GUIBaseVehicle::removeActiveAddVisualisation(GUISUMOAbstractView* const parent, int which) {
914
myAdditionalVisualizations[parent] &= ~which;
915
if (myAdditionalVisualizations[parent] == 0) {
916
myAdditionalVisualizations.erase(parent);
917
}
918
parent->removeAdditionalGLVisualisation(this);
919
}
920
921
922
void
923
GUIBaseVehicle::drawRoute(const GUIVisualizationSettings& s, int routeNo, double darken, bool future, bool noLoop) const {
924
RGBColor vehColor = setColor(s);
925
RGBColor darker = vehColor.changedBrightness((int)(darken * -255));
926
if (darker == RGBColor::BLACK) {
927
darker = vehColor.multiply(1 - darken);
928
}
929
GLHelper::setColor(darker);
930
if (routeNo == 0) {
931
drawRouteHelper(s, myVehicle.getRoutePtr(), future, noLoop, darker);
932
return;
933
}
934
ConstMSRoutePtr route = myRoutes->getRoute(routeNo - 1); // only prior routes are stored
935
if (route != nullptr) {
936
drawRouteHelper(s, route, future, noLoop, darker);
937
}
938
}
939
940
941
void
942
GUIBaseVehicle::drawStopLabels(const GUIVisualizationSettings& s, bool noLoop, const RGBColor& col) const {
943
// (vertical shift for repeated stops at the same position
944
std::map<const MSLane*, int> repeat; // count repeated occurrences of the same position
945
int stopIndex = 0;
946
for (const MSStop& stop : myVehicle.getStops()) {
947
double stopLanePos;
948
if (stop.getSpeed() > 0) {
949
stopLanePos = stop.reached ? stop.pars.endPos : stop.pars.startPos;
950
} else {
951
stopLanePos = stop.reached ? myVehicle.getPositionOnLane() : MAX2(0.0, stop.getEndPos(myVehicle));
952
}
953
if (stop.isOpposite && !stop.reached) {
954
stopLanePos = stop.lane->getLength() - stopLanePos;
955
}
956
Position pos = stop.lane->geometryPositionAtOffset(stopLanePos);
957
GLHelper::setColor(col);
958
GLHelper::drawBoxLines(stop.lane->getShape().getOrthogonal(pos, 10, true, stop.lane->getWidth()), 0.1);
959
std::string label = (stop.getSpeed() > 0
960
? (stop.reached ? "passing waypoint" : "waypoint ")
961
: (stop.reached ? "stopped" : "stop "));
962
if (!stop.reached) {
963
label += toString(stopIndex);
964
}
965
966
if (stop.isOpposite) {
967
label += " (opposite)";
968
}
969
#ifdef _DEBUG
970
label += " (" + toString(stop.edge - myVehicle.getCurrentRouteEdge()) + "e)";
971
#endif
972
if (myVehicle.isStoppedTriggered()) {
973
label += " triggered:";
974
if (stop.triggered) {
975
label += "person";
976
if (stop.numExpectedPerson > 0) {
977
label += "(" + toString(stop.numExpectedPerson) + ")";
978
}
979
}
980
if (stop.containerTriggered) {
981
label += "container";
982
if (stop.numExpectedContainer > 0) {
983
label += "(" + toString(stop.numExpectedContainer) + ")";
984
}
985
}
986
if (stop.joinTriggered) {
987
label += "join";
988
if (stop.pars.join != "") {
989
label += "(" + stop.pars.join + ")";
990
}
991
}
992
}
993
if (stop.pars.ended >= 0 && MSGlobals::gUseStopEnded) {
994
label += " ended:" + time2string(stop.pars.ended);
995
} else if (stop.pars.until >= 0) {
996
label += " until:" + time2string(stop.pars.until);
997
}
998
if (stop.duration >= 0 || stop.pars.duration > 0) {
999
if (STEPS2TIME(stop.duration) > 3600 * 24) {
1000
label += " duration:1day+";
1001
} else {
1002
label += " duration:" + time2string(stop.duration);
1003
}
1004
}
1005
if (stop.getSpeed() > 0) {
1006
if (stop.skipOnDemand) {
1007
label += " onDemand (skipped)";
1008
} else {
1009
label += " speed:" + toString(stop.getSpeed());
1010
}
1011
}
1012
if (stop.pars.actType != "") {
1013
label += " actType:" + stop.pars.actType;
1014
}
1015
const double nameSize = s.vehicleName.size / s.scale;
1016
Position pos2 = pos - Position(0, nameSize * repeat[stop.lane]);
1017
if (noLoop && repeat[stop.lane] > 0) {
1018
break;
1019
}
1020
GLHelper::drawTextSettings(s.vehicleText, label, pos2, s.scale, s.angle, 1.0);
1021
repeat[stop.lane]++;
1022
stopIndex++;
1023
}
1024
// indicate arrivalPos if set
1025
if (myVehicle.getParameter().wasSet(VEHPARS_ARRIVALPOS_SET) || myVehicle.getArrivalLane() >= 0) {
1026
const int arrivalEdge = myVehicle.getParameter().arrivalEdge >= 0
1027
? myVehicle.getParameter().arrivalEdge
1028
: (int)myVehicle.getRoute().getEdges().size() - 1;
1029
const MSLane* arrivalLane = myVehicle.getRoute().getEdges()[arrivalEdge]->getLanes()[MAX2(0, myVehicle.getArrivalLane())];
1030
Position pos = arrivalLane->geometryPositionAtOffset(myVehicle.getArrivalPos());
1031
GLHelper::setColor(col);
1032
GLHelper::drawBoxLines(arrivalLane->getShape().getOrthogonal(pos, 10, true, arrivalLane->getWidth() * 0.5, 90), 0.1);
1033
GLHelper::drawBoxLines(arrivalLane->getShape().getOrthogonal(pos, 10, true, arrivalLane->getWidth() * 0.5, 270), 0.1);
1034
GLHelper::drawTextSettings(s.vehicleText, "arrival", pos, s.scale, s.angle, 1.0);
1035
1036
}
1037
}
1038
1039
void
1040
GUIBaseVehicle::drawParkingInfo(const GUIVisualizationSettings& s) const {
1041
if (s.showParkingInfo) {
1042
const StoppingPlaceMemory* pm = myVehicle.getParkingMemory();
1043
if (pm != nullptr) {
1044
for (auto item : *pm) {
1045
const GUIParkingArea* pa = dynamic_cast<const GUIParkingArea*>(item.first);
1046
if (item.second.blockedAtTime >= 0) {
1047
std::string seenAgo = time2string(SIMSTEP - item.second.blockedAtTime);
1048
//if (item.second.blockedAtTime >= 0) {
1049
// seenAgo += ", " + time2string(SIMSTEP - item.second.blockedAtTimeLocal);
1050
//}
1051
GLHelper::drawTextSettings(s.vehicleValue, seenAgo, pa->getSignPos(), s.scale, s.angle, 1.0);
1052
}
1053
if (item.second.score != "") {
1054
const double dist = 0.4 * (s.vehicleText.scaledSize(s.scale) + s.vehicleValue.scaledSize(s.scale));
1055
Position shift(0, -dist);
1056
GLHelper::drawTextSettings(s.vehicleText, item.second.score, pa->getSignPos() + shift, s.scale, s.angle, 1.0);
1057
}
1058
}
1059
}
1060
}
1061
}
1062
1063
void
1064
GUIBaseVehicle::drawChargingInfo(const GUIVisualizationSettings& s) const {
1065
if (s.showChargingInfo) {
1066
const StoppingPlaceMemory* pm = myVehicle.getChargingMemory();
1067
if (pm != nullptr) {
1068
for (auto item : *pm) {
1069
const GUIChargingStation* cs = dynamic_cast<const GUIChargingStation*>(item.first);
1070
if (item.second.blockedAtTime >= 0) {
1071
std::string seenAgo = time2string(SIMSTEP - item.second.blockedAtTime);
1072
GLHelper::drawTextSettings(s.vehicleValue, seenAgo, cs->getSignPos(), s.scale, s.angle, 1.0);
1073
}
1074
if (item.second.score != "") {
1075
const double dist = 0.4 * (s.vehicleText.scaledSize(s.scale) + s.vehicleValue.scaledSize(s.scale));
1076
Position shift(0, -dist);
1077
GLHelper::drawTextSettings(s.vehicleText, item.second.score, cs->getSignPos() + shift, s.scale, s.angle, 1.0);
1078
}
1079
}
1080
}
1081
}
1082
}
1083
1084
const GUIBaseVehicle::Seat&
1085
GUIBaseVehicle::getSeatPosition(int personIndex) const {
1086
/// if there are not enough seats in the vehicle people have to squeeze onto the last seat
1087
return mySeatPositions[MIN2(personIndex, (int)mySeatPositions.size() - 1)];
1088
}
1089
1090
const GUIBaseVehicle::Seat&
1091
GUIBaseVehicle::getContainerPosition(int containerIndex) const {
1092
/// if there are not enough positions in the vehicle containers have to squeeze onto the last position
1093
return myContainerPositions[MIN2(containerIndex, (int)myContainerPositions.size() - 1)];
1094
}
1095
1096
1097
void
1098
GUIBaseVehicle::drawAction_drawPersonsAndContainers(const GUIVisualizationSettings& s) const {
1099
if (myVehicle.myPersonDevice != nullptr) {
1100
const std::vector<MSTransportable*>& ps = myVehicle.myPersonDevice->getTransportables();
1101
int personIndex = 0;
1102
for (std::vector<MSTransportable*>::const_iterator i = ps.begin(); i != ps.end(); ++i) {
1103
GUIPerson* person = dynamic_cast<GUIPerson*>(*i);
1104
assert(person != 0);
1105
person->setPositionInVehicle(getSeatPosition(personIndex++));
1106
person->drawGL(s);
1107
}
1108
}
1109
if (myVehicle.myContainerDevice != nullptr) {
1110
const std::vector<MSTransportable*>& cs = myVehicle.myContainerDevice->getTransportables();
1111
int containerIndex = 0;
1112
for (std::vector<MSTransportable*>::const_iterator i = cs.begin(); i != cs.end(); ++i) {
1113
GUIContainer* container = dynamic_cast<GUIContainer*>(*i);
1114
assert(container != 0);
1115
container->setPositionInVehicle(getContainerPosition(containerIndex++));
1116
container->drawGL(s);
1117
}
1118
}
1119
#ifdef DRAW_BOUNDING_BOX
1120
if (!MSGlobals::gUseMesoSim) {
1121
MSVehicle& microVeh = dynamic_cast<MSVehicle&>(myVehicle);
1122
GLHelper::pushName(getGlID());
1123
GLHelper::pushMatrix();
1124
glTranslated(0, 0, getType());
1125
PositionVector smallBB = microVeh.getBoundingPoly();
1126
glColor3d(0.5, .8, 0);
1127
GLHelper::drawBoxLines(smallBB, 0.3);
1128
glTranslated(0, 0, 0.1);
1129
PositionVector boundingBox = microVeh.getBoundingBox();
1130
boundingBox.push_back(boundingBox.front());
1131
glColor3d(1, 0, 0);
1132
GLHelper::drawBoxLines(boundingBox, 0.15);
1133
GLHelper::popMatrix();
1134
GLHelper::popName();
1135
}
1136
#endif
1137
}
1138
1139
bool
1140
GUIBaseVehicle::drawReversed(const GUIVisualizationSettings& s) const {
1141
return myVehicle.isReversed() && s.drawReversed;
1142
}
1143
1144
bool
1145
GUIBaseVehicle::drawAction_drawVehicleAsPolyWithCarriagges(const GUIVisualizationSettings& s, double scaledLength, bool asImage) const {
1146
if (getVType().getParameter().carriageLength > 0 &&
1147
(!myVehicle.isParking() || myVehicle.getNextStop().parkingarea == nullptr || myVehicle.getNextStop().parkingarea->parkOnRoad())) {
1148
drawAction_drawCarriageClass(s, scaledLength, asImage);
1149
return true;
1150
} else {
1151
if (asImage && GUIBaseVehicleHelper::drawAction_drawVehicleAsImage(
1152
s, getVType().getImgFile(), this, getVType().getWidth(), scaledLength)) {
1153
return false;
1154
}
1155
GUIBaseVehicleHelper::drawAction_drawVehicleAsPoly(s, getVType().getGuiShape(), getVType().getWidth(), scaledLength, -1, myVehicle.isStopped(), drawReversed(s));
1156
return false;
1157
}
1158
}
1159
1160
1161
int
1162
GUIBaseVehicle::getNumPassengers() const {
1163
if (myVehicle.getPersonDevice() != nullptr) {
1164
return (int)myVehicle.getPersonDevice()->size();
1165
}
1166
return 0;
1167
}
1168
1169
1170
int
1171
GUIBaseVehicle::getNumContainers() const {
1172
if (myVehicle.getContainerDevice() != nullptr) {
1173
return (int)myVehicle.getContainerDevice()->size();
1174
}
1175
return 0;
1176
}
1177
1178
std::string
1179
GUIBaseVehicle::getDeviceDescription() {
1180
std::vector<std::string> devs;
1181
for (MSDevice* d : myVehicle.getDevices()) {
1182
devs.push_back(d->deviceName());
1183
}
1184
return joinToString(devs, " ");
1185
}
1186
1187
1188
void
1189
GUIBaseVehicle::computeSeats(const Position& front, const Position& back, double seatOffset, int maxSeats, double exaggeration, int& requiredSeats, Seats& into, double extraOffset) const {
1190
if (requiredSeats <= 0) {
1191
return;
1192
}
1193
maxSeats = MAX2(maxSeats, 1); // compute at least one seat
1194
seatOffset *= exaggeration;
1195
const double vehWidth = getVType().getSeatingWidth() * exaggeration;
1196
const double length = front.distanceTo2D(back);
1197
const int rowSize = MAX2(1, (int)floor(vehWidth / seatOffset));
1198
const double frontSeatPos = getVType().getFrontSeatPos() + extraOffset;
1199
const double rowOffset = MAX2(1.0, (length - frontSeatPos - 1)) / ceil((double)maxSeats / rowSize);
1200
const double sideOffset = (rowSize - 1) / 2.0 * seatOffset;
1201
double rowPos = frontSeatPos - rowOffset;
1202
double angle = back.angleTo2D(front);
1203
const int fillDirection = MSGlobals::gLefthand ? -1 : 1;
1204
//if (myVehicle.getID() == "v0") std::cout << SIMTIME << " seatOffset=" << seatOffset << " max=" << maxSeats << " ex=" << exaggeration << " req=" << requiredSeats << " rowSize=" << rowSize << " sideOffset=" << sideOffset << " front=" << front << " back=" << back << " a=" << angle << " da=" << RAD2DEG(angle) << "\n";
1205
for (int i = 0; requiredSeats > 0 && i < maxSeats; i++) {
1206
int seat = (i % rowSize);
1207
if (seat == 0) {
1208
rowPos += rowOffset;
1209
}
1210
into.push_back(Seat(PositionVector::positionAtOffset2D(front, back, rowPos, (sideOffset - seat * seatOffset) * fillDirection), angle));
1211
requiredSeats--;
1212
}
1213
}
1214
1215
1216
/****************************************************************************/
1217
1218