Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/elements/demand/GNEStop.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 GNEStop.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date March 2019
17
///
18
// Representation of Stops in netedit
19
/****************************************************************************/
20
21
#include <netedit/changes/GNEChange_Attribute.h>
22
#include <netedit/changes/GNEChange_ToggleAttribute.h>
23
#include <netedit/elements/moving/GNEMoveElementLaneDouble.h>
24
#include <netedit/frames/demand/GNEStopFrame.h>
25
#include <netedit/frames/GNEDemandSelector.h>
26
#include <netedit/GNENet.h>
27
#include <netedit/GNEUndoList.h>
28
#include <netedit/GNEViewParent.h>
29
#include <utils/gui/div/GLHelper.h>
30
31
#include "GNEStop.h"
32
33
// ===========================================================================
34
// member method definitions
35
// ===========================================================================
36
#ifdef _MSC_VER
37
#pragma warning(push)
38
#pragma warning(disable: 4355) // mask warning about "this" in initializers
39
#endif
40
GNEStop::GNEStop(SumoXMLTag tag, GNENet* net) :
41
GNEDemandElement(net, tag),
42
GNEDemandElementPlan(this, -1, -1),
43
myMoveElementLaneDouble(new GNEMoveElementLaneDouble(this, SUMO_ATTR_STARTPOS, startPos, SUMO_ATTR_ENDPOS, endPos, friendlyPos)),
44
myCreationIndex(myNet->getAttributeCarriers()->getStopIndex()) {
45
// enable parking for stops in parkin)gAreas
46
if ((tag == GNE_TAG_STOP_PARKINGAREA) || (tag == GNE_TAG_WAYPOINT_PARKINGAREA)) {
47
parametersSet |= STOP_PARKING_SET;
48
}
49
// set parking
50
if (parametersSet & STOP_PARKING_SET) {
51
parking = ParkingType::OFFROAD;
52
}
53
// set waypoint speed
54
myTagProperty->isVehicleWaypoint() ? parametersSet |= STOP_SPEED_SET : parametersSet &= ~STOP_SPEED_SET;
55
// set jump
56
(jump != -1) ? parametersSet |= STOP_JUMP_SET : parametersSet &= ~STOP_JUMP_SET;
57
// set locator sufix
58
setStopMicrosimID();
59
}
60
61
62
GNEStop::GNEStop(SumoXMLTag tag, GNEDemandElement* stopParent, GNEAdditional* stoppingPlace,
63
const SUMOVehicleParameter::Stop& stopParameter) :
64
GNEDemandElement(stopParent, tag),
65
SUMOVehicleParameter::Stop(stopParameter),
66
GNEDemandElementPlan(this, -1, -1),
67
myMoveElementLaneDouble(new GNEMoveElementLaneDouble(this, SUMO_ATTR_STARTPOS, startPos, SUMO_ATTR_ENDPOS, endPos, friendlyPos)),
68
myCreationIndex(myNet->getAttributeCarriers()->getStopIndex()) {
69
// set parents
70
setParent<GNEAdditional*>(stoppingPlace);
71
setParent<GNEDemandElement*>(stopParent);
72
// set triggered values
73
if (triggered) {
74
parametersSet |= STOP_TRIGGER_SET;
75
if (awaitedPersons.size() > 0) {
76
parametersSet |= STOP_EXPECTED_SET;
77
}
78
} else if (containerTriggered) {
79
parametersSet |= STOP_TRIGGER_SET;
80
parametersSet |= STOP_CONTAINER_TRIGGER_SET;
81
if (awaitedPersons.size() > 0) {
82
parametersSet |= STOP_EXPECTED_CONTAINERS_SET;
83
}
84
} else if (joinTriggered) {
85
parametersSet |= STOP_TRIGGER_SET;
86
}
87
// set parking
88
if (parametersSet & STOP_PARKING_SET) {
89
parking = ParkingType::OFFROAD;
90
}
91
// set tripID and line
92
(stopParameter.tripId.size() > 0) ? parametersSet |= STOP_TRIP_ID_SET : parametersSet &= ~STOP_TRIP_ID_SET;
93
(stopParameter.line.size() > 0) ? parametersSet |= STOP_LINE_SET : parametersSet &= ~STOP_LINE_SET;
94
stopParameter.onDemand ? parametersSet |= STOP_ONDEMAND_SET : parametersSet &= ~STOP_ONDEMAND_SET;
95
// set waypoint speed
96
myTagProperty->isVehicleWaypoint() ? parametersSet |= STOP_SPEED_SET : parametersSet &= ~STOP_SPEED_SET;
97
// set jump
98
(jump != -1) ? parametersSet |= STOP_JUMP_SET : parametersSet &= ~STOP_JUMP_SET;
99
// set locator sufix
100
setStopMicrosimID();
101
}
102
103
104
GNEStop::GNEStop(SumoXMLTag tag, GNEDemandElement* stopParent, GNELane* lane,
105
const SUMOVehicleParameter::Stop& stopParameter) :
106
GNEDemandElement(stopParent, tag),
107
SUMOVehicleParameter::Stop(stopParameter),
108
GNEDemandElementPlan(this, -1, -1),
109
myMoveElementLaneDouble(new GNEMoveElementLaneDouble(this, SUMO_ATTR_STARTPOS, startPos, SUMO_ATTR_ENDPOS, endPos, friendlyPos)),
110
myCreationIndex(myNet->getAttributeCarriers()->getStopIndex()) {
111
// set parents
112
setParent<GNELane*>(lane);
113
setParent<GNEDemandElement*>(stopParent);
114
// set triggered values
115
if (triggered) {
116
parametersSet |= STOP_TRIGGER_SET;
117
if (awaitedPersons.size() > 0) {
118
parametersSet |= STOP_EXPECTED_SET;
119
}
120
} else if (containerTriggered) {
121
parametersSet |= STOP_TRIGGER_SET;
122
parametersSet |= STOP_CONTAINER_TRIGGER_SET;
123
if (awaitedPersons.size() > 0) {
124
parametersSet |= STOP_EXPECTED_CONTAINERS_SET;
125
}
126
} else if (joinTriggered) {
127
parametersSet |= STOP_TRIGGER_SET;
128
}
129
// set parking
130
if (parametersSet & STOP_PARKING_SET) {
131
parking = ParkingType::OFFROAD;
132
}
133
// set trigger
134
(stopParameter.tripId.size() > 0) ? parametersSet |= STOP_TRIP_ID_SET : parametersSet &= ~STOP_TRIP_ID_SET;
135
// set tripID and line
136
(stopParameter.tripId.size() > 0) ? parametersSet |= STOP_TRIP_ID_SET : parametersSet &= ~STOP_TRIP_ID_SET;
137
(stopParameter.line.size() > 0) ? parametersSet |= STOP_LINE_SET : parametersSet &= ~STOP_LINE_SET;
138
stopParameter.onDemand ? parametersSet |= STOP_ONDEMAND_SET : parametersSet &= ~STOP_ONDEMAND_SET;
139
// set waypoint speed
140
myTagProperty->isVehicleWaypoint() ? parametersSet |= STOP_SPEED_SET : parametersSet &= ~STOP_SPEED_SET;
141
// set jump
142
(jump != -1) ? parametersSet |= STOP_JUMP_SET : parametersSet &= ~STOP_JUMP_SET;
143
// set locator sufix
144
setStopMicrosimID();
145
}
146
#ifdef _MSC_VER
147
#pragma warning(pop)
148
#endif
149
150
GNEStop::~GNEStop() {}
151
152
153
GNEMoveElement*
154
GNEStop::getMoveElement() const {
155
return myMoveElementLaneDouble;
156
}
157
158
159
Parameterised*
160
GNEStop::getParameters() {
161
return this;
162
}
163
164
165
const Parameterised*
166
GNEStop::getParameters() const {
167
return this;
168
}
169
170
171
void
172
GNEStop::writeDemandElement(OutputDevice& device) const {
173
device.openTag(SUMO_TAG_STOP);
174
if (getParentAdditionals().size() > 0) {
175
if (getParentAdditionals().front()->getTagProperty()->getTag() == SUMO_TAG_BUS_STOP) {
176
device.writeAttr(SUMO_ATTR_BUS_STOP, getParentAdditionals().front()->getID());
177
}
178
if (getParentAdditionals().front()->getTagProperty()->getTag() == SUMO_TAG_TRAIN_STOP) {
179
device.writeAttr(SUMO_ATTR_TRAIN_STOP, getParentAdditionals().front()->getID());
180
}
181
if (getParentAdditionals().front()->getTagProperty()->getTag() == SUMO_TAG_CONTAINER_STOP) {
182
device.writeAttr(SUMO_ATTR_CONTAINER_STOP, getParentAdditionals().front()->getID());
183
}
184
if (getParentAdditionals().front()->getTagProperty()->getTag() == SUMO_TAG_CHARGING_STATION) {
185
device.writeAttr(SUMO_ATTR_CHARGING_STATION, getParentAdditionals().front()->getID());
186
}
187
if (getParentAdditionals().front()->getTagProperty()->getTag() == SUMO_TAG_PARKING_AREA) {
188
device.writeAttr(SUMO_ATTR_PARKING_AREA, getParentAdditionals().front()->getID());
189
}
190
} else {
191
if (getParentLanes().size() > 0) {
192
device.writeAttr(SUMO_ATTR_LANE, getParentLanes().front()->getID());
193
}
194
if (startPos != INVALID_DOUBLE) {
195
device.writeAttr(SUMO_ATTR_STARTPOS, startPos);
196
}
197
if (endPos != INVALID_DOUBLE) {
198
device.writeAttr(SUMO_ATTR_ENDPOS, endPos);
199
}
200
}
201
// write rest of attributes
202
write(device, true, false);
203
}
204
205
206
GNEDemandElement::Problem
207
GNEStop::isDemandElementValid() const {
208
if (getPathStopIndex() == -1) {
209
return Problem::STOP_DOWNSTREAM;
210
} else if ((getParentLanes().size() > 0) && !myMoveElementLaneDouble->isMoveElementValid()) {
211
return Problem::INVALID_STOPPOSITION;
212
} else {
213
return Problem::OK;
214
}
215
}
216
217
218
std::string
219
GNEStop::getDemandElementProblem() const {
220
if (getPathStopIndex() == -1) {
221
return ("Downstream stop");
222
} else if (getParentLanes().size() > 0) {
223
return myMoveElementLaneDouble->getMovingProblem();
224
} else {
225
return "";
226
}
227
}
228
229
230
void
231
GNEStop::fixDemandElementProblem() {
232
// currently only for stops over lanes
233
if (GNEStop::isDemandElementValid() == Problem::INVALID_STOPPOSITION) {
234
myMoveElementLaneDouble->fixMovingProblem();
235
}
236
}
237
238
239
SUMOVehicleClass
240
GNEStop::getVClass() const {
241
return getParentDemandElements().front()->getVClass();
242
}
243
244
245
const RGBColor&
246
GNEStop::getColor() const {
247
// get inspected AC
248
const auto inspectedAC = myNet->getViewNet()->getInspectedElements().getFirstAC();
249
if (inspectedAC) {
250
// check if is a route or a vehicle
251
if ((inspectedAC->getTagProperty()->isRoute() || inspectedAC->getTagProperty()->isVehicle()) && (inspectedAC != getParentDemandElements().front())) {
252
return RGBColor::GREY;
253
}
254
} else if (myNet->getViewParent()->getStopFrame()->shown()) {
255
if (myNet->getViewParent()->getStopFrame()->getStopParentSelector()->getCurrentDemandElement() != getParentDemandElements().front()) {
256
return RGBColor::GREY;
257
}
258
}
259
// return default color
260
if (myTagProperty->isVehicleWaypoint()) {
261
return myNet->getViewNet()->getVisualisationSettings().colorSettings.waypointColor;
262
} else {
263
return myNet->getViewNet()->getVisualisationSettings().colorSettings.stopColor;
264
}
265
}
266
267
268
void
269
GNEStop::updateGeometry() {
270
// update geometry depending of parent
271
if (getParentLanes().size() > 0) {
272
// Cut shape using as delimitators fixed start position and fixed end position
273
myDemandElementGeometry.updateGeometry(getParentLanes().front()->getLaneShape(), getStartGeometryPositionOverLane(), getEndGeometryPositionOverLane(), myMoveElementLaneDouble->myMovingLateralOffset);
274
} else if (getParentAdditionals().size() > 0) {
275
// use geometry of additional (busStop)
276
myDemandElementGeometry = getParentAdditionals().at(0)->getAdditionalGeometry();
277
}
278
}
279
280
281
Position
282
GNEStop::getPositionInView() const {
283
if (getParentLanes().size() > 0) {
284
return getParentLanes().front()->getLaneShape().positionAtOffset((startPos + endPos) / 2.0);
285
} else if (getParentAdditionals().size() > 0) {
286
return getParentAdditionals().front()->getPositionInView();
287
} else {
288
throw ProcessError(TL("Invalid Stop parent"));
289
}
290
}
291
292
293
std::string
294
GNEStop::getParentName() const {
295
if (getParentDemandElements().size() > 0) {
296
return getParentDemandElements().front()->getID();
297
} else if (getParentAdditionals().size() > 0) {
298
return getParentAdditionals().front()->getID();
299
} else if (getParentLanes().size() > 0) {
300
return getParentLanes().front()->getID();
301
} else {
302
throw ProcessError(TL("Invalid parent"));
303
}
304
}
305
306
307
double
308
GNEStop::getExaggeration(const GUIVisualizationSettings& s) const {
309
return s.addSize.getExaggeration(s, this);
310
}
311
312
313
Boundary
314
GNEStop::getCenteringBoundary() const {
315
Boundary b;
316
// Return Boundary depending if myMovingGeometryBoundary is initialised (important for move geometry)
317
if (getParentAdditionals().size() > 0) {
318
return getParentAdditionals().at(0)->getCenteringBoundary();
319
} else if (myMovingGeometryBoundary.isInitialised()) {
320
return myMovingGeometryBoundary;
321
} else if (myDemandElementGeometry.getShape().size() > 0) {
322
b = myDemandElementGeometry.getShape().getBoxBoundary();
323
} else {
324
b.add(getPositionInView());
325
}
326
b.grow(20);
327
return b;
328
}
329
330
331
void
332
GNEStop::splitEdgeGeometry(const double /*splitPosition*/, const GNENetworkElement* /*originalElement*/, const GNENetworkElement* /*newElement*/, GNEUndoList* /*undoList*/) {
333
// geometry of this element cannot be splitted
334
}
335
336
337
void
338
GNEStop::drawGL(const GUIVisualizationSettings& s) const {
339
// check if draw an stop for person/containers or for vehicles/routes
340
if (canDrawVehicleStop()) {
341
// get exaggeration
342
const auto exaggeration = getExaggeration(s);
343
// get lane
344
const auto& stopLane = getParentLanes().size() > 0 ? getParentLanes().front() : nullptr;
345
// get lane width
346
const double width = stopLane ? stopLane->getParentEdge()->getNBEdge()->getLaneWidth(stopLane->getIndex()) * 0.5 : exaggeration * 0.8;
347
// get detail level
348
const auto d = s.getDetailLevel(exaggeration);
349
// draw geometry only if we'rent in drawForObjectUnderCursor mode
350
if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {
351
// get color
352
const auto color = drawUsingSelectColor() ? s.colorSettings.selectedRouteColor : getColor();
353
// Add a layer matrix
354
GLHelper::pushMatrix();
355
// set Color
356
GLHelper::setColor(color);
357
// Start with the drawing of the area traslating matrix to origin
358
drawInLayer(getType());
359
// draw depending if is over lane or over stoppingP
360
if (getParentLanes().size() > 0) {
361
drawStopOverLane(s, d, color, width, exaggeration);
362
} else {
363
drawStopOverStoppingPlace(d, color, width, exaggeration);
364
}
365
// pop layer matrix
366
GLHelper::popMatrix();
367
if (s.showParkingInfo) {
368
// draw above demand elements
369
GLHelper::pushMatrix();
370
glTranslated(myDemandElementGeometry.getShape().back().x(), myDemandElementGeometry.getShape().back().y(), GLO_VEHICLELABELS);
371
drawStopLabel(s);
372
GLHelper::popMatrix();
373
}
374
// draw lock icon
375
GNEViewNetHelper::LockIcon::drawLockIcon(d, this, getType(), getPositionInView(), exaggeration);
376
// draw dotted contour
377
myStopContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);
378
}
379
// calculate contour and draw dotted geometry
380
if (getParentAdditionals().size() > 0) {
381
myStopContour.calculateContourExtrudedShape(s, d, this, myDemandElementGeometry.getShape(), getType(), width, exaggeration, true, true,
382
0, nullptr, getParentAdditionals().front()->getParentLanes().front()->getParentEdge());
383
} else {
384
myStopContour.calculateContourExtrudedShape(s, d, this, myDemandElementGeometry.getShape(), getType(), width, exaggeration, true, true,
385
0, nullptr, getParentLanes().front()->getParentEdge());
386
}
387
}
388
}
389
390
391
void
392
GNEStop::drawStopLabel(const GUIVisualizationSettings& s) const {
393
const SUMOVehicleParameter::Stop& stop = *this;
394
std::string label;
395
if (stop.speed > 0) {
396
label += "waypoint";
397
} else if (stop.busstop != "") {
398
label += "busStop:" + stop.busstop;
399
} else if (stop.containerstop != "") {
400
label += "containerStop:" + stop.containerstop;
401
} else if (stop.parkingarea != "") {
402
label += "parkingArea:" + stop.parkingarea;
403
} else if (stop.chargingStation != "") {
404
label += "chargingStation:" + stop.chargingStation;
405
} else if (stop.overheadWireSegment != "") {
406
label += "overheadWireSegment:" + stop.overheadWireSegment;
407
} else {
408
label += "stop";
409
}
410
if (stop.triggered || stop.containerTriggered || stop.joinTriggered) {
411
label += " triggered:";
412
if (stop.triggered) {
413
label += "person";
414
if (!stop.awaitedPersons.empty()) {
415
label += "(" + toString(stop.awaitedPersons) + ")";
416
}
417
}
418
if (stop.containerTriggered) {
419
label += "container";
420
if (!stop.awaitedContainers.empty()) {
421
label += "(" + toString(stop.awaitedContainers) + ")";
422
}
423
}
424
if (stop.joinTriggered) {
425
label += "join";
426
if (stop.join != "") {
427
label += "(" + stop.join + ")";
428
}
429
}
430
}
431
if (stop.arrival >= 0) {
432
label += " arrival:" + time2string(stop.arrival);
433
}
434
if (stop.until >= 0) {
435
label += " until:" + time2string(stop.until);
436
}
437
if (stop.started >= 0) {
438
label += " started:" + time2string(stop.started);
439
}
440
if (stop.ended >= 0) {
441
label += " ended:" + time2string(stop.ended);
442
}
443
if (stop.duration >= 0 || stop.duration > 0) {
444
if (STEPS2TIME(stop.duration) > 3600 * 24) {
445
label += " duration:1day+";
446
} else {
447
label += " duration:" + time2string(stop.duration);
448
}
449
}
450
if (stop.actType != "") {
451
label += " actType:" + stop.actType;
452
}
453
GLHelper::drawTextSettings(s.vehicleText, label, Position(0, 0), s.scale, s.angle, 0);
454
}
455
456
457
void
458
GNEStop::computePathElement() {
459
// only update geometry
460
updateGeometry();
461
}
462
463
464
void
465
GNEStop::drawLanePartialGL(const GUIVisualizationSettings& /*s*/, const GNESegment* /*segment*/, const double /*offsetFront*/) const {
466
// Stops don't use drawJunctionPartialGL
467
}
468
469
470
void
471
GNEStop::drawJunctionPartialGL(const GUIVisualizationSettings& /*s*/, const GNESegment* /*segment*/, const double /*offsetFront*/) const {
472
// Stops don't use drawJunctionPartialGL
473
}
474
475
476
GNELane*
477
GNEStop::getFirstPathLane() const {
478
// check if stop is placed over a busStop
479
if (getParentAdditionals().size() > 0) {
480
return getParentAdditionals().front()->getParentLanes().front();
481
} else {
482
return getParentLanes().front();
483
}
484
}
485
486
487
GNELane*
488
GNEStop::getLastPathLane() const {
489
// first and last path lane are the same
490
return getFirstPathLane();
491
}
492
493
494
std::string
495
GNEStop::getAttribute(SumoXMLAttr key) const {
496
switch (key) {
497
case SUMO_ATTR_ID:
498
return getMicrosimID();
499
case SUMO_ATTR_DURATION:
500
if (isAttributeEnabled(key)) {
501
return time2string(duration);
502
} else {
503
return "";
504
}
505
case SUMO_ATTR_UNTIL:
506
if (isAttributeEnabled(key)) {
507
return time2string(until);
508
} else {
509
return "";
510
}
511
case SUMO_ATTR_EXTENSION:
512
if (isAttributeEnabled(key)) {
513
return time2string(extension);
514
} else {
515
return "";
516
}
517
case SUMO_ATTR_TRIGGERED:
518
if (triggered) {
519
return "person";
520
} else if (containerTriggered) {
521
return "container";
522
} else if (joinTriggered) {
523
return "join";
524
} else {
525
return "false";
526
}
527
case SUMO_ATTR_EXPECTED:
528
if (triggered) {
529
return toString(awaitedPersons);
530
} else if (containerTriggered) {
531
return toString(awaitedContainers);
532
} else {
533
return "";
534
}
535
case SUMO_ATTR_JOIN:
536
if (joinTriggered) {
537
return join;
538
} else {
539
return "";
540
}
541
case SUMO_ATTR_PERMITTED:
542
return toString(permitted);
543
case SUMO_ATTR_PARKING:
544
if (parametersSet & STOP_PARKING_SET) {
545
return "true";
546
} else {
547
return "false";
548
}
549
case SUMO_ATTR_ACTTYPE:
550
return actType;
551
case SUMO_ATTR_TRIP_ID:
552
return tripId;
553
case SUMO_ATTR_LINE:
554
return line;
555
case SUMO_ATTR_ONDEMAND:
556
return toString(onDemand);
557
case SUMO_ATTR_JUMP:
558
if (parametersSet & STOP_JUMP_SET) {
559
return time2string(jump);
560
} else {
561
return "";
562
}
563
// only for waypoints
564
case SUMO_ATTR_SPEED:
565
return toString(speed);
566
// specific of Stops over stoppingPlaces
567
case SUMO_ATTR_BUS_STOP:
568
case SUMO_ATTR_TRAIN_STOP:
569
case SUMO_ATTR_CONTAINER_STOP:
570
case SUMO_ATTR_CHARGING_STATION:
571
case SUMO_ATTR_PARKING_AREA:
572
return getParentAdditionals().front()->getID();
573
// specific of stops over lanes
574
case SUMO_ATTR_POSITION_LAT:
575
if (posLat == INVALID_DOUBLE) {
576
return "";
577
} else {
578
return toString(posLat);
579
}
580
case SUMO_ATTR_SPLIT:
581
return split;
582
//
583
case GNE_ATTR_PARENT:
584
return getParentDemandElements().front()->getID();
585
case GNE_ATTR_STOPINDEX: {
586
// extract all stops of demandElement parent
587
std::vector<GNEDemandElement*> stops;
588
for (const auto& parent : getParentDemandElements().front()->getChildDemandElements()) {
589
if (parent->getTagProperty()->isVehicleStop()) {
590
stops.push_back(parent);
591
}
592
}
593
// find index in stops
594
for (int i = 0; i < (int)stops.size(); i++) {
595
if (stops.at(i) == this) {
596
return toString(i);
597
}
598
}
599
return "invalid index";
600
}
601
case GNE_ATTR_PATHSTOPINDEX:
602
return toString(getPathStopIndex());
603
default:
604
return myMoveElementLaneDouble->getMovingAttribute(key);
605
}
606
}
607
608
609
double
610
GNEStop::getAttributeDouble(SumoXMLAttr key) const {
611
switch (key) {
612
case SUMO_ATTR_INDEX: // for writting sorted
613
return (double)myCreationIndex;
614
case GNE_ATTR_STOPINDEX: {
615
// extract all stops of demandElement parent
616
std::vector<GNEDemandElement*> stops, filteredStops;
617
for (const auto& parent : getParentDemandElements().front()->getChildDemandElements()) {
618
if (parent->getTagProperty()->isVehicleStop()) {
619
stops.push_back(parent);
620
}
621
}
622
// now filter stops with the same startPos
623
for (const auto& stop : stops) {
624
if (stop->getAttributeDouble(SUMO_ATTR_STARTPOS) == getAttributeDouble(SUMO_ATTR_STARTPOS)) {
625
filteredStops.push_back(stop);
626
}
627
}
628
// get index
629
for (int i = 0; i < (int)filteredStops.size(); i++) {
630
if (filteredStops.at(i) == this) {
631
return i;
632
}
633
}
634
return 0;
635
}
636
case GNE_ATTR_PATHSTOPINDEX:
637
return (double)getPathStopIndex();
638
default:
639
return myMoveElementLaneDouble->getMovingAttributeDouble(key);
640
}
641
}
642
643
644
Position
645
GNEStop::getAttributePosition(SumoXMLAttr key) const {
646
switch (key) {
647
case GNE_ATTR_PLAN_GEOMETRY_ENDPOS: {
648
if (getParentAdditionals().size() > 0) {
649
// return first position of busStop
650
return getParentAdditionals().front()->getAdditionalGeometry().getShape().front();
651
} else {
652
// get lane shape
653
const PositionVector& laneShape = getLastPathLane()->getLaneShape();
654
// continue depending of arrival position
655
if (endPos == 0) {
656
return laneShape.front();
657
} else if ((endPos == -1) || (endPos >= laneShape.length2D())) {
658
return laneShape.back();
659
} else {
660
return laneShape.positionAtOffset2D(endPos);
661
}
662
}
663
}
664
default:
665
return getCommonAttributePosition(key);
666
}
667
}
668
669
670
void
671
GNEStop::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
672
if (value == getAttribute(key)) {
673
return; //avoid needless changes, later logic relies on the fact that attributes have changed
674
}
675
switch (key) {
676
case SUMO_ATTR_DURATION:
677
case SUMO_ATTR_UNTIL:
678
case SUMO_ATTR_EXTENSION:
679
case SUMO_ATTR_TRIGGERED:
680
case SUMO_ATTR_EXPECTED:
681
case SUMO_ATTR_JOIN:
682
case SUMO_ATTR_PERMITTED:
683
case SUMO_ATTR_PARKING:
684
case SUMO_ATTR_ACTTYPE:
685
case SUMO_ATTR_TRIP_ID:
686
case SUMO_ATTR_LINE:
687
case SUMO_ATTR_ONDEMAND:
688
case SUMO_ATTR_JUMP:
689
// only for waypoints
690
case SUMO_ATTR_SPEED:
691
// specific of Stops over stoppingPlaces
692
case SUMO_ATTR_BUS_STOP:
693
case SUMO_ATTR_TRAIN_STOP:
694
case SUMO_ATTR_CONTAINER_STOP:
695
case SUMO_ATTR_CHARGING_STATION:
696
case SUMO_ATTR_PARKING_AREA:
697
// specific of stops over lanes
698
case SUMO_ATTR_POSITION_LAT:
699
case SUMO_ATTR_SPLIT:
700
// other
701
case GNE_ATTR_PARENT:
702
GNEChange_Attribute::changeAttribute(this, key, value, undoList);
703
break;
704
default:
705
myMoveElementLaneDouble->setMovingAttribute(key, value, undoList);
706
break;
707
}
708
}
709
710
711
bool
712
GNEStop::isValid(SumoXMLAttr key, const std::string& value) {
713
// declare string error
714
std::string error;
715
switch (key) {
716
case SUMO_ATTR_DURATION:
717
case SUMO_ATTR_UNTIL:
718
case SUMO_ATTR_EXTENSION:
719
if (canParse<SUMOTime>(value)) {
720
return parse<SUMOTime>(value) >= 0;
721
} else {
722
return false;
723
}
724
case SUMO_ATTR_TRIGGERED: {
725
const auto expectedValues = myTagProperty->getAttributeProperties(key)->getDiscreteValues();
726
const auto triggeredValues = parse<std::vector<std::string> >(value);
727
for (const auto& triggeredValue : triggeredValues) {
728
if (std::find(expectedValues.begin(), expectedValues.end(), triggeredValue) == expectedValues.end()) {
729
return false;
730
}
731
}
732
return true;
733
}
734
case SUMO_ATTR_EXPECTED:
735
if (value.empty()) {
736
return false;
737
} else {
738
const std::vector<std::string> expectedValues = parse<std::vector<std::string> >(value);
739
for (const auto& expectedValue : expectedValues) {
740
if (!SUMOXMLDefinitions::isValidVehicleID(expectedValue)) {
741
return false;
742
}
743
}
744
return true;
745
}
746
case SUMO_ATTR_JOIN:
747
if (value.empty()) {
748
return false;
749
} else {
750
return SUMOXMLDefinitions::isValidVehicleID(value);
751
}
752
case SUMO_ATTR_PERMITTED: {
753
const std::vector<std::string> expectedValues = parse<std::vector<std::string> >(value);
754
for (const auto& expectedValue : expectedValues) {
755
if (!SUMOXMLDefinitions::isValidVehicleID(expectedValue)) {
756
return false;
757
}
758
}
759
return true;
760
}
761
case SUMO_ATTR_PARKING: {
762
if (value == "opportunistic") {
763
return false; // Currrently deactivated opportunistic in netedit waiting for the implementation in SUMO
764
}
765
const auto expectedValues = myTagProperty->getAttributeProperties(key)->getDiscreteValues();
766
const auto triggeredValues = parse<std::vector<std::string> >(value);
767
for (const auto& triggeredValue : triggeredValues) {
768
if (std::find(expectedValues.begin(), expectedValues.end(), triggeredValue) == expectedValues.end()) {
769
return false;
770
}
771
}
772
return true;
773
}
774
case SUMO_ATTR_ACTTYPE:
775
return true;
776
case SUMO_ATTR_TRIP_ID:
777
return SUMOXMLDefinitions::isValidVehicleID(value);
778
case SUMO_ATTR_LINE:
779
return true;
780
case SUMO_ATTR_ONDEMAND:
781
return canParse<bool>(value);
782
case SUMO_ATTR_JUMP:
783
if ((value == "-1") || (value.empty())) {
784
return true;
785
} else if (canParse<double>(value)) {
786
return parse<double>(value) >= 0;
787
} else {
788
return false;
789
}
790
// only for waypoints
791
case SUMO_ATTR_SPEED:
792
if (canParse<double>(value)) {
793
return (parse<double>(value) >= 0);
794
} else {
795
return false;
796
}
797
// specific of Stops over stoppingPlaces
798
case SUMO_ATTR_BUS_STOP:
799
return (myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_BUS_STOP, value, false) != nullptr);
800
case SUMO_ATTR_TRAIN_STOP:
801
return (myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_TRAIN_STOP, value, false) != nullptr);
802
case SUMO_ATTR_CONTAINER_STOP:
803
return (myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_CONTAINER_STOP, value, false) != nullptr);
804
case SUMO_ATTR_CHARGING_STATION:
805
return (myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_CHARGING_STATION, value, false) != nullptr);
806
case SUMO_ATTR_PARKING_AREA:
807
return (myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_PARKING_AREA, value, false) != nullptr);
808
// specific of stops over lanes
809
case SUMO_ATTR_POSITION_LAT:
810
if (value.empty()) {
811
return true;
812
} else {
813
return canParse<double>(value);
814
}
815
case SUMO_ATTR_SPLIT:
816
if (value.empty()) {
817
return true;
818
} else {
819
return SUMOXMLDefinitions::isValidVehicleID(value);
820
}
821
//
822
case GNE_ATTR_PARENT:
823
return false;
824
default:
825
return myMoveElementLaneDouble->isMovingAttributeValid(key, value);
826
}
827
}
828
829
830
void
831
GNEStop::enableAttribute(SumoXMLAttr key, GNEUndoList* undoList) {
832
switch (key) {
833
case SUMO_ATTR_DURATION:
834
case SUMO_ATTR_UNTIL:
835
case SUMO_ATTR_EXTENSION:
836
undoList->add(new GNEChange_ToggleAttribute(this, key, true), true);
837
break;
838
default:
839
throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
840
}
841
}
842
843
844
void
845
GNEStop::disableAttribute(SumoXMLAttr key, GNEUndoList* undoList) {
846
switch (key) {
847
case SUMO_ATTR_DURATION:
848
case SUMO_ATTR_UNTIL:
849
case SUMO_ATTR_EXTENSION:
850
undoList->add(new GNEChange_ToggleAttribute(this, key, false), true);
851
break;
852
default:
853
throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
854
}
855
}
856
857
858
bool
859
GNEStop::isAttributeEnabled(SumoXMLAttr key) const {
860
switch (key) {
861
// Currently stops parents cannot be edited
862
case SUMO_ATTR_BUS_STOP:
863
case SUMO_ATTR_TRAIN_STOP:
864
case SUMO_ATTR_CONTAINER_STOP:
865
case SUMO_ATTR_CHARGING_STATION:
866
case SUMO_ATTR_PARKING_AREA:
867
return false;
868
case SUMO_ATTR_DURATION:
869
return (parametersSet & STOP_DURATION_SET) != 0;
870
case SUMO_ATTR_UNTIL:
871
return (parametersSet & STOP_UNTIL_SET) != 0;
872
case SUMO_ATTR_EXTENSION:
873
return (parametersSet & STOP_EXTENSION_SET) != 0;
874
case SUMO_ATTR_EXPECTED:
875
return triggered || containerTriggered;
876
case SUMO_ATTR_JOIN:
877
return joinTriggered;
878
case SUMO_ATTR_PARKING:
879
// for stops/waypoints over parking areas, always enabled
880
if ((myTagProperty->getTag() == GNE_TAG_STOP_PARKINGAREA) || (myTagProperty->getTag() == GNE_TAG_WAYPOINT_PARKINGAREA)) {
881
return false;
882
} else {
883
return true;
884
}
885
default:
886
return true;
887
}
888
}
889
890
891
std::string
892
GNEStop::getPopUpID() const {
893
return getTagStr();
894
}
895
896
897
std::string
898
GNEStop::getHierarchyName() const {
899
if (getParentAdditionals().size() > 0) {
900
if (getParentAdditionals().front()->getTagProperty()->getTag() == SUMO_TAG_BUS_STOP) {
901
return "BusStop: " + getParentAdditionals().front()->getID();
902
} else if (getParentAdditionals().front()->getTagProperty()->getTag() == SUMO_TAG_TRAIN_STOP) {
903
return "TrainStop: " + getParentAdditionals().front()->getID();
904
} else if (getParentAdditionals().front()->getTagProperty()->getTag() == SUMO_TAG_CONTAINER_STOP) {
905
return "containerStop: " + getParentAdditionals().front()->getID();
906
} else if (getParentAdditionals().front()->getTagProperty()->getTag() == SUMO_TAG_CHARGING_STATION) {
907
return "chargingStation: " + getParentAdditionals().front()->getID();
908
} else {
909
return "parkingArea: " + getParentAdditionals().front()->getID();
910
}
911
} else if (getParentLanes().size() > 0) {
912
return "lane: " + getParentLanes().front()->getID();
913
} else {
914
return "";
915
}
916
}
917
918
919
double
920
GNEStop::getStartGeometryPositionOverLane() const {
921
double fixedPos = startPos;
922
const double len = getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength();
923
if (fixedPos < 0) {
924
fixedPos += len;
925
}
926
return fixedPos * getParentLanes().front()->getLengthGeometryFactor();
927
}
928
929
930
double
931
GNEStop::getEndGeometryPositionOverLane() const {
932
double fixedPos = endPos;
933
const double len = getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength();
934
if (fixedPos < 0) {
935
fixedPos += len;
936
}
937
return fixedPos * getParentLanes().front()->getLengthGeometryFactor();
938
}
939
940
// ===========================================================================
941
// protected
942
// ===========================================================================
943
944
bool
945
GNEStop::canDrawVehicleStop() const {
946
const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();
947
if (isAttributeCarrierSelected()) {
948
return true;
949
} else if (inspectedElements.isACInspected(this)) {
950
return true;
951
} else if (inspectedElements.isACInspected(getParentDemandElements().front())) {
952
return true;
953
} else if (myNet->getViewNet()->getDemandViewOptions().showAllTrips()) {
954
return true;
955
} else if ((getParentDemandElements().front()->getTagProperty()->getTag() == GNE_TAG_VEHICLE_WITHROUTE) ||
956
(getParentDemandElements().front()->getTagProperty()->getTag() == GNE_TAG_FLOW_WITHROUTE)) {
957
if (inspectedElements.isACInspected(getParentDemandElements().front()->getChildDemandElements().front())) {
958
return true;
959
} else {
960
return false;
961
}
962
} else {
963
return false;
964
}
965
}
966
967
968
bool
969
GNEStop::drawIndex() const {
970
// get stop frame
971
const auto stopFrame = myNet->getViewParent()->getStopFrame();
972
// check conditions
973
if (myNet->getViewNet()->getInspectedElements().isACInspected(getParentDemandElements().front())) {
974
return true;
975
} else if (stopFrame->shown() && (stopFrame->getStopParentSelector()->getCurrentDemandElement() == getParentDemandElements().front())) {
976
return true;
977
} else {
978
return false;
979
}
980
}
981
982
983
984
void
985
GNEStop::drawStopOverLane(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d, const RGBColor& color,
986
const double width, const double exaggeration) const {
987
// Draw top and bot lines using shape, shapeRotations, shapeLengths and value of exaggeration
988
GLHelper::drawBoxLines(myDemandElementGeometry.getShape(),
989
myDemandElementGeometry.getShapeRotations(),
990
myDemandElementGeometry.getShapeLengths(),
991
exaggeration * 0.1, 0, width);
992
GLHelper::drawBoxLines(myDemandElementGeometry.getShape(),
993
myDemandElementGeometry.getShapeRotations(),
994
myDemandElementGeometry.getShapeLengths(),
995
exaggeration * 0.1, 0, width * -1);
996
// Add a detail matrix
997
GLHelper::pushMatrix();
998
// move to geometry front
999
glTranslated(myDemandElementGeometry.getShape().back().x(), myDemandElementGeometry.getShape().back().y(), 0.1);
1000
// rotate
1001
if (myDemandElementGeometry.getShapeRotations().size() > 0) {
1002
glRotated(myDemandElementGeometry.getShapeRotations().back(), 0, 0, 1);
1003
}
1004
// move again
1005
glTranslated(0, exaggeration * 0.5, 0);
1006
// draw stop front
1007
GLHelper::drawBoxLine(Position(0, 0), 0, exaggeration * 0.5, width);
1008
// move to symbol position
1009
glTranslated(0, 1, 0.1);
1010
// draw text depending of detail
1011
if (d <= GUIVisualizationSettings::Detail::Text) {
1012
// draw symbol
1013
GLHelper::drawText(myTagProperty->isVehicleWaypoint() ? "W" : "S", Position(), .1, 2.8, color, 180);
1014
// move to subtitle position
1015
glTranslated(0, 1.4, 0);
1016
// draw subtitle depending of tag
1017
GLHelper::drawText("lane", Position(), .1, 1, color, 180);
1018
// check if draw index
1019
if (drawIndex()) {
1020
// move to index position
1021
glTranslated(-2.1, -2.4, 0);
1022
glRotated(-90, 0, 0, 1);
1023
// draw index
1024
GLHelper::drawText(getAttribute(GNE_ATTR_STOPINDEX), Position(0, getAttributeDouble(GNE_ATTR_STOPINDEX) * -1, 0), .1, 1, color, 180);
1025
}
1026
} else {
1027
GLHelper::drawBoxLine(Position(0, 1), 0, 2, 1);
1028
}
1029
// pop detail matrix
1030
GLHelper::popMatrix();
1031
// draw geometry points
1032
drawGeometryPoints(s, d, color);
1033
}
1034
1035
1036
void
1037
GNEStop::drawStopOverStoppingPlace(const GUIVisualizationSettings::Detail d, const RGBColor& color,
1038
const double width, const double exaggeration) const {
1039
// Draw the area using shape, shapeRotations, shapeLengths and value of exaggeration taked from stoppingPlace parent
1040
GUIGeometry::drawGeometry(d, myDemandElementGeometry, width);
1041
// only draw text if isn't being drawn for selecting
1042
if ((d <= GUIVisualizationSettings::Detail::Text) && drawIndex()) {
1043
// Add a detail matrix
1044
GLHelper::pushMatrix();
1045
// move to geometry front
1046
glTranslated(myDemandElementGeometry.getShape().back().x(), myDemandElementGeometry.getShape().back().y(), 0.1);
1047
// rotate
1048
if (myDemandElementGeometry.getShapeRotations().size() > 0) {
1049
glRotated(myDemandElementGeometry.getShapeRotations().back(), 0, 0, 1);
1050
}
1051
// move to index position
1052
glTranslated(-1.4, exaggeration * 0.5, 0.1);
1053
glRotated(-90, 0, 0, 1);
1054
// draw index
1055
GLHelper::drawText(getAttribute(GNE_ATTR_STOPINDEX), Position(0, getAttributeDouble(GNE_ATTR_STOPINDEX) * -1, 0), .1, 1, color, 180);
1056
// pop detail matrix
1057
GLHelper::popMatrix();
1058
}
1059
}
1060
1061
// ===========================================================================
1062
// private
1063
// ===========================================================================
1064
1065
void
1066
GNEStop::setAttribute(SumoXMLAttr key, const std::string& value) {
1067
switch (key) {
1068
case SUMO_ATTR_DURATION:
1069
if (value.empty()) {
1070
toggleAttribute(key, false);
1071
} else {
1072
toggleAttribute(key, true);
1073
duration = string2time(value);
1074
}
1075
break;
1076
case SUMO_ATTR_UNTIL:
1077
if (value.empty()) {
1078
toggleAttribute(key, false);
1079
} else {
1080
toggleAttribute(key, true);
1081
until = string2time(value);
1082
}
1083
break;
1084
case SUMO_ATTR_EXTENSION:
1085
if (value.empty()) {
1086
toggleAttribute(key, false);
1087
} else {
1088
toggleAttribute(key, true);
1089
extension = string2time(value);
1090
}
1091
break;
1092
case SUMO_ATTR_TRIGGERED:
1093
// reset all flags
1094
triggered = false;
1095
containerTriggered = false;
1096
joinTriggered = false;
1097
// disable all flags
1098
parametersSet &= ~STOP_JOIN_SET;
1099
parametersSet &= ~STOP_TRIGGER_SET;
1100
parametersSet &= ~STOP_EXPECTED_SET;
1101
parametersSet &= ~STOP_CONTAINER_TRIGGER_SET;
1102
parametersSet &= ~STOP_EXPECTED_CONTAINERS_SET;
1103
// check value
1104
if ((value == "person") || (value == "true")) {
1105
parametersSet |= STOP_TRIGGER_SET;
1106
triggered = true;
1107
if (awaitedPersons.size() > 0) {
1108
parametersSet |= STOP_EXPECTED_SET;
1109
}
1110
} else if (value == "container") {
1111
parametersSet |= STOP_TRIGGER_SET;
1112
parametersSet |= STOP_CONTAINER_TRIGGER_SET;
1113
containerTriggered = true;
1114
if (awaitedPersons.size() > 0) {
1115
parametersSet |= STOP_EXPECTED_CONTAINERS_SET;
1116
}
1117
} else if (value == "join") {
1118
parametersSet |= STOP_TRIGGER_SET;
1119
joinTriggered = true;
1120
}
1121
break;
1122
case SUMO_ATTR_EXPECTED:
1123
if (triggered) {
1124
awaitedPersons = parse<std::set<std::string> >(value);
1125
if (awaitedPersons.size() > 0) {
1126
parametersSet |= STOP_EXPECTED_SET;
1127
} else {
1128
parametersSet &= ~STOP_EXPECTED_SET;
1129
}
1130
} else if (containerTriggered) {
1131
awaitedContainers = parse<std::set<std::string> >(value);
1132
if (awaitedContainers.size() > 0) {
1133
parametersSet |= STOP_EXPECTED_CONTAINERS_SET;
1134
} else {
1135
parametersSet &= ~STOP_EXPECTED_CONTAINERS_SET;
1136
}
1137
}
1138
break;
1139
case SUMO_ATTR_JOIN:
1140
if (joinTriggered) {
1141
join = value;
1142
if (join.size() > 0) {
1143
parametersSet |= STOP_JOIN_SET;
1144
} else {
1145
parametersSet &= ~STOP_JOIN_SET;
1146
}
1147
}
1148
break;
1149
case SUMO_ATTR_PERMITTED:
1150
if (value.empty()) {
1151
parametersSet &= ~STOP_PERMITTED_SET;
1152
} else {
1153
parametersSet |= STOP_PERMITTED_SET;
1154
permitted = parse<std::set<std::string> >(value);
1155
}
1156
break;
1157
case SUMO_ATTR_PARKING:
1158
parking = SUMOVehicleParameter::parseParkingType(value);
1159
if (parking == ParkingType::ONROAD) {
1160
parametersSet &= ~STOP_PARKING_SET;
1161
} else {
1162
parametersSet |= STOP_PARKING_SET;
1163
}
1164
break;
1165
case SUMO_ATTR_ACTTYPE:
1166
actType = value;
1167
break;
1168
case SUMO_ATTR_TRIP_ID:
1169
tripId = value;
1170
toggleAttribute(key, (value.size() > 0));
1171
break;
1172
case SUMO_ATTR_LINE:
1173
line = value;
1174
toggleAttribute(key, (value.size() > 0));
1175
break;
1176
case SUMO_ATTR_ONDEMAND:
1177
if (parse<bool>(value)) {
1178
parametersSet |= STOP_ONDEMAND_SET;
1179
} else {
1180
parametersSet &= ~STOP_ONDEMAND_SET;
1181
}
1182
// set flag
1183
onDemand = ((parametersSet & STOP_ONDEMAND_SET) != 0);
1184
break;
1185
case SUMO_ATTR_JUMP:
1186
if ((value == "-1") || value.empty()) {
1187
parametersSet &= ~STOP_JUMP_SET;
1188
jump = -1;
1189
} else {
1190
parametersSet |= STOP_JUMP_SET;
1191
jump = string2time(value);
1192
}
1193
break;
1194
// only for waypoints
1195
case SUMO_ATTR_SPEED:
1196
speed = parse<double>(value);
1197
break;
1198
// specific of Stops over stoppingPlaces
1199
case SUMO_ATTR_BUS_STOP:
1200
replaceFirstParentAdditional(SUMO_TAG_BUS_STOP, value);
1201
updateGeometry();
1202
break;
1203
case SUMO_ATTR_TRAIN_STOP:
1204
replaceFirstParentAdditional(SUMO_TAG_TRAIN_STOP, value);
1205
updateGeometry();
1206
break;
1207
case SUMO_ATTR_CONTAINER_STOP:
1208
replaceFirstParentAdditional(SUMO_TAG_CONTAINER_STOP, value);
1209
updateGeometry();
1210
break;
1211
case SUMO_ATTR_CHARGING_STATION:
1212
replaceFirstParentAdditional(SUMO_TAG_CHARGING_STATION, value);
1213
updateGeometry();
1214
break;
1215
case SUMO_ATTR_PARKING_AREA:
1216
replaceFirstParentAdditional(SUMO_TAG_PARKING_AREA, value);
1217
updateGeometry();
1218
break;
1219
// specific of Stops over lanes
1220
case SUMO_ATTR_LANE:
1221
replaceFirstParentLane(value);
1222
updateGeometry();
1223
break;
1224
case SUMO_ATTR_POSITION_LAT:
1225
if (value.empty()) {
1226
posLat = INVALID_DOUBLE;
1227
parametersSet &= ~STOP_POSLAT_SET;
1228
} else {
1229
posLat = parse<double>(value);
1230
parametersSet |= STOP_POSLAT_SET;
1231
}
1232
break;
1233
case SUMO_ATTR_SPLIT:
1234
split = value;
1235
if (split.size() > 0) {
1236
parametersSet |= STOP_SPLIT_SET;
1237
} else {
1238
parametersSet &= ~STOP_SPLIT_SET;
1239
}
1240
break;
1241
//
1242
case GNE_ATTR_PARENT:
1243
updateGeometry();
1244
break;
1245
default:
1246
myMoveElementLaneDouble->setMovingAttribute(key, value);
1247
break;
1248
}
1249
}
1250
1251
1252
void
1253
GNEStop::toggleAttribute(SumoXMLAttr key, const bool value) {
1254
switch (key) {
1255
case SUMO_ATTR_DURATION:
1256
if (value) {
1257
parametersSet |= STOP_DURATION_SET;
1258
} else {
1259
parametersSet &= ~STOP_DURATION_SET;
1260
}
1261
break;
1262
case SUMO_ATTR_UNTIL:
1263
if (value) {
1264
parametersSet |= STOP_UNTIL_SET;
1265
} else {
1266
parametersSet &= ~STOP_UNTIL_SET;
1267
}
1268
break;
1269
case SUMO_ATTR_EXTENSION:
1270
if (value) {
1271
parametersSet |= STOP_EXTENSION_SET;
1272
} else {
1273
parametersSet &= ~STOP_EXTENSION_SET;
1274
}
1275
break;
1276
case SUMO_ATTR_TRIP_ID:
1277
if (value) {
1278
parametersSet |= STOP_TRIP_ID_SET;
1279
} else {
1280
parametersSet &= ~STOP_TRIP_ID_SET;
1281
}
1282
break;
1283
case SUMO_ATTR_LINE:
1284
if (value) {
1285
parametersSet |= STOP_LINE_SET;
1286
} else {
1287
parametersSet &= ~STOP_LINE_SET;
1288
}
1289
break;
1290
case SUMO_ATTR_ONDEMAND:
1291
if (value) {
1292
parametersSet |= STOP_ONDEMAND_SET;
1293
} else {
1294
parametersSet &= ~STOP_ONDEMAND_SET;
1295
}
1296
break;
1297
default:
1298
throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1299
}
1300
}
1301
1302
1303
void
1304
GNEStop::drawGeometryPoints(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d, const RGBColor& baseColor) const {
1305
// first check that we're in move mode and shift key is pressed
1306
if (drawMovingGeometryPoints()) {
1307
// calculate new color
1308
const RGBColor color = baseColor.changedBrightness(-50);
1309
// push matrix
1310
GLHelper::pushMatrix();
1311
// translated to front
1312
glTranslated(0, 0, 0.1);
1313
// set color
1314
GLHelper::setColor(color);
1315
// draw points
1316
if (startPos != INVALID_DOUBLE) {
1317
// push geometry point matrix
1318
GLHelper::pushMatrix();
1319
glTranslated(myDemandElementGeometry.getShape().front().x(), myDemandElementGeometry.getShape().front().y(), 0.1);
1320
// draw geometry point
1321
GLHelper::drawFilledCircleDetailled(d, s.neteditSizeSettings.additionalGeometryPointRadius);
1322
// pop geometry point matrix
1323
GLHelper::popMatrix();
1324
}
1325
if (endPos != INVALID_DOUBLE) {
1326
// push geometry point matrix
1327
GLHelper::pushMatrix();
1328
glTranslated(myDemandElementGeometry.getShape().back().x(), myDemandElementGeometry.getShape().back().y(), 0.1);
1329
// draw geometry point
1330
GLHelper::drawFilledCircleDetailled(d, s.neteditSizeSettings.additionalGeometryPointRadius);
1331
// pop geometry point matrix
1332
GLHelper::popMatrix();
1333
}
1334
// pop draw matrix
1335
GLHelper::popMatrix();
1336
}
1337
}
1338
1339
1340
int
1341
GNEStop::getPathStopIndex() const {
1342
// get edge stop indexes
1343
const auto edgeStopIndex = getEdgeStopIndex();
1344
// finally find stopIndex in edgeStopIndexes
1345
for (const auto& edgeStop : edgeStopIndex) {
1346
for (const auto& stop : edgeStop.stops) {
1347
if (stop == this) {
1348
return edgeStop.stopIndex;
1349
}
1350
}
1351
}
1352
// not found, then return -1
1353
return -1;
1354
}
1355
1356
1357
void
1358
GNEStop::setStopMicrosimID() {
1359
if (getParentAdditionals().size() > 0) {
1360
setDemandElementID(getMicrosimID() + " (" + getParentAdditionals().front()->getTagStr() + ")");
1361
} else if (getParentLanes().size() > 0) {
1362
setDemandElementID(getMicrosimID() + " (" + getParentLanes().front()->getTagStr() + ")");
1363
}
1364
}
1365
1366
/****************************************************************************/
1367
1368