Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/elements/demand/GNEVehicle.cpp
185790 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 GNEVehicle.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Jan 2019
17
///
18
// Representation of vehicles in netedit
19
/****************************************************************************/
20
21
#include <microsim/devices/MSDevice_BTreceiver.h>
22
#include <netedit/changes/GNEChange_Attribute.h>
23
#include <netedit/changes/GNEChange_DemandElement.h>
24
#include <netedit/elements/moving/GNEMoveElementVehicle.h>
25
#include <netedit/elements/moving/GNEMoveElementView.h>
26
#include <netedit/frames/demand/GNETypeFrame.h>
27
#include <netedit/GNENet.h>
28
#include <netedit/GNESegment.h>
29
#include <netedit/GNETagProperties.h>
30
#include <netedit/GNEUndoList.h>
31
#include <netedit/GNEViewParent.h>
32
#include <utils/gui/div/GLHelper.h>
33
#include <utils/gui/div/GUIBaseVehicleHelper.h>
34
#include <utils/gui/div/GUIDesigns.h>
35
#include <utils/gui/windows/GUIAppEnum.h>
36
#include <utils/xml/NamespaceIDs.h>
37
38
#include "GNEVehicle.h"
39
#include "GNERoute.h"
40
#include "GNERouteHandler.h"
41
42
// ===========================================================================
43
// FOX callback mapping
44
// ===========================================================================
45
46
FXDEFMAP(GNEVehicle::GNESingleVehiclePopupMenu) GNESingleVehiclePopupMenuMap[] = {
47
FXMAPFUNCS(SEL_COMMAND, MID_GNE_VEHICLE_TRANSFORM_TRIP, MID_GNE_VEHICLE_TRANSFORM_FLOW_TAZS, GNEVehicle::GNESingleVehiclePopupMenu::onCmdTransform),
48
};
49
50
FXDEFMAP(GNEVehicle::GNESelectedVehiclesPopupMenu) GNESelectedVehiclesPopupMenuMap[] = {
51
FXMAPFUNCS(SEL_COMMAND, MID_GNE_VEHICLE_TRANSFORM_TRIP, MID_GNE_VEHICLE_TRANSFORM_FLOW_TAZS, GNEVehicle::GNESelectedVehiclesPopupMenu::onCmdTransform),
52
};
53
54
// Object implementation
55
FXIMPLEMENT(GNEVehicle::GNESingleVehiclePopupMenu, GUIGLObjectPopupMenu, GNESingleVehiclePopupMenuMap, ARRAYNUMBER(GNESingleVehiclePopupMenuMap))
56
FXIMPLEMENT(GNEVehicle::GNESelectedVehiclesPopupMenu, GUIGLObjectPopupMenu, GNESelectedVehiclesPopupMenuMap, ARRAYNUMBER(GNESelectedVehiclesPopupMenuMap))
57
58
// ===========================================================================
59
// GNEVehicle::GNESingleVehiclePopupMenu
60
// ===========================================================================
61
62
GNEVehicle::GNESingleVehiclePopupMenu::GNESingleVehiclePopupMenu(GNEVehicle* vehicle, GUIMainWindow& app, GUISUMOAbstractView& parent) :
63
GUIGLObjectPopupMenu(app, parent, vehicle),
64
myVehicle(vehicle) {
65
// build common options
66
vehicle->buildPopUpMenuCommonOptions(this, app, vehicle->myNet->getViewNet(), vehicle->getTagProperty()->getTag(), vehicle->isAttributeCarrierSelected());
67
// route length
68
vehicle->buildMenuCommandRouteLength(this);
69
// add transform functions only in demand mode
70
if (myVehicle->getNet()->getViewNet()->getEditModes().isCurrentSupermodeDemand()) {
71
// add reverse
72
vehicle->buildMenuAddReverse(this);
73
// continue depending of type
74
if (myVehicle->getTagProperty()->vehicleJunctions()) {
75
// create menu pane for transform operations
76
FXMenuPane* transformOperation = new FXMenuPane(this);
77
this->insertMenuPaneChild(transformOperation);
78
new FXMenuCascade(this, TL("transform to"), nullptr, transformOperation);
79
// Create menu commands for all transform
80
GUIDesigns::buildFXMenuCommand(transformOperation,
81
TL("Trip (over junctions)"),
82
GUIIconSubSys::getIcon(GUIIcon::TRIP_JUNCTIONS), this, MID_GNE_VEHICLE_TRANSFORM_TRIP_JUNCTIONS,
83
(myVehicle->getTagProperty()->getTag() == GNE_TAG_TRIP_JUNCTIONS));
84
GUIDesigns::buildFXMenuCommand(transformOperation,
85
TL("Flow (over junctions)"),
86
GUIIconSubSys::getIcon(GUIIcon::FLOW_JUNCTIONS), this, MID_GNE_VEHICLE_TRANSFORM_FLOW_JUNCTIONS,
87
(myVehicle->getTagProperty()->getTag() == GNE_TAG_FLOW_JUNCTIONS));
88
} else if (myVehicle->getTagProperty()->vehicleTAZs()) {
89
// create menu pane for transform operations
90
FXMenuPane* transformOperation = new FXMenuPane(this);
91
this->insertMenuPaneChild(transformOperation);
92
new FXMenuCascade(this, TL("transform to"), nullptr, transformOperation);
93
// Create menu commands for all transform
94
GUIDesigns::buildFXMenuCommand(transformOperation,
95
TL("Trip (over TAZs)"),
96
GUIIconSubSys::getIcon(GUIIcon::TRIP_TAZS), this, MID_GNE_VEHICLE_TRANSFORM_TRIP_TAZS,
97
(myVehicle->getTagProperty()->getTag() == GNE_TAG_TRIP_TAZS));
98
GUIDesigns::buildFXMenuCommand(transformOperation,
99
TL("Flow (over TAZs)"),
100
GUIIconSubSys::getIcon(GUIIcon::FLOW_TAZS), this, MID_GNE_VEHICLE_TRANSFORM_FLOW_TAZS,
101
(myVehicle->getTagProperty()->getTag() == GNE_TAG_FLOW_TAZS));
102
} else {
103
// create menu pane for transform operations
104
FXMenuPane* transformOperation = new FXMenuPane(this);
105
this->insertMenuPaneChild(transformOperation);
106
new FXMenuCascade(this, TL("transform to"), nullptr, transformOperation);
107
// Create menu commands for all transform
108
GUIDesigns::buildFXMenuCommand(transformOperation,
109
TL("Vehicle"),
110
GUIIconSubSys::getIcon(GUIIcon::VEHICLE), this, MID_GNE_VEHICLE_TRANSFORM_VEHICLE,
111
(myVehicle->getTagProperty()->getTag() == SUMO_TAG_VEHICLE));
112
GUIDesigns::buildFXMenuCommand(transformOperation,
113
TL("Vehicle (embedded route)"),
114
GUIIconSubSys::getIcon(GUIIcon::VEHICLE), this, MID_GNE_VEHICLE_TRANSFORM_VEHICLE_EMBEDDED,
115
(myVehicle->getTagProperty()->getTag() == GNE_TAG_VEHICLE_WITHROUTE));
116
GUIDesigns::buildFXMenuCommand(transformOperation,
117
TL("RouteFlow"),
118
GUIIconSubSys::getIcon(GUIIcon::ROUTEFLOW), this, MID_GNE_VEHICLE_TRANSFORM_ROUTEFLOW,
119
(myVehicle->getTagProperty()->getTag() == GNE_TAG_FLOW_ROUTE));
120
GUIDesigns::buildFXMenuCommand(transformOperation,
121
TL("RouteFlow (embedded route)"),
122
GUIIconSubSys::getIcon(GUIIcon::ROUTEFLOW), this, MID_GNE_VEHICLE_TRANSFORM_FLOW_EMBEDDED,
123
(myVehicle->getTagProperty()->getTag() == GNE_TAG_FLOW_WITHROUTE));
124
GUIDesigns::buildFXMenuCommand(transformOperation,
125
TL("Trip"),
126
GUIIconSubSys::getIcon(GUIIcon::TRIP), this, MID_GNE_VEHICLE_TRANSFORM_TRIP,
127
(myVehicle->getTagProperty()->getTag() == SUMO_TAG_TRIP));
128
GUIDesigns::buildFXMenuCommand(transformOperation,
129
TL("Flow"),
130
GUIIconSubSys::getIcon(GUIIcon::FLOW), this, MID_GNE_VEHICLE_TRANSFORM_FLOW,
131
(myVehicle->getTagProperty()->getTag() == SUMO_TAG_FLOW));
132
}
133
}
134
}
135
136
137
GNEVehicle::GNESingleVehiclePopupMenu::~GNESingleVehiclePopupMenu() {}
138
139
140
long
141
GNEVehicle::GNESingleVehiclePopupMenu::onCmdTransform(FXObject*, FXSelector sel, void*) {
142
switch (FXSELID(sel)) {
143
case MID_GNE_VEHICLE_TRANSFORM_TRIP:
144
GNERouteHandler::transformToTrip(myVehicle);
145
break;
146
case MID_GNE_VEHICLE_TRANSFORM_FLOW:
147
GNERouteHandler::transformToFlow(myVehicle);
148
break;
149
case MID_GNE_VEHICLE_TRANSFORM_VEHICLE:
150
GNERouteHandler::transformToVehicle(myVehicle, false);
151
break;
152
case MID_GNE_VEHICLE_TRANSFORM_ROUTEFLOW:
153
GNERouteHandler::transformToRouteFlow(myVehicle, false);
154
break;
155
case MID_GNE_VEHICLE_TRANSFORM_VEHICLE_EMBEDDED:
156
GNERouteHandler::transformToVehicle(myVehicle, true);
157
break;
158
case MID_GNE_VEHICLE_TRANSFORM_FLOW_EMBEDDED:
159
GNERouteHandler::transformToRouteFlow(myVehicle, true);
160
break;
161
case MID_GNE_VEHICLE_TRANSFORM_TRIP_JUNCTIONS:
162
GNERouteHandler::transformToTripJunctions(myVehicle);
163
break;
164
case MID_GNE_VEHICLE_TRANSFORM_FLOW_JUNCTIONS:
165
GNERouteHandler::transformToFlowJunctions(myVehicle);
166
break;
167
case MID_GNE_VEHICLE_TRANSFORM_TRIP_TAZS:
168
GNERouteHandler::transformToTripTAZs(myVehicle);
169
break;
170
case MID_GNE_VEHICLE_TRANSFORM_FLOW_TAZS:
171
GNERouteHandler::transformToFlowTAZs(myVehicle);
172
break;
173
default:
174
break;
175
}
176
return 1;
177
}
178
179
// ===========================================================================
180
// GNEVehicle::GNESelectedVehiclesPopupMenu
181
// ===========================================================================
182
183
GNEVehicle::GNESelectedVehiclesPopupMenu::GNESelectedVehiclesPopupMenu(GNEVehicle* vehicle, const std::vector<GNEVehicle*>& selectedVehicle, GUIMainWindow& app, GUISUMOAbstractView& parent) :
184
GUIGLObjectPopupMenu(app, parent, vehicle),
185
mySelectedVehicles(selectedVehicle),
186
myVehicleTag(vehicle->getTagProperty()->getTag()) {
187
// build common options
188
vehicle->buildPopUpMenuCommonOptions(this, app, vehicle->myNet->getViewNet(), vehicle->getTagProperty()->getTag(), vehicle->isAttributeCarrierSelected());
189
// route length
190
vehicle->buildMenuCommandRouteLength(this);
191
// add transform functions only in demand mode
192
if (vehicle->getNet()->getViewNet()->getEditModes().isCurrentSupermodeDemand()) {
193
// add reverse
194
vehicle->buildMenuAddReverse(this);
195
// continue depending of type
196
if (vehicle->getTagProperty()->vehicleJunctions()) {
197
// create menu pane for transform operations
198
FXMenuPane* transformOperation = new FXMenuPane(this);
199
this->insertMenuPaneChild(transformOperation);
200
new FXMenuCascade(this, TL("transform selected to"), nullptr, transformOperation);
201
// Create menu commands for restricted transforms
202
myRestrictedMenuCommands[GUIDesigns::buildFXMenuCommand(transformOperation,
203
TLF("Trips (over junctions) (only %)", toString(GNE_TAG_TRIP_JUNCTIONS)),
204
GUIIconSubSys::getIcon(GUIIcon::TRIP_JUNCTIONS), this, MID_GNE_VEHICLE_TRANSFORM_TRIP_JUNCTIONS)] = GNE_TAG_TRIP_JUNCTIONS;
205
myRestrictedMenuCommands[GUIDesigns::buildFXMenuCommand(transformOperation,
206
TLF("Flows (over junctions) (only %)", toString(GNE_TAG_FLOW_JUNCTIONS)),
207
GUIIconSubSys::getIcon(GUIIcon::FLOW_JUNCTIONS), this, MID_GNE_VEHICLE_TRANSFORM_FLOW_JUNCTIONS)] = GNE_TAG_FLOW_JUNCTIONS;
208
// create separator
209
new FXMenuSeparator(transformOperation);
210
// Create menu commands for all transform
211
GUIDesigns::buildFXMenuCommand(transformOperation,
212
TL("Trips (over junctions)"),
213
GUIIconSubSys::getIcon(GUIIcon::TRIP_JUNCTIONS), this, MID_GNE_VEHICLE_TRANSFORM_TRIP_JUNCTIONS);
214
GUIDesigns::buildFXMenuCommand(transformOperation,
215
TL("Flows (over junctions)"),
216
GUIIconSubSys::getIcon(GUIIcon::FLOW_JUNCTIONS), this, MID_GNE_VEHICLE_TRANSFORM_FLOW_JUNCTIONS);
217
} else if (vehicle->getTagProperty()->vehicleTAZs()) {
218
// create menu pane for transform operations
219
FXMenuPane* transformOperation = new FXMenuPane(this);
220
this->insertMenuPaneChild(transformOperation);
221
new FXMenuCascade(this, TL("transform selected to"), nullptr, transformOperation);
222
// Create menu commands for all transform
223
myRestrictedMenuCommands[GUIDesigns::buildFXMenuCommand(transformOperation,
224
TLF("Trips (over TAZs) (only %)", toString(GNE_TAG_TRIP_TAZS)),
225
GUIIconSubSys::getIcon(GUIIcon::TRIP_TAZS), this, MID_GNE_VEHICLE_TRANSFORM_TRIP_TAZS)] = GNE_TAG_TRIP_TAZS;
226
myRestrictedMenuCommands[GUIDesigns::buildFXMenuCommand(transformOperation,
227
TLF("Flows (over TAZs) (only %)", toString(GNE_TAG_FLOW_TAZS)),
228
GUIIconSubSys::getIcon(GUIIcon::FLOW_TAZS), this, MID_GNE_VEHICLE_TRANSFORM_FLOW_TAZS)] = GNE_TAG_FLOW_TAZS;
229
// create separator
230
new FXMenuSeparator(transformOperation);
231
// Create menu commands for all transform
232
GUIDesigns::buildFXMenuCommand(transformOperation,
233
TL("Trips (over TAZs)"),
234
GUIIconSubSys::getIcon(GUIIcon::TRIP_TAZS), this, MID_GNE_VEHICLE_TRANSFORM_TRIP_TAZS);
235
GUIDesigns::buildFXMenuCommand(transformOperation,
236
TL("Flows (over TAZs)"),
237
GUIIconSubSys::getIcon(GUIIcon::FLOW_TAZS), this, MID_GNE_VEHICLE_TRANSFORM_FLOW_TAZS);
238
} else {
239
// create menu pane for transform operations
240
FXMenuPane* transformOperation = new FXMenuPane(this);
241
this->insertMenuPaneChild(transformOperation);
242
new FXMenuCascade(this, TL("transform selected to"), nullptr, transformOperation);
243
// Create menu commands for all transform
244
myRestrictedMenuCommands[GUIDesigns::buildFXMenuCommand(transformOperation,
245
TLF("Vehicles (only %)", toString(SUMO_TAG_VEHICLE)),
246
GUIIconSubSys::getIcon(GUIIcon::VEHICLE), this, MID_GNE_VEHICLE_TRANSFORM_VEHICLE)] = SUMO_TAG_VEHICLE;
247
myRestrictedMenuCommands[GUIDesigns::buildFXMenuCommand(transformOperation,
248
TLF("Vehicles (embedded route) (only %)", toString(GNE_TAG_VEHICLE_WITHROUTE)),
249
GUIIconSubSys::getIcon(GUIIcon::VEHICLE), this, MID_GNE_VEHICLE_TRANSFORM_VEHICLE_EMBEDDED)] = GNE_TAG_VEHICLE_WITHROUTE;
250
myRestrictedMenuCommands[GUIDesigns::buildFXMenuCommand(transformOperation,
251
TLF("RouteFlows (only %)", toString(GNE_TAG_FLOW_ROUTE)),
252
GUIIconSubSys::getIcon(GUIIcon::ROUTEFLOW), this, MID_GNE_VEHICLE_TRANSFORM_ROUTEFLOW)] = GNE_TAG_FLOW_ROUTE;
253
myRestrictedMenuCommands[GUIDesigns::buildFXMenuCommand(transformOperation,
254
TLF("RouteFlows (embedded route) (only %)", toString(GNE_TAG_FLOW_WITHROUTE)),
255
GUIIconSubSys::getIcon(GUIIcon::ROUTEFLOW), this, MID_GNE_VEHICLE_TRANSFORM_FLOW_EMBEDDED)] = GNE_TAG_FLOW_WITHROUTE;
256
myRestrictedMenuCommands[GUIDesigns::buildFXMenuCommand(transformOperation,
257
TLF("Trips (only %)", toString(SUMO_TAG_TRIP)),
258
GUIIconSubSys::getIcon(GUIIcon::TRIP), this, MID_GNE_VEHICLE_TRANSFORM_TRIP)] = SUMO_TAG_TRIP;
259
myRestrictedMenuCommands[GUIDesigns::buildFXMenuCommand(transformOperation,
260
TLF("Flows (only %)", toString(SUMO_TAG_FLOW)),
261
GUIIconSubSys::getIcon(GUIIcon::FLOW), this, MID_GNE_VEHICLE_TRANSFORM_FLOW)] = SUMO_TAG_FLOW;
262
// create separator
263
new FXMenuSeparator(transformOperation);
264
// Create menu commands for all transform
265
GUIDesigns::buildFXMenuCommand(transformOperation,
266
TL("Vehicles"),
267
GUIIconSubSys::getIcon(GUIIcon::VEHICLE), this, MID_GNE_VEHICLE_TRANSFORM_VEHICLE);
268
GUIDesigns::buildFXMenuCommand(transformOperation,
269
TL("Vehicles (embedded route)"),
270
GUIIconSubSys::getIcon(GUIIcon::VEHICLE), this, MID_GNE_VEHICLE_TRANSFORM_VEHICLE_EMBEDDED);
271
GUIDesigns::buildFXMenuCommand(transformOperation,
272
TL("RouteFlows"),
273
GUIIconSubSys::getIcon(GUIIcon::ROUTEFLOW), this, MID_GNE_VEHICLE_TRANSFORM_ROUTEFLOW);
274
GUIDesigns::buildFXMenuCommand(transformOperation,
275
TL("RouteFlows (embedded route)"),
276
GUIIconSubSys::getIcon(GUIIcon::ROUTEFLOW), this, MID_GNE_VEHICLE_TRANSFORM_FLOW_EMBEDDED);
277
GUIDesigns::buildFXMenuCommand(transformOperation,
278
TL("Trips"),
279
GUIIconSubSys::getIcon(GUIIcon::TRIP), this, MID_GNE_VEHICLE_TRANSFORM_TRIP);
280
GUIDesigns::buildFXMenuCommand(transformOperation,
281
TL("Flows"),
282
GUIIconSubSys::getIcon(GUIIcon::FLOW), this, MID_GNE_VEHICLE_TRANSFORM_FLOW);
283
}
284
}
285
}
286
287
288
GNEVehicle::GNESelectedVehiclesPopupMenu::~GNESelectedVehiclesPopupMenu() {}
289
290
291
long
292
GNEVehicle::GNESelectedVehiclesPopupMenu::onCmdTransform(FXObject* obj, FXSelector sel, void*) {
293
// iterate over all selected vehicles
294
for (const auto& vehicle : mySelectedVehicles) {
295
switch (FXSELID(sel)) {
296
case MID_GNE_VEHICLE_TRANSFORM_TRIP:
297
if (!vehicle->getTagProperty()->vehicleJunctions() && !vehicle->getTagProperty()->vehicleTAZs()) {
298
if (myRestrictedMenuCommands.count(obj) > 0) {
299
if (vehicle->getTagProperty()->getTag() == myRestrictedMenuCommands.at(obj)) {
300
GNERouteHandler::transformToTrip(vehicle);
301
}
302
} else {
303
GNERouteHandler::transformToTrip(vehicle);
304
}
305
}
306
break;
307
case MID_GNE_VEHICLE_TRANSFORM_FLOW:
308
if (!vehicle->getTagProperty()->vehicleJunctions() && !vehicle->getTagProperty()->vehicleTAZs()) {
309
if (myRestrictedMenuCommands.count(obj) > 0) {
310
if (vehicle->getTagProperty()->getTag() == myRestrictedMenuCommands.at(obj)) {
311
GNERouteHandler::transformToFlow(vehicle);
312
}
313
} else {
314
GNERouteHandler::transformToFlow(vehicle);
315
}
316
}
317
break;
318
case MID_GNE_VEHICLE_TRANSFORM_VEHICLE:
319
if (!vehicle->getTagProperty()->vehicleJunctions() && !vehicle->getTagProperty()->vehicleTAZs()) {
320
if (myRestrictedMenuCommands.count(obj) > 0) {
321
if (vehicle->getTagProperty()->getTag() == myRestrictedMenuCommands.at(obj)) {
322
GNERouteHandler::transformToVehicle(vehicle, false);
323
}
324
} else {
325
GNERouteHandler::transformToVehicle(vehicle, false);
326
}
327
}
328
break;
329
case MID_GNE_VEHICLE_TRANSFORM_ROUTEFLOW:
330
if (!vehicle->getTagProperty()->vehicleJunctions() && !vehicle->getTagProperty()->vehicleTAZs()) {
331
if (myRestrictedMenuCommands.count(obj) > 0) {
332
if (vehicle->getTagProperty()->getTag() == myRestrictedMenuCommands.at(obj)) {
333
GNERouteHandler::transformToRouteFlow(vehicle, false);
334
}
335
} else {
336
GNERouteHandler::transformToRouteFlow(vehicle, false);
337
}
338
}
339
break;
340
case MID_GNE_VEHICLE_TRANSFORM_VEHICLE_EMBEDDED:
341
if (!vehicle->getTagProperty()->vehicleJunctions() && !vehicle->getTagProperty()->vehicleTAZs()) {
342
if (myRestrictedMenuCommands.count(obj) > 0) {
343
if (vehicle->getTagProperty()->getTag() == myRestrictedMenuCommands.at(obj)) {
344
GNERouteHandler::transformToVehicle(vehicle, true);
345
}
346
} else {
347
GNERouteHandler::transformToVehicle(vehicle, true);
348
}
349
}
350
break;
351
case MID_GNE_VEHICLE_TRANSFORM_FLOW_EMBEDDED:
352
if (!vehicle->getTagProperty()->vehicleJunctions() && !vehicle->getTagProperty()->vehicleTAZs()) {
353
if (myRestrictedMenuCommands.count(obj) > 0) {
354
if (vehicle->getTagProperty()->getTag() == myRestrictedMenuCommands.at(obj)) {
355
GNERouteHandler::transformToRouteFlow(vehicle, true);
356
}
357
} else {
358
GNERouteHandler::transformToRouteFlow(vehicle, true);
359
}
360
}
361
break;
362
case MID_GNE_VEHICLE_TRANSFORM_TRIP_JUNCTIONS:
363
if (vehicle->getTagProperty()->vehicleJunctions()) {
364
if (myRestrictedMenuCommands.count(obj) > 0) {
365
if (vehicle->getTagProperty()->getTag() == myRestrictedMenuCommands.at(obj)) {
366
GNERouteHandler::transformToTripJunctions(vehicle);
367
}
368
} else {
369
GNERouteHandler::transformToTripJunctions(vehicle);
370
}
371
}
372
break;
373
case MID_GNE_VEHICLE_TRANSFORM_FLOW_JUNCTIONS:
374
if (vehicle->getTagProperty()->vehicleJunctions()) {
375
if (myRestrictedMenuCommands.count(obj) > 0) {
376
if (vehicle->getTagProperty()->getTag() == myRestrictedMenuCommands.at(obj)) {
377
GNERouteHandler::transformToFlowJunctions(vehicle);
378
}
379
} else {
380
GNERouteHandler::transformToFlowJunctions(vehicle);
381
}
382
}
383
break;
384
case MID_GNE_VEHICLE_TRANSFORM_TRIP_TAZS:
385
if (vehicle->getTagProperty()->vehicleTAZs()) {
386
if (myRestrictedMenuCommands.count(obj) > 0) {
387
if (vehicle->getTagProperty()->getTag() == myRestrictedMenuCommands.at(obj)) {
388
GNERouteHandler::transformToTripTAZs(vehicle);
389
}
390
} else {
391
GNERouteHandler::transformToTripTAZs(vehicle);
392
}
393
}
394
break;
395
case MID_GNE_VEHICLE_TRANSFORM_FLOW_TAZS:
396
if (vehicle->getTagProperty()->vehicleTAZs()) {
397
if (myRestrictedMenuCommands.count(obj) > 0) {
398
if (vehicle->getTagProperty()->getTag() == myRestrictedMenuCommands.at(obj)) {
399
GNERouteHandler::transformToFlowTAZs(vehicle);
400
}
401
} else {
402
GNERouteHandler::transformToFlowTAZs(vehicle);
403
}
404
}
405
break;
406
default:
407
break;
408
}
409
}
410
return 1;
411
}
412
413
// ===========================================================================
414
// member method definitions
415
// ===========================================================================
416
#ifdef _MSC_VER
417
#pragma warning(push)
418
#pragma warning(disable: 4355) // mask warning about "this" in initializers
419
#endif
420
GNEVehicle::GNEVehicle(SumoXMLTag tag, GNENet* net) :
421
GNEDemandElement(net, tag),
422
GNEDemandElementFlow(this),
423
myMoveElementView(new GNEMoveElementView(this, GNEMoveElementView::AttributesFormat::POSITION,
424
SUMO_ATTR_POSITION, myPosOverView)) {
425
// set end and vehPerHours as default flow values
426
toggleAttribute(SUMO_ATTR_END, true);
427
toggleAttribute(SUMO_ATTR_VEHSPERHOUR, true);
428
}
429
430
431
GNEVehicle::GNEVehicle(SumoXMLTag tag, const std::string& vehicleID, GNENet* net, FileBucket* fileBucket,
432
GNEDemandElement* vehicleType, GNEDemandElement* route) :
433
GNEDemandElement(vehicleID, net, tag, fileBucket),
434
GNEDemandElementFlow(this),
435
myMoveElementView(new GNEMoveElementView(this, GNEMoveElementView::AttributesFormat::POSITION,
436
SUMO_ATTR_POSITION, myPosOverView)) {
437
// set parents
438
setParents<GNEDemandElement*>({vehicleType, route});
439
// SUMOVehicleParameter ID has to be set manually
440
id = vehicleID;
441
// set manually vtypeID (needed for saving)
442
vtypeid = vehicleType->getID();
443
}
444
445
446
GNEVehicle::GNEVehicle(SumoXMLTag tag, GNENet* net, FileBucket* fileBucket, GNEDemandElement* vehicleType,
447
GNEDemandElement* route, const SUMOVehicleParameter& vehicleParameters) :
448
GNEDemandElement(vehicleParameters.id, net, tag, fileBucket),
449
GNEDemandElementFlow(this, vehicleParameters),
450
myMoveElementView(new GNEMoveElementView(this, GNEMoveElementView::AttributesFormat::POSITION,
451
SUMO_ATTR_POSITION, myPosOverView)) {
452
// set parents
453
setParents<GNEDemandElement*>({vehicleType, route});
454
// SUMOVehicleParameter ID has to be set manually
455
id = vehicleParameters.id;
456
// set manually vtypeID (needed for saving)
457
vtypeid = vehicleType->getID();
458
}
459
460
461
GNEVehicle::GNEVehicle(SumoXMLTag tag, GNENet* net, FileBucket* fileBucket, GNEDemandElement* vehicleType,
462
const SUMOVehicleParameter& vehicleParameters) :
463
GNEDemandElement(vehicleParameters.id, net, tag, fileBucket),
464
GNEDemandElementFlow(this, vehicleParameters),
465
myMoveElementView(new GNEMoveElementView(this, GNEMoveElementView::AttributesFormat::POSITION,
466
SUMO_ATTR_POSITION, myPosOverView)) {
467
// set parents
468
setParent<GNEDemandElement*>(vehicleType);
469
// SUMOVehicleParameter ID has to be set manually
470
id = vehicleParameters.id;
471
// reset routeid
472
routeid.clear();
473
// set manually vtypeID (needed for saving)
474
vtypeid = vehicleType->getID();
475
}
476
477
478
GNEVehicle::GNEVehicle(SumoXMLTag tag, const std::string& vehicleID, GNENet* net, FileBucket* fileBucket,
479
GNEDemandElement* vehicleType, GNEEdge* fromEdge, GNEEdge* toEdge) :
480
GNEDemandElement(vehicleID, net, tag, fileBucket),
481
GNEDemandElementFlow(this),
482
myMoveElementVehicle(new GNEMoveElementVehicle(this, fromEdge, toEdge)),
483
myMoveElementView(new GNEMoveElementView(this, GNEMoveElementView::AttributesFormat::POSITION,
484
SUMO_ATTR_POSITION, myPosOverView)) {
485
// set parents
486
setParents<GNEEdge*>({fromEdge, toEdge});
487
setParent<GNEDemandElement*>(vehicleType);
488
}
489
490
491
GNEVehicle::GNEVehicle(SumoXMLTag tag, GNENet* net, FileBucket* fileBucket, GNEDemandElement* vehicleType,
492
GNEEdge* fromEdge, GNEEdge* toEdge, const SUMOVehicleParameter& vehicleParameters) :
493
GNEDemandElement(vehicleParameters.id, net, tag, fileBucket),
494
GNEDemandElementFlow(this, vehicleParameters),
495
myMoveElementVehicle(new GNEMoveElementVehicle(this, fromEdge, toEdge)),
496
myMoveElementView(new GNEMoveElementView(this, GNEMoveElementView::AttributesFormat::POSITION,
497
SUMO_ATTR_POSITION, myPosOverView)) {
498
// set parents
499
setParents<GNEEdge*>({fromEdge, toEdge});
500
setParent<GNEDemandElement*>(vehicleType);
501
}
502
503
504
GNEVehicle::GNEVehicle(SumoXMLTag tag, const std::string& vehicleID, GNENet* net, FileBucket* fileBucket,
505
GNEDemandElement* vehicleType, GNEJunction* fromJunction, GNEJunction* toJunction) :
506
GNEDemandElement(vehicleID, net, tag, fileBucket),
507
GNEDemandElementFlow(this),
508
myMoveElementView(new GNEMoveElementView(this, GNEMoveElementView::AttributesFormat::POSITION,
509
SUMO_ATTR_POSITION, myPosOverView)) {
510
// set parents
511
setParents<GNEJunction*>({fromJunction, toJunction});
512
setParent<GNEDemandElement*>(vehicleType);
513
}
514
515
516
GNEVehicle::GNEVehicle(SumoXMLTag tag, GNENet* net, FileBucket* fileBucket, GNEDemandElement* vehicleType,
517
GNEJunction* fromJunction, GNEJunction* toJunction, const SUMOVehicleParameter& vehicleParameters) :
518
GNEDemandElement(vehicleParameters.id, net, tag, fileBucket),
519
GNEDemandElementFlow(this, vehicleParameters),
520
myMoveElementView(new GNEMoveElementView(this, GNEMoveElementView::AttributesFormat::POSITION,
521
SUMO_ATTR_POSITION, myPosOverView)) {
522
// set parents
523
setParents<GNEJunction*>({fromJunction, toJunction});
524
setParent<GNEDemandElement*>(vehicleType);
525
}
526
527
528
GNEVehicle::GNEVehicle(SumoXMLTag tag, GNENet* net, FileBucket* fileBucket, GNEDemandElement* vehicleType,
529
GNEAdditional* fromTAZ, GNEAdditional* toTAZ, const SUMOVehicleParameter& vehicleParameters) :
530
GNEDemandElement(vehicleParameters.id, net, tag, fileBucket),
531
GNEDemandElementFlow(this, vehicleParameters),
532
myMoveElementView(new GNEMoveElementView(this, GNEMoveElementView::AttributesFormat::POSITION,
533
SUMO_ATTR_POSITION, myPosOverView)) {
534
// set parents
535
setParents<GNEAdditional*>({fromTAZ, toTAZ});
536
setParent<GNEDemandElement*>(vehicleType);
537
// mark taz parameters as set
538
parametersSet |= VEHPARS_FROM_TAZ_SET;
539
parametersSet |= VEHPARS_TO_TAZ_SET;
540
fromTaz = fromTAZ->getID();
541
toTaz = toTAZ->getID();
542
}
543
#ifdef _MSC_VER
544
#pragma warning(pop)
545
#endif
546
547
548
GNEVehicle::~GNEVehicle() {}
549
550
551
GNEMoveElement*
552
GNEVehicle::getMoveElement() const {
553
return myMoveElementVehicle;
554
}
555
556
557
Parameterised*
558
GNEVehicle::getParameters() {
559
return this;
560
}
561
562
563
const Parameterised*
564
GNEVehicle::getParameters() const {
565
return this;
566
}
567
568
569
void
570
GNEVehicle::writeDemandElement(OutputDevice& device) const {
571
// attribute VType must not be written if is DEFAULT_VTYPE_ID
572
if (getTypeParent()->getID() == DEFAULT_VTYPE_ID) {
573
// unset VType parameter
574
parametersSet &= ~VEHPARS_VTYPE_SET;
575
// write vehicle attributes (VType will not be written)
576
write(device, OptionsCont::getOptions(), myTagProperty->getXMLTag());
577
// set VType parameter again
578
parametersSet |= VEHPARS_VTYPE_SET;
579
} else {
580
// write vehicle attributes, including type/distribution
581
write(device, OptionsCont::getOptions(), myTagProperty->getXMLTag(), getParentDemandElements().front()->getID());
582
}
583
// write route
584
if (myTagProperty->vehicleRoute()) {
585
// write route
586
device.writeAttr(SUMO_ATTR_ROUTE, getRouteParent()->getID());
587
}
588
// write from, to and edge vias
589
if (myTagProperty->vehicleEdges()) {
590
// write manually from/to edges (it correspond to front and back parent edges)
591
device.writeAttr(SUMO_ATTR_FROM, getParentEdges().front()->getID());
592
device.writeAttr(SUMO_ATTR_TO, getParentEdges().back()->getID());
593
// only write via if there isn't empty
594
if (via.size() > 0) {
595
device.writeAttr(SUMO_ATTR_VIA, via);
596
}
597
}
598
// write from and to junctions
599
if (myTagProperty->vehicleJunctions()) {
600
// write manually from/to junctions (it correspond to front and back parent junctions)
601
device.writeAttr(SUMO_ATTR_FROM_JUNCTION, getParentJunctions().front()->getID());
602
device.writeAttr(SUMO_ATTR_TO_JUNCTION, getParentJunctions().back()->getID());
603
}
604
// write parameters
605
writeParams(device);
606
// write route elements associated to this vehicle (except for calibrator FLows)
607
if ((getChildDemandElements().size() > 0) && !myTagProperty->isCalibrator()) {
608
if (getChildDemandElements().front()->getTagProperty()->getTag() == GNE_TAG_ROUTE_EMBEDDED) {
609
// write embedded route
610
getChildDemandElements().front()->writeDemandElement(device);
611
// write stops
612
for (const auto& demandElement : getChildDemandElements()) {
613
if (demandElement->getTagProperty()->isVehicleStop()) {
614
demandElement->writeDemandElement(device);
615
}
616
}
617
} else {
618
for (const auto& route : getChildDemandElements()) {
619
route->writeDemandElement(device);
620
}
621
}
622
}
623
// close vehicle tag
624
device.closeTag();
625
}
626
627
628
GNEDemandElement::Problem
629
GNEVehicle::isDemandElementValid() const {
630
// check conditions
631
if (myTagProperty->vehicleTAZs()) {
632
// vehicles and flows over tazs are always valid
633
return Problem::OK;
634
} else if (myTagProperty->vehicleEdges()) {
635
// check vehicles and flows paths
636
if (getParentEdges().front() == getParentEdges().back()) {
637
return Problem::OK;
638
} else if (myNet->getDemandPathManager()->isPathValid(this)) {
639
return Problem::OK;
640
} else {
641
return Problem::INVALID_PATH;
642
}
643
} else if (myTagProperty->vehicleJunctions()) {
644
// check vehicles and flows paths
645
if (getParentJunctions().front() == getParentJunctions().back()) {
646
return Problem::OK;
647
} else if (myNet->getDemandPathManager()->isPathValid(this)) {
648
return Problem::OK;
649
} else {
650
return Problem::INVALID_PATH;
651
}
652
} else if (myTagProperty->vehicleRoute()) {
653
// check if routeParent is a distribution
654
if (getRouteParent()->getTagProperty()->isRouteDistribution()) {
655
return Problem::OK;
656
} else {
657
// check if exist a valid path using route parent edges
658
if (myNet->getDemandPathManager()->getPathCalculator()->calculateDijkstraPath(getTypeParent()->getVClass(), getRouteParent()->getParentEdges()).size() > 0) {
659
return Problem::OK;
660
} else {
661
return Problem::INVALID_PATH;
662
}
663
}
664
} else if (myTagProperty->vehicleRouteEmbedded()) {
665
// check if exist a valid path using route child edges
666
if (myNet->getDemandPathManager()->getPathCalculator()->calculateDijkstraPath(getTypeParent()->getVClass(), getChildDemandElements().at(0)->getParentEdges()).size() > 0) {
667
return Problem::OK;
668
} else {
669
return Problem::INVALID_PATH;
670
}
671
} else {
672
return Problem::INVALID_ELEMENT;
673
}
674
}
675
676
677
std::string
678
GNEVehicle::getDemandElementProblem() const {
679
// only trips or flows can have problems
680
if (myTagProperty->vehicleEdges()) {
681
// check if exist at least a connection between every edge
682
for (int i = 1; i < (int)getParentEdges().size(); i++) {
683
if (myNet->getDemandPathManager()->getPathCalculator()->consecutiveEdgesConnected(getTypeParent()->getVClass(), getParentEdges().at((int)i - 1), getParentEdges().at(i)) == false) {
684
return ("There is no valid path between edges '" + getParentEdges().at((int)i - 1)->getID() + "' and '" + getParentEdges().at(i)->getID() + "'");
685
}
686
}
687
// if there are connections between all edges, then all is ok
688
return "";
689
} else if (myTagProperty->vehicleJunctions()) {
690
return ("No path between junction '" + getParentJunctions().front()->getID() + "' and '" + getParentJunctions().back()->getID() + "'");
691
} else if (myTagProperty->vehicleRoute()) {
692
// get route parent edges
693
const std::vector<GNEEdge*>& routeEdges = getRouteParent()->getParentEdges();
694
// check if exist at least a connection between every edge
695
for (int i = 1; i < (int)routeEdges.size(); i++) {
696
if (myNet->getDemandPathManager()->getPathCalculator()->consecutiveEdgesConnected(getTypeParent()->getVClass(), routeEdges.at((int)i - 1), routeEdges.at(i)) == false) {
697
return ("There is no valid path between route edges '" + routeEdges.at((int)i - 1)->getID() + "' and '" + routeEdges.at(i)->getID() + "'");
698
}
699
}
700
// if there are connections between all edges, then all is ok
701
return "";
702
} else if (myTagProperty->vehicleRouteEmbedded()) {
703
// get route parent edges
704
const std::vector<GNEEdge*>& routeEdges = getChildDemandElements().at(0)->getParentEdges();
705
// check if exist at least a connection between every edge
706
for (int i = 1; i < (int)routeEdges.size(); i++) {
707
if (myNet->getDemandPathManager()->getPathCalculator()->consecutiveEdgesConnected(getTypeParent()->getVClass(), routeEdges.at((int)i - 1), routeEdges.at(i)) == false) {
708
return ("There is no valid path between embedded route edges '" + routeEdges.at((int)i - 1)->getID() + "' and '" + routeEdges.at(i)->getID() + "'");
709
}
710
}
711
// if there are connections between all edges, then all is ok
712
return "";
713
} else {
714
return "";
715
}
716
}
717
718
719
void
720
GNEVehicle::fixDemandElementProblem() {
721
//
722
}
723
724
725
SUMOVehicleClass
726
GNEVehicle::getVClass() const {
727
return getParentDemandElements().front()->getVClass();
728
}
729
730
731
const RGBColor&
732
GNEVehicle::getColor() const {
733
return color;
734
}
735
736
737
void
738
GNEVehicle::updateGeometry() {
739
if (myTagProperty->vehicleRoute() && getRouteParent()->getTagProperty()->isRouteDistribution()) {
740
// remove vehicle from grid
741
myNet->removeGLObjectFromGrid(this);
742
// reset view position to 0
743
myPosOverView = Position(0, 0);
744
// continue depending if the routeDistribution have references
745
for (auto routeRef : getParentDemandElements().at(1)->getChildDemandElements()) {
746
if (routeRef->getTagProperty()->isDistributionReference()) {
747
myPosOverView = routeRef->getParentDemandElements().at(1)->getParentEdges().front()->getChildLanes().at(0)->getLaneShape().front();
748
break;
749
}
750
}
751
// update vehicle geometry
752
myDemandElementGeometry.updateGeometry({myPosOverView - Position(1, 0), myPosOverView + Position(1, 0)});
753
// add object in grid again
754
myNet->addGLObjectIntoGrid(this);
755
} else if (getParentJunctions().size() > 0) {
756
// calculate rotation between both junctions
757
const Position posA = getParentJunctions().front()->getPositionInView();
758
const Position posB = getParentJunctions().back()->getPositionInView();
759
const double rot = ((double)atan2((posB.x() - posA.x()), (posA.y() - posB.y())) * (double) -180.0 / (double)M_PI);
760
// update Geometry
761
myDemandElementGeometry.updateSinglePosGeometry(getParentJunctions().front()->getPositionInView(), rot);
762
} else if (getParentAdditionals().size() > 0) {
763
// calculate rotation between both TAZs
764
const Position posA = getParentAdditionals().front()->getAttribute(SUMO_ATTR_CENTER).empty() ?
765
getParentAdditionals().front()->getAttributePosition(GNE_ATTR_TAZ_CENTROID) :
766
getParentAdditionals().front()->getAttributePosition(SUMO_ATTR_CENTER);
767
const Position posB = getParentAdditionals().back()->getAttribute(SUMO_ATTR_CENTER).empty() ?
768
getParentAdditionals().back()->getAttributePosition(GNE_ATTR_TAZ_CENTROID) :
769
getParentAdditionals().back()->getAttributePosition(SUMO_ATTR_CENTER);
770
const double rot = ((double)atan2((posB.x() - posA.x()), (posA.y() - posB.y())) * (double) -180.0 / (double)M_PI);
771
// update Geometry
772
myDemandElementGeometry.updateSinglePosGeometry(posA, rot);
773
} else {
774
// get first path lane
775
const GNELane* firstPathLane = getFirstPathLane();
776
// check path lane
777
if (firstPathLane) {
778
// declare departPos
779
double posOverLane = 0;
780
if (wasSet(VEHPARS_DEPARTPOS_SET) && (departPosProcedure == DepartPosDefinition::GIVEN)) {
781
posOverLane = departPos;
782
}
783
// update Geometry
784
myDemandElementGeometry.updateGeometry(firstPathLane->getLaneShape(), posOverLane, 0 /*myMovingLateralOffset*/);
785
// compute route embedded associated with this vehicle
786
for (const auto& demandElement : getChildDemandElements()) {
787
if (demandElement->getTagProperty()->getTag() == GNE_TAG_ROUTE_EMBEDDED) {
788
demandElement->computePathElement();
789
}
790
demandElement->updateGeometry();
791
}
792
}
793
}
794
}
795
796
797
Position
798
GNEVehicle::getPositionInView() const {
799
if (myTagProperty->vehicleRouteEmbedded()) {
800
return myPosOverView;
801
} else {
802
return myDemandElementGeometry.getShape().front();
803
}
804
}
805
806
807
bool
808
GNEVehicle::checkDrawRelatedContour() const {
809
// get edit modes
810
const auto& editModes = myNet->getViewNet()->getEditModes();
811
// check if we're editing a type
812
if (editModes.isCurrentSupermodeDemand() && (editModes.demandEditMode == DemandEditMode::DEMAND_TYPE) &&
813
(myNet->getViewParent()->getTypeFrame()->getTypeSelector()->getCurrentType() == getParentDemandElements().front())) {
814
return true;
815
}
816
// check opened popup
817
if (myNet->getViewNet()->getPopup()) {
818
return myNet->getViewNet()->getPopup()->getGLObject() == this;
819
}
820
return false;
821
}
822
823
824
GUIGLObjectPopupMenu*
825
GNEVehicle::getPopUpMenu(GUIMainWindow& app, GUISUMOAbstractView& parent) {
826
if (isAttributeCarrierSelected()) {
827
// obtain all selected vehicles
828
const auto selectedDemandElements = myNet->getAttributeCarriers()->getSelectedDemandElements();
829
std::vector<GNEVehicle*> selectedVehicles;
830
selectedVehicles.reserve(selectedDemandElements.size());
831
for (const auto& selectedDemandElement : selectedDemandElements) {
832
if (selectedDemandElement->getTagProperty()->isVehicle()) {
833
selectedVehicles.push_back(dynamic_cast<GNEVehicle*>(selectedDemandElement));
834
}
835
}
836
// return a GNESelectedVehiclesPopupMenu
837
return new GNESelectedVehiclesPopupMenu(this, selectedVehicles, app, parent);
838
} else {
839
// return a GNESingleVehiclePopupMenu
840
return new GNESingleVehiclePopupMenu(this, app, parent);
841
}
842
}
843
844
845
std::string
846
GNEVehicle::getParentName() const {
847
if (myTagProperty->vehicleRoute()) {
848
return getRouteParent()->getID();
849
} else if (myTagProperty->vehicleEdges()) {
850
return getParentEdges().front()->getID();
851
} else if (myTagProperty->vehicleJunctions()) {
852
return getParentJunctions().front()->getID();
853
} else if (myTagProperty->vehicleTAZs()) {
854
return getParentAdditionals().front()->getID();
855
} else {
856
throw ProcessError(TL("Invalid vehicle tag"));
857
}
858
}
859
860
861
double
862
GNEVehicle::getExaggeration(const GUIVisualizationSettings& s) const {
863
return s.vehicleSize.getExaggeration(s, this);
864
}
865
866
867
Boundary
868
GNEVehicle::getCenteringBoundary() const {
869
Boundary vehicleBoundary;
870
if (myTagProperty->vehicleRoute() && getRouteParent()->getTagProperty()->isRouteDistribution()) {
871
vehicleBoundary.add(myPosOverView);
872
} else {
873
vehicleBoundary.add(myDemandElementGeometry.getShape().front());
874
}
875
vehicleBoundary.grow(20);
876
return vehicleBoundary;
877
}
878
879
880
void
881
GNEVehicle::splitEdgeGeometry(const double /*splitPosition*/, const GNENetworkElement* /*originalElement*/, const GNENetworkElement* /*newElement*/, GNEUndoList* /*undoList*/) {
882
// geometry of this element cannot be splitted
883
}
884
885
886
void
887
GNEVehicle::drawGL(const GUIVisualizationSettings& s) const {
888
// only drawn in super mode demand
889
if (myNet->getViewNet()->getNetworkViewOptions().showDemandElements() &&
890
myNet->getViewNet()->getDataViewOptions().showDemandElements() &&
891
myNet->getViewNet()->getDemandViewOptions().showNonInspectedDemandElements(this)) {
892
// declare common attributes
893
const bool drawSpreadVehicles = (myNet->getViewNet()->getNetworkViewOptions().drawSpreadVehicles() || myNet->getViewNet()->getDemandViewOptions().drawSpreadVehicles());
894
const double exaggeration = getExaggeration(s);
895
const double width = getTypeParent()->getAttributeDouble(SUMO_ATTR_WIDTH);
896
const double length = getTypeParent()->getAttributeDouble(SUMO_ATTR_LENGTH);
897
// obtain Position an rotation (depending of draw spread vehicles)
898
if ((!drawSpreadVehicles || (mySpreadGeometry.getShape().size() > 0)) && (myDemandElementGeometry.getShape().size() > 0)) {
899
const Position vehiclePosition = drawSpreadVehicles ? mySpreadGeometry.getShape().front() : myDemandElementGeometry.getShape().front();
900
const double vehicleRotation = drawSpreadVehicles ? mySpreadGeometry.getShapeRotations().front() : myDemandElementGeometry.getShapeRotations().front();
901
// check that position is valid
902
if (vehiclePosition == Position::INVALID) {
903
return;
904
}
905
// get detail level
906
const auto d = s.getDetailLevel(exaggeration);
907
// draw geometry only if we'rent in drawForObjectUnderCursor mode
908
if (s.checkDrawVehicle(d, isAttributeCarrierSelected())) {
909
SUMOVehicleShape shape = getVehicleShapeID(getTypeParent()->getAttribute(SUMO_ATTR_GUISHAPE));
910
// push draw matrix
911
GLHelper::pushMatrix();
912
// Start with the drawing of the area translating matrix to origin
913
drawInLayer(getType());
914
// translate to drawing position
915
glTranslated(vehiclePosition.x(), vehiclePosition.y(), 0);
916
glRotated(vehicleRotation, 0, 0, -1);
917
// extra translation needed to draw vehicle over edge (to avoid selecting problems)
918
glTranslated(0, (-1) * length * exaggeration, 0);
919
// set lane color
920
GLHelper::setColor(getDrawingColor(s));
921
double upscaleLength = exaggeration;
922
if ((exaggeration > 1) && (length > 5)) {
923
// reduce the length/width ratio because this is not useful at high zoom
924
upscaleLength = MAX2(1.0, upscaleLength * (5 + sqrt(length - 5)) / length);
925
}
926
glScaled(exaggeration, upscaleLength, 1);
927
// draw the vehicle depending of detail level
928
if (d <= GUIVisualizationSettings::Detail::VehiclePoly) {
929
GUIBaseVehicleHelper::drawAction_drawVehicleAsPoly(s, shape, width, length);
930
} else if (d <= GUIVisualizationSettings::Detail::VehicleBox) {
931
GUIBaseVehicleHelper::drawAction_drawVehicleAsBoxPlus(width, length);
932
} else if (d <= GUIVisualizationSettings::Detail::VehicleTriangle) {
933
GUIBaseVehicleHelper::drawAction_drawVehicleAsTrianglePlus(width, length);
934
}
935
// check if min gap has to be drawn
936
if (s.drawMinGap) {
937
const double minGap = -1 * getTypeParent()->getAttributeDouble(SUMO_ATTR_MINGAP);
938
glColor3d(0., 1., 0.);
939
glBegin(GL_LINES);
940
glVertex2d(0., 0);
941
glVertex2d(0., minGap);
942
glVertex2d(-.5, minGap);
943
glVertex2d(.5, minGap);
944
glEnd();
945
}
946
// drawing name at GLO_MAX fails unless translating z
947
glTranslated(0, MIN2(length / 2, double(5)), -getType());
948
glScaled(1 / exaggeration, 1 / upscaleLength, 1);
949
glRotated(-vehicleRotation, 0, 0, -1);
950
drawName(Position(0, 0), s.scale, getTypeParent()->getAttribute(SUMO_ATTR_GUISHAPE) == "pedestrian" ? s.personName : s.vehicleName, s.angle);
951
// draw line
952
if (s.vehicleName.show(this) && line != "") {
953
glTranslated(0, 0.6 * s.vehicleName.scaledSize(s.scale), 0);
954
GLHelper::drawTextSettings(s.vehicleName, "line:" + line, Position(0, 0), s.scale, s.angle);
955
}
956
// pop draw matrix
957
GLHelper::popMatrix();
958
// draw line between junctions if path isn't valid
959
if ((getParentJunctions().size() > 0) && !myNet->getDemandPathManager()->isPathValid(this)) {
960
drawJunctionLine(this);
961
}
962
// draw lock icon
963
GNEViewNetHelper::LockIcon::drawLockIcon(d, this, getType(), vehiclePosition, exaggeration);
964
// draw stack label
965
if ((myStackedLabelNumber > 0) && !drawSpreadVehicles) {
966
drawStackLabel(myStackedLabelNumber, "Vehicle", vehiclePosition, vehicleRotation, width, length, exaggeration);
967
}
968
// draw flow label
969
if (myTagProperty->isFlow()) {
970
drawFlowLabel(vehiclePosition, vehicleRotation, width, length, exaggeration);
971
}
972
// draw dotted contour
973
myVehicleContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);
974
}
975
// draw squared shape
976
myVehicleContour.calculateContourRectangleShape(s, d, this, vehiclePosition, length * 0.5, width * 0.5, getType(),
977
length * -0.5, 0, vehicleRotation, exaggeration, nullptr);
978
}
979
}
980
}
981
982
983
void
984
GNEVehicle::computePathElement() {
985
// calculate path (only for flows and trips)
986
if (myTagProperty->vehicleJunctions()) {
987
// calculate path
988
myNet->getDemandPathManager()->calculatePath(this, getVClass(), getParentJunctions().front(), getParentJunctions().back());
989
} else if (myTagProperty->vehicleEdges()) {
990
// save edges in wich this vehicle has to stop
991
std::vector<GNEEdge*> edgeStops;
992
// iterate over child demand elements
993
for (const auto& demandElement : getChildDemandElements()) {
994
// extract lanes
995
if (demandElement->getTagProperty()->isVehicleStop()) {
996
GNEEdge* edgeStop = nullptr;
997
if (demandElement->getParentAdditionals().size() > 0) {
998
edgeStop = demandElement->getParentAdditionals().front()->getParentLanes().front()->getParentEdge();
999
} else {
1000
edgeStop = demandElement->getParentLanes().front()->getParentEdge();
1001
}
1002
if (edgeStop) {
1003
// avoid double edge stops
1004
if (stops.empty()) {
1005
edgeStops.push_back(edgeStop);
1006
} else if (edgeStops.back() != edgeStop) {
1007
edgeStops.push_back(edgeStop);
1008
}
1009
}
1010
}
1011
}
1012
// declare edge vector
1013
std::vector<GNEEdge*> edgePath;
1014
// get first and last lanes
1015
const auto firstLane = getFirstPathLane();
1016
const auto lastLane = getLastPathLane();
1017
// check first and last lanes
1018
if (firstLane && lastLane) {
1019
// add first lane
1020
edgePath.push_back(firstLane->getParentEdge());
1021
// give more priority to stops instead via
1022
if (edgeStops.size() > 0) {
1023
// add stops only if they're accesibles
1024
for (const auto& edgeStop : edgeStops) {
1025
// check if exist a valid path that includes the last edge
1026
auto edgePathStop = edgePath;
1027
edgePathStop.push_back(edgeStop);
1028
edgePathStop.push_back(lastLane->getParentEdge());
1029
auto path = myNet->getDemandPathManager()->getPathCalculator()->calculateDijkstraPath(getVClass(), edgePathStop);
1030
if (path.size() > 0) {
1031
edgePath.push_back(edgeStop);
1032
}
1033
}
1034
} else {
1035
// add via lanes
1036
for (const auto& edgeViaID : via) {
1037
const auto edgeVia = myNet->getAttributeCarriers()->retrieveEdge(edgeViaID, false);
1038
if (edgeVia) {
1039
// check if exist a valid path that includes the last edge
1040
auto edgePathStop = edgePath;
1041
edgePathStop.push_back(edgeVia);
1042
edgePathStop.push_back(lastLane->getParentEdge());
1043
if (myNet->getDemandPathManager()->getPathCalculator()->calculateDijkstraPath(getVClass(), edgePathStop).size() > 0) {
1044
edgePath.push_back(edgeVia);
1045
}
1046
}
1047
}
1048
}
1049
// add last lane
1050
edgePath.push_back(lastLane->getParentEdge());
1051
// calculate path
1052
myNet->getDemandPathManager()->calculatePath(this, getVClass(), edgePath);
1053
}
1054
}
1055
// update geometry
1056
updateGeometry();
1057
}
1058
1059
1060
void
1061
GNEVehicle::drawLanePartialGL(const GUIVisualizationSettings& s, const GNESegment* segment, const double offsetFront) const {
1062
// conditions for draw always in network mode
1063
const bool drawInNetworkMode = myNet->getViewNet()->getEditModes().isCurrentSupermodeNetwork() &&
1064
myNet->getViewNet()->getNetworkViewOptions().showDemandElements() &&
1065
myNet->getViewNet()->getDemandViewOptions().showAllTrips();
1066
// conditions for draw always in demand mode
1067
const bool drawInDemandMode = myNet->getViewNet()->getEditModes().isCurrentSupermodeDemand() &&
1068
myNet->getViewNet()->getDemandViewOptions().showAllTrips();
1069
// conditions for draw if is selected
1070
const bool isSelected = myNet->getViewNet()->getEditModes().isCurrentSupermodeDemand() &&
1071
isAttributeCarrierSelected();
1072
// conditions for draw if is inspected
1073
const bool isInspected = myNet->getViewNet()->getEditModes().isCurrentSupermodeDemand() &&
1074
myNet->getViewNet()->getInspectedElements().isACInspected(this);
1075
// check drawing conditions
1076
if (segment->getLane() && (drawInNetworkMode || drawInDemandMode || isSelected || isInspected) &&
1077
myNet->getDemandPathManager()->getPathDraw()->checkDrawPathGeometry(s, segment->getLane(), myTagProperty->getTag(), false)) {
1078
// get detail level
1079
const auto d = s.getDetailLevel(1);
1080
// calculate width
1081
const double width = s.vehicleSize.getExaggeration(s, segment->getLane()) * s.widthSettings.tripWidth;
1082
// calculate startPos
1083
const double geometryDepartPos = (getParentJunctions().size() > 0) ? 0 : getAttributeDouble(SUMO_ATTR_DEPARTPOS) + getTypeParent()->getAttributeDouble(SUMO_ATTR_LENGTH);
1084
// get endPos
1085
const double geometryEndPos = (getParentJunctions().size() > 0) ? segment->getLane()->getLaneGeometry().getShape().length2D() : getAttributeDouble(SUMO_ATTR_ARRIVALPOS);
1086
// declare path geometry
1087
GUIGeometry vehicleGeometry;
1088
// update pathGeometry depending of first and last segment
1089
if (segment->isFirstSegment() && segment->isLastSegment()) {
1090
vehicleGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1091
geometryDepartPos,
1092
Position::INVALID,
1093
geometryEndPos,
1094
Position::INVALID);
1095
} else if (segment->isFirstSegment()) {
1096
vehicleGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1097
geometryDepartPos,
1098
Position::INVALID,
1099
-1,
1100
Position::INVALID);
1101
} else if (segment->isLastSegment()) {
1102
vehicleGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1103
-1,
1104
Position::INVALID,
1105
geometryEndPos,
1106
Position::INVALID);
1107
} else {
1108
vehicleGeometry = segment->getLane()->getLaneGeometry();
1109
}
1110
// draw geometry only if we'rent in drawForObjectUnderCursor mode
1111
if (s.checkDrawVehicle(d, isAttributeCarrierSelected())) {
1112
// obtain color
1113
const RGBColor pathColor = drawUsingSelectColor() ? s.colorSettings.selectedVehicleColor : s.colorSettings.vehicleTripColor;
1114
// Add a draw matrix
1115
GLHelper::pushMatrix();
1116
// Start with the drawing of the area translating matrix to origin
1117
glTranslated(0, 0, getType() + offsetFront);
1118
// Set color
1119
GLHelper::setColor(pathColor);
1120
// draw geometry
1121
GUIGeometry::drawGeometry(d, vehicleGeometry, width);
1122
// show index over every edge
1123
if (isInspected && s.showRouteIndex) {
1124
const double textSize = s.vehicleName.size / s.scale;
1125
std::string label = toString(segment->getLaneIndex());
1126
Position pos = segment->getLane()->getLaneShape().front() - Position(0, textSize * 1);
1127
GLHelper::drawTextSettings(s.vehicleName, label, pos, s.scale, s.angle, 1.0);
1128
}
1129
// Pop last matrix
1130
GLHelper::popMatrix();
1131
// check if we have to draw a red line to the next segment (if next segment isnt' a junction
1132
if (segment->getNextLane()) {
1133
// push draw matrix
1134
GLHelper::pushMatrix();
1135
// Start with the drawing of the area translating matrix to origin
1136
drawInLayer(getType());
1137
// Set red color
1138
GLHelper::setColor(RGBColor::RED);
1139
// get firstPosition (last position of current lane shape)
1140
const Position& firstPosition = segment->getLane()->getLaneShape().back();
1141
// get lastPosition (first position of next lane shape)
1142
const Position& arrivalPosition = segment->getNextLane()->getLaneShape().front();
1143
// draw box line
1144
GLHelper::drawBoxLine(arrivalPosition,
1145
RAD2DEG(firstPosition.angleTo2D(arrivalPosition)) - 90,
1146
firstPosition.distanceTo2D(arrivalPosition), .05);
1147
// pop draw matrix
1148
GLHelper::popMatrix();
1149
}
1150
// check if this is the last segment
1151
if (segment->isLastSegment() && (getParentJunctions().size() == 0)) {
1152
// get geometryEndPos
1153
const Position geometryEndPosition = getAttributePosition(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
1154
// check if endPos can be drawn
1155
if (myNet->getViewNet()->getPositionInformation().distanceSquaredTo2D(geometryEndPosition) <= ((GNEMoveElementVehicle::arrivalPositionDiameter * GNEMoveElementVehicle::arrivalPositionDiameter) + 2)) {
1156
// push draw matrix
1157
GLHelper::pushMatrix();
1158
// Start with the drawing of the area translating matrix to origin
1159
drawInLayer(getType());
1160
// translate to geometryEndPos
1161
glTranslated(geometryEndPosition.x(), geometryEndPosition.y(), 0);
1162
// Set person plan color
1163
GLHelper::setColor(pathColor);
1164
// resolution of drawn circle depending of the zoom (To improve smoothness)
1165
GLHelper::drawFilledCircleDetailled(d, GNEMoveElementVehicle::arrivalPositionDiameter);
1166
// pop draw matrix
1167
GLHelper::popMatrix();
1168
}
1169
}
1170
// draw dotted contour
1171
segment->getContour()->drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);
1172
}
1173
// calculate contour and draw dotted geometry
1174
if (segment->isFirstSegment() || segment->isLastSegment()) {
1175
segment->getContour()->calculateContourExtrudedShape(s, d, this, vehicleGeometry.getShape(), getType(), width, 1, false, segment->isLastSegment(),
1176
0, segment, segment->getLane()->getParentEdge());
1177
} else {
1178
segment->getContour()->calculateContourExtrudedShape(s, d, this, segment->getLane()->getLaneShape(), getType(), width, 1, false, segment->isLastSegment(),
1179
0, segment, segment->getLane()->getParentEdge());
1180
}
1181
// check if add this path element to redraw buffer
1182
if (!gViewObjectsHandler.isPathElementMarkForRedraw(this) && segment->getContour()->checkDrawPathContour(s, d, this)) {
1183
gViewObjectsHandler.addToRedrawPathElements(this);
1184
}
1185
}
1186
}
1187
1188
1189
void
1190
GNEVehicle::drawJunctionPartialGL(const GUIVisualizationSettings& s, const GNESegment* segment, const double offsetFront) const {
1191
// conditions for draw always in network mode
1192
const bool drawInNetworkMode = myNet->getViewNet()->getEditModes().isCurrentSupermodeNetwork() &&
1193
myNet->getViewNet()->getNetworkViewOptions().showDemandElements() &&
1194
myNet->getViewNet()->getDemandViewOptions().showAllTrips();
1195
// conditions for draw always in demand mode
1196
const bool drawInDemandMode = myNet->getViewNet()->getEditModes().isCurrentSupermodeDemand() &&
1197
myNet->getViewNet()->getDemandViewOptions().showAllTrips();
1198
// conditions for draw if is selected
1199
const bool isSelected = myNet->getViewNet()->getEditModes().isCurrentSupermodeDemand() &&
1200
isAttributeCarrierSelected();
1201
// conditions for draw if is inspected
1202
const bool isInspected = myNet->getViewNet()->getEditModes().isCurrentSupermodeDemand() &&
1203
myNet->getViewNet()->getInspectedElements().isACInspected(this);
1204
// check drawing conditions
1205
if (segment->getJunction() && (drawInNetworkMode || drawInDemandMode || isSelected || isInspected) &&
1206
myNet->getDemandPathManager()->getPathDraw()->checkDrawPathGeometry(s, segment, myTagProperty->getTag(), false)) {
1207
// get detail level
1208
const auto d = s.getDetailLevel(1);
1209
// calculate width
1210
const double width = s.vehicleSize.getExaggeration(s, segment->getPreviousLane()) * s.widthSettings.tripWidth;
1211
// draw geometry only if we'rent in drawForObjectUnderCursor mode
1212
if (s.checkDrawVehicle(d, isAttributeCarrierSelected())) {
1213
// Add a draw matrix
1214
GLHelper::pushMatrix();
1215
// Start with the drawing of the area translating matrix to origin
1216
glTranslated(0, 0, getType() + offsetFront);
1217
// Set color of the base
1218
if (drawUsingSelectColor()) {
1219
GLHelper::setColor(s.colorSettings.selectedVehicleColor);
1220
} else {
1221
GLHelper::setColor(s.colorSettings.vehicleTripColor);
1222
}
1223
// continue depending if we're in the middle of two lanes or in the begin/end of a junction route
1224
if (segment->getPreviousLane() && segment->getNextLane()) {
1225
// draw lane2lane
1226
GUIGeometry::drawGeometry(d, segment->getPreviousLane()->getLane2laneConnections().getLane2laneGeometry(segment->getNextLane()), width);
1227
} else if (segment->getPreviousLane() && myTagProperty->vehicleJunctions()) {
1228
// draw line between center of junction and last lane shape
1229
GLHelper::drawBoxLines({segment->getPreviousLane()->getLaneShape().back(), getParentJunctions().back()->getPositionInView()}, width);
1230
} else if (segment->getNextLane() && myTagProperty->vehicleJunctions()) {
1231
// draw line between center of junction and first lane shape
1232
GLHelper::drawBoxLines({getParentJunctions().front()->getPositionInView(), segment->getNextLane()->getLaneShape().front()}, width);
1233
}
1234
// Pop last matrix
1235
GLHelper::popMatrix();
1236
// draw dotted contour
1237
segment->getContour()->drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);
1238
}
1239
// continue depending if we're in the middle of two lanes or in the begin/end of a junction route
1240
if (segment->getPreviousLane() && segment->getNextLane()) {
1241
// calculate contour and draw dotted geometry
1242
segment->getContour()->calculateContourExtrudedShape(s, d, this, segment->getPreviousLane()->getLane2laneConnections().getLane2laneGeometry(segment->getNextLane()).getShape(),
1243
getType(), width, 1, false, false, 0, segment, segment->getJunction());
1244
} else if (segment->getPreviousLane() && myTagProperty->vehicleJunctions()) {
1245
segment->getContour()->calculateContourExtrudedShape(s, d, this, {segment->getPreviousLane()->getLaneShape().back(), getParentJunctions().back()->getPositionInView()},
1246
getType(), width, 1, true, true, 0, segment, segment->getJunction());
1247
} else if (segment->getNextLane() && myTagProperty->vehicleJunctions()) {
1248
segment->getContour()->calculateContourExtrudedShape(s, d, this, {getParentJunctions().front()->getPositionInView(), segment->getNextLane()->getLaneShape().front()},
1249
getType(), width, 1, true, true, 0, segment, segment->getJunction());
1250
}
1251
// check if add this path element to redraw buffer
1252
if (!gViewObjectsHandler.isPathElementMarkForRedraw(this) && segment->getContour()->checkDrawPathContour(s, d, this)) {
1253
gViewObjectsHandler.addToRedrawPathElements(this);
1254
}
1255
}
1256
}
1257
1258
1259
GNELane*
1260
GNEVehicle::getFirstPathLane() const {
1261
// declare first edge
1262
GNEEdge* firstEdge = nullptr;
1263
// continue depending of tags
1264
if (myTagProperty->vehicleRoute()) {
1265
// check departEdge
1266
if ((departEdge > 0) && (departEdge < (int)getRouteParent()->getParentEdges().size())) {
1267
// use departEdge
1268
firstEdge = getRouteParent()->getParentEdges().at(departEdge);
1269
} else {
1270
// use first route edge
1271
firstEdge = getRouteParent()->getParentEdges().front();
1272
}
1273
} else if (myTagProperty->vehicleRouteEmbedded()) {
1274
// check if embedded route exist (due during loading embedded route doesn't exist)
1275
if (getChildDemandElements().empty()) {
1276
return nullptr;
1277
}
1278
// check departEdge
1279
if ((departEdge > 0) && (departEdge < (int)getChildDemandElements().front()->getParentEdges().size())) {
1280
// use depart edge
1281
firstEdge = getChildDemandElements().front()->getParentEdges().at(departEdge);
1282
} else if (getChildDemandElements().front()->getParentEdges().size() > 0) {
1283
firstEdge = getChildDemandElements().front()->getParentEdges().front();
1284
} else if (getChildDemandElements().front()->getParentLanes().size() > 0) {
1285
firstEdge = getChildDemandElements().front()->getParentLanes().front()->getParentEdge();
1286
} else {
1287
return nullptr;
1288
}
1289
} else if (getParentEdges().size() > 0) {
1290
// use first parent edge
1291
firstEdge = getParentEdges().front();
1292
} else {
1293
// defined over junctions
1294
return nullptr;
1295
}
1296
// get departLane index
1297
const int departLaneIndex = (int)getAttributeDouble(SUMO_ATTR_DEPARTLANE);
1298
// check departLane index
1299
if ((departLaneIndex >= 0) && (departLaneIndex < (int)firstEdge->getChildLanes().size())) {
1300
return firstEdge->getChildLanes().at(departLaneIndex);
1301
} else {
1302
// get first allowed VClass
1303
return firstEdge->getLaneByAllowedVClass(getVClass());
1304
}
1305
}
1306
1307
1308
GNELane*
1309
GNEVehicle::getLastPathLane() const {
1310
// declare last edge
1311
GNEEdge* lastEdge = nullptr;
1312
// continue depending of tags
1313
if (myTagProperty->vehicleRoute()) {
1314
// check arrivalEdge
1315
if ((arrivalEdge > 0) && (arrivalEdge < (int)getRouteParent()->getParentEdges().size())) {
1316
// use arrival edge
1317
lastEdge = getRouteParent()->getParentEdges().at(arrivalEdge);
1318
} else {
1319
// use last route edge
1320
lastEdge = getRouteParent()->getParentEdges().back();
1321
}
1322
} else if (myTagProperty->vehicleRouteEmbedded()) {
1323
// check if embedded route exist (due during loading embedded route doesn't exist)
1324
if (getChildDemandElements().empty()) {
1325
return nullptr;
1326
}
1327
// check arrivalEdge
1328
if ((arrivalEdge > 0) && (arrivalEdge < (int)getChildDemandElements().front()->getParentEdges().size())) {
1329
// use arrival edge
1330
lastEdge = getChildDemandElements().front()->getParentEdges().at(arrivalEdge);
1331
} else if (getChildDemandElements().front()->getParentEdges().size() > 0) {
1332
// use last route edge
1333
lastEdge = getChildDemandElements().front()->getParentEdges().back();
1334
} else if (getChildDemandElements().front()->getParentLanes().size() > 0) {
1335
// use lane
1336
lastEdge = getChildDemandElements().front()->getParentLanes().back()->getParentEdge();
1337
} else {
1338
return nullptr;
1339
}
1340
} else if (getParentEdges().size() > 0) {
1341
// use last parent edge
1342
lastEdge = getParentEdges().back();
1343
} else {
1344
// defined over junctions
1345
return nullptr;
1346
}
1347
// get arrivalLane index
1348
const int arrivalLaneIndex = (int)getAttributeDouble(SUMO_ATTR_ARRIVALLANE);
1349
// check arrivalLane index
1350
if ((arrivalLaneIndex >= 0) && (arrivalLaneIndex < (int)lastEdge->getChildLanes().size())) {
1351
return lastEdge->getChildLanes().at(arrivalLaneIndex);
1352
} else {
1353
// get last allowed VClass
1354
return lastEdge->getLaneByAllowedVClass(getVClass());
1355
}
1356
}
1357
1358
1359
std::string
1360
GNEVehicle::getAttribute(SumoXMLAttr key) const {
1361
switch (key) {
1362
case SUMO_ATTR_ID:
1363
return getMicrosimID();
1364
case SUMO_ATTR_TYPE:
1365
return vtypeid;
1366
case SUMO_ATTR_COLOR:
1367
if (wasSet(VEHPARS_COLOR_SET)) {
1368
return toString(color);
1369
} else {
1370
return myTagProperty->getDefaultStringValue(SUMO_ATTR_COLOR);
1371
}
1372
case SUMO_ATTR_DEPARTLANE:
1373
if (wasSet(VEHPARS_DEPARTLANE_SET)) {
1374
return getDepartLane();
1375
} else {
1376
return myTagProperty->getDefaultStringValue(SUMO_ATTR_DEPARTLANE);
1377
}
1378
case SUMO_ATTR_DEPARTPOS:
1379
if (wasSet(VEHPARS_DEPARTPOS_SET)) {
1380
return getDepartPos();
1381
} else {
1382
return myTagProperty->getDefaultStringValue(SUMO_ATTR_DEPARTPOS);
1383
}
1384
case SUMO_ATTR_DEPARTSPEED:
1385
if (wasSet(VEHPARS_DEPARTSPEED_SET)) {
1386
return getDepartSpeed();
1387
} else {
1388
return myTagProperty->getDefaultStringValue(SUMO_ATTR_DEPARTSPEED);
1389
}
1390
case SUMO_ATTR_ARRIVALLANE:
1391
if (wasSet(VEHPARS_ARRIVALLANE_SET)) {
1392
return getArrivalLane();
1393
} else {
1394
return myTagProperty->getDefaultStringValue(SUMO_ATTR_ARRIVALLANE);
1395
}
1396
case SUMO_ATTR_ARRIVALPOS:
1397
if (wasSet(VEHPARS_ARRIVALPOS_SET)) {
1398
return getArrivalPos();
1399
} else {
1400
return myTagProperty->getDefaultStringValue(SUMO_ATTR_ARRIVALPOS);
1401
}
1402
case SUMO_ATTR_ARRIVALSPEED:
1403
if (wasSet(VEHPARS_ARRIVALSPEED_SET)) {
1404
return getArrivalSpeed();
1405
} else {
1406
return myTagProperty->getDefaultStringValue(SUMO_ATTR_ARRIVALSPEED);
1407
}
1408
case SUMO_ATTR_LINE:
1409
if (wasSet(VEHPARS_LINE_SET)) {
1410
return line;
1411
} else {
1412
return myTagProperty->getDefaultStringValue(SUMO_ATTR_LINE);
1413
}
1414
case SUMO_ATTR_PERSON_NUMBER:
1415
if (wasSet(VEHPARS_PERSON_NUMBER_SET)) {
1416
return toString(personNumber);
1417
} else {
1418
return myTagProperty->getDefaultStringValue(SUMO_ATTR_PERSON_NUMBER);
1419
}
1420
case SUMO_ATTR_CONTAINER_NUMBER:
1421
if (wasSet(VEHPARS_CONTAINER_NUMBER_SET)) {
1422
return toString(containerNumber);
1423
} else {
1424
return myTagProperty->getDefaultStringValue(SUMO_ATTR_CONTAINER_NUMBER);
1425
}
1426
case SUMO_ATTR_REROUTE:
1427
if (wasSet(VEHPARS_CONTAINER_NUMBER_SET)) {
1428
return "true";
1429
} else {
1430
return "false";
1431
}
1432
case SUMO_ATTR_DEPARTPOS_LAT:
1433
if (wasSet(VEHPARS_DEPARTPOSLAT_SET)) {
1434
return getDepartPosLat();
1435
} else {
1436
return myTagProperty->getDefaultStringValue(SUMO_ATTR_DEPARTPOS_LAT);
1437
}
1438
case SUMO_ATTR_ARRIVALPOS_LAT:
1439
if (wasSet(VEHPARS_ARRIVALPOSLAT_SET)) {
1440
return getArrivalPosLat();
1441
} else {
1442
return myTagProperty->getDefaultStringValue(SUMO_ATTR_ARRIVALPOS_LAT);
1443
}
1444
case SUMO_ATTR_INSERTIONCHECKS:
1445
return getInsertionChecks();
1446
// Specific of vehicles over routes
1447
case SUMO_ATTR_ROUTE:
1448
if (getParentDemandElements().size() == 2) {
1449
return getRouteParent()->getID();
1450
} else {
1451
return "";
1452
}
1453
// Specific of from-to edge
1454
case SUMO_ATTR_FROM:
1455
return getParentEdges().front()->getID();
1456
case SUMO_ATTR_TO:
1457
return getParentEdges().back()->getID();
1458
case SUMO_ATTR_VIA:
1459
return toString(via);
1460
case SUMO_ATTR_DEPARTEDGE:
1461
if (departEdge == -1) {
1462
return "";
1463
} else {
1464
return toString(departEdge);
1465
}
1466
case SUMO_ATTR_ARRIVALEDGE:
1467
if (arrivalEdge == -1) {
1468
return "";
1469
} else {
1470
return toString(arrivalEdge);
1471
}
1472
// Specific of from-to junctions
1473
case SUMO_ATTR_FROM_JUNCTION:
1474
return getParentJunctions().front()->getID();
1475
case SUMO_ATTR_TO_JUNCTION:
1476
return getParentJunctions().back()->getID();
1477
// Specific of from-to tazs
1478
case SUMO_ATTR_FROM_TAZ:
1479
return getParentAdditionals().front()->getID();
1480
case SUMO_ATTR_TO_TAZ:
1481
return getParentAdditionals().back()->getID();
1482
// other
1483
case GNE_ATTR_FLOWPARAMETERS:
1484
return toString(parametersSet);
1485
default:
1486
return getFlowAttribute(this, key);
1487
}
1488
}
1489
1490
1491
double
1492
GNEVehicle::getAttributeDouble(SumoXMLAttr key) const {
1493
switch (key) {
1494
case SUMO_ATTR_DEPARTLANE:
1495
if (wasSet(VEHPARS_DEPARTLANE_SET) && (departLaneProcedure == DepartLaneDefinition::GIVEN)) {
1496
return departLane;
1497
} else {
1498
return -1;
1499
}
1500
case SUMO_ATTR_DEPARTPOS:
1501
// only return departPos it if is given
1502
if (departPosProcedure == DepartPosDefinition::GIVEN) {
1503
return departPos;
1504
} else {
1505
return 0;
1506
}
1507
case SUMO_ATTR_ARRIVALLANE:
1508
if (wasSet(VEHPARS_ARRIVALLANE_SET) && (arrivalLaneProcedure == ArrivalLaneDefinition::GIVEN)) {
1509
return arrivalLane;
1510
} else {
1511
return -1;
1512
}
1513
case SUMO_ATTR_ARRIVALPOS:
1514
// only return departPos it if is given
1515
if (arrivalPosProcedure == ArrivalPosDefinition::GIVEN) {
1516
return arrivalPos;
1517
} else {
1518
return -1;
1519
}
1520
case SUMO_ATTR_WIDTH:
1521
case SUMO_ATTR_LENGTH:
1522
case SUMO_ATTR_MINGAP:
1523
return getTypeParent()->getAttributeDouble(key);
1524
default:
1525
return getFlowAttributeDouble(key);
1526
}
1527
}
1528
1529
1530
Position
1531
GNEVehicle::getAttributePosition(SumoXMLAttr key) const {
1532
switch (key) {
1533
case GNE_ATTR_PLAN_GEOMETRY_STARTPOS: {
1534
// check if this vehicle was defined over junctions
1535
if (getParentJunctions().size() > 0) {
1536
return getParentJunctions().front()->getPositionInView();
1537
} else {
1538
// get first path lane shape
1539
const PositionVector& laneShape = getFirstPathLane()->getLaneShape();
1540
// check arrivalPosProcedure
1541
if (departPosProcedure == DepartPosDefinition::GIVEN) {
1542
if (departPos < 0) {
1543
return laneShape.front();
1544
} else if (departPos > laneShape.length2D()) {
1545
return laneShape.back();
1546
} else {
1547
return laneShape.positionAtOffset2D(departPos);
1548
}
1549
} else {
1550
return laneShape.front();
1551
}
1552
}
1553
}
1554
case GNE_ATTR_PLAN_GEOMETRY_ENDPOS: {
1555
// check if this vehicle was defined over junctions
1556
if (getParentJunctions().size() > 0) {
1557
return getParentJunctions().back()->getPositionInView();
1558
} else {
1559
// get last path lane shape
1560
const PositionVector& laneShape = getLastPathLane()->getLaneShape();
1561
// check arrivalPosProcedure
1562
if (arrivalPosProcedure == ArrivalPosDefinition::GIVEN) {
1563
if (arrivalPos < 0) {
1564
return laneShape.front();
1565
} else if (arrivalPos > laneShape.length2D()) {
1566
return laneShape.back();
1567
} else {
1568
return laneShape.positionAtOffset2D(arrivalPos);
1569
}
1570
} else {
1571
return laneShape.back();
1572
}
1573
}
1574
}
1575
default:
1576
return getCommonAttributePosition(key);
1577
}
1578
}
1579
1580
1581
void
1582
GNEVehicle::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
1583
if (value == getAttribute(key)) {
1584
return; //avoid needless changes, later logic relies on the fact that attributes have changed
1585
}
1586
switch (key) {
1587
case SUMO_ATTR_ID:
1588
case SUMO_ATTR_TYPE:
1589
case SUMO_ATTR_COLOR:
1590
case SUMO_ATTR_DEPARTLANE:
1591
case SUMO_ATTR_DEPARTPOS:
1592
case SUMO_ATTR_DEPARTSPEED:
1593
case SUMO_ATTR_ARRIVALLANE:
1594
case SUMO_ATTR_ARRIVALPOS:
1595
case SUMO_ATTR_ARRIVALSPEED:
1596
case SUMO_ATTR_LINE:
1597
case SUMO_ATTR_PERSON_NUMBER:
1598
case SUMO_ATTR_CONTAINER_NUMBER:
1599
case SUMO_ATTR_REROUTE:
1600
case SUMO_ATTR_DEPARTPOS_LAT:
1601
case SUMO_ATTR_ARRIVALPOS_LAT:
1602
case SUMO_ATTR_INSERTIONCHECKS:
1603
// Specific of vehicles over routes
1604
case SUMO_ATTR_ROUTE:
1605
// Specific of from-to edges
1606
case SUMO_ATTR_FROM:
1607
case SUMO_ATTR_TO:
1608
case SUMO_ATTR_VIA:
1609
case SUMO_ATTR_DEPARTEDGE:
1610
case SUMO_ATTR_ARRIVALEDGE:
1611
// Specific of from-to junctions
1612
case SUMO_ATTR_FROM_JUNCTION:
1613
case SUMO_ATTR_TO_JUNCTION:
1614
// Specific of from-to taz
1615
case SUMO_ATTR_FROM_TAZ:
1616
case SUMO_ATTR_TO_TAZ:
1617
GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1618
break;
1619
default:
1620
setFlowAttribute(this, key, value, undoList);
1621
break;
1622
}
1623
}
1624
1625
1626
bool
1627
GNEVehicle::isValid(SumoXMLAttr key, const std::string& value) {
1628
// get ACs
1629
const auto ACs = myNet->getAttributeCarriers();
1630
// declare string error
1631
std::string error;
1632
switch (key) {
1633
case SUMO_ATTR_ID:
1634
return isValidDemandElementID(NamespaceIDs::vehicles, value);
1635
case SUMO_ATTR_TYPE:
1636
return (myNet->getAttributeCarriers()->retrieveDemandElements(NamespaceIDs::types, value, false) != nullptr);
1637
case SUMO_ATTR_COLOR:
1638
return canParse<RGBColor>(value);
1639
case SUMO_ATTR_DEPARTLANE: {
1640
int dummyDepartLane;
1641
DepartLaneDefinition dummyDepartLaneProcedure;
1642
parseDepartLane(value, myTagProperty->getTagStr(), id, dummyDepartLane, dummyDepartLaneProcedure, error);
1643
// if error is empty, check if depart lane is correct
1644
if (error.empty()) {
1645
if (dummyDepartLaneProcedure != DepartLaneDefinition::GIVEN) {
1646
return true;
1647
} else if (isTemplate()) {
1648
return true;
1649
} else if (getParentJunctions().size() > 0) {
1650
return (dummyDepartLane == 0);
1651
} else if (getParentAdditionals().size() > 0) {
1652
return (dummyDepartLane == 0);
1653
} else {
1654
return dummyDepartLane < (int)getFirstPathLane()->getParentEdge()->getChildLanes().size();
1655
}
1656
} else {
1657
return false;
1658
}
1659
}
1660
case SUMO_ATTR_DEPARTPOS: {
1661
double dummyDepartPos;
1662
DepartPosDefinition dummyDepartPosProcedure;
1663
parseDepartPos(value, myTagProperty->getTagStr(), id, dummyDepartPos, dummyDepartPosProcedure, error);
1664
// if error is empty, given value is valid
1665
return error.empty();
1666
}
1667
case SUMO_ATTR_DEPARTSPEED: {
1668
double dummyDepartSpeed;
1669
DepartSpeedDefinition dummyDepartSpeedProcedure;
1670
parseDepartSpeed(value, myTagProperty->getTagStr(), id, dummyDepartSpeed, dummyDepartSpeedProcedure, error);
1671
// if error is empty, check if depart speed is correct
1672
if (error.empty()) {
1673
if (dummyDepartSpeedProcedure != DepartSpeedDefinition::GIVEN) {
1674
return true;
1675
} else if (isTemplate()) {
1676
return true;
1677
} else {
1678
return (dummyDepartSpeed <= getTypeParent()->getAttributeDouble(SUMO_ATTR_MAXSPEED));
1679
}
1680
} else {
1681
return false;
1682
}
1683
}
1684
case SUMO_ATTR_ARRIVALLANE: {
1685
int dummyArrivalLane;
1686
ArrivalLaneDefinition dummyArrivalLaneProcedure;
1687
parseArrivalLane(value, myTagProperty->getTagStr(), id, dummyArrivalLane, dummyArrivalLaneProcedure, error);
1688
// if error is empty, given value is valid
1689
if (error.empty()) {
1690
if (dummyArrivalLaneProcedure != ArrivalLaneDefinition::GIVEN) {
1691
return true;
1692
} else if (isTemplate()) {
1693
return true;
1694
} else if (getParentJunctions().size() > 0) {
1695
return (dummyArrivalLane == 0);
1696
} else if (getParentAdditionals().size() > 0) {
1697
return (dummyArrivalLane == 0);
1698
} else {
1699
return dummyArrivalLane < (int)getLastPathLane()->getParentEdge()->getChildLanes().size();
1700
}
1701
} else {
1702
return false;
1703
}
1704
}
1705
case SUMO_ATTR_ARRIVALPOS: {
1706
double dummyArrivalPos;
1707
ArrivalPosDefinition dummyArrivalPosProcedure;
1708
parseArrivalPos(value, myTagProperty->getTagStr(), id, dummyArrivalPos, dummyArrivalPosProcedure, error);
1709
// if error is empty, given value is valid
1710
return error.empty();
1711
}
1712
case SUMO_ATTR_ARRIVALSPEED: {
1713
double dummyArrivalSpeed;
1714
ArrivalSpeedDefinition dummyArrivalSpeedProcedure;
1715
parseArrivalSpeed(value, myTagProperty->getTagStr(), id, dummyArrivalSpeed, dummyArrivalSpeedProcedure, error);
1716
// if error is empty, given value is valid
1717
return error.empty();
1718
}
1719
case SUMO_ATTR_LINE:
1720
return true;
1721
case SUMO_ATTR_PERSON_NUMBER:
1722
return canParse<int>(value) && parse<int>(value) >= 0;
1723
case SUMO_ATTR_CONTAINER_NUMBER:
1724
return canParse<int>(value) && parse<int>(value) >= 0;
1725
case SUMO_ATTR_REROUTE:
1726
return true; // check
1727
case SUMO_ATTR_DEPARTPOS_LAT: {
1728
double dummyDepartPosLat;
1729
DepartPosLatDefinition dummyDepartPosLatProcedure;
1730
parseDepartPosLat(value, myTagProperty->getTagStr(), id, dummyDepartPosLat, dummyDepartPosLatProcedure, error);
1731
// if error is empty, given value is valid
1732
return error.empty();
1733
}
1734
case SUMO_ATTR_ARRIVALPOS_LAT: {
1735
double dummyArrivalPosLat;
1736
ArrivalPosLatDefinition dummyArrivalPosLatProcedure;
1737
parseArrivalPosLat(value, myTagProperty->getTagStr(), id, dummyArrivalPosLat, dummyArrivalPosLatProcedure, error);
1738
// if error is empty, given value is valid
1739
return error.empty();
1740
}
1741
case SUMO_ATTR_INSERTIONCHECKS:
1742
return areInsertionChecksValid(value);
1743
// Specific of vehicles over routes
1744
case SUMO_ATTR_ROUTE:
1745
if (getParentDemandElements().size() == 2) {
1746
return (myNet->getAttributeCarriers()->retrieveDemandElements(NamespaceIDs::routes, value, false) != nullptr);
1747
} else {
1748
return true;
1749
}
1750
// Specific of from-to edges
1751
case SUMO_ATTR_FROM:
1752
case SUMO_ATTR_TO:
1753
return (ACs->retrieveEdge(value, false) != nullptr);
1754
case SUMO_ATTR_DEPARTEDGE:
1755
case SUMO_ATTR_ARRIVALEDGE: {
1756
if (value.empty()) {
1757
return true;
1758
} else if (canParse<int>(value)) {
1759
// get index
1760
const int index = parse<int>(value);
1761
// check conditions
1762
if (index < 0) {
1763
return false;
1764
} else if (myTagProperty->vehicleRoute()) {
1765
// check parent route
1766
return (index < (int)getRouteParent()->getParentEdges().size());
1767
} else {
1768
// check embedded route
1769
return (index < (int)getChildDemandElements().front()->getParentEdges().size());
1770
}
1771
} else {
1772
return false;
1773
}
1774
}
1775
case SUMO_ATTR_VIA:
1776
return canParse<std::vector<GNEEdge*> >(myNet, value, false);
1777
// Specific of from-to junctions
1778
case SUMO_ATTR_FROM_JUNCTION:
1779
case SUMO_ATTR_TO_JUNCTION:
1780
return (ACs->retrieveJunction(value, false) != nullptr);
1781
// Specific of from-to taz
1782
case SUMO_ATTR_FROM_TAZ:
1783
case SUMO_ATTR_TO_TAZ:
1784
return (ACs->retrieveAdditional(SUMO_TAG_TAZ, value, false) != nullptr);
1785
default:
1786
return isValidFlowAttribute(this, key, value);
1787
}
1788
}
1789
1790
1791
void
1792
GNEVehicle::enableAttribute(SumoXMLAttr key, GNEUndoList* undoList) {
1793
enableFlowAttribute(this, key, undoList);
1794
}
1795
1796
1797
void
1798
GNEVehicle::disableAttribute(SumoXMLAttr key, GNEUndoList* undoList) {
1799
disableFlowAttribute(this, key, undoList);
1800
}
1801
1802
1803
bool
1804
GNEVehicle::isAttributeEnabled(SumoXMLAttr key) const {
1805
return isFlowAttributeEnabled(key);
1806
}
1807
1808
1809
std::string
1810
GNEVehicle::getPopUpID() const {
1811
return getTagStr();
1812
}
1813
1814
1815
std::string
1816
GNEVehicle::getHierarchyName() const {
1817
const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();
1818
// special case for Trips and flow
1819
if (myTagProperty->vehicleEdges()) {
1820
// check if we're inspecting a Edge
1821
if (inspectedElements.getFirstAC() && (inspectedElements.getFirstAC()->getTagProperty()->getTag() == SUMO_TAG_EDGE)) {
1822
// check if edge correspond to a "from", "to" or "via" edge
1823
if (inspectedElements.isACInspected(getParentEdges().front())) {
1824
return getTagStr() + ": " + getAttribute(SUMO_ATTR_ID) + " (from)";
1825
} else if (inspectedElements.isACInspected(getParentEdges().front())) {
1826
return getTagStr() + ": " + getAttribute(SUMO_ATTR_ID) + " (to)";
1827
} else {
1828
// iterate over via
1829
for (const auto& viaEdgeID : via) {
1830
if (viaEdgeID == inspectedElements.getFirstAC()->getID()) {
1831
return getTagStr() + ": " + getAttribute(SUMO_ATTR_ID) + " (via)";
1832
}
1833
}
1834
}
1835
}
1836
}
1837
return getTagStr() + ": " + getAttribute(SUMO_ATTR_ID);
1838
}
1839
1840
1841
GNEDemandElement*
1842
GNEVehicle::copyVehicle(const GNEVehicle* originalVehicle) {
1843
// get net and undoList
1844
const auto net = originalVehicle->getNet();
1845
auto undoList = net->getViewNet()->getUndoList();
1846
// declare new route, vehicle and embedded route
1847
GNERoute* newRoute = nullptr;
1848
GNEVehicle* newVehicle = nullptr;
1849
GNERoute* newEmbeddedRoute = nullptr;
1850
// generate new vehicle ID
1851
const std::string newRouteID = net->getAttributeCarriers()->generateDemandElementID(SUMO_TAG_ROUTE);
1852
const std::string newVehicleID = net->getAttributeCarriers()->generateDemandElementID(originalVehicle->getTagProperty()->getTag());
1853
// extract vehicle parameters and update ID
1854
auto newVehicleParameters = originalVehicle->getSUMOVehicleParameter();
1855
newVehicleParameters.id = newVehicleID;
1856
// create vehicle using vehicleParameters
1857
if (originalVehicle->getTagProperty()->vehicleRoute()) {
1858
newRoute = new GNERoute(newRouteID, originalVehicle->getParentDemandElements().at(1));
1859
newVehicle = new GNEVehicle(originalVehicle->getTagProperty()->getTag(), net,
1860
originalVehicle->getFileBucket(),
1861
originalVehicle->getParentDemandElements().at(0), newRoute,
1862
newVehicleParameters);
1863
} else if (originalVehicle->getTagProperty()->vehicleRouteEmbedded()) {
1864
newVehicle = new GNEVehicle(originalVehicle->getTagProperty()->getTag(), net,
1865
originalVehicle->getFileBucket(),
1866
originalVehicle->getParentDemandElements().at(0),
1867
newVehicleParameters);
1868
newEmbeddedRoute = new GNERoute(newVehicle, originalVehicle->getChildDemandElements().front());
1869
} else if (originalVehicle->getTagProperty()->vehicleEdges()) {
1870
newVehicle = new GNEVehicle(originalVehicle->getTagProperty()->getTag(), net,
1871
originalVehicle->getFileBucket(),
1872
originalVehicle->getParentDemandElements().at(0),
1873
originalVehicle->getParentEdges().front(),
1874
originalVehicle->getParentEdges().back(),
1875
newVehicleParameters);
1876
} else if (originalVehicle->getTagProperty()->vehicleJunctions()) {
1877
newVehicle = new GNEVehicle(originalVehicle->getTagProperty()->getTag(), net,
1878
originalVehicle->getFileBucket(),
1879
originalVehicle->getParentDemandElements().at(0),
1880
originalVehicle->getParentJunctions().front(),
1881
originalVehicle->getParentJunctions().back(),
1882
newVehicleParameters);
1883
} else if (originalVehicle->getTagProperty()->vehicleTAZs()) {
1884
newVehicle = new GNEVehicle(originalVehicle->getTagProperty()->getTag(), net,
1885
originalVehicle->getFileBucket(),
1886
originalVehicle->getParentDemandElements().at(0),
1887
originalVehicle->getParentAdditionals().front(),
1888
originalVehicle->getParentAdditionals().back(),
1889
newVehicleParameters);
1890
}
1891
// add new vehicle
1892
undoList->begin(originalVehicle, TLF("copy % '%'", newVehicle->getTagStr(), newVehicleID));
1893
if (newRoute) {
1894
net->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(newRoute, true), true);
1895
}
1896
undoList->add(new GNEChange_DemandElement(newVehicle, true), true);
1897
if (newEmbeddedRoute) {
1898
net->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(newEmbeddedRoute, true), true);
1899
}
1900
undoList->end();
1901
return newVehicle;
1902
}
1903
1904
// ===========================================================================
1905
// protected
1906
// ===========================================================================
1907
1908
RGBColor
1909
GNEVehicle::getDrawingColor(const GUIVisualizationSettings& s) const {
1910
// change color
1911
if (drawUsingSelectColor()) {
1912
return s.colorSettings.selectedVehicleColor;
1913
} else {
1914
return getColorByScheme(s.vehicleColorer, this);
1915
}
1916
}
1917
1918
1919
const SUMOVehicleParameter&
1920
GNEVehicle::getSUMOVehicleParameter() const {
1921
return *this;
1922
}
1923
1924
// ===========================================================================
1925
// private
1926
// ===========================================================================
1927
1928
void
1929
GNEVehicle::setAttribute(SumoXMLAttr key, const std::string& value) {
1930
// declare string error
1931
std::string error;
1932
// flag to upate stack label
1933
bool updateSpreadStackGeometry = false;
1934
switch (key) {
1935
case SUMO_ATTR_ID:
1936
// update microsimID
1937
setDemandElementID(value);
1938
// set manually vehicle ID (needed for saving)
1939
id = value;
1940
break;
1941
case SUMO_ATTR_TYPE:
1942
if (getID().size() > 0) {
1943
replaceDemandElementParent(NamespaceIDs::types, value, 0);
1944
// set manually vtypeID (needed for saving)
1945
vtypeid = value;
1946
}
1947
break;
1948
case SUMO_ATTR_COLOR:
1949
if (!value.empty() && (value != myTagProperty->getDefaultStringValue(key))) {
1950
color = parse<RGBColor>(value);
1951
// mark parameter as set
1952
parametersSet |= VEHPARS_COLOR_SET;
1953
} else {
1954
// set default value
1955
color = myTagProperty->getDefaultColorValue(key);
1956
// unset parameter
1957
parametersSet &= ~VEHPARS_COLOR_SET;
1958
}
1959
break;
1960
case SUMO_ATTR_DEPARTLANE:
1961
if (!value.empty() && (value != myTagProperty->getDefaultStringValue(key))) {
1962
parseDepartLane(value, myTagProperty->getTagStr(), id, departLane, departLaneProcedure, error);
1963
// mark parameter as set
1964
parametersSet |= VEHPARS_DEPARTLANE_SET;
1965
} else {
1966
// set default value
1967
parseDepartLane(myTagProperty->getDefaultStringValue(key), myTagProperty->getTagStr(), id, departLane, departLaneProcedure, error);
1968
// unset parameter
1969
parametersSet &= ~VEHPARS_DEPARTLANE_SET;
1970
}
1971
break;
1972
case SUMO_ATTR_DEPARTPOS:
1973
if (value == toString(INVALID_DOUBLE)) {
1974
parseDepartPos(value, myTagProperty->getTagStr(), id, departPos, departPosProcedure, error);
1975
// mark parameter as set
1976
parametersSet |= VEHPARS_DEPARTPOS_SET;
1977
} else if (!value.empty() && (value != myTagProperty->getDefaultStringValue(key))) {
1978
parseDepartPos(value, myTagProperty->getTagStr(), id, departPos, departPosProcedure, error);
1979
// mark parameter as set
1980
parametersSet |= VEHPARS_DEPARTPOS_SET;
1981
} else {
1982
// set default value
1983
parseDepartPos(myTagProperty->getDefaultStringValue(key), myTagProperty->getTagStr(), id, departPos, departPosProcedure, error);
1984
// unset parameter
1985
parametersSet &= ~VEHPARS_DEPARTPOS_SET;
1986
}
1987
if (getID().size() > 0) {
1988
updateGeometry();
1989
updateSpreadStackGeometry = true;
1990
}
1991
break;
1992
case SUMO_ATTR_DEPARTSPEED:
1993
if (!value.empty() && (value != myTagProperty->getDefaultStringValue(key))) {
1994
parseDepartSpeed(value, myTagProperty->getTagStr(), id, departSpeed, departSpeedProcedure, error);
1995
// mark parameter as set
1996
parametersSet |= VEHPARS_DEPARTSPEED_SET;
1997
} else {
1998
// set default value
1999
parseDepartSpeed(myTagProperty->getDefaultStringValue(key), myTagProperty->getTagStr(), id, departSpeed, departSpeedProcedure, error);
2000
// unset parameter
2001
parametersSet &= ~VEHPARS_DEPARTSPEED_SET;
2002
}
2003
break;
2004
case SUMO_ATTR_ARRIVALLANE:
2005
if (!value.empty() && (value != myTagProperty->getDefaultStringValue(key))) {
2006
parseArrivalLane(value, myTagProperty->getTagStr(), id, arrivalLane, arrivalLaneProcedure, error);
2007
// mark parameter as set
2008
parametersSet |= VEHPARS_ARRIVALLANE_SET;
2009
} else {
2010
// set default value
2011
parseArrivalLane(myTagProperty->getDefaultStringValue(key), myTagProperty->getTagStr(), id, arrivalLane, arrivalLaneProcedure, error);
2012
// unset parameter
2013
parametersSet &= ~VEHPARS_ARRIVALLANE_SET;
2014
}
2015
break;
2016
case SUMO_ATTR_ARRIVALPOS:
2017
if (value == toString(INVALID_DOUBLE)) {
2018
parseArrivalPos("max", myTagProperty->getTagStr(), id, arrivalPos, arrivalPosProcedure, error);
2019
// mark parameter as set
2020
parametersSet |= VEHPARS_ARRIVALPOS_SET;
2021
} else if (!value.empty() && (value != myTagProperty->getDefaultStringValue(key))) {
2022
parseArrivalPos(value, myTagProperty->getTagStr(), id, arrivalPos, arrivalPosProcedure, error);
2023
// mark parameter as set
2024
parametersSet |= VEHPARS_ARRIVALPOS_SET;
2025
} else {
2026
// set default value
2027
parseArrivalPos(myTagProperty->getDefaultStringValue(key), myTagProperty->getTagStr(), id, arrivalPos, arrivalPosProcedure, error);
2028
// unset parameter
2029
parametersSet &= ~VEHPARS_ARRIVALPOS_SET;
2030
}
2031
if (getID().size() > 0) {
2032
updateGeometry();
2033
updateSpreadStackGeometry = true;
2034
}
2035
break;
2036
case SUMO_ATTR_ARRIVALSPEED:
2037
if (!value.empty() && (value != myTagProperty->getDefaultStringValue(key))) {
2038
parseArrivalSpeed(value, myTagProperty->getTagStr(), id, arrivalSpeed, arrivalSpeedProcedure, error);
2039
// mark parameter as set
2040
parametersSet |= VEHPARS_ARRIVALSPEED_SET;
2041
} else {
2042
// set default value
2043
parseArrivalSpeed(myTagProperty->getDefaultStringValue(key), myTagProperty->getTagStr(), id, arrivalSpeed, arrivalSpeedProcedure, error);
2044
// unset parameter
2045
parametersSet &= ~VEHPARS_ARRIVALSPEED_SET;
2046
}
2047
break;
2048
case SUMO_ATTR_LINE:
2049
if (!value.empty() && (value != myTagProperty->getDefaultStringValue(key))) {
2050
line = value;
2051
// mark parameter as set
2052
parametersSet |= VEHPARS_LINE_SET;
2053
} else {
2054
// set default value
2055
line = myTagProperty->getDefaultStringValue(key);
2056
// unset parameter
2057
parametersSet &= ~VEHPARS_LINE_SET;
2058
}
2059
break;
2060
case SUMO_ATTR_PERSON_NUMBER:
2061
if (!value.empty() && (value != myTagProperty->getDefaultStringValue(key))) {
2062
personNumber = parse<int>(value);
2063
// mark parameter as set
2064
parametersSet |= VEHPARS_PERSON_NUMBER_SET;
2065
} else {
2066
// set default value
2067
personNumber = myTagProperty->getDefaultIntValue(key);
2068
// unset parameter
2069
parametersSet &= ~VEHPARS_PERSON_NUMBER_SET;
2070
}
2071
break;
2072
case SUMO_ATTR_CONTAINER_NUMBER:
2073
if (!value.empty() && (value != myTagProperty->getDefaultStringValue(key))) {
2074
containerNumber = parse<int>(value);
2075
// mark parameter as set
2076
parametersSet |= VEHPARS_CONTAINER_NUMBER_SET;
2077
} else {
2078
// set default value
2079
containerNumber = myTagProperty->getDefaultIntValue(key);
2080
// unset parameter
2081
parametersSet &= ~VEHPARS_CONTAINER_NUMBER_SET;
2082
}
2083
break;
2084
case SUMO_ATTR_REROUTE:
2085
if (!value.empty() && (value != myTagProperty->getDefaultStringValue(key))) {
2086
// mark parameter as set
2087
parametersSet |= VEHPARS_ROUTE_SET;
2088
} else {
2089
// unset parameter
2090
parametersSet &= ~VEHPARS_ROUTE_SET;
2091
}
2092
break;
2093
case SUMO_ATTR_DEPARTPOS_LAT:
2094
if (!value.empty() && (value != myTagProperty->getDefaultStringValue(key))) {
2095
parseDepartPosLat(value, myTagProperty->getTagStr(), id, departPosLat, departPosLatProcedure, error);
2096
// mark parameter as set
2097
parametersSet |= VEHPARS_DEPARTPOSLAT_SET;
2098
} else {
2099
// set default value
2100
parseDepartPosLat(myTagProperty->getDefaultStringValue(key), myTagProperty->getTagStr(), id, departPosLat, departPosLatProcedure, error);
2101
// unset parameter
2102
parametersSet &= ~VEHPARS_DEPARTPOSLAT_SET;
2103
}
2104
break;
2105
case SUMO_ATTR_ARRIVALPOS_LAT:
2106
if (!value.empty() && (value != myTagProperty->getDefaultStringValue(key))) {
2107
parseArrivalPosLat(value, myTagProperty->getTagStr(), id, arrivalPosLat, arrivalPosLatProcedure, error);
2108
// mark parameter as set
2109
parametersSet |= VEHPARS_ARRIVALPOSLAT_SET;
2110
} else {
2111
// set default value
2112
parseArrivalPosLat(myTagProperty->getDefaultStringValue(key), myTagProperty->getTagStr(), id, arrivalPosLat, arrivalPosLatProcedure, error);
2113
// unset parameter
2114
parametersSet &= ~VEHPARS_ARRIVALPOSLAT_SET;
2115
}
2116
parseArrivalPosLat(value, myTagProperty->getTagStr(), id, arrivalPosLat, arrivalPosLatProcedure, error);
2117
break;
2118
case SUMO_ATTR_INSERTIONCHECKS:
2119
if (value.empty() || (value == "all")) {
2120
// unset parameter
2121
parametersSet &= ~VEHPARS_INSERTION_CHECKS_SET;
2122
} else {
2123
// mark parameter as set
2124
parametersSet |= VEHPARS_INSERTION_CHECKS_SET;
2125
}
2126
insertionChecks = parseInsertionChecks(value);
2127
break;
2128
// Specific of vehicles over routes
2129
case SUMO_ATTR_ROUTE:
2130
if (getParentDemandElements().size() == 2) {
2131
replaceDemandElementParent(NamespaceIDs::routes, value, 1);
2132
}
2133
updateGeometry();
2134
updateSpreadStackGeometry = true;
2135
break;
2136
// Specific of from-to edges
2137
case SUMO_ATTR_FROM: {
2138
// change first edge
2139
replaceFirstParentEdge(value);
2140
// compute vehicle
2141
computePathElement();
2142
updateSpreadStackGeometry = true;
2143
break;
2144
}
2145
case SUMO_ATTR_TO: {
2146
// change last edge
2147
replaceLastParentEdge(value);
2148
// compute vehicle
2149
computePathElement();
2150
updateSpreadStackGeometry = true;
2151
break;
2152
}
2153
case SUMO_ATTR_VIA: {
2154
if (!value.empty()) {
2155
// set new via edges
2156
via = parse< std::vector<std::string> >(value);
2157
// mark parameter as set
2158
parametersSet |= VEHPARS_VIA_SET;
2159
} else {
2160
// clear via
2161
via.clear();
2162
// unset parameter
2163
parametersSet &= ~VEHPARS_VIA_SET;
2164
}
2165
// compute vehicle
2166
computePathElement();
2167
updateSpreadStackGeometry = true;
2168
break;
2169
}
2170
case SUMO_ATTR_DEPARTEDGE: {
2171
// update depart edge
2172
if (value.empty()) {
2173
// unset parameter
2174
parametersSet &= ~VEHPARS_DEPARTEDGE_SET;
2175
departEdge = -1;
2176
departEdgeProcedure = RouteIndexDefinition::DEFAULT;
2177
} else {
2178
// mark parameter as set
2179
parametersSet |= VEHPARS_DEPARTEDGE_SET;
2180
departEdge = parse<int>(value);
2181
departEdgeProcedure = RouteIndexDefinition::GIVEN;
2182
}
2183
// compute vehicle
2184
if (getID().size() > 0) {
2185
computePathElement();
2186
updateSpreadStackGeometry = true;
2187
}
2188
break;
2189
}
2190
case SUMO_ATTR_ARRIVALEDGE: {
2191
// update arrival edge
2192
if (value.empty()) {
2193
// unset parameter
2194
parametersSet &= ~VEHPARS_ARRIVALEDGE_SET;
2195
arrivalEdge = -1;
2196
arrivalEdgeProcedure = RouteIndexDefinition::DEFAULT;
2197
} else {
2198
// mark parameter as set
2199
parametersSet |= VEHPARS_ARRIVALEDGE_SET;
2200
arrivalEdge = parse<int>(value);
2201
arrivalEdgeProcedure = RouteIndexDefinition::GIVEN;
2202
}
2203
if (getID().size() > 0) {
2204
// compute vehicle
2205
computePathElement();
2206
updateSpreadStackGeometry = true;
2207
}
2208
break;
2209
}
2210
// Specific of from-to junctions
2211
case SUMO_ATTR_FROM_JUNCTION: {
2212
// change first junction
2213
replaceFirstParentJunction(value);
2214
// compute vehicle
2215
computePathElement();
2216
updateSpreadStackGeometry = true;
2217
break;
2218
}
2219
case SUMO_ATTR_TO_JUNCTION: {
2220
// change last junction
2221
replaceLastParentJunction(value);
2222
// compute vehicle
2223
computePathElement();
2224
updateSpreadStackGeometry = true;
2225
break;
2226
}
2227
// Specific of from-to TAZs
2228
case SUMO_ATTR_FROM_TAZ: {
2229
// change first additional
2230
replaceFirstParentAdditional(SUMO_TAG_TAZ, value);
2231
// set taz manually
2232
fromTaz = value;
2233
// compute vehicle
2234
computePathElement();
2235
updateSpreadStackGeometry = true;
2236
break;
2237
}
2238
case SUMO_ATTR_TO_TAZ: {
2239
// change last additional
2240
replaceLastParentAdditional(SUMO_TAG_TAZ, value);
2241
// set taz manually
2242
toTaz = value;
2243
// compute vehicle
2244
computePathElement();
2245
updateSpreadStackGeometry = true;
2246
break;
2247
}
2248
default:
2249
setFlowAttribute(this, key, value);
2250
break;
2251
}
2252
// check if stack label has to be updated
2253
if (updateSpreadStackGeometry) {
2254
if (myTagProperty->vehicleEdges()) {
2255
getParentEdges().front()->updateVehicleStackLabels();
2256
getParentEdges().front()->updateVehicleSpreadGeometries();
2257
} else if (myTagProperty->vehicleRoute() && !getRouteParent()->getTagProperty()->isRouteDistribution()) {
2258
getRouteParent()->getParentEdges().front()->updateVehicleStackLabels();
2259
getRouteParent()->getParentEdges().front()->updateVehicleSpreadGeometries();
2260
} else if (myTagProperty->vehicleRouteEmbedded()) {
2261
getChildDemandElements().front()->getParentEdges().front()->updateVehicleStackLabels();
2262
getChildDemandElements().front()->getParentEdges().front()->updateVehicleSpreadGeometries();
2263
}
2264
}
2265
}
2266
2267
2268
void
2269
GNEVehicle::toggleAttribute(SumoXMLAttr key, const bool value) {
2270
// toggle flow attributes
2271
toggleFlowAttribute(key, value);
2272
}
2273
2274
/****************************************************************************/
2275
2276