Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/elements/additional/GNERerouter.cpp
169684 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 GNERerouter.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Nov 2015
17
///
18
//
19
/****************************************************************************/
20
#include <config.h>
21
22
#include <netedit/GNENet.h>
23
#include <netedit/GNETagProperties.h>
24
#include <netedit/GNEUndoList.h>
25
#include <netedit/GNEViewNet.h>
26
#include <netedit/changes/GNEChange_Additional.h>
27
#include <netedit/changes/GNEChange_Attribute.h>
28
#include <netedit/dialogs/elements/GNERerouterDialog.h>
29
30
#include "GNERerouter.h"
31
#include "GNERerouterSymbol.h"
32
33
// ===========================================================================
34
// member method definitions
35
// ===========================================================================
36
37
GNERerouter::GNERerouter(GNENet* net) :
38
GNEAdditional("", net, "", SUMO_TAG_REROUTER, ""),
39
myProbability(0),
40
myOff(false),
41
myOptional(false),
42
myTimeThreshold(0) {
43
}
44
45
46
GNERerouter::GNERerouter(const std::string& id, GNENet* net, const std::string& filename, const Position& pos, const std::string& name,
47
double probability, bool off, bool optional, SUMOTime timeThreshold, const std::vector<std::string>& vTypes,
48
const Parameterised::Map& parameters) :
49
GNEAdditional(id, net, filename, SUMO_TAG_REROUTER, name),
50
Parameterised(parameters),
51
myPosition(pos),
52
myProbability(probability),
53
myOff(off),
54
myOptional(optional),
55
myTimeThreshold(timeThreshold),
56
myVTypes(vTypes) {
57
// update centering boundary without updating grid
58
updateCenteringBoundary(false);
59
}
60
61
62
GNERerouter::~GNERerouter() {
63
}
64
65
66
void
67
GNERerouter::writeAdditional(OutputDevice& device) const {
68
// avoid write rerouters without edges
69
if (getAttribute(SUMO_ATTR_EDGES).size() > 0) {
70
device.openTag(SUMO_TAG_REROUTER);
71
device.writeAttr(SUMO_ATTR_ID, getID());
72
device.writeAttr(SUMO_ATTR_EDGES, getAttribute(SUMO_ATTR_EDGES));
73
device.writeAttr(SUMO_ATTR_POSITION, myPosition);
74
if (!myAdditionalName.empty()) {
75
device.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(myAdditionalName));
76
}
77
if (myProbability != 1.0) {
78
device.writeAttr(SUMO_ATTR_PROB, myProbability);
79
}
80
if (time2string(myTimeThreshold) != "0.00") {
81
device.writeAttr(SUMO_ATTR_HALTING_TIME_THRESHOLD, time2string(myTimeThreshold));
82
}
83
if (!myVTypes.empty()) {
84
device.writeAttr(SUMO_ATTR_VTYPES, myVTypes);
85
}
86
if (myOff) {
87
device.writeAttr(SUMO_ATTR_OFF, myOff);
88
}
89
if (myOptional) {
90
device.writeAttr(SUMO_ATTR_OPTIONAL, myOptional);
91
}
92
// write all rerouter interval
93
for (const auto& rerouterInterval : getChildAdditionals()) {
94
if (!rerouterInterval->getTagProperty()->isSymbol()) {
95
rerouterInterval->writeAdditional(device);
96
}
97
}
98
// write parameters (Always after children to avoid problems with additionals.xsd)
99
writeParams(device);
100
device.closeTag();
101
} else {
102
WRITE_WARNING("Rerouter '" + getID() + TL("' needs at least one edge"));
103
}
104
}
105
106
107
bool
108
GNERerouter::isAdditionalValid() const {
109
return true;
110
}
111
112
113
std::string GNERerouter::getAdditionalProblem() const {
114
return "";
115
}
116
117
118
void
119
GNERerouter::fixAdditionalProblem() {
120
// nothing to fix
121
}
122
123
124
bool
125
GNERerouter::checkDrawMoveContour() const {
126
// get edit modes
127
const auto& editModes = myNet->getViewNet()->getEditModes();
128
// check if we're in move mode
129
if (!myNet->getViewNet()->isCurrentlyMovingElements() && editModes.isCurrentSupermodeNetwork() &&
130
!myNet->getViewNet()->getEditNetworkElementShapes().getEditedNetworkElement() &&
131
(editModes.networkEditMode == NetworkEditMode::NETWORK_MOVE) && myNet->getViewNet()->checkOverLockedElement(this, mySelected)) {
132
// only move the first element
133
return myNet->getViewNet()->getViewObjectsSelector().getGUIGlObjectFront() == this;
134
} else {
135
return false;
136
}
137
}
138
139
140
GNEMoveOperation*
141
GNERerouter::getMoveOperation() {
142
// return move operation for additional placed in view
143
return new GNEMoveOperation(this, myPosition);
144
}
145
146
147
void
148
GNERerouter::updateGeometry() {
149
// update additional geometry
150
myAdditionalGeometry.updateSinglePosGeometry(myPosition, 0);
151
// update geometries (boundaries of all children)
152
for (const auto& additionalChildren : getChildAdditionals()) {
153
additionalChildren->updateGeometry();
154
for (const auto& rerouterElement : additionalChildren->getChildAdditionals()) {
155
rerouterElement->updateGeometry();
156
}
157
}
158
}
159
160
161
Position
162
GNERerouter::getPositionInView() const {
163
return myPosition;
164
}
165
166
167
void
168
GNERerouter::updateCenteringBoundary(const bool updateGrid) {
169
// remove additional from grid
170
if (updateGrid) {
171
myNet->removeGLObjectFromGrid(this);
172
}
173
// now update geometry
174
updateGeometry();
175
// add shape boundary
176
myAdditionalBoundary = myAdditionalGeometry.getShape().getBoxBoundary();
177
/*
178
// add positions of all childrens (intervals and symbols)
179
for (const auto& additionalChildren : getChildAdditionals()) {
180
myAdditionalBoundary.add(additionalChildren->getPositionInView());
181
for (const auto& rerouterElement : additionalChildren->getChildAdditionals()) {
182
myAdditionalBoundary.add(rerouterElement->getPositionInView());
183
// special case for parking area rerouter
184
if (rerouterElement->getTagProperty()->getTag() == SUMO_TAG_PARKING_AREA_REROUTE) {
185
myAdditionalBoundary.add(rerouterElement->getParentAdditionals().at(1)->getCenteringBoundary());
186
}
187
}
188
}
189
*/
190
// grow
191
myAdditionalBoundary.grow(5);
192
// add additional into RTREE again
193
if (updateGrid) {
194
myNet->addGLObjectIntoGrid(this);
195
}
196
}
197
198
199
void
200
GNERerouter::splitEdgeGeometry(const double /*splitPosition*/, const GNENetworkElement* /*originalElement*/, const GNENetworkElement* /*newElement*/, GNEUndoList* /*undoList*/) {
201
// geometry of this element cannot be splitted
202
}
203
204
205
void
206
GNERerouter::openAdditionalDialog() {
207
// Open rerouter dialog
208
GNERerouterDialog(this);
209
}
210
211
212
std::string
213
GNERerouter::getParentName() const {
214
return myNet->getMicrosimID();
215
}
216
217
218
void
219
GNERerouter::drawGL(const GUIVisualizationSettings& s) const {
220
const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();
221
// first check if additional has to be drawn
222
if (myNet->getViewNet()->getDataViewOptions().showAdditionals()) {
223
// draw parent and child lines
224
drawParentChildLines(s, s.additionalSettings.connectionColor, true);
225
// draw Rerouter
226
drawSquaredAdditional(s, myPosition, s.additionalSettings.rerouterSize, GUITexture::REROUTER, GUITexture::REROUTER_SELECTED);
227
// iterate over additionals and check if drawn
228
for (const auto& interval : getChildAdditionals()) {
229
// if rerouter or their intevals are selected, then draw
230
if (myNet->getViewNet()->getNetworkViewOptions().showSubAdditionals() ||
231
isAttributeCarrierSelected() || inspectedElements.isACInspected(this) ||
232
interval->isAttributeCarrierSelected() || inspectedElements.isACInspected(interval) ||
233
interval->isMarkedForDrawingFront()) {
234
interval->drawGL(s);
235
} else {
236
// if rerouterElements are inspected or selected, then draw
237
for (const auto& rerouterElement : interval->getChildAdditionals()) {
238
if (rerouterElement->isAttributeCarrierSelected() || inspectedElements.isACInspected(rerouterElement) ||
239
rerouterElement->isMarkedForDrawingFront()) {
240
interval->drawGL(s);
241
}
242
}
243
}
244
}
245
}
246
}
247
248
249
std::string
250
GNERerouter::getAttribute(SumoXMLAttr key) const {
251
switch (key) {
252
case SUMO_ATTR_ID:
253
return getMicrosimID();
254
case SUMO_ATTR_EDGES: {
255
std::vector<std::string> edges;
256
for (const auto& rerouterSymbol : getChildAdditionals()) {
257
if (rerouterSymbol->getTagProperty()->isSymbol()) {
258
edges.push_back(rerouterSymbol->getAttribute(SUMO_ATTR_EDGE));
259
}
260
}
261
return toString(edges);
262
}
263
case SUMO_ATTR_POSITION:
264
return toString(myPosition);
265
case SUMO_ATTR_NAME:
266
return myAdditionalName;
267
case SUMO_ATTR_PROB:
268
return toString(myProbability);
269
case SUMO_ATTR_HALTING_TIME_THRESHOLD:
270
return time2string(myTimeThreshold);
271
case SUMO_ATTR_VTYPES:
272
return toString(myVTypes);
273
case SUMO_ATTR_OFF:
274
return toString(myOff);
275
case SUMO_ATTR_OPTIONAL:
276
return toString(myOptional);
277
default:
278
return getCommonAttribute(this, key);
279
}
280
}
281
282
283
double
284
GNERerouter::getAttributeDouble(SumoXMLAttr key) const {
285
switch (key) {
286
case SUMO_ATTR_PROB:
287
return myProbability;
288
default:
289
throw InvalidArgument(getTagStr() + " doesn't have a double attribute of type '" + toString(key) + "'");
290
}
291
}
292
293
294
const Parameterised::Map&
295
GNERerouter::getACParametersMap() const {
296
return getParametersMap();
297
}
298
299
300
void
301
GNERerouter::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
302
if (value == getAttribute(key)) {
303
return; //avoid needless changes, later logic relies on the fact that attributes have changed
304
}
305
switch (key) {
306
// special case for lanes due rerouter Symbols
307
case SUMO_ATTR_EDGES:
308
// rebuild rerouter Symbols
309
rebuildRerouterSymbols(value, undoList);
310
break;
311
case SUMO_ATTR_ID:
312
case SUMO_ATTR_POSITION:
313
case SUMO_ATTR_NAME:
314
case SUMO_ATTR_PROB:
315
case SUMO_ATTR_HALTING_TIME_THRESHOLD:
316
case SUMO_ATTR_VTYPES:
317
case SUMO_ATTR_OFF:
318
case SUMO_ATTR_OPTIONAL:
319
GNEChange_Attribute::changeAttribute(this, key, value, undoList);
320
break;
321
default:
322
setCommonAttribute(key, value, undoList);
323
break;
324
}
325
}
326
327
328
bool
329
GNERerouter::isValid(SumoXMLAttr key, const std::string& value) {
330
switch (key) {
331
case SUMO_ATTR_ID:
332
return isValidAdditionalID(value);
333
case SUMO_ATTR_EDGES:
334
return canParse<std::vector<GNEEdge*> >(myNet, value, false);
335
case SUMO_ATTR_POSITION:
336
return canParse<Position>(value);
337
case SUMO_ATTR_NAME:
338
return SUMOXMLDefinitions::isValidAttribute(value);
339
case SUMO_ATTR_PROB:
340
return canParse<double>(value) && (parse<double>(value) >= 0) && (parse<double>(value) <= 1);
341
case SUMO_ATTR_HALTING_TIME_THRESHOLD:
342
return canParse<SUMOTime>(value);
343
case SUMO_ATTR_VTYPES:
344
if (value.empty()) {
345
return true;
346
} else {
347
return SUMOXMLDefinitions::isValidListOfTypeID(value);
348
}
349
case SUMO_ATTR_OFF:
350
return canParse<bool>(value);
351
case SUMO_ATTR_OPTIONAL:
352
return canParse<bool>(value);
353
default:
354
return isCommonValid(key, value);
355
}
356
}
357
358
359
std::string
360
GNERerouter::getPopUpID() const {
361
return getTagStr() + ": " + getID();
362
}
363
364
365
std::string
366
GNERerouter::getHierarchyName() const {
367
return getTagStr();
368
}
369
370
// ===========================================================================
371
// private
372
// ===========================================================================
373
374
void
375
GNERerouter::setAttribute(SumoXMLAttr key, const std::string& value) {
376
switch (key) {
377
case SUMO_ATTR_EDGES:
378
throw InvalidArgument(getTagStr() + " cannot be edited");
379
case SUMO_ATTR_ID:
380
// update microsimID
381
setAdditionalID(value);
382
break;
383
case SUMO_ATTR_POSITION:
384
myPosition = parse<Position>(value);
385
// update boundary (except for template)
386
if (getID().size() > 0) {
387
updateCenteringBoundary(true);
388
}
389
break;
390
case SUMO_ATTR_NAME:
391
myAdditionalName = value;
392
break;
393
case SUMO_ATTR_PROB:
394
myProbability = parse<double>(value);
395
break;
396
case SUMO_ATTR_HALTING_TIME_THRESHOLD:
397
myTimeThreshold = parse<SUMOTime>(value);
398
break;
399
case SUMO_ATTR_VTYPES:
400
myVTypes = parse<std::vector<std::string> >(value);
401
break;
402
case SUMO_ATTR_OFF:
403
myOff = parse<bool>(value);
404
break;
405
case SUMO_ATTR_OPTIONAL:
406
myOptional = parse<bool>(value);
407
break;
408
default:
409
setCommonAttribute(this, key, value);
410
break;
411
}
412
}
413
414
415
void
416
GNERerouter::setMoveShape(const GNEMoveResult& moveResult) {
417
// update position
418
myPosition = moveResult.shapeToUpdate.front();
419
// update geometry
420
updateGeometry();
421
}
422
423
424
void
425
GNERerouter::commitMoveShape(const GNEMoveResult& moveResult, GNEUndoList* undoList) {
426
undoList->begin(this, "position of " + getTagStr());
427
GNEChange_Attribute::changeAttribute(this, SUMO_ATTR_POSITION, toString(moveResult.shapeToUpdate.front()), undoList);
428
undoList->end();
429
}
430
431
432
void
433
GNERerouter::rebuildRerouterSymbols(const std::string& value, GNEUndoList* undoList) {
434
undoList->begin(this, ("change " + getTagStr() + " attribute").c_str());
435
// drop all additional children
436
while (getChildAdditionals().size() > 0) {
437
undoList->add(new GNEChange_Additional(getChildAdditionals().front(), false), true);
438
}
439
// get edge vector
440
const std::vector<GNEEdge*> edges = parse<std::vector<GNEEdge*> >(myNet, value);
441
// create new VSS Symbols
442
for (const auto& edge : edges) {
443
// create VSS Symbol
444
GNEAdditional* VSSSymbol = new GNERerouterSymbol(this, edge);
445
// add it using GNEChange_Additional
446
myNet->getViewNet()->getUndoList()->add(new GNEChange_Additional(VSSSymbol, true), true);
447
}
448
undoList->end();
449
}
450
451
452
/****************************************************************************/
453
454