Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/elements/demand/GNEContainer.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 GNEContainer.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date May 2019
17
///
18
// Representation of containers in netedit
19
/****************************************************************************/
20
21
#include <microsim/devices/MSDevice_BTreceiver.h>
22
#include <netedit/changes/GNEChange_Attribute.h>
23
#include <netedit/elements/moving/GNEMoveElementPlanParent.h>
24
#include <netedit/GNENet.h>
25
#include <netedit/GNETagProperties.h>
26
#include <utils/gui/div/GLHelper.h>
27
#include <utils/gui/div/GUIDesigns.h>
28
#include <utils/gui/images/GUITextureSubSys.h>
29
#include <utils/gui/windows/GUIAppEnum.h>
30
#include <utils/xml/NamespaceIDs.h>
31
32
#include "GNEContainer.h"
33
#include "GNERouteHandler.h"
34
35
// ===========================================================================
36
// FOX callback mapping
37
// ===========================================================================
38
39
FXDEFMAP(GNEContainer::GNEContainerPopupMenu) containerPopupMenuMap[] = {
40
FXMAPFUNC(SEL_COMMAND, MID_GNE_CONTAINER_TRANSFORM, GNEContainer::GNEContainerPopupMenu::onCmdTransform),
41
};
42
43
FXDEFMAP(GNEContainer::GNESelectedContainersPopupMenu) selectedContainersPopupMenuMap[] = {
44
FXMAPFUNC(SEL_COMMAND, MID_GNE_CONTAINER_TRANSFORM, GNEContainer::GNESelectedContainersPopupMenu::onCmdTransform),
45
};
46
47
// Object implementation
48
FXIMPLEMENT(GNEContainer::GNEContainerPopupMenu, GUIGLObjectPopupMenu, containerPopupMenuMap, ARRAYNUMBER(containerPopupMenuMap))
49
FXIMPLEMENT(GNEContainer::GNESelectedContainersPopupMenu, GUIGLObjectPopupMenu, selectedContainersPopupMenuMap, ARRAYNUMBER(selectedContainersPopupMenuMap))
50
51
// ===========================================================================
52
// GNEContainer::GNEContainerPopupMenu
53
// ===========================================================================
54
55
GNEContainer::GNEContainerPopupMenu::GNEContainerPopupMenu(GNEContainer* container, GUIMainWindow& app, GUISUMOAbstractView& parent) :
56
GUIGLObjectPopupMenu(app, parent, container),
57
myContainer(container),
58
myTransformToContainer(nullptr),
59
myTransformToContainerFlow(nullptr) {
60
// build common options
61
container->buildPopUpMenuCommonOptions(this, app, container->myNet->getViewNet(), container->getTagProperty()->getTag(), container->isAttributeCarrierSelected());
62
// add transform functions only in demand mode
63
if (myContainer->getNet()->getViewNet()->getEditModes().isCurrentSupermodeDemand()) {
64
// create menu pane for transform operations
65
FXMenuPane* transformOperation = new FXMenuPane(this);
66
this->insertMenuPaneChild(transformOperation);
67
new FXMenuCascade(this, "transform to", nullptr, transformOperation);
68
// Create menu comands for all transformations
69
myTransformToContainer = GUIDesigns::buildFXMenuCommand(transformOperation, "Container", GUIIconSubSys::getIcon(GUIIcon::CONTAINER), this, MID_GNE_CONTAINER_TRANSFORM);
70
myTransformToContainerFlow = GUIDesigns::buildFXMenuCommand(transformOperation, "ContainerFlow", GUIIconSubSys::getIcon(GUIIcon::CONTAINERFLOW), this, MID_GNE_CONTAINER_TRANSFORM);
71
// check what menu command has to be disabled
72
if (myContainer->getTagProperty()->getTag() == SUMO_TAG_CONTAINER) {
73
myTransformToContainer->disable();
74
} else if (myContainer->getTagProperty()->getTag() == SUMO_TAG_CONTAINERFLOW) {
75
myTransformToContainerFlow->disable();
76
}
77
}
78
}
79
80
81
GNEContainer::GNEContainerPopupMenu::~GNEContainerPopupMenu() {}
82
83
84
long
85
GNEContainer::GNEContainerPopupMenu::onCmdTransform(FXObject* obj, FXSelector, void*) {
86
if (obj == myTransformToContainer) {
87
GNERouteHandler::transformToContainer(myContainer);
88
} else if (obj == myTransformToContainerFlow) {
89
GNERouteHandler::transformToContainerFlow(myContainer);
90
}
91
return 1;
92
}
93
94
95
// ===========================================================================
96
// GNEContainer::GNESelectedContainersPopupMenu
97
// ===========================================================================
98
99
GNEContainer::GNESelectedContainersPopupMenu::GNESelectedContainersPopupMenu(GNEContainer* container, const std::vector<GNEContainer*>& selectedContainer, GUIMainWindow& app, GUISUMOAbstractView& parent) :
100
GUIGLObjectPopupMenu(app, parent, container),
101
myContainerTag(container->getTagProperty()->getTag()),
102
mySelectedContainers(selectedContainer),
103
myTransformToContainer(nullptr),
104
myTransformToContainerFlow(nullptr) {
105
// build common options
106
container->buildPopUpMenuCommonOptions(this, app, container->myNet->getViewNet(), container->getTagProperty()->getTag(), container->isAttributeCarrierSelected());
107
// add transform functions only in demand mode
108
if (container->getNet()->getViewNet()->getEditModes().isCurrentSupermodeDemand()) {
109
// create menu pane for transform operations
110
FXMenuPane* transformOperation = new FXMenuPane(this);
111
this->insertMenuPaneChild(transformOperation);
112
new FXMenuCascade(this, "transform to", nullptr, transformOperation);
113
// Create menu comands for all transformations
114
myTransformToContainer = GUIDesigns::buildFXMenuCommand(transformOperation, "Container", GUIIconSubSys::getIcon(GUIIcon::CONTAINER), this, MID_GNE_CONTAINER_TRANSFORM);
115
myTransformToContainerFlow = GUIDesigns::buildFXMenuCommand(transformOperation, "ContainerFlow", GUIIconSubSys::getIcon(GUIIcon::CONTAINERFLOW), this, MID_GNE_CONTAINER_TRANSFORM);
116
}
117
}
118
119
120
GNEContainer::GNESelectedContainersPopupMenu::~GNESelectedContainersPopupMenu() {}
121
122
123
long
124
GNEContainer::GNESelectedContainersPopupMenu::onCmdTransform(FXObject* obj, FXSelector, void*) {
125
// iterate over all selected containers
126
for (const auto& container : mySelectedContainers) {
127
if ((obj == myTransformToContainer) &&
128
(container->getTagProperty()->getTag() == myContainerTag)) {
129
GNERouteHandler::transformToContainer(container);
130
} else if ((obj == myTransformToContainerFlow) &&
131
(container->getTagProperty()->getTag() == myContainerTag)) {
132
GNERouteHandler::transformToContainer(container);
133
}
134
}
135
return 1;
136
}
137
138
// ===========================================================================
139
// member method definitions
140
// ===========================================================================
141
142
#ifdef _MSC_VER
143
#pragma warning(push)
144
#pragma warning(disable: 4355) // mask warning about "this" in initializers
145
#endif
146
GNEContainer::GNEContainer(SumoXMLTag tag, GNENet* net) :
147
GNEDemandElement(net, tag),
148
GNEDemandElementFlow(this),
149
myMoveElementPlanParent(new GNEMoveElementPlanParent(this, departPos, departPosProcedure)) {
150
// set end and container per hours as default flow values
151
toggleAttribute(SUMO_ATTR_END, 1);
152
toggleAttribute(SUMO_ATTR_CONTAINERSPERHOUR, 1);
153
}
154
155
156
GNEContainer::GNEContainer(SumoXMLTag tag, GNENet* net, FileBucket* fileBucket,
157
GNEDemandElement* pType, const SUMOVehicleParameter& containerparameters) :
158
GNEDemandElement(containerparameters.id, net, tag, fileBucket),
159
GNEDemandElementFlow(this, containerparameters),
160
myMoveElementPlanParent(new GNEMoveElementPlanParent(this, departPos, departPosProcedure)) {
161
// set parents
162
setParent<GNEDemandElement*>(pType);
163
// set manually vtypeID (needed for saving)
164
vtypeid = pType->getID();
165
}
166
#ifdef _MSC_VER
167
#pragma warning(pop)
168
#endif
169
170
GNEContainer::~GNEContainer() {}
171
172
173
GNEMoveElement*
174
GNEContainer::getMoveElement() const {
175
return myMoveElementPlanParent;
176
}
177
178
179
Parameterised*
180
GNEContainer::getParameters() {
181
return this;
182
}
183
184
185
const Parameterised*
186
GNEContainer::getParameters() const {
187
return this;
188
}
189
190
191
void
192
GNEContainer::writeDemandElement(OutputDevice& device) const {
193
// attribute VType musn't be written if is DEFAULT_PEDTYPE_ID
194
if (getTypeParent()->getID() == DEFAULT_CONTAINERTYPE_ID) {
195
// unset VType parameter
196
parametersSet &= ~VEHPARS_VTYPE_SET;
197
// write container attributes (VType will not be written)
198
write(device, OptionsCont::getOptions(), myTagProperty->getXMLTag());
199
// set VType parameter again
200
parametersSet |= VEHPARS_VTYPE_SET;
201
} else {
202
// write container attributes, including VType
203
write(device, OptionsCont::getOptions(), myTagProperty->getXMLTag(), getTypeParent()->getID());
204
}
205
// write parameters
206
writeParams(device);
207
// write child demand elements associated to this container (Rides, Walks...)
208
for (const auto& containerPlan : getChildDemandElements()) {
209
containerPlan->writeDemandElement(device);
210
}
211
// close container tag
212
device.closeTag();
213
}
214
215
216
GNEDemandElement::Problem
217
GNEContainer::isDemandElementValid() const {
218
if (getChildDemandElements().size() == 0) {
219
return Problem::NO_PLANS;
220
} else {
221
return Problem::OK;
222
}
223
}
224
225
226
std::string
227
GNEContainer::getDemandElementProblem() const {
228
if (getChildDemandElements().size() == 0) {
229
return "Container needs at least one plan";
230
} else {
231
return "";
232
}
233
}
234
235
236
void
237
GNEContainer::fixDemandElementProblem() {
238
// nothing to fix
239
}
240
241
242
SUMOVehicleClass
243
GNEContainer::getVClass() const {
244
return getParentDemandElements().front()->getVClass();
245
}
246
247
248
const RGBColor&
249
GNEContainer::getColor() const {
250
return color;
251
}
252
253
254
void
255
GNEContainer::updateGeometry() {
256
// only update geometry of childrens
257
for (const auto& demandElement : getChildDemandElements()) {
258
demandElement->updateGeometry();
259
}
260
}
261
262
263
Position
264
GNEContainer::getPositionInView() const {
265
return getAttributePosition(SUMO_ATTR_DEPARTPOS);
266
}
267
268
269
GUIGLObjectPopupMenu*
270
GNEContainer::getPopUpMenu(GUIMainWindow& app, GUISUMOAbstractView& parent) {
271
// return a GNEContainerPopupMenu
272
return new GNEContainerPopupMenu(this, app, parent);
273
}
274
275
276
std::string
277
GNEContainer::getParentName() const {
278
return getParentDemandElements().front()->getID();
279
}
280
281
282
double
283
GNEContainer::getExaggeration(const GUIVisualizationSettings& s) const {
284
return s.containerSize.getExaggeration(s, this, 80);
285
}
286
287
288
Boundary
289
GNEContainer::getCenteringBoundary() const {
290
Boundary containerBoundary;
291
if (getChildDemandElements().size() > 0) {
292
if (getChildDemandElements().front()->getTagProperty()->isPlanStopContainer()) {
293
// use boundary of stop center
294
return getChildDemandElements().front()->getCenteringBoundary();
295
} else {
296
containerBoundary.add(getPositionInView());
297
}
298
} else {
299
containerBoundary = Boundary(-0.1, -0.1, 0.1, 0.1);
300
}
301
containerBoundary.grow(20);
302
return containerBoundary;
303
}
304
305
306
void
307
GNEContainer::splitEdgeGeometry(const double /*splitPosition*/, const GNENetworkElement* /*originalElement*/,
308
const GNENetworkElement* /*newElement*/, GNEUndoList* /*undoList*/) {
309
// geometry of this element cannot be splitted
310
}
311
312
313
void
314
GNEContainer::drawGL(const GUIVisualizationSettings& s) const {
315
bool drawContainer = true;
316
// check if container can be drawn
317
if (!myNet->getViewNet()->getNetworkViewOptions().showDemandElements()) {
318
drawContainer = false;
319
} else if (!myNet->getViewNet()->getDataViewOptions().showDemandElements()) {
320
drawContainer = false;
321
} else if (!myNet->getViewNet()->getDemandViewOptions().showNonInspectedDemandElements(this)) {
322
drawContainer = false;
323
} else if (getChildDemandElements().empty()) {
324
drawContainer = false;
325
}
326
// continue if container can be drawn
327
if (drawContainer) {
328
// obtain exaggeration (and add the special containerExaggeration)
329
const double exaggeration = getExaggeration(s) + 10;
330
// get detail level
331
const auto d = s.getDetailLevel(exaggeration);
332
// obtain position
333
const Position containerPosition = getAttributePosition(SUMO_ATTR_DEPARTPOS);
334
if (containerPosition == Position::INVALID) {
335
return;
336
}
337
// draw geometry only if we'rent in drawForObjectUnderCursor mode
338
if (s.checkDrawContainer(d, isAttributeCarrierSelected())) {
339
// obtain img file
340
const std::string file = getTypeParent()->getAttribute(SUMO_ATTR_IMGFILE);
341
// push draw matrix
342
GLHelper::pushMatrix();
343
// Start with the drawing of the area traslating matrix to origin
344
drawInLayer(getType());
345
// translate and rotate
346
glTranslated(containerPosition.x(), containerPosition.y(), 0);
347
glRotated(90, 0, 0, 1);
348
// set container color
349
GLHelper::setColor(getDrawingColor(s));
350
// set scale
351
glScaled(exaggeration, exaggeration, 1);
352
// draw container depending of detail level
353
switch (s.containerQuality) {
354
case 0:
355
case 1:
356
case 2:
357
drawAction_drawAsPoly();
358
break;
359
case 3:
360
default:
361
drawAction_drawAsImage(s);
362
break;
363
}
364
// pop matrix
365
GLHelper::popMatrix();
366
// draw line between junctions if container plan isn't valid
367
for (const auto& containerPlan : getChildDemandElements()) {
368
if (containerPlan->getTagProperty()->isPlanContainer() && (containerPlan->getParentJunctions().size() > 0) &&
369
!myNet->getDemandPathManager()->isPathValid(containerPlan)) {
370
drawJunctionLine(containerPlan);
371
}
372
}
373
// draw stack label
374
if (myStackedLabelNumber > 0) {
375
drawStackLabel(myStackedLabelNumber, "container", Position(containerPosition.x() - 2.5, containerPosition.y() - 0.8), -90, 1.3, 5, getExaggeration(s));
376
} else if (getChildDemandElements().front()->getTagProperty()->getTag() == GNE_TAG_STOPCONTAINER_CONTAINERSTOP) {
377
// declare counter for stacked containers over stops
378
int stackedCounter = 0;
379
// get stoppingPlace
380
const auto stoppingPlace = getChildDemandElements().front()->getParentAdditionals().front();
381
// get stacked containers
382
for (const auto& stopContainer : stoppingPlace->getChildDemandElements()) {
383
if (stopContainer->getTagProperty()->getTag() == GNE_TAG_STOPCONTAINER_CONTAINERSTOP) {
384
// get container parent
385
const auto containerParent = stopContainer->getParentDemandElements().front();
386
// check if the stop if the first container plan parent
387
if (stopContainer->getPreviousChildDemandElement(containerParent) == nullptr) {
388
stackedCounter++;
389
}
390
}
391
}
392
// if we have more than two stacked elements, draw label
393
if (stackedCounter > 1) {
394
drawStackLabel(stackedCounter, "container", Position(containerPosition.x() - 2.5, containerPosition.y() - 0.8), -90, 1.3, 5, getExaggeration(s));
395
}
396
}
397
// draw flow label
398
if (myTagProperty->isFlow()) {
399
drawFlowLabel(Position(containerPosition.x() - 1, containerPosition.y() - 4.25), -90, 1.8, 2, getExaggeration(s));
400
}
401
// draw name
402
drawName(containerPosition, s.scale, s.containerName, s.angle);
403
// draw lock icon
404
GNEViewNetHelper::LockIcon::drawLockIcon(d, this, getType(), getPositionInView(), exaggeration);
405
// draw dotted contour
406
myContainerContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);
407
}
408
// calculate contour
409
myContainerContour.calculateContourRectangleShape(s, d, this, containerPosition, 0.5, 0.18, getType(), -5.5, 0, 0, exaggeration, nullptr);
410
}
411
}
412
413
414
void
415
GNEContainer::computePathElement() {
416
// compute all container plan children (because aren't computed in "computeDemandElements()")
417
for (const auto& demandElement : getChildDemandElements()) {
418
demandElement->computePathElement();
419
}
420
}
421
422
423
void
424
GNEContainer::drawLanePartialGL(const GUIVisualizationSettings& /*s*/, const GNESegment* /*segment*/, const double /*offsetFront*/) const {
425
// Stops don't use drawJunctionPartialGL
426
}
427
428
429
void
430
GNEContainer::drawJunctionPartialGL(const GUIVisualizationSettings& /*s*/, const GNESegment* /*segment*/, const double /*offsetFront*/) const {
431
// Stops don't use drawJunctionPartialGL
432
}
433
434
435
GNELane*
436
GNEContainer::getFirstPathLane() const {
437
// use path lane of first container plan
438
return getChildDemandElements().front()->getFirstPathLane();
439
}
440
441
442
GNELane*
443
GNEContainer::getLastPathLane() const {
444
// use path lane of first container plan
445
return getChildDemandElements().front()->getLastPathLane();
446
}
447
448
449
std::string
450
GNEContainer::getAttribute(SumoXMLAttr key) const {
451
// declare string error
452
std::string error;
453
switch (key) {
454
case SUMO_ATTR_ID:
455
return getMicrosimID();
456
case SUMO_ATTR_TYPE:
457
return getTypeParent()->getID();
458
case SUMO_ATTR_COLOR:
459
if (wasSet(VEHPARS_COLOR_SET)) {
460
return toString(color);
461
} else {
462
return myTagProperty->getDefaultStringValue(SUMO_ATTR_COLOR);
463
}
464
case SUMO_ATTR_DEPARTPOS:
465
if (wasSet(VEHPARS_DEPARTPOS_SET)) {
466
return getDepartPos();
467
} else {
468
return myTagProperty->getDefaultStringValue(SUMO_ATTR_DEPARTPOS);
469
}
470
default:
471
return getFlowAttribute(this, key);
472
}
473
}
474
475
476
double
477
GNEContainer::getAttributeDouble(SumoXMLAttr key) const {
478
switch (key) {
479
case SUMO_ATTR_DEPARTPOS:
480
if (departPosProcedure == DepartPosDefinition::GIVEN) {
481
return departPos;
482
} else {
483
return 0;
484
}
485
default:
486
return getFlowAttributeDouble(key);
487
}
488
}
489
490
491
Position
492
GNEContainer::getAttributePosition(SumoXMLAttr key) const {
493
switch (key) {
494
case SUMO_ATTR_DEPARTPOS: {
495
// first check number of child demand elements
496
if (getChildDemandElements().empty()) {
497
return Position();
498
}
499
// get container plan
500
const GNEDemandElement* containerPlan = getChildDemandElements().front();
501
// first check if first container plan is a stop
502
if (containerPlan->getTagProperty()->isPlanStopContainer()) {
503
// stop center
504
return containerPlan->getPositionInView();
505
} else if (containerPlan->getTagProperty()->planFromTAZ()) {
506
// TAZ
507
if (containerPlan->getParentAdditionals().front()->getAttribute(SUMO_ATTR_CENTER).empty()) {
508
return containerPlan->getParentAdditionals().front()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
509
} else {
510
return containerPlan->getParentAdditionals().front()->getAttributePosition(SUMO_ATTR_CENTER);
511
}
512
} else if (containerPlan->getTagProperty()->planFromJunction()) {
513
// juncrtion
514
return containerPlan->getParentJunctions().front()->getPositionInView();
515
} else {
516
return containerPlan->getAttributePosition(GNE_ATTR_PLAN_GEOMETRY_STARTPOS);
517
}
518
}
519
default:
520
return getCommonAttributePosition(key);
521
}
522
}
523
524
525
void
526
GNEContainer::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
527
switch (key) {
528
case SUMO_ATTR_ID:
529
case SUMO_ATTR_TYPE:
530
case SUMO_ATTR_COLOR:
531
case SUMO_ATTR_DEPARTPOS:
532
GNEChange_Attribute::changeAttribute(this, key, value, undoList);
533
break;
534
default:
535
setFlowAttribute(this, key, value, undoList);
536
break;
537
}
538
}
539
540
541
bool
542
GNEContainer::isValid(SumoXMLAttr key, const std::string& value) {
543
// declare string error
544
std::string error;
545
switch (key) {
546
case SUMO_ATTR_ID:
547
return isValidDemandElementID(NamespaceIDs::containers, value);
548
case SUMO_ATTR_TYPE:
549
return (myNet->getAttributeCarriers()->retrieveDemandElements(NamespaceIDs::types, value, false) != nullptr);
550
case SUMO_ATTR_COLOR:
551
return canParse<RGBColor>(value);
552
case SUMO_ATTR_DEPARTPOS: {
553
double dummyDepartPos;
554
DepartPosDefinition dummyDepartPosProcedure;
555
parseDepartPos(value, myTagProperty->getTagStr(), id, dummyDepartPos, dummyDepartPosProcedure, error);
556
// if error is empty, given value is valid
557
return error.empty();
558
}
559
default:
560
return isValidFlowAttribute(this, key, value);
561
}
562
}
563
564
565
void
566
GNEContainer::enableAttribute(SumoXMLAttr key, GNEUndoList* undoList) {
567
enableFlowAttribute(this, key, undoList);
568
}
569
570
571
void
572
GNEContainer::disableAttribute(SumoXMLAttr key, GNEUndoList* undoList) {
573
disableFlowAttribute(this, key, undoList);
574
}
575
576
577
bool
578
GNEContainer::isAttributeEnabled(SumoXMLAttr key) const {
579
return isFlowAttributeEnabled(key);
580
}
581
582
583
std::string
584
GNEContainer::getPopUpID() const {
585
return getTagStr();
586
}
587
588
589
std::string
590
GNEContainer::getHierarchyName() const {
591
const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();
592
// special case for Trips and flow
593
if ((myTagProperty->getTag() == SUMO_TAG_TRIP) || (myTagProperty->getTag() == SUMO_TAG_FLOW)) {
594
// check if we're inspecting an Edge
595
if (inspectedElements.getFirstAC() && (inspectedElements.getFirstAC()->getTagProperty()->getTag() == SUMO_TAG_EDGE)) {
596
// check if edge correspond to a "from", "to" or "via" edge
597
if (inspectedElements.isACInspected(getParentEdges().front())) {
598
return getTagStr() + ": " + getAttribute(SUMO_ATTR_ID) + " (from)";
599
} else if (inspectedElements.isACInspected(getParentEdges().front())) {
600
return getTagStr() + ": " + getAttribute(SUMO_ATTR_ID) + " (to)";
601
} else {
602
// iterate over via
603
for (const auto& viaEdgeID : via) {
604
if (viaEdgeID == inspectedElements.getFirstAC()->getID()) {
605
return getTagStr() + ": " + getAttribute(SUMO_ATTR_ID) + " (via)";
606
}
607
}
608
}
609
}
610
}
611
return getTagStr() + ": " + getAttribute(SUMO_ATTR_ID);
612
}
613
614
// ===========================================================================
615
// protected
616
// ===========================================================================
617
618
RGBColor
619
GNEContainer::getDrawingColor(const GUIVisualizationSettings& s) const {
620
// change color
621
if (drawUsingSelectColor()) {
622
return s.colorSettings.selectedContainerColor;
623
} else {
624
return getColorByScheme(s.containerColorer, this);
625
}
626
}
627
628
629
void
630
GNEContainer::drawAction_drawAsPoly() const {
631
// obtain width and length
632
const double length = getTypeParent()->getAttributeDouble(SUMO_ATTR_LENGTH);
633
const double width = getTypeParent()->getAttributeDouble(SUMO_ATTR_WIDTH);
634
// draw pedestrian shape
635
glScaled(length * 0.2, width * 0.2, 1);
636
glBegin(GL_QUADS);
637
glVertex2d(0, 0.5);
638
glVertex2d(0, -0.5);
639
glVertex2d(-1, -0.5);
640
glVertex2d(-1, 0.5);
641
glEnd();
642
GLHelper::setColor(GLHelper::getColor().changedBrightness(-30));
643
glTranslated(0, 0, .045);
644
glBegin(GL_QUADS);
645
glVertex2d(-0.1, 0.4);
646
glVertex2d(-0.1, -0.4);
647
glVertex2d(-0.9, -0.4);
648
glVertex2d(-0.9, 0.4);
649
glEnd();
650
}
651
652
653
void
654
GNEContainer::drawAction_drawAsImage(const GUIVisualizationSettings& s) const {
655
const std::string& file = getTypeParent()->getAttribute(SUMO_ATTR_IMGFILE);
656
// obtain width and length
657
const double length = getTypeParent()->getAttributeDouble(SUMO_ATTR_LENGTH);
658
const double width = getTypeParent()->getAttributeDouble(SUMO_ATTR_WIDTH);
659
if (file != "") {
660
// @todo invent an option for controlling whether images should be rotated or not
661
//if (getVehicleType().getGuiShape() == SVS_CONTAINER) {
662
// glRotated(RAD2DEG(getAngle() + M_PI / 2.), 0, 0, 1);
663
//}
664
int textureID = GUITexturesHelper::getTextureID(file);
665
if (textureID > 0) {
666
const double exaggeration = s.containerSize.getExaggeration(s, this);
667
const double halfLength = length / 2.0 * exaggeration;
668
const double halfWidth = width / 2.0 * exaggeration;
669
GUITexturesHelper::drawTexturedBox(textureID, -halfWidth, -halfLength, halfWidth, halfLength);
670
}
671
} else {
672
// fallback if no image is defined
673
drawAction_drawAsPoly();
674
}
675
}
676
677
// ===========================================================================
678
// private
679
// ===========================================================================
680
681
GNEContainer::containerPlanSegment::containerPlanSegment(GNEDemandElement* _containerPlan) :
682
containerPlan(_containerPlan),
683
edge(nullptr),
684
arrivalPos(-1) {
685
}
686
687
688
GNEContainer::containerPlanSegment::containerPlanSegment() :
689
containerPlan(nullptr),
690
edge(nullptr),
691
arrivalPos(-1) {
692
}
693
694
695
void
696
GNEContainer::setAttribute(SumoXMLAttr key, const std::string& value) {
697
// declare string error
698
std::string error;
699
switch (key) {
700
case SUMO_ATTR_ID:
701
// update microsimID
702
setDemandElementID(value);
703
// update id
704
id = value;
705
break;
706
case SUMO_ATTR_TYPE:
707
if (getID().size() > 0) {
708
replaceDemandElementParent(NamespaceIDs::types, value, 0);
709
// set manually vtypeID (needed for saving)
710
vtypeid = value;
711
}
712
break;
713
case SUMO_ATTR_COLOR:
714
if (!value.empty() && (value != myTagProperty->getDefaultStringValue(key))) {
715
color = parse<RGBColor>(value);
716
// mark parameter as set
717
parametersSet |= VEHPARS_COLOR_SET;
718
} else {
719
// set default value
720
color = parse<RGBColor>(myTagProperty->getDefaultStringValue(key));
721
// unset parameter
722
parametersSet &= ~VEHPARS_COLOR_SET;
723
}
724
break;
725
case SUMO_ATTR_DEPARTPOS:
726
if (!value.empty() && (value != myTagProperty->getDefaultStringValue(key))) {
727
parseDepartPos(value, myTagProperty->getTagStr(), id, departPos, departPosProcedure, error);
728
// mark parameter as set
729
parametersSet |= VEHPARS_DEPARTPOS_SET;
730
} else {
731
// set default value
732
parseDepartPos(myTagProperty->getDefaultStringValue(key), myTagProperty->getTagStr(), id, departPos, departPosProcedure, error);
733
// unset parameter
734
parametersSet &= ~VEHPARS_DEPARTPOS_SET;
735
}
736
// compute container
737
updateGeometry();
738
break;
739
default:
740
setFlowAttribute(this, key, value);
741
break;
742
}
743
}
744
745
void
746
GNEContainer::toggleAttribute(SumoXMLAttr key, const bool value) {
747
// toggle flow attributes
748
toggleFlowAttribute(key, value);
749
}
750
751
/****************************************************************************/
752
753