Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/elements/demand/GNEStopPlan.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 GNEStopPlan.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Oct 2023
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/GNENet.h>
24
#include <netedit/GNEUndoList.h>
25
#include <utils/gui/div/GLHelper.h>
26
#include <utils/gui/images/GUITextureSubSys.h>
27
28
#include "GNEStopPlan.h"
29
30
// ===========================================================================
31
// member method definitions
32
// ===========================================================================
33
#ifdef _MSC_VER
34
#pragma warning(push)
35
#pragma warning(disable: 4355) // mask warning about "this" in initializers
36
#endif
37
GNEStopPlan::GNEStopPlan(SumoXMLTag tag, GNENet* net) :
38
GNEDemandElement(net, tag),
39
GNEDemandElementPlan(this, -1, -1) {
40
}
41
42
43
GNEStopPlan::GNEStopPlan(SumoXMLTag tag, GNEDemandElement* personParent, const GNEPlanParents& planParameters,
44
const double endPos, const SUMOTime duration, const SUMOTime until, const std::string& actType,
45
const bool friendlyPos, const int parameterSet) :
46
GNEDemandElement(personParent, tag),
47
GNEDemandElementPlan(this, -1, endPos),
48
myDuration(duration),
49
myUntil(until),
50
myActType(actType),
51
myFriendlyPos(friendlyPos),
52
myParametersSet(parameterSet) {
53
// set parents
54
setParents<GNEJunction*>(planParameters.getJunctions());
55
setParents<GNEEdge*>(planParameters.getEdges());
56
setParents<GNEAdditional*>(planParameters.getAdditionalElements());
57
setParents<GNEDemandElement*>(planParameters.getDemandElements(personParent));
58
// update centering boundary without updating grid
59
updatePlanCenteringBoundary(false);
60
}
61
#ifdef _MSC_VER
62
#pragma warning(pop)
63
#endif
64
65
66
GNEStopPlan::~GNEStopPlan() {}
67
68
69
GNEMoveElement*
70
GNEStopPlan::getMoveElement() const {
71
return myMoveElementPlan;
72
}
73
74
75
Parameterised*
76
GNEStopPlan::getParameters() {
77
return nullptr;
78
}
79
80
81
const Parameterised*
82
GNEStopPlan::getParameters() const {
83
return nullptr;
84
}
85
86
87
void
88
GNEStopPlan::writeDemandElement(OutputDevice& device) const {
89
device.openTag(SUMO_TAG_STOP);
90
writeLocationAttributes(device);
91
// write stop attributes
92
if (isAttributeEnabled(SUMO_ATTR_DURATION)) {
93
device.writeAttr(SUMO_ATTR_DURATION, getAttribute(SUMO_ATTR_DURATION));
94
}
95
if (isAttributeEnabled(SUMO_ATTR_UNTIL)) {
96
device.writeAttr(SUMO_ATTR_UNTIL, getAttribute(SUMO_ATTR_UNTIL));
97
}
98
if (myActType.size() > 0) {
99
device.writeAttr(SUMO_ATTR_ACTTYPE, myActType);
100
}
101
if (myFriendlyPos) {
102
device.writeAttr(SUMO_ATTR_FRIENDLY_POS, myFriendlyPos);
103
}
104
device.closeTag();
105
}
106
107
108
GNEDemandElement::Problem
109
GNEStopPlan::isDemandElementValid() const {
110
return isPlanPersonValid();
111
}
112
113
114
std::string
115
GNEStopPlan::getDemandElementProblem() const {
116
return getPersonPlanProblem();
117
}
118
119
120
void
121
GNEStopPlan::fixDemandElementProblem() {
122
// currently the only solution is removing stop
123
}
124
125
126
SUMOVehicleClass
127
GNEStopPlan::getVClass() const {
128
return SVC_PASSENGER;
129
}
130
131
132
const RGBColor&
133
GNEStopPlan::getColor() const {
134
return myNet->getViewNet()->getVisualisationSettings().colorSettings.stopPersonColor;
135
}
136
137
138
void
139
GNEStopPlan::updateGeometry() {
140
const auto& viewSettings = myNet->getViewNet()->getVisualisationSettings();
141
PositionVector shape;
142
// update geometry depending of parent
143
if (getParentAdditionals().size() > 0) {
144
const double stopWidth = (getParentAdditionals().front()->getTagProperty()->getTag() == SUMO_TAG_BUS_STOP) ?
145
viewSettings.stoppingPlaceSettings.busStopWidth : viewSettings.stoppingPlaceSettings.trainStopWidth;
146
// get busStop shape
147
const PositionVector& busStopShape = getParentAdditionals().front()->getAdditionalGeometry().getShape();
148
PositionVector shapeA = {busStopShape[-1], busStopShape[-2]};
149
PositionVector shapeB = {busStopShape[-1], busStopShape[-2]};
150
shapeA.rotateAroundFirstElement2D(DEG2RAD(90));
151
shapeB.rotateAroundFirstElement2D(-DEG2RAD(90));
152
shape = {shapeA.positionAtOffset2D(stopWidth), shapeB.positionAtOffset2D(stopWidth)};
153
} else if (getParentEdges().size() > 0) {
154
// get front and back lane
155
const GNELane* frontLane = getParentEdges().front()->getChildLanes().front();
156
const GNELane* backLane = getParentEdges().front()->getChildLanes().back();
157
// calculate front position
158
const Position frontPosition = frontLane->getLaneShape().positionAtOffset2D(getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS),
159
frontLane->getDrawingConstants()->getDrawingWidth());
160
// calulate length between both shapes
161
const double length = backLane->getLaneShape().distance2D(frontPosition, true);
162
// calculate back position
163
const Position backPosition = frontLane->getLaneShape().positionAtOffset2D(getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS),
164
(length + backLane->getDrawingConstants()->getDrawingWidth() - frontLane->getDrawingConstants()->getDrawingWidth()) * -1);
165
// update demand element geometry using both positions
166
shape = {frontPosition, backPosition};
167
}
168
// extrapolate for sign
169
shape.extrapolate(0.1, true);
170
myDemandElementGeometry.updateGeometry(shape);
171
shape.extrapolate(viewSettings.additionalSettings.stopEdgeSize - 0.1, true);
172
mySignPosition = shape.front();
173
}
174
175
176
Position
177
GNEStopPlan::getPositionInView() const {
178
return getPlanPositionInView();
179
}
180
181
182
std::string
183
GNEStopPlan::getParentName() const {
184
return getParentDemandElements().front()->getID();
185
}
186
187
188
double
189
GNEStopPlan::getExaggeration(const GUIVisualizationSettings& s) const {
190
return s.addSize.getExaggeration(s, this);
191
}
192
193
194
Boundary
195
GNEStopPlan::getCenteringBoundary() const {
196
return getPlanCenteringBoundary();
197
}
198
199
200
void
201
GNEStopPlan::splitEdgeGeometry(const double /*splitPosition*/, const GNENetworkElement* /*originalElement*/, const GNENetworkElement* /*newElement*/, GNEUndoList* /*undoList*/) {
202
// geometry of this element cannot be splitted
203
}
204
205
206
void
207
GNEStopPlan::drawGL(const GUIVisualizationSettings& s) const {
208
// check if stop can be draw
209
if ((getTagProperty()->isPlanStopPerson() && checkDrawPersonPlan()) ||
210
(getTagProperty()->isPlanStopContainer() && checkDrawContainerPlan())) {
211
// Obtain exaggeration of the draw
212
const double exaggeration = getExaggeration(s);
213
// get detail level
214
const auto d = s.getDetailLevel(exaggeration);
215
// draw geometry only if we'rent in drawForObjectUnderCursor mode
216
if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {
217
// declare stop color
218
const RGBColor stopColor = drawUsingSelectColor() ? s.colorSettings.selectedPersonPlanColor : s.colorSettings.stopColor;
219
// Add layer matrix matrix
220
GLHelper::pushMatrix();
221
// translate to front
222
drawInLayer(getType());
223
// declare stop color
224
// declare central line color
225
const RGBColor centralLineColor = drawUsingSelectColor() ? stopColor.changedBrightness(-32) : RGBColor::WHITE;
226
// set base color
227
GLHelper::setColor(stopColor);
228
// Draw the area using shape, shapeRotations, shapeLengths and value of exaggeration
229
GUIGeometry::drawGeometry(d, myDemandElementGeometry, 0.3 * exaggeration);
230
// move to front
231
glTranslated(0, 0, .1);
232
// set central color
233
GLHelper::setColor(centralLineColor);
234
// Draw the area using shape, shapeRotations, shapeLengths and value of exaggeration
235
GUIGeometry::drawGeometry(d, myDemandElementGeometry, 0.05 * exaggeration);
236
// move to icon position and front
237
glTranslated(mySignPosition.x(), mySignPosition.y(), .1);
238
// rotate over lane
239
GUIGeometry::rotateOverLane((myDemandElementGeometry.getShapeRotations().front() * -1) + 90);
240
// draw icon depending of detail level
241
if (d <= GUIVisualizationSettings::Detail::AdditionalDetails) {
242
// set color
243
glColor3d(1, 1, 1);
244
// rotate texture
245
glRotated(180, 0, 0, 1);
246
// draw texture
247
if (drawUsingSelectColor()) {
248
GUITexturesHelper::drawTexturedBox(GUITextureSubSys::getTexture(GUITexture::STOPPERSON_SELECTED), s.additionalSettings.stopEdgeSize * exaggeration);
249
} else {
250
GUITexturesHelper::drawTexturedBox(GUITextureSubSys::getTexture(GUITexture::STOPPERSON), s.additionalSettings.stopEdgeSize * exaggeration);
251
}
252
} else {
253
// set stop color
254
GLHelper::setColor(stopColor);
255
// draw filled circle
256
GLHelper::drawFilledCircleDetailled(d, 0.1 + s.additionalSettings.stopEdgeSize);
257
}
258
// pop layer matrix
259
GLHelper::popMatrix();
260
// draw lock icon
261
GNEViewNetHelper::LockIcon::drawLockIcon(d, this, getType(), mySignPosition, exaggeration);
262
// draw dotted contour
263
myStopContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);
264
myStopSignContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidthSmall, true);
265
}
266
// calculate contour and draw dotted geometry
267
if (getParentLanes().size() > 0) {
268
myStopContour.calculateContourExtrudedShape(s, d, this, myDemandElementGeometry.getShape(), getType(), 0.3, exaggeration, false, true, 0, nullptr, getParentLanes().front()->getParentEdge());
269
myStopSignContour.calculateContourCircleShape(s, d, this, mySignPosition, s.additionalSettings.stopEdgeSize, getType(), exaggeration, getParentLanes().front()->getParentEdge());
270
} else if (getParentEdges().size() > 0) {
271
myStopContour.calculateContourExtrudedShape(s, d, this, myDemandElementGeometry.getShape(), getType(), 0.3, exaggeration, false, true, 0, nullptr, getParentEdges().front());
272
myStopSignContour.calculateContourCircleShape(s, d, this, mySignPosition, s.additionalSettings.stopEdgeSize, getType(), exaggeration, getParentEdges().front());
273
} else {
274
myStopContour.calculateContourExtrudedShape(s, d, this, myDemandElementGeometry.getShape(), getType(), 0.3, exaggeration, false, true, 0, nullptr, getParentAdditionals().front());
275
myStopSignContour.calculateContourCircleShape(s, d, this, mySignPosition, s.additionalSettings.stopEdgeSize, getType(), exaggeration, getParentAdditionals().front());
276
}
277
}
278
// check if draw plan parent
279
if (getParentDemandElements().at(0)->getPreviousChildDemandElement(this) == nullptr) {
280
getParentDemandElements().at(0)->drawGL(s);
281
}
282
}
283
284
285
void
286
GNEStopPlan::computePathElement() {
287
// only update geometry
288
updateGeometry();
289
}
290
291
292
void
293
GNEStopPlan::drawLanePartialGL(const GUIVisualizationSettings& /*s*/, const GNESegment* /*segment*/, const double /*offsetFront*/) const {
294
// Stops don't use drawJunctionPartialGL
295
}
296
297
298
void
299
GNEStopPlan::drawJunctionPartialGL(const GUIVisualizationSettings& /*s*/, const GNESegment* /*segment*/, const double /*offsetFront*/) const {
300
// Stops don't use drawJunctionPartialGL
301
}
302
303
304
GNELane*
305
GNEStopPlan::getFirstPathLane() const {
306
return getFirstPlanPathLane();
307
}
308
309
310
GNELane*
311
GNEStopPlan::getLastPathLane() const {
312
return getLastPlanPathLane();
313
}
314
315
316
std::string
317
GNEStopPlan::getAttribute(SumoXMLAttr key) const {
318
switch (key) {
319
case SUMO_ATTR_DURATION:
320
if (isAttributeEnabled(key)) {
321
return time2string(myDuration);
322
} else {
323
return "";
324
}
325
case SUMO_ATTR_UNTIL:
326
if (isAttributeEnabled(key)) {
327
return time2string(myUntil);
328
} else {
329
return "";
330
}
331
case SUMO_ATTR_ACTTYPE:
332
return myActType;
333
case SUMO_ATTR_FRIENDLY_POS:
334
return toString(myFriendlyPos);
335
default:
336
return getPlanAttribute(key);
337
}
338
}
339
340
341
double
342
GNEStopPlan::getAttributeDouble(SumoXMLAttr key) const {
343
return getPlanAttributeDouble(key);
344
}
345
346
347
Position
348
GNEStopPlan::getAttributePosition(SumoXMLAttr key) const {
349
return getPlanAttributePosition(key);
350
}
351
352
353
void
354
GNEStopPlan::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
355
switch (key) {
356
case SUMO_ATTR_DURATION:
357
case SUMO_ATTR_UNTIL:
358
case SUMO_ATTR_ACTTYPE:
359
case SUMO_ATTR_FRIENDLY_POS:
360
GNEChange_Attribute::changeAttribute(this, key, value, undoList);
361
break;
362
default:
363
setPlanAttribute(key, value, undoList);
364
break;
365
}
366
}
367
368
369
bool
370
GNEStopPlan::isValid(SumoXMLAttr key, const std::string& value) {
371
switch (key) {
372
case SUMO_ATTR_DURATION:
373
case SUMO_ATTR_UNTIL:
374
if (canParse<SUMOTime>(value)) {
375
return parse<SUMOTime>(value) >= 0;
376
} else {
377
return false;
378
}
379
case SUMO_ATTR_ACTTYPE:
380
return true;
381
case SUMO_ATTR_FRIENDLY_POS:
382
return canParse<bool>(value);
383
default:
384
return isPlanValid(key, value);
385
}
386
}
387
388
389
void
390
GNEStopPlan::enableAttribute(SumoXMLAttr key, GNEUndoList* undoList) {
391
switch (key) {
392
case SUMO_ATTR_DURATION:
393
case SUMO_ATTR_UNTIL:
394
undoList->add(new GNEChange_ToggleAttribute(this, key, true), true);
395
break;
396
default:
397
throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
398
}
399
}
400
401
402
void
403
GNEStopPlan::disableAttribute(SumoXMLAttr key, GNEUndoList* undoList) {
404
switch (key) {
405
case SUMO_ATTR_DURATION:
406
case SUMO_ATTR_UNTIL:
407
undoList->add(new GNEChange_ToggleAttribute(this, key, false), true);
408
break;
409
default:
410
throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
411
}
412
}
413
414
415
bool
416
GNEStopPlan::isAttributeEnabled(SumoXMLAttr key) const {
417
switch (key) {
418
case SUMO_ATTR_DURATION:
419
return (myParametersSet & STOP_DURATION_SET) != 0;
420
case SUMO_ATTR_UNTIL:
421
return (myParametersSet & STOP_UNTIL_SET) != 0;
422
default:
423
return isPlanAttributeEnabled(key);
424
}
425
}
426
427
428
std::string
429
GNEStopPlan::getPopUpID() const {
430
return getTagStr();
431
}
432
433
434
std::string
435
GNEStopPlan::getHierarchyName() const {
436
return getPlanHierarchyName();
437
}
438
439
// ===========================================================================
440
// private
441
// ===========================================================================
442
443
void
444
GNEStopPlan::setAttribute(SumoXMLAttr key, const std::string& value) {
445
switch (key) {
446
case SUMO_ATTR_DURATION:
447
if (value.empty()) {
448
toggleAttribute(key, false);
449
} else {
450
toggleAttribute(key, true);
451
myDuration = string2time(value);
452
}
453
break;
454
case SUMO_ATTR_UNTIL:
455
if (value.empty()) {
456
toggleAttribute(key, false);
457
} else {
458
toggleAttribute(key, true);
459
myUntil = string2time(value);
460
}
461
break;
462
case SUMO_ATTR_ACTTYPE:
463
myActType = value;
464
break;
465
case SUMO_ATTR_FRIENDLY_POS:
466
myFriendlyPos = parse<bool>(value);
467
break;
468
default:
469
setPlanAttribute(key, value);
470
break;
471
}
472
}
473
474
475
void
476
GNEStopPlan::toggleAttribute(SumoXMLAttr key, const bool value) {
477
switch (key) {
478
case SUMO_ATTR_DURATION:
479
if (value) {
480
myParametersSet |= STOP_DURATION_SET;
481
} else {
482
myParametersSet &= ~STOP_DURATION_SET;
483
}
484
break;
485
case SUMO_ATTR_UNTIL:
486
if (value) {
487
myParametersSet |= STOP_UNTIL_SET;
488
} else {
489
myParametersSet &= ~STOP_UNTIL_SET;
490
}
491
break;
492
default:
493
throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
494
}
495
}
496
497
/****************************************************************************/
498
499