Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/elements/additional/GNEAdditionalHandler.cpp
193678 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-2026 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 GNEAdditionalHandler.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Nov 2015
17
///
18
// Builds trigger objects for netedit
19
/****************************************************************************/
20
#include <config.h>
21
22
#include <netedit/changes/GNEChange_Additional.h>
23
#include <netedit/changes/GNEChange_TAZSourceSink.h>
24
#include <netedit/dialogs/basic/GNEOverwriteElement.h>
25
#include <netedit/GNEApplicationWindow.h>
26
#include <netedit/GNENet.h>
27
#include <netedit/GNETagProperties.h>
28
#include <netedit/GNEUndoList.h>
29
#include <utils/options/OptionsCont.h>
30
#include <utils/xml/NamespaceIDs.h>
31
32
#include "GNEAccess.h"
33
#include "GNEAdditionalHandler.h"
34
#include "GNEBusStop.h"
35
#include "GNECalibrator.h"
36
#include "GNECalibratorFlow.h"
37
#include "GNEChargingStation.h"
38
#include "GNEClosingLaneReroute.h"
39
#include "GNEClosingReroute.h"
40
#include "GNEContainerStop.h"
41
#include "GNEDestProbReroute.h"
42
#include "GNEEntryExitDetector.h"
43
#include "GNEInductionLoopDetector.h"
44
#include "GNEInstantInductionLoopDetector.h"
45
#include "GNELaneAreaDetector.h"
46
#include "GNEMultiEntryExitDetector.h"
47
#include "GNEOverheadWire.h"
48
#include "GNEPOI.h"
49
#include "GNEParkingArea.h"
50
#include "GNEParkingAreaReroute.h"
51
#include "GNEParkingSpace.h"
52
#include "GNEPoly.h"
53
#include "GNERerouter.h"
54
#include "GNERerouterInterval.h"
55
#include "GNERerouterSymbol.h"
56
#include "GNERouteProbReroute.h"
57
#include "GNERouteProbe.h"
58
#include "GNETAZ.h"
59
#include "GNETractionSubstation.h"
60
#include "GNEVaporizer.h"
61
#include "GNEVariableSpeedSign.h"
62
#include "GNEVariableSpeedSignStep.h"
63
#include "GNEVariableSpeedSignSymbol.h"
64
65
// ===========================================================================
66
// GNEAdditionalHandler method definitions
67
// ===========================================================================
68
69
GNEAdditionalHandler::GNEAdditionalHandler(GNENet* net, FileBucket* fileBucket, const bool allowUndoRedo) :
70
AdditionalHandler(fileBucket),
71
myNet(net),
72
myAllowUndoRedo(allowUndoRedo) {
73
}
74
75
76
GNEAdditionalHandler::~GNEAdditionalHandler() {
77
// update options based in current buckets
78
myNet->getGNEApplicationWindow()->getFileBucketHandler()->updateOptions();
79
}
80
81
82
bool
83
GNEAdditionalHandler::buildBusStop(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id,
84
const std::string& laneID, const double startPos, const double endPos, const std::string& name,
85
const std::vector<std::string>& lines, const int personCapacity, const double parkingLength,
86
const RGBColor& color, const bool friendlyPosition, const double angle,
87
const Parameterised::Map& parameters) {
88
// check conditions
89
const auto element = retrieveAdditionalElement(NamespaceIDs::busStops, id);
90
if (!checkElement(SUMO_TAG_BUS_STOP, element)) {
91
return false;
92
} else if (!checkValidAdditionalID(SUMO_TAG_BUS_STOP, id)) {
93
return false;
94
} else {
95
// get lane
96
GNELane* lane = myNet->getAttributeCarriers()->retrieveLane(laneID, false);
97
// check lane
98
if (lane == nullptr) {
99
return writeErrorInvalidParent(SUMO_TAG_BUS_STOP, id, {SUMO_TAG_LANE}, laneID);
100
} else if (!checkLaneDoublePosition(startPos, endPos, lane->getParentEdge()->getNBEdge()->getFinalLength(), friendlyPosition)) {
101
return writeErrorInvalidPosition(SUMO_TAG_BUS_STOP, id);
102
} else if (!checkNegative(SUMO_TAG_BUS_STOP, id, SUMO_ATTR_PERSON_CAPACITY, personCapacity, true)) {
103
return false;
104
} else if (!checkNegative(SUMO_TAG_BUS_STOP, id, SUMO_ATTR_PARKING_LENGTH, parkingLength, true)) {
105
return false;
106
} else {
107
// build busStop
108
GNEAdditional* busStop = GNEBusStop::buildBusStop(id, myNet, myFileBucket, lane, startPos, endPos, name, lines, personCapacity,
109
parkingLength, color, friendlyPosition, angle, parameters);
110
// insert depending of allowUndoRedo
111
if (myAllowUndoRedo) {
112
myNet->getUndoList()->begin(busStop, TL("add bus stop '") + id + "'");
113
myNet->getUndoList()->add(new GNEChange_Additional(busStop, true), true);
114
myNet->getUndoList()->end();
115
} else {
116
myNet->getAttributeCarriers()->insertAdditional(busStop);
117
lane->addChildElement(busStop);
118
busStop->incRef("buildBusStop");
119
}
120
return true;
121
}
122
}
123
}
124
125
126
bool
127
GNEAdditionalHandler::buildTrainStop(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id,
128
const std::string& laneID, const double startPos, const double endPos, const std::string& name,
129
const std::vector<std::string>& lines, const int personCapacity, const double parkingLength,
130
const RGBColor& color, const bool friendlyPosition, const double angle,
131
const Parameterised::Map& parameters) {
132
// check conditions
133
const auto element = retrieveAdditionalElement(NamespaceIDs::busStops, id);
134
if (!checkElement(SUMO_TAG_TRAIN_STOP, element)) {
135
return false;
136
} else if (!checkValidAdditionalID(SUMO_TAG_TRAIN_STOP, id)) {
137
return false;
138
} else {
139
// get lane
140
GNELane* lane = myNet->getAttributeCarriers()->retrieveLane(laneID, false);
141
// check lane
142
if (lane == nullptr) {
143
return writeErrorInvalidParent(SUMO_TAG_TRAIN_STOP, id, {SUMO_TAG_LANE}, laneID);
144
} else if (!checkLaneDoublePosition(startPos, endPos, lane->getParentEdge()->getNBEdge()->getFinalLength(), friendlyPosition)) {
145
return writeErrorInvalidPosition(SUMO_TAG_TRAIN_STOP, id);
146
} else if (!checkNegative(SUMO_TAG_TRAIN_STOP, id, SUMO_ATTR_PERSON_CAPACITY, personCapacity, true)) {
147
return false;
148
} else if (!checkNegative(SUMO_TAG_TRAIN_STOP, id, SUMO_ATTR_PARKING_LENGTH, parkingLength, true)) {
149
return false;
150
} else {
151
// build trainStop
152
GNEAdditional* trainStop = GNEBusStop::buildTrainStop(id, myNet, myFileBucket, lane, startPos, endPos, name, lines, personCapacity,
153
parkingLength, color, friendlyPosition, angle, parameters);
154
// insert depending of allowUndoRedo
155
if (myAllowUndoRedo) {
156
myNet->getUndoList()->begin(trainStop, TL("add train stop '") + id + "'");
157
myNet->getUndoList()->add(new GNEChange_Additional(trainStop, true), true);
158
myNet->getUndoList()->end();
159
} else {
160
myNet->getAttributeCarriers()->insertAdditional(trainStop);
161
lane->addChildElement(trainStop);
162
trainStop->incRef("buildTrainStop");
163
}
164
return true;
165
}
166
}
167
}
168
169
170
bool
171
GNEAdditionalHandler::buildAccess(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& laneID,
172
const std::string& pos, const double length, const bool friendlyPos, const Parameterised::Map& parameters) {
173
// get lane
174
GNELane* lane = myNet->getAttributeCarriers()->retrieveLane(laneID, false);
175
// get busStop (or trainStop)
176
const auto busStop = getAdditionalParent(sumoBaseObject, SUMO_TAG_BUS_STOP);
177
const auto trainStop = getAdditionalParent(sumoBaseObject, SUMO_TAG_TRAIN_STOP);
178
const auto containerStop = getAdditionalParent(sumoBaseObject, SUMO_TAG_CONTAINER_STOP);
179
// check parent
180
if ((busStop == nullptr) && (trainStop == nullptr) && (containerStop == nullptr)) {
181
if (sumoBaseObject->getParentSumoBaseObject()->hasStringAttribute(SUMO_ATTR_ID)) {
182
return writeErrorInvalidParent(SUMO_TAG_ACCESS, {SUMO_TAG_BUS_STOP, SUMO_TAG_TRAIN_STOP, SUMO_TAG_CONTAINER_STOP}, sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID));
183
} else {
184
return writeErrorInvalidParent(SUMO_TAG_ACCESS, {SUMO_TAG_BUS_STOP, SUMO_TAG_TRAIN_STOP, SUMO_TAG_CONTAINER_STOP});
185
}
186
}
187
GNEAdditional* accessParent = busStop ? busStop : trainStop ? trainStop : containerStop;
188
// pos double
189
bool validPos = true;
190
double posDouble = 0;
191
if (lane) {
192
if (GNEAttributeCarrier::canParse<double>(pos)) {
193
posDouble = GNEAttributeCarrier::parse<double>(pos);
194
validPos = checkLanePosition(posDouble, 0, lane->getParentEdge()->getNBEdge()->getFinalLength(), friendlyPos);
195
} else if (pos == "random" || pos == "doors" || pos == "carriage") {
196
posDouble = INVALID_DOUBLE;
197
} else if (pos.empty()) {
198
posDouble = 0;
199
} else {
200
validPos = false;
201
}
202
}
203
// Check if lane is correct
204
if (lane == nullptr) {
205
return writeErrorInvalidParent(SUMO_TAG_ACCESS, "", {SUMO_TAG_LANE}, laneID);
206
} else if (!validPos) {
207
return writeErrorInvalidPosition(SUMO_TAG_ACCESS, accessParent->getID());
208
} else if ((length != -1) && !checkNegative(SUMO_TAG_ACCESS, accessParent->getID(), SUMO_ATTR_LENGTH, length, true)) {
209
return false;
210
} else if (!accessExists(accessParent, lane->getParentEdge())) {
211
return writeError(TLF("Could not build access in netedit; % '%' already owns an access in the edge '%'", accessParent->getTagStr(), accessParent->getID(), lane->getParentEdge()->getID()));
212
} else if (!containerStop && !lane->allowPedestrians()) {
213
// only for busStops and trainStops
214
return writeError(TLF("Could not build access in netedit; The lane '%' doesn't support pedestrians", lane->getID()));
215
} else {
216
// build access
217
GNEAdditional* access = new GNEAccess(accessParent, lane, posDouble, pos, friendlyPos, length, parameters);
218
// insert depending of allowUndoRedo
219
if (myAllowUndoRedo) {
220
myNet->getUndoList()->begin(access, TL("add access in '") + accessParent->getID() + "'");
221
myNet->getUndoList()->add(new GNEChange_Additional(access, true), true);
222
myNet->getUndoList()->end();
223
} else {
224
myNet->getAttributeCarriers()->insertAdditional(access);
225
lane->addChildElement(access);
226
accessParent->addChildElement(access);
227
access->incRef("buildAccess");
228
}
229
return true;
230
}
231
}
232
233
234
bool
235
GNEAdditionalHandler::buildContainerStop(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id, const std::string& laneID,
236
const double startPos, const double endPos, const std::string& name, const std::vector<std::string>& lines, const int containerCapacity,
237
const double parkingLength, const RGBColor& color, const bool friendlyPosition, const double angle, const Parameterised::Map& parameters) {
238
// check conditions
239
const auto element = retrieveAdditionalElement({SUMO_TAG_CONTAINER_STOP}, id);
240
if (!checkElement(SUMO_TAG_CONTAINER_STOP, element)) {
241
return false;
242
} else if (!checkValidAdditionalID(SUMO_TAG_CONTAINER_STOP, id)) {
243
return false;
244
} else {
245
// get lane
246
GNELane* lane = myNet->getAttributeCarriers()->retrieveLane(laneID, false);
247
// check lane
248
if (lane == nullptr) {
249
return writeErrorInvalidParent(SUMO_TAG_CONTAINER_STOP, id, {SUMO_TAG_LANE}, laneID);
250
} else if (!checkLaneDoublePosition(startPos, endPos, lane->getParentEdge()->getNBEdge()->getFinalLength(), friendlyPosition)) {
251
return writeErrorInvalidPosition(SUMO_TAG_CONTAINER_STOP, id);
252
} else if (!checkNegative(SUMO_TAG_CONTAINER_STOP, id, SUMO_ATTR_CONTAINER_CAPACITY, containerCapacity, true)) {
253
return false;
254
} else if (!checkNegative(SUMO_TAG_CONTAINER_STOP, id, SUMO_ATTR_PARKING_LENGTH, parkingLength, true)) {
255
return false;
256
} else {
257
// build containerStop
258
GNEAdditional* containerStop = new GNEContainerStop(id, myNet, myFileBucket, lane, startPos, endPos, name, lines, containerCapacity, parkingLength,
259
color, friendlyPosition, angle, parameters);
260
// insert depending of allowUndoRedo
261
if (myAllowUndoRedo) {
262
myNet->getUndoList()->begin(containerStop, TL("add container stop '") + id + "'");
263
myNet->getUndoList()->add(new GNEChange_Additional(containerStop, true), true);
264
myNet->getUndoList()->end();
265
} else {
266
myNet->getAttributeCarriers()->insertAdditional(containerStop);
267
lane->addChildElement(containerStop);
268
containerStop->incRef("buildContainerStop");
269
}
270
return true;
271
}
272
}
273
}
274
275
276
bool
277
GNEAdditionalHandler::buildChargingStation(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id,
278
const std::string& laneID, const double startPos, const double endPos, const std::string& name, const double chargingPower,
279
const double totalPower, const double efficiency, const bool chargeInTransit, const SUMOTime chargeDelay, const std::string& chargeType,
280
const SUMOTime waitingTime, const bool friendlyPosition, const std::string& parkingAreaID, const Parameterised::Map& parameters) {
281
// check conditions
282
const auto element = retrieveAdditionalElement({SUMO_TAG_CHARGING_STATION}, id);
283
if (!checkElement(SUMO_TAG_CHARGING_STATION, element)) {
284
return false;
285
} else if (!checkValidAdditionalID(SUMO_TAG_CHARGING_STATION, id)) {
286
return false;
287
} else {
288
// get lane
289
GNELane* lane = myNet->getAttributeCarriers()->retrieveLane(laneID, false);
290
// check lane
291
if (lane == nullptr) {
292
return writeErrorInvalidParent(SUMO_TAG_CHARGING_STATION, id, {SUMO_TAG_LANE}, laneID);
293
} else if (!checkLaneDoublePosition(startPos, endPos, lane->getParentEdge()->getNBEdge()->getFinalLength(), friendlyPosition)) {
294
return writeErrorInvalidPosition(SUMO_TAG_CHARGING_STATION, id);
295
} else if (!checkNegative(SUMO_TAG_CHARGING_STATION, id, SUMO_ATTR_CHARGINGPOWER, chargingPower, true)) {
296
return false;
297
} else if (!checkNegative(SUMO_TAG_CHARGING_STATION, id, SUMO_ATTR_TOTALPOWER, totalPower, true)) {
298
return false;
299
} else if (!checkNegative(SUMO_TAG_CHARGING_STATION, id, SUMO_ATTR_CHARGEDELAY, chargeDelay, true)) {
300
return false;
301
} else if (!SUMOXMLDefinitions::ChargeTypes.hasString(chargeType)) {
302
return writeError(TLF("Could not build % with ID '%' in netedit; Invalid charge type '%' .", toString(SUMO_TAG_CHARGING_STATION), id, chargeType));
303
} else {
304
// build chargingStation
305
GNEAdditional* chargingStation = new GNEChargingStation(id, myNet, myFileBucket, lane, startPos, endPos, name, chargingPower, totalPower, efficiency, chargeInTransit,
306
chargeDelay, chargeType, waitingTime, parkingAreaID, friendlyPosition, parameters);
307
// insert depending of allowUndoRedo
308
if (myAllowUndoRedo) {
309
myNet->getUndoList()->begin(chargingStation, TL("add charging station '") + id + "'");
310
myNet->getUndoList()->add(new GNEChange_Additional(chargingStation, true), true);
311
myNet->getUndoList()->end();
312
} else {
313
myNet->getAttributeCarriers()->insertAdditional(chargingStation);
314
lane->addChildElement(chargingStation);
315
chargingStation->incRef("buildChargingStation");
316
}
317
return true;
318
}
319
}
320
}
321
322
323
bool
324
GNEAdditionalHandler::buildParkingArea(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id, const std::string& laneID,
325
const double startPos, const double endPos, const std::string& departPos, const std::string& name,
326
const std::vector<std::string>& badges, const bool friendlyPosition, const int roadSideCapacity, const bool onRoad,
327
const double width, const double length, const double angle, const bool lefthand, const Parameterised::Map& parameters) {
328
// check conditions
329
const auto element = retrieveAdditionalElement({SUMO_TAG_PARKING_AREA}, id);
330
if (!checkElement(SUMO_TAG_PARKING_AREA, element)) {
331
return false;
332
} else if (!checkValidAdditionalID(SUMO_TAG_PARKING_AREA, id)) {
333
return false;
334
} else {
335
// get lane
336
GNELane* lane = myNet->getAttributeCarriers()->retrieveLane(laneID, false);
337
// get departPos double
338
const double departPosDouble = GNEAttributeCarrier::canParse<double>(departPos) ? GNEAttributeCarrier::parse<double>(departPos) : 0;
339
// check lane
340
if (lane == nullptr) {
341
return writeErrorInvalidParent(SUMO_TAG_PARKING_AREA, id, {SUMO_TAG_LANE}, laneID);
342
} else if (!checkLaneDoublePosition(startPos, endPos, lane->getParentEdge()->getNBEdge()->getFinalLength(), friendlyPosition)) {
343
return writeErrorInvalidPosition(SUMO_TAG_PARKING_AREA, id);
344
} else if (!checkNegative(SUMO_TAG_PARKING_AREA, id, SUMO_ATTR_ROADSIDE_CAPACITY, roadSideCapacity, true)) {
345
return false;
346
} else if (!checkNegative(SUMO_TAG_PARKING_AREA, id, SUMO_ATTR_WIDTH, width, true)) {
347
return false;
348
} else if (!checkNegative(SUMO_TAG_PARKING_AREA, id, SUMO_ATTR_LENGTH, length, true)) {
349
return false;
350
} else if ((departPosDouble < 0) || (departPosDouble > lane->getParentEdge()->getNBEdge()->getFinalLength())) {
351
return writeError(TLF("Could not build parking area with ID '%' in netedit; Invalid departPos over lane.", id));
352
} else {
353
// build parkingArea
354
GNEAdditional* parkingArea = new GNEParkingArea(id, myNet, myFileBucket, lane, startPos, endPos, GNEAttributeCarrier::canParse<double>(departPos) ? departPos : "",
355
name, badges, friendlyPosition, roadSideCapacity, onRoad,
356
(width == 0) ? SUMO_const_laneWidth : width, length, angle, lefthand, parameters);
357
// insert depending of allowUndoRedo
358
if (myAllowUndoRedo) {
359
myNet->getUndoList()->begin(parkingArea, TL("add parking area '") + id + "'");
360
myNet->getUndoList()->add(new GNEChange_Additional(parkingArea, true), true);
361
myNet->getUndoList()->end();
362
} else {
363
myNet->getAttributeCarriers()->insertAdditional(parkingArea);
364
lane->addChildElement(parkingArea);
365
parkingArea->incRef("buildParkingArea");
366
}
367
return true;
368
}
369
}
370
}
371
372
373
bool
374
GNEAdditionalHandler::buildParkingSpace(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const double x, const double y, const double z,
375
const std::string& name, const std::string& width, const std::string& length, const std::string& angle, const double slope,
376
const Parameterised::Map& parameters) {
377
// check width and heights
378
if (!width.empty() && !GNEAttributeCarrier::canParse<double>(width)) {
379
return writeError(TL("Could not build parking space in netedit; attribute width cannot be parse to float."));
380
} else if (!length.empty() && !GNEAttributeCarrier::canParse<double>(length)) {
381
return writeError(TL("Could not build parking space in netedit; attribute length cannot be parse to float."));
382
} else if (!angle.empty() && !GNEAttributeCarrier::canParse<double>(angle)) {
383
return writeError(TL("Could not build parking space in netedit; attribute angle cannot be parse to float."));
384
} else {
385
// get lane
386
GNEAdditional* parkingArea = getAdditionalParent(sumoBaseObject, SUMO_TAG_PARKING_AREA);
387
// get double values
388
const double widthDouble = width.empty() ? INVALID_DOUBLE : GNEAttributeCarrier::parse<double>(width);
389
const double lengthDouble = length.empty() ? INVALID_DOUBLE : GNEAttributeCarrier::parse<double>(length);
390
const double angleDouble = angle.empty() ? INVALID_DOUBLE : GNEAttributeCarrier::parse<double>(angle);
391
// check lane
392
if (parkingArea == nullptr) {
393
return writeErrorInvalidParent(SUMO_TAG_PARKING_SPACE, "", {SUMO_TAG_PARKING_AREA}, sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID));
394
} else if ((widthDouble != INVALID_DOUBLE) && !checkNegative(SUMO_TAG_PARKING_SPACE, parkingArea->getID(), SUMO_ATTR_WIDTH, widthDouble, true)) {
395
return false;
396
} else if ((lengthDouble != INVALID_DOUBLE) && !checkNegative(SUMO_TAG_PARKING_SPACE, parkingArea->getID(), SUMO_ATTR_LENGTH, lengthDouble, true)) {
397
return false;
398
} else {
399
// build parkingSpace
400
GNEAdditional* parkingSpace = new GNEParkingSpace(parkingArea, Position(x, y, z), widthDouble, lengthDouble, angleDouble, slope, name, parameters);
401
// insert depending of allowUndoRedo
402
if (myAllowUndoRedo) {
403
myNet->getUndoList()->begin(parkingSpace, TL("add parking space in '") + parkingArea->getID() + "'");
404
myNet->getUndoList()->add(new GNEChange_Additional(parkingSpace, true), true);
405
myNet->getUndoList()->end();
406
} else {
407
myNet->getAttributeCarriers()->insertAdditional(parkingSpace);
408
parkingArea->addChildElement(parkingSpace);
409
parkingSpace->incRef("buildParkingSpace");
410
}
411
// update geometry (due boundaries)
412
parkingSpace->updateGeometry();
413
return true;
414
}
415
}
416
}
417
418
419
bool
420
GNEAdditionalHandler::buildE1Detector(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id, const std::string& laneID,
421
const double position, const SUMOTime period, const std::string& file, const std::vector<std::string>& vehicleTypes,
422
const std::vector<std::string>& nextEdges, const std::string& detectPersons, const std::string& name,
423
const bool friendlyPos, const Parameterised::Map& parameters) {
424
// check conditions
425
const auto element = retrieveAdditionalElement({SUMO_TAG_INDUCTION_LOOP}, id);
426
if (!checkElement(SUMO_TAG_INDUCTION_LOOP, element)) {
427
return false;
428
} else if (!checkValidDetectorID(SUMO_TAG_INDUCTION_LOOP, id)) {
429
return false;
430
} else {
431
// get lane
432
GNELane* lane = myNet->getAttributeCarriers()->retrieveLane(laneID, false);
433
// check lane
434
if (lane == nullptr) {
435
return writeErrorInvalidParent(SUMO_TAG_INDUCTION_LOOP, id, {SUMO_TAG_LANE}, laneID);
436
} else if (!checkLanePosition(position, 0, lane->getParentEdge()->getNBEdge()->getFinalLength(), friendlyPos)) {
437
return writeErrorInvalidPosition(SUMO_TAG_INDUCTION_LOOP, id);
438
} else if (!checkNegative(SUMO_TAG_INDUCTION_LOOP, id, SUMO_ATTR_PERIOD, period, true)) {
439
return false;
440
} else if (!checkFileName(SUMO_TAG_INDUCTION_LOOP, id, SUMO_ATTR_FILE, file)) {
441
return false;
442
} else if (!checkListOfVehicleTypes(SUMO_TAG_INDUCTION_LOOP, id, vehicleTypes)) {
443
return false;
444
} else {
445
// build E1
446
GNEAdditional* detectorE1 = new GNEInductionLoopDetector(id, myNet, myFileBucket, lane, position, period, file, vehicleTypes,
447
nextEdges, detectPersons, name, friendlyPos, parameters);
448
// insert depending of allowUndoRedo
449
if (myAllowUndoRedo) {
450
myNet->getUndoList()->begin(detectorE1, TL("add induction loop '") + id + "'");
451
myNet->getUndoList()->add(new GNEChange_Additional(detectorE1, true), true);
452
myNet->getUndoList()->end();
453
} else {
454
myNet->getAttributeCarriers()->insertAdditional(detectorE1);
455
lane->addChildElement(detectorE1);
456
detectorE1->incRef("buildDetectorE1");
457
}
458
return true;
459
}
460
}
461
}
462
463
464
bool
465
GNEAdditionalHandler::buildSingleLaneDetectorE2(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id, const std::string& laneID,
466
const double pos, const double length, const SUMOTime period, const std::string& trafficLight, const std::string& filename,
467
const std::vector<std::string>& vehicleTypes, const std::vector<std::string>& nextEdges, const std::string& detectPersons,
468
const std::string& name, const SUMOTime timeThreshold, const double speedThreshold, const double jamThreshold,
469
const bool friendlyPos, const bool show, const Parameterised::Map& parameters) {
470
// check conditions
471
const auto element = retrieveAdditionalElement(NamespaceIDs::laneAreaDetectors, id);
472
if (!checkElement(SUMO_TAG_LANE_AREA_DETECTOR, element)) {
473
return false;
474
} else if (!checkValidDetectorID(SUMO_TAG_LANE_AREA_DETECTOR, id)) {
475
return false;
476
} else {
477
// get lane
478
GNELane* lane = myNet->getAttributeCarriers()->retrieveLane(laneID, false);
479
// check lane
480
if (lane == nullptr) {
481
return writeErrorInvalidParent(SUMO_TAG_LANE_AREA_DETECTOR, id, {SUMO_TAG_LANE}, laneID);
482
} else {
483
// check friendlyPos in small lanes
484
const bool friendlyPosCheck = checkFriendlyPosSmallLanes(pos, length, lane->getParentEdge()->getNBEdge()->getFinalLength(), friendlyPos);
485
if (!checkLanePosition(pos, length, lane->getParentEdge()->getNBEdge()->getFinalLength(), friendlyPosCheck)) {
486
return writeErrorInvalidPosition(SUMO_TAG_LANE_AREA_DETECTOR, id);
487
} else if (!checkNegative(SUMO_TAG_LANE_AREA_DETECTOR, id, SUMO_ATTR_LENGTH, length, true)) {
488
return false;
489
} else if ((period != -1) && !checkNegative(SUMO_TAG_LANE_AREA_DETECTOR, id, SUMO_ATTR_PERIOD, period, true)) {
490
return false;
491
} else if ((trafficLight.size() > 0) && !(SUMOXMLDefinitions::isValidNetID(trafficLight))) {
492
// temporal
493
return writeError(TLF("Could not build lane area detector with ID '%' in netedit; invalid traffic light ID.", id));
494
} else if (!checkNegative(SUMO_TAG_LANE_AREA_DETECTOR, id, SUMO_ATTR_HALTING_TIME_THRESHOLD, timeThreshold, true)) {
495
return false;
496
} else if (!checkNegative(SUMO_TAG_LANE_AREA_DETECTOR, id, SUMO_ATTR_HALTING_SPEED_THRESHOLD, speedThreshold, true)) {
497
return false;
498
} else if (!checkNegative(SUMO_TAG_LANE_AREA_DETECTOR, id, SUMO_ATTR_JAM_DIST_THRESHOLD, jamThreshold, true)) {
499
return false;
500
} else if (!checkFileName(SUMO_TAG_LANE_AREA_DETECTOR, id, SUMO_ATTR_FILE, filename)) {
501
return false;
502
} else if (!checkListOfVehicleTypes(SUMO_TAG_LANE_AREA_DETECTOR, id, vehicleTypes)) {
503
return false;
504
} else {
505
// build E2 single lane
506
GNEAdditional* detectorE2 = new GNELaneAreaDetector(id, myNet, myFileBucket, lane, pos, length, period, trafficLight, filename,
507
vehicleTypes, nextEdges, detectPersons, name, timeThreshold,
508
speedThreshold, jamThreshold, friendlyPosCheck, show, parameters);
509
// insert depending of allowUndoRedo
510
if (myAllowUndoRedo) {
511
myNet->getUndoList()->begin(detectorE2, TL("add lane area detector '") + id + "'");
512
myNet->getUndoList()->add(new GNEChange_Additional(detectorE2, true), true);
513
myNet->getUndoList()->end();
514
} else {
515
myNet->getAttributeCarriers()->insertAdditional(detectorE2);
516
lane->addChildElement(detectorE2);
517
detectorE2->incRef("buildDetectorE2");
518
}
519
return true;
520
}
521
}
522
}
523
}
524
525
526
bool
527
GNEAdditionalHandler::buildMultiLaneDetectorE2(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id, const std::vector<std::string>& laneIDs,
528
const double pos, const double endPos, const SUMOTime period, const std::string& trafficLight, const std::string& filename,
529
const std::vector<std::string>& vehicleTypes, const std::vector<std::string>& nextEdges, const std::string& detectPersons,
530
const std::string& name, const SUMOTime timeThreshold, const double speedThreshold, const double jamThreshold,
531
const bool friendlyPos, const bool show, const Parameterised::Map& parameters) {
532
// check conditions
533
const auto element = retrieveAdditionalElement(NamespaceIDs::laneAreaDetectors, id);
534
if (!checkElement(GNE_TAG_MULTI_LANE_AREA_DETECTOR, element)) {
535
return false;
536
} else if (!checkValidDetectorID(GNE_TAG_MULTI_LANE_AREA_DETECTOR, id)) {
537
return false;
538
} else {
539
// get lanes
540
const auto lanes = parseLanes(GNE_TAG_MULTI_LANE_AREA_DETECTOR, id, laneIDs);
541
// check lanes
542
if (lanes.empty()) {
543
return false;
544
} else {
545
// calculate path
546
if (!GNEAdditional::areLaneConsecutives(lanes)) {
547
return writeError(TLF("Could not build lane area detector with ID '%' in netedit; Lanes aren't consecutives.", id));
548
} else if (!checkMultiLanePosition(
549
pos, lanes.front()->getParentEdge()->getNBEdge()->getFinalLength(),
550
endPos, lanes.back()->getParentEdge()->getNBEdge()->getFinalLength(), friendlyPos)) {
551
return writeErrorInvalidPosition(GNE_TAG_MULTI_LANE_AREA_DETECTOR, id);
552
} else if ((period != -1) && !checkNegative(GNE_TAG_MULTI_LANE_AREA_DETECTOR, id, SUMO_ATTR_PERIOD, period, true)) {
553
return false;
554
} else if ((trafficLight.size() > 0) && !(SUMOXMLDefinitions::isValidNetID(trafficLight))) {
555
// temporal
556
return writeError(TLF("Could not build lane area detector with ID '%' in netedit; invalid traffic light ID.", id));
557
} else if (!checkNegative(GNE_TAG_MULTI_LANE_AREA_DETECTOR, id, SUMO_ATTR_HALTING_TIME_THRESHOLD, timeThreshold, true)) {
558
return false;
559
} else if (!checkNegative(GNE_TAG_MULTI_LANE_AREA_DETECTOR, id, SUMO_ATTR_HALTING_SPEED_THRESHOLD, speedThreshold, true)) {
560
return false;
561
} else if (!checkNegative(GNE_TAG_MULTI_LANE_AREA_DETECTOR, id, SUMO_ATTR_JAM_DIST_THRESHOLD, jamThreshold, true)) {
562
return false;
563
} else if (!checkFileName(GNE_TAG_MULTI_LANE_AREA_DETECTOR, id, SUMO_ATTR_FILE, filename)) {
564
return false;
565
} else if (!checkListOfVehicleTypes(GNE_TAG_MULTI_LANE_AREA_DETECTOR, id, vehicleTypes)) {
566
return false;
567
} else {
568
// build E2 multilane detector
569
GNEAdditional* detectorE2 = new GNELaneAreaDetector(id, myNet, myFileBucket, lanes, pos, endPos, period, trafficLight, filename,
570
vehicleTypes, nextEdges, detectPersons, name, timeThreshold,
571
speedThreshold, jamThreshold, friendlyPos, show, parameters);
572
// insert depending of allowUndoRedo
573
if (myAllowUndoRedo) {
574
myNet->getUndoList()->begin(detectorE2, TL("add lane area detector '") + id + "'");
575
myNet->getUndoList()->add(new GNEChange_Additional(detectorE2, true), true);
576
myNet->getUndoList()->end();
577
} else {
578
myNet->getAttributeCarriers()->insertAdditional(detectorE2);
579
for (const auto& lane : lanes) {
580
lane->addChildElement(detectorE2);
581
}
582
detectorE2->incRef("buildDetectorE2Multilane");
583
}
584
return true;
585
}
586
}
587
}
588
}
589
590
591
bool
592
GNEAdditionalHandler::buildDetectorE3(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id, const Position& pos, const SUMOTime period,
593
const std::string& filename, const std::vector<std::string>& vehicleTypes, const std::vector<std::string>& nextEdges,
594
const std::string& detectPersons, const std::string& name, const SUMOTime timeThreshold, const double speedThreshold,
595
const bool openEntry, const bool expectedArrival, const Parameterised::Map& parameters) {
596
// check conditions
597
const auto element = retrieveAdditionalElement({SUMO_TAG_ENTRY_EXIT_DETECTOR}, id);
598
if (!checkElement(SUMO_TAG_ENTRY_EXIT_DETECTOR, element)) {
599
return false;
600
} else if (!checkValidDetectorID(SUMO_TAG_ENTRY_EXIT_DETECTOR, id)) {
601
return false;
602
} else if (!checkNegative(SUMO_TAG_ENTRY_EXIT_DETECTOR, id, SUMO_ATTR_PERIOD, period, true)) {
603
return false;
604
} else if (!checkNegative(SUMO_TAG_ENTRY_EXIT_DETECTOR, id, SUMO_ATTR_HALTING_TIME_THRESHOLD, timeThreshold, true)) {
605
return false;
606
} else if (!checkNegative(SUMO_TAG_ENTRY_EXIT_DETECTOR, id, SUMO_ATTR_HALTING_SPEED_THRESHOLD, speedThreshold, true)) {
607
return false;
608
} else if (!checkFileName(SUMO_TAG_ENTRY_EXIT_DETECTOR, id, SUMO_ATTR_FILE, filename)) {
609
return false;
610
} else if (!checkListOfVehicleTypes(SUMO_TAG_ENTRY_EXIT_DETECTOR, id, vehicleTypes)) {
611
return false;
612
} else {
613
// build E3
614
GNEAdditional* E3 = new GNEMultiEntryExitDetector(id, myNet, myFileBucket, pos, period, filename, vehicleTypes, nextEdges, detectPersons,
615
name, timeThreshold, speedThreshold, openEntry, expectedArrival, parameters);
616
// insert depending of allowUndoRedo
617
if (myAllowUndoRedo) {
618
myNet->getUndoList()->begin(E3, TL("add entry-exit detector '") + id + "'");
619
myNet->getUndoList()->add(new GNEChange_Additional(E3, true), true);
620
myNet->getUndoList()->end();
621
} else {
622
myNet->getAttributeCarriers()->insertAdditional(E3);
623
E3->incRef("buildDetectorE3");
624
}
625
return true;
626
}
627
}
628
629
630
bool
631
GNEAdditionalHandler::buildDetectorEntry(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& laneID, const double pos,
632
const bool friendlyPos, const Parameterised::Map& parameters) {
633
// get lane
634
GNELane* lane = myNet->getAttributeCarriers()->retrieveLane(laneID, false);
635
// get E3 parent
636
GNEAdditional* E3 = getAdditionalParent(sumoBaseObject, SUMO_TAG_ENTRY_EXIT_DETECTOR);
637
// Check if Detector E3 parent and lane is correct
638
if (lane == nullptr) {
639
return writeErrorInvalidParent(SUMO_TAG_DET_ENTRY, "", {SUMO_TAG_LANE}, laneID);
640
} else if (E3 == nullptr) {
641
return writeErrorInvalidParent(SUMO_TAG_DET_ENTRY, "", {SUMO_TAG_ENTRY_EXIT_DETECTOR}, sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID));
642
} else if (!checkLanePosition(pos, 0, lane->getParentEdge()->getNBEdge()->getFinalLength(), friendlyPos)) {
643
return writeErrorInvalidPosition(SUMO_TAG_DET_ENTRY, E3->getID());
644
} else {
645
// build entry instant
646
GNEAdditional* entry = new GNEEntryExitDetector(SUMO_TAG_DET_ENTRY, E3, lane, pos, friendlyPos, parameters);
647
// insert depending of allowUndoRedo
648
if (myAllowUndoRedo) {
649
myNet->getUndoList()->begin(entry, TL("add entry detector in '") + E3->getID() + "'");
650
myNet->getUndoList()->add(new GNEChange_Additional(entry, true), true);
651
myNet->getUndoList()->end();
652
} else {
653
myNet->getAttributeCarriers()->insertAdditional(entry);
654
lane->addChildElement(entry);
655
E3->addChildElement(entry);
656
entry->incRef("buildDetectorEntry");
657
}
658
return true;
659
}
660
}
661
662
663
bool
664
GNEAdditionalHandler::buildDetectorExit(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& laneID, const double pos,
665
const bool friendlyPos, const Parameterised::Map& parameters) {
666
// get lane
667
GNELane* lane = myNet->getAttributeCarriers()->retrieveLane(laneID, false);
668
// get E3 parent
669
GNEAdditional* E3 = getAdditionalParent(sumoBaseObject, SUMO_TAG_ENTRY_EXIT_DETECTOR);
670
// Check if Detector E3 parent and lane is correct
671
if (lane == nullptr) {
672
return writeErrorInvalidParent(SUMO_TAG_DET_EXIT, "", {SUMO_TAG_LANE}, laneID);
673
} else if (E3 == nullptr) {
674
return writeErrorInvalidParent(SUMO_TAG_DET_EXIT, "", {SUMO_TAG_ENTRY_EXIT_DETECTOR}, sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID));
675
} else if (!checkLanePosition(pos, 0, lane->getParentEdge()->getNBEdge()->getFinalLength(), friendlyPos)) {
676
return writeErrorInvalidPosition(SUMO_TAG_DET_EXIT, E3->getID());
677
} else {
678
// build exit instant
679
GNEAdditional* exit = new GNEEntryExitDetector(SUMO_TAG_DET_EXIT, E3, lane, pos, friendlyPos, parameters);
680
// insert depending of allowUndoRedo
681
if (myAllowUndoRedo) {
682
myNet->getUndoList()->begin(exit, TL("add exit detector in '") + E3->getID() + "'");
683
myNet->getUndoList()->add(new GNEChange_Additional(exit, true), true);
684
myNet->getUndoList()->end();
685
} else {
686
myNet->getAttributeCarriers()->insertAdditional(exit);
687
lane->addChildElement(exit);
688
E3->addChildElement(exit);
689
exit->incRef("buildDetectorExit");
690
}
691
return true;
692
}
693
}
694
695
696
bool
697
GNEAdditionalHandler::buildDetectorE1Instant(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id, const std::string& laneID, double pos,
698
const std::string& filename, const std::vector<std::string>& vehicleTypes, const std::vector<std::string>& nextEdges,
699
const std::string& detectPersons, const std::string& name, const bool friendlyPos, const Parameterised::Map& parameters) {
700
// check conditions
701
const auto element = retrieveAdditionalElement({SUMO_TAG_INSTANT_INDUCTION_LOOP}, id);
702
if (!checkElement(SUMO_TAG_INSTANT_INDUCTION_LOOP, element)) {
703
return false;
704
} else if (!checkValidDetectorID(SUMO_TAG_INSTANT_INDUCTION_LOOP, id)) {
705
return false;
706
} else {
707
// get lane
708
GNELane* lane = myNet->getAttributeCarriers()->retrieveLane(laneID, false);
709
// check lane
710
if (lane == nullptr) {
711
return writeErrorInvalidParent(SUMO_TAG_INSTANT_INDUCTION_LOOP, id, {SUMO_TAG_LANE}, laneID);
712
} else if (!checkFileName(SUMO_TAG_INSTANT_INDUCTION_LOOP, id, SUMO_ATTR_FILE, filename)) {
713
return false;
714
} else if (!checkLanePosition(pos, 0, lane->getParentEdge()->getNBEdge()->getFinalLength(), friendlyPos)) {
715
return writeErrorInvalidPosition(SUMO_TAG_INSTANT_INDUCTION_LOOP, id);
716
} else {
717
// build E1 instant
718
GNEAdditional* detectorE1Instant = new GNEInstantInductionLoopDetector(id, myNet, myFileBucket, lane, pos, filename, vehicleTypes, nextEdges,
719
detectPersons, name, friendlyPos, parameters);
720
// insert depending of allowUndoRedo
721
if (myAllowUndoRedo) {
722
myNet->getUndoList()->begin(detectorE1Instant, TL("add instant induction loop '") + id + "'");
723
myNet->getUndoList()->add(new GNEChange_Additional(detectorE1Instant, true), true);
724
myNet->getUndoList()->end();
725
} else {
726
myNet->getAttributeCarriers()->insertAdditional(detectorE1Instant);
727
lane->addChildElement(detectorE1Instant);
728
detectorE1Instant->incRef("buildDetectorE1Instant");
729
}
730
return true;
731
}
732
}
733
}
734
735
736
bool
737
GNEAdditionalHandler::buildLaneCalibrator(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& id, const std::string& laneID, const double pos,
738
const std::string& name, const std::string& outfile, const SUMOTime period, const std::string& routeprobeID, const double jamThreshold, const std::vector<std::string>& vTypes,
739
const Parameterised::Map& parameters) {
740
// get lane
741
GNELane* lane = myNet->getAttributeCarriers()->retrieveLane(laneID, false);
742
// get routeProbe
743
GNEAdditional* routeProbe = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_ROUTEPROBE, routeprobeID, false);
744
// check conditions
745
const auto element = retrieveAdditionalElement(NamespaceIDs::calibrators, id);
746
if (!checkElement(GNE_TAG_CALIBRATOR_LANE, element)) {
747
return false;
748
} else if (!checkValidAdditionalID(GNE_TAG_CALIBRATOR_LANE, id)) {
749
return false;
750
} else if ((routeprobeID.size() > 0) && (routeProbe == nullptr)) {
751
return writeErrorInvalidParent(GNE_TAG_CALIBRATOR_LANE, id, {SUMO_TAG_ROUTEPROBE}, routeprobeID);
752
} else if (lane == nullptr) {
753
return writeErrorInvalidParent(GNE_TAG_CALIBRATOR_LANE, id, {SUMO_TAG_LANE}, laneID);
754
} else {
755
// check lane
756
if (!checkLanePosition(pos, 0, lane->getParentEdge()->getNBEdge()->getFinalLength(), false)) {
757
return writeErrorInvalidPosition(GNE_TAG_CALIBRATOR_LANE, id);
758
} else if (!checkNegative(GNE_TAG_CALIBRATOR_LANE, id, SUMO_ATTR_PERIOD, period, true)) {
759
return false;
760
} else if (!checkNegative(GNE_TAG_CALIBRATOR_LANE, id, SUMO_ATTR_JAM_DIST_THRESHOLD, jamThreshold, true)) {
761
return false;
762
} else {
763
// build Calibrator
764
GNEAdditional* calibrator = (routeProbe == nullptr) ?
765
new GNECalibrator(id, myNet, myFileBucket, lane, pos, period, name, outfile, jamThreshold, vTypes, parameters) :
766
new GNECalibrator(id, myNet, myFileBucket, lane, pos, period, name, outfile, routeProbe, jamThreshold, vTypes, parameters);
767
// insert depending of allowUndoRedo
768
if (myAllowUndoRedo) {
769
myNet->getUndoList()->begin(calibrator, TL("add lane calibrator '") + id + "'");
770
myNet->getUndoList()->add(new GNEChange_Additional(calibrator, true), true);
771
myNet->getUndoList()->end();
772
// check if center after creation
773
if (sumoBaseObject->hasBoolAttribute(GNE_ATTR_CENTER_AFTER_CREATION) &&
774
sumoBaseObject->getBoolAttribute(GNE_ATTR_CENTER_AFTER_CREATION)) {
775
myNet->getViewNet()->centerTo(calibrator->getPositionInView(), false);
776
}
777
} else {
778
myNet->getAttributeCarriers()->insertAdditional(calibrator);
779
lane->addChildElement(calibrator);
780
if (routeProbe) {
781
routeProbe->addChildElement(calibrator);
782
}
783
calibrator->incRef("buildCalibrator");
784
}
785
return true;
786
}
787
}
788
}
789
790
791
bool
792
GNEAdditionalHandler::buildEdgeCalibrator(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& id, const std::string& edgeID, const double pos,
793
const std::string& name, const std::string& outfile, const SUMOTime period, const std::string& routeprobeID, const double jamThreshold, const std::vector<std::string>& vTypes,
794
const Parameterised::Map& parameters) {
795
// get edge
796
GNEEdge* edge = myNet->getAttributeCarriers()->retrieveEdge(edgeID, false);
797
// get routeProbe
798
GNEAdditional* routeProbe = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_ROUTEPROBE, routeprobeID, false);
799
// check conditions
800
const auto element = retrieveAdditionalElement(NamespaceIDs::calibrators, id);
801
if (!checkElement(SUMO_TAG_CALIBRATOR, element)) {
802
return false;
803
} else if (!checkValidAdditionalID(SUMO_TAG_CALIBRATOR, id)) {
804
return false;
805
} else if ((routeprobeID.size() > 0) && (routeProbe == nullptr)) {
806
return writeErrorInvalidParent(SUMO_TAG_CALIBRATOR, id, {SUMO_TAG_ROUTEPROBE}, routeprobeID);
807
} else if (edge == nullptr) {
808
return writeErrorInvalidParent(SUMO_TAG_CALIBRATOR, id, {SUMO_TAG_EDGE}, edgeID);
809
} else {
810
if (!checkLanePosition(pos, 0, edge->getChildLanes().front()->getParentEdge()->getNBEdge()->getFinalLength(), false)) {
811
return writeErrorInvalidPosition(SUMO_TAG_CALIBRATOR, id);
812
} else if (!checkNegative(SUMO_TAG_CALIBRATOR, id, SUMO_ATTR_PERIOD, period, true)) {
813
return false;
814
} else if (!checkNegative(SUMO_TAG_CALIBRATOR, id, SUMO_ATTR_JAM_DIST_THRESHOLD, jamThreshold, true)) {
815
return false;
816
} else {
817
// build Calibrator
818
GNEAdditional* calibrator = (routeProbe == nullptr) ?
819
new GNECalibrator(id, myNet, myFileBucket, edge, pos, period, name, outfile, jamThreshold, vTypes, parameters) :
820
new GNECalibrator(id, myNet, myFileBucket, edge, pos, period, name, outfile, routeProbe, jamThreshold, vTypes, parameters);
821
// insert depending of allowUndoRedo
822
if (myAllowUndoRedo) {
823
myNet->getUndoList()->begin(calibrator, TL("add calibrator '") + id + "'");
824
myNet->getUndoList()->add(new GNEChange_Additional(calibrator, true), true);
825
myNet->getUndoList()->end();
826
// check if center after creation
827
if (sumoBaseObject->hasBoolAttribute(GNE_ATTR_CENTER_AFTER_CREATION) &&
828
sumoBaseObject->getBoolAttribute(GNE_ATTR_CENTER_AFTER_CREATION)) {
829
myNet->getViewNet()->centerTo(calibrator->getPositionInView(), false);
830
}
831
} else {
832
myNet->getAttributeCarriers()->insertAdditional(calibrator);
833
edge->addChildElement(calibrator);
834
if (routeProbe) {
835
routeProbe->addChildElement(calibrator);
836
}
837
calibrator->incRef("buildCalibrator");
838
}
839
return true;
840
}
841
}
842
}
843
844
845
bool
846
GNEAdditionalHandler::buildCalibratorFlow(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const SUMOVehicleParameter& vehicleParameter) {
847
// get vType
848
GNEDemandElement* vType = myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_VTYPE, vehicleParameter.vtypeid.empty() ? DEFAULT_VTYPE_ID : vehicleParameter.vtypeid, false);
849
// get route
850
GNEDemandElement* route = myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_ROUTE, vehicleParameter.routeid, false);
851
// get calibrator parent
852
GNEAdditional* calibrator = myNet->getAttributeCarriers()->retrieveAdditional(sumoBaseObject->getParentSumoBaseObject()->getTag(), sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID), false);
853
// check parents
854
if (vType == nullptr) {
855
return writeErrorInvalidParent(SUMO_TAG_FLOW, "", {SUMO_TAG_VTYPE}, vehicleParameter.vtypeid);
856
} else if (route == nullptr) {
857
return writeErrorInvalidParent(SUMO_TAG_FLOW, "", {SUMO_TAG_ROUTE}, vehicleParameter.routeid);
858
} else if (calibrator == nullptr) {
859
return writeErrorInvalidParent(SUMO_TAG_FLOW, "", {SUMO_TAG_CALIBRATOR}, sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID));
860
} else {
861
// create calibrator flow
862
GNEAdditional* flow = new GNECalibratorFlow(calibrator, vType, route, vehicleParameter);
863
// insert depending of allowUndoRedo
864
if (myAllowUndoRedo) {
865
myNet->getUndoList()->begin(flow, TL("add calibrator flow in '") + calibrator->getID() + "'");
866
myNet->getUndoList()->add(new GNEChange_Additional(flow, true), true);
867
myNet->getUndoList()->end();
868
} else {
869
myNet->getAttributeCarriers()->insertAdditional(flow);
870
calibrator->addChildElement(flow);
871
route->addChildElement(flow);
872
vType->addChildElement(flow);
873
flow->incRef("buildCalibratorFlow");
874
}
875
return true;
876
}
877
}
878
879
880
bool
881
GNEAdditionalHandler::buildRerouter(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id, const Position& pos,
882
const std::vector<std::string>& edgeIDs, const double prob, const std::string& name,
883
const bool off, const bool optional, const SUMOTime timeThreshold,
884
const std::vector<std::string>& vTypes, const Parameterised::Map& parameters) {
885
// check conditions
886
const auto element = retrieveAdditionalElement({SUMO_TAG_REROUTER}, id);
887
if (!checkElement(SUMO_TAG_REROUTER, element)) {
888
return false;
889
} else if (!checkValidAdditionalID(SUMO_TAG_REROUTER, id)) {
890
return false;
891
} else if (!checkNegative(SUMO_TAG_REROUTER, id, SUMO_ATTR_PROB, prob, true)) {
892
return false;
893
} else if (!checkNegative(SUMO_TAG_REROUTER, id, SUMO_ATTR_HALTING_TIME_THRESHOLD, timeThreshold, true)) {
894
return false;
895
} else if (!checkListOfVehicleTypes(SUMO_TAG_REROUTER, id, vTypes)) {
896
return false;
897
} else {
898
// parse edges
899
std::vector<GNEEdge*> edges = parseEdges(SUMO_TAG_REROUTER, id, edgeIDs);
900
// check edges
901
if (edges.empty()) {
902
return false;
903
} else {
904
GNEAdditional* rerouter = nullptr;
905
// continue depending of position
906
if (pos == Position::INVALID) {
907
if (edges.size() > 0) {
908
PositionVector laneShape = edges.front()->getChildLanes().front()->getLaneShape();
909
// move to side
910
laneShape.move2side(3);
911
// create rerouter
912
rerouter = new GNERerouter(id, myNet, myFileBucket, laneShape.positionAtOffset2D(laneShape.length2D() - 6), name, prob, off, optional, timeThreshold, vTypes, parameters);
913
} else {
914
rerouter = new GNERerouter(id, myNet, myFileBucket, Position(0, 0), name, prob, off, optional, timeThreshold, vTypes, parameters);
915
}
916
} else {
917
rerouter = new GNERerouter(id, myNet, myFileBucket, pos, name, prob, off, optional, timeThreshold, vTypes, parameters);
918
}
919
// create rerouter Symbols
920
std::vector<GNEAdditional*> rerouterSymbols;
921
for (const auto& edge : edges) {
922
rerouterSymbols.push_back(new GNERerouterSymbol(rerouter, edge));
923
}
924
// insert depending of allowUndoRedo
925
if (myAllowUndoRedo) {
926
myNet->getUndoList()->begin(rerouter, TL("add rerouter '") + id + "'");
927
myNet->getUndoList()->add(new GNEChange_Additional(rerouter, true), true);
928
// add symbols
929
for (const auto& rerouterSymbol : rerouterSymbols) {
930
myNet->getUndoList()->add(new GNEChange_Additional(rerouterSymbol, true), true);
931
}
932
myNet->getUndoList()->end();
933
} else {
934
myNet->getAttributeCarriers()->insertAdditional(rerouter);
935
rerouter->incRef("buildRerouter");
936
// add symbols into rerouter
937
for (const auto& rerouterSymbol : rerouterSymbols) {
938
rerouter->addChildElement(rerouterSymbol);
939
}
940
// add symbols into edges
941
for (int i = 0; i < (int)edges.size(); i++) {
942
edges.at(i)->addChildElement(rerouterSymbols.at(i));
943
}
944
}
945
return true;
946
}
947
}
948
}
949
950
951
bool
952
GNEAdditionalHandler::buildRerouterInterval(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const SUMOTime begin, const SUMOTime end) {
953
// get rerouter parent
954
GNEAdditional* rerouter = getAdditionalParent(sumoBaseObject, SUMO_TAG_REROUTER);
955
// check if rerouter exist
956
if (rerouter == nullptr) {
957
return writeErrorInvalidParent(SUMO_TAG_INTERVAL, "", {SUMO_TAG_REROUTER}, sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID));
958
} else if (!checkNegative(SUMO_TAG_INTERVAL, rerouter->getID(), SUMO_ATTR_BEGIN, begin, true)) {
959
return false;
960
} else if (!checkNegative(SUMO_TAG_INTERVAL, rerouter->getID(), SUMO_ATTR_END, end, true)) {
961
return false;
962
} else if (end < begin) {
963
return writeError(TLF("Could not build interval with ID '%' in netedit; begin is greater than end.", rerouter->getID()));
964
} else {
965
// check if new interval will produce a overlapping
966
if (checkOverlappingRerouterIntervals(rerouter, begin, end)) {
967
// create rerouter interval and add it into rerouter parent
968
GNEAdditional* rerouterInterval = new GNERerouterInterval(rerouter, begin, end);
969
// insert depending of allowUndoRedo
970
if (myAllowUndoRedo) {
971
myNet->getUndoList()->begin(rerouterInterval, TL("add rerouter interval in '") + rerouter->getID() + "'");
972
myNet->getUndoList()->add(new GNEChange_Additional(rerouterInterval, true), true);
973
myNet->getUndoList()->end();
974
} else {
975
rerouter->addChildElement(rerouterInterval);
976
rerouterInterval->incRef("buildRerouterInterval");
977
}
978
} else {
979
return writeError(TLF("Could not build interval with begin '%' and end '%' in '%' due overlapping.", toString(begin), toString(end), rerouter->getID()));
980
}
981
// update centering boundary of rerouter parent
982
rerouter->updateCenteringBoundary(true);
983
return true;
984
}
985
}
986
987
988
bool
989
GNEAdditionalHandler::buildClosingLaneReroute(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& closedLaneID, SVCPermissions permissions) {
990
// get rerouter interval parent
991
GNEAdditional* rerouterInterval = getRerouterIntervalParent(sumoBaseObject);
992
// get closed lane
993
GNELane* lane = myNet->getAttributeCarriers()->retrieveLane(closedLaneID, false);
994
// check parents
995
if (lane == nullptr) {
996
return writeErrorInvalidParent(SUMO_TAG_CLOSING_LANE_REROUTE, "", {SUMO_TAG_LANE}, closedLaneID);
997
} else if (rerouterInterval == nullptr) {
998
return writeErrorInvalidParent(SUMO_TAG_CLOSING_LANE_REROUTE, "", {SUMO_TAG_INTERVAL}, "");
999
} else {
1000
// create closing lane reroute
1001
GNEAdditional* closingLaneReroute = new GNEClosingLaneReroute(rerouterInterval, lane, permissions);
1002
// add it to interval parent depending of allowUndoRedo
1003
if (myAllowUndoRedo) {
1004
myNet->getUndoList()->begin(closingLaneReroute, TL("add closing lane reroute in '") + lane->getID() + "'");
1005
myNet->getUndoList()->add(new GNEChange_Additional(closingLaneReroute, true), true);
1006
myNet->getUndoList()->end();
1007
} else {
1008
rerouterInterval->addChildElement(closingLaneReroute);
1009
closingLaneReroute->incRef("buildClosingLaneReroute");
1010
}
1011
// update centering boundary of rerouter parent
1012
rerouterInterval->getParentAdditionals().front()->updateCenteringBoundary(true);
1013
return true;
1014
}
1015
}
1016
1017
1018
bool
1019
GNEAdditionalHandler::buildClosingReroute(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& closedEdgeID, SVCPermissions permissions) {
1020
// get rerouter interval parent
1021
GNEAdditional* rerouterInterval = getRerouterIntervalParent(sumoBaseObject);
1022
// get closed edge
1023
GNEEdge* edge = myNet->getAttributeCarriers()->retrieveEdge(closedEdgeID, false);
1024
// check parents
1025
if (edge == nullptr) {
1026
return writeErrorInvalidParent(SUMO_TAG_CLOSING_REROUTE, "", {SUMO_TAG_EDGE}, closedEdgeID);
1027
} else if (rerouterInterval == nullptr) {
1028
return writeErrorInvalidParent(SUMO_TAG_CLOSING_REROUTE, "", {SUMO_TAG_INTERVAL}, "");
1029
} else {
1030
// create closing reroute
1031
GNEAdditional* closingLaneReroute = new GNEClosingReroute(rerouterInterval, edge, permissions);
1032
// add it to interval parent depending of allowUndoRedo
1033
if (myAllowUndoRedo) {
1034
myNet->getUndoList()->begin(closingLaneReroute, TL("add closing reroute in '") + edge->getID() + "'");
1035
myNet->getUndoList()->add(new GNEChange_Additional(closingLaneReroute, true), true);
1036
myNet->getUndoList()->end();
1037
} else {
1038
rerouterInterval->addChildElement(closingLaneReroute);
1039
closingLaneReroute->incRef("buildClosingLaneReroute");
1040
}
1041
// update centering boundary of rerouter parent
1042
rerouterInterval->getParentAdditionals().front()->updateCenteringBoundary(true);
1043
return true;
1044
}
1045
}
1046
1047
bool
1048
GNEAdditionalHandler::buildDestProbReroute(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& newEdgeDestinationID, const double probability) {
1049
// get rerouter interval parent
1050
GNEAdditional* rerouterInterval = getRerouterIntervalParent(sumoBaseObject);
1051
// get edge
1052
GNEEdge* edge = myNet->getAttributeCarriers()->retrieveEdge(newEdgeDestinationID, false);
1053
// check parents
1054
if (edge == nullptr) {
1055
return writeErrorInvalidParent(SUMO_TAG_DEST_PROB_REROUTE, "", {SUMO_TAG_EDGE}, newEdgeDestinationID);
1056
} else if (rerouterInterval == nullptr) {
1057
return writeErrorInvalidParent(SUMO_TAG_DEST_PROB_REROUTE, "", {SUMO_TAG_INTERVAL}, "");
1058
} else {
1059
// create dest probability reroute
1060
GNEAdditional* destProbReroute = new GNEDestProbReroute(rerouterInterval, edge, probability);
1061
// add it to interval parent depending of allowUndoRedo
1062
if (myAllowUndoRedo) {
1063
myNet->getUndoList()->begin(destProbReroute, TL("add dest prob reroute in '") + edge->getID() + "'");
1064
myNet->getUndoList()->add(new GNEChange_Additional(destProbReroute, true), true);
1065
myNet->getUndoList()->end();
1066
} else {
1067
rerouterInterval->addChildElement(destProbReroute);
1068
destProbReroute->incRef("builDestProbReroute");
1069
}
1070
// update centering boundary of rerouter parent
1071
rerouterInterval->getParentAdditionals().front()->updateCenteringBoundary(true);
1072
return true;
1073
}
1074
}
1075
1076
1077
bool
1078
GNEAdditionalHandler::buildParkingAreaReroute(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& newParkignAreaID, const double probability, const bool visible) {
1079
// get rerouter interval parent
1080
GNEAdditional* rerouterInterval = getRerouterIntervalParent(sumoBaseObject);
1081
// get parking area
1082
GNEAdditional* parkingArea = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_PARKING_AREA, newParkignAreaID, false);
1083
// check parents
1084
if (parkingArea == nullptr) {
1085
return writeErrorInvalidParent(SUMO_TAG_PARKING_AREA_REROUTE, "", {SUMO_TAG_PARKING_AREA}, newParkignAreaID);
1086
} else if (rerouterInterval == nullptr) {
1087
return writeErrorInvalidParent(SUMO_TAG_PARKING_AREA_REROUTE, "", {SUMO_TAG_INTERVAL}, "");
1088
} else {
1089
// create parking area reroute
1090
GNEAdditional* parkingAreaReroute = new GNEParkingAreaReroute(rerouterInterval, parkingArea, probability, visible);
1091
// add it to interval parent depending of allowUndoRedo
1092
if (myAllowUndoRedo) {
1093
myNet->getUndoList()->begin(parkingAreaReroute, TL("add parking area reroute in '") + parkingArea->getID() + "'");
1094
myNet->getUndoList()->add(new GNEChange_Additional(parkingAreaReroute, true), true);
1095
myNet->getUndoList()->end();
1096
} else {
1097
rerouterInterval->addChildElement(parkingAreaReroute);
1098
parkingAreaReroute->incRef("builParkingAreaReroute");
1099
}
1100
// update centering boundary of rerouter parent
1101
rerouterInterval->getParentAdditionals().front()->updateCenteringBoundary(true);
1102
return true;
1103
}
1104
}
1105
1106
1107
bool
1108
GNEAdditionalHandler::buildRouteProbReroute(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& newRouteID, const double probability) {
1109
// get rerouter interval parent
1110
GNEAdditional* rerouterInterval = getRerouterIntervalParent(sumoBaseObject);
1111
// get route parent
1112
GNEDemandElement* route = myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_ROUTE, newRouteID, false);
1113
// check parents
1114
if (route == nullptr) {
1115
return writeErrorInvalidParent(SUMO_TAG_ROUTE_PROB_REROUTE, "", {SUMO_TAG_ROUTE}, newRouteID);
1116
} else if (rerouterInterval == nullptr) {
1117
return writeErrorInvalidParent(SUMO_TAG_ROUTE_PROB_REROUTE, "", {SUMO_TAG_INTERVAL}, "");
1118
} else {
1119
// create rout prob reroute
1120
GNEAdditional* routeProbReroute = new GNERouteProbReroute(rerouterInterval, route, probability);
1121
// add it to interval parent depending of allowUndoRedo
1122
if (myAllowUndoRedo) {
1123
myNet->getUndoList()->begin(routeProbReroute, TL("add route prob reroute in '") + route->getID() + "'");
1124
myNet->getUndoList()->add(new GNEChange_Additional(routeProbReroute, true), true);
1125
myNet->getUndoList()->end();
1126
} else {
1127
rerouterInterval->addChildElement(routeProbReroute);
1128
routeProbReroute->incRef("buildRouteProbReroute");
1129
}
1130
// update centering boundary of rerouter parent
1131
rerouterInterval->getParentAdditionals().front()->updateCenteringBoundary(true);
1132
return true;
1133
}
1134
}
1135
1136
1137
bool
1138
GNEAdditionalHandler::buildRouteProbe(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& id, const std::string& edgeID, const SUMOTime period,
1139
const std::string& name, const std::string& file, const SUMOTime begin, const std::vector<std::string>& vTypes,
1140
const Parameterised::Map& parameters) {
1141
// check conditions
1142
const auto element = retrieveAdditionalElement({SUMO_TAG_ROUTEPROBE}, id);
1143
if (!checkElement(SUMO_TAG_ROUTEPROBE, element)) {
1144
return false;
1145
} else if (!checkValidAdditionalID(SUMO_TAG_ROUTEPROBE, id)) {
1146
return false;
1147
} else {
1148
// get edge
1149
GNEEdge* edge = myNet->getAttributeCarriers()->retrieveEdge(edgeID, false);
1150
// check lane
1151
if (edge == nullptr) {
1152
return writeErrorInvalidParent(SUMO_TAG_ROUTEPROBE, id, {SUMO_TAG_EDGE}, edgeID);
1153
} else if (!checkNegative(SUMO_TAG_ROUTEPROBE, id, SUMO_ATTR_PERIOD, period, true)) {
1154
return false;
1155
} else if (!checkNegative(SUMO_TAG_ROUTEPROBE, id, SUMO_ATTR_BEGIN, begin, true)) {
1156
return false;
1157
} else if (!checkFileName(SUMO_TAG_ROUTEPROBE, id, SUMO_ATTR_FILE, file)) {
1158
return false;
1159
} else {
1160
// build route probe
1161
GNEAdditional* routeProbe = new GNERouteProbe(id, myNet, myFileBucket, edge, period, name, file, begin, vTypes, parameters);
1162
// insert depending of allowUndoRedo
1163
if (myAllowUndoRedo) {
1164
myNet->getUndoList()->begin(routeProbe, TL("add route probe '") + id + "'");
1165
myNet->getUndoList()->add(new GNEChange_Additional(routeProbe, true), true);
1166
myNet->getUndoList()->end();
1167
// check if center after creation
1168
if (sumoBaseObject->hasBoolAttribute(GNE_ATTR_CENTER_AFTER_CREATION) &&
1169
sumoBaseObject->getBoolAttribute(GNE_ATTR_CENTER_AFTER_CREATION)) {
1170
myNet->getViewNet()->centerTo(routeProbe->getPositionInView(), false);
1171
}
1172
} else {
1173
myNet->getAttributeCarriers()->insertAdditional(routeProbe);
1174
edge->addChildElement(routeProbe);
1175
routeProbe->incRef("buildRouteProbe");
1176
}
1177
return true;
1178
}
1179
}
1180
}
1181
1182
1183
bool
1184
GNEAdditionalHandler::buildVariableSpeedSign(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id, const Position& pos,
1185
const std::vector<std::string>& laneIDs, const std::string& name, const std::vector<std::string>& vTypes, const Parameterised::Map& parameters) {
1186
// check conditions
1187
const auto element = retrieveAdditionalElement({SUMO_TAG_VSS}, id);
1188
if (!checkElement(SUMO_TAG_VSS, element)) {
1189
return false;
1190
} else if (!checkValidAdditionalID(SUMO_TAG_VSS, id)) {
1191
return false;
1192
} else {
1193
// parse lanes
1194
std::vector<GNELane*> lanes = parseLanes(SUMO_TAG_VSS, id, laneIDs);
1195
// check lane
1196
if (lanes.empty()) {
1197
return false;
1198
} else {
1199
// check vTypes
1200
if (!checkListOfVehicleTypes(SUMO_TAG_VSS, id, vTypes)) {
1201
return false;
1202
} else {
1203
// create VSS
1204
GNEAdditional* variableSpeedSign = new GNEVariableSpeedSign(id, myNet, myFileBucket, pos, name, vTypes, parameters);
1205
// create VSS Symbols
1206
std::vector<GNEAdditional*> VSSSymbols;
1207
for (const auto& lane : lanes) {
1208
VSSSymbols.push_back(new GNEVariableSpeedSignSymbol(variableSpeedSign, lane));
1209
}
1210
// insert depending of allowUndoRedo
1211
if (myAllowUndoRedo) {
1212
myNet->getUndoList()->begin(variableSpeedSign, TL("add Variable Speed Sign '") + id + "'");
1213
myNet->getUndoList()->add(new GNEChange_Additional(variableSpeedSign, true), true);
1214
for (const auto& VSSSymbol : VSSSymbols) {
1215
myNet->getUndoList()->add(new GNEChange_Additional(VSSSymbol, true), true);
1216
}
1217
myNet->getUndoList()->end();
1218
} else {
1219
myNet->getAttributeCarriers()->insertAdditional(variableSpeedSign);
1220
variableSpeedSign->incRef("buildVariableSpeedSign");
1221
// add symbols into VSS
1222
for (const auto& VSSSymbol : VSSSymbols) {
1223
variableSpeedSign->addChildElement(VSSSymbol);
1224
}
1225
// add symbols into lanes
1226
for (int i = 0; i < (int)lanes.size(); i++) {
1227
lanes.at(i)->addChildElement(VSSSymbols.at(i));
1228
}
1229
}
1230
}
1231
return true;
1232
}
1233
}
1234
}
1235
1236
1237
bool
1238
GNEAdditionalHandler::buildVariableSpeedSignStep(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const SUMOTime time, const double speed) {
1239
// get VSS parent
1240
GNEAdditional* VSS = getAdditionalParent(sumoBaseObject, SUMO_TAG_VSS);
1241
// check lane
1242
if (VSS == nullptr) {
1243
return writeErrorInvalidParent(SUMO_TAG_STEP, "", {SUMO_TAG_VSS}, sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID));
1244
} else if (!checkNegative(SUMO_TAG_STEP, VSS->getID(), SUMO_ATTR_TIME, time, true)) {
1245
return false;
1246
} else {
1247
// create Variable Speed Sign
1248
GNEAdditional* variableSpeedSignStep = new GNEVariableSpeedSignStep(VSS, time, speed);
1249
// add it depending of allow undoRedo
1250
if (myAllowUndoRedo) {
1251
myNet->getUndoList()->begin(variableSpeedSignStep, TL("add VSS Step in '") + VSS->getID() + "'");
1252
myNet->getUndoList()->add(new GNEChange_Additional(variableSpeedSignStep, true), true);
1253
myNet->getUndoList()->end();
1254
} else {
1255
VSS->addChildElement(variableSpeedSignStep);
1256
variableSpeedSignStep->incRef("buildVariableSpeedSignStep");
1257
}
1258
// update centering boundary of VSS parent
1259
VSS->updateCenteringBoundary(true);
1260
return true;
1261
}
1262
}
1263
1264
1265
bool
1266
GNEAdditionalHandler::buildVaporizer(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& edgeID, const SUMOTime beginTime,
1267
const SUMOTime endTime, const std::string& name, const Parameterised::Map& parameters) {
1268
// check conditions
1269
const auto element = retrieveAdditionalElement({SUMO_TAG_VAPORIZER}, edgeID);
1270
if (!checkElement(SUMO_TAG_VAPORIZER, element)) {
1271
return false;
1272
} else if (!checkValidAdditionalID(SUMO_TAG_VAPORIZER, edgeID)) {
1273
return false;
1274
} else {
1275
// get edge
1276
GNEEdge* edge = myNet->getAttributeCarriers()->retrieveEdge(edgeID, false);
1277
// check lane
1278
if (edge == nullptr) {
1279
return writeErrorInvalidParent(SUMO_TAG_VAPORIZER, "", {SUMO_TAG_EDGE}, edgeID);
1280
} else if (!checkNegative(SUMO_TAG_VAPORIZER, edge->getID(), SUMO_ATTR_BEGIN, beginTime, true)) {
1281
return false;
1282
} else if (!checkNegative(SUMO_TAG_VAPORIZER, edge->getID(), SUMO_ATTR_END, endTime, true)) {
1283
return false;
1284
} else if (endTime < beginTime) {
1285
return writeError(TLF("Could not build Vaporizer with ID '%' in netedit; begin is greater than end.", edge->getID()));
1286
} else {
1287
// build vaporizer
1288
GNEAdditional* vaporizer = new GNEVaporizer(myNet, myFileBucket, edge, beginTime, endTime, name, parameters);
1289
// add it depending of allow undoRed
1290
if (myAllowUndoRedo) {
1291
myNet->getUndoList()->begin(vaporizer, TL("add vaporizer in '") + edge->getID() + "'");
1292
myNet->getUndoList()->add(new GNEChange_Additional(vaporizer, true), true);
1293
myNet->getUndoList()->end();
1294
// check if center after creation
1295
if (sumoBaseObject->hasBoolAttribute(GNE_ATTR_CENTER_AFTER_CREATION) &&
1296
sumoBaseObject->getBoolAttribute(GNE_ATTR_CENTER_AFTER_CREATION)) {
1297
myNet->getViewNet()->centerTo(vaporizer->getPositionInView(), false);
1298
}
1299
} else {
1300
myNet->getAttributeCarriers()->insertAdditional(vaporizer);
1301
edge->addChildElement(vaporizer);
1302
vaporizer->incRef("buildVaporizer");
1303
}
1304
return true;
1305
}
1306
}
1307
}
1308
1309
1310
bool
1311
GNEAdditionalHandler::buildTAZ(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& id, const PositionVector& shape,
1312
const Position& center, const bool fill, const RGBColor& color, const std::vector<std::string>& edgeIDs,
1313
const std::string& name, const Parameterised::Map& parameters) {
1314
// parse edges
1315
const std::vector<GNEEdge*> edges = parseEdges(SUMO_TAG_TAZ, id, edgeIDs);
1316
if (edges.size() != edgeIDs.size()) {
1317
return false;
1318
} else {
1319
// check TAZShape
1320
PositionVector TAZShape = shape;
1321
if (TAZShape.size() == 0) {
1322
// declare boundary
1323
Boundary TAZBoundary;
1324
for (const auto& edge : edges) {
1325
TAZBoundary.add(edge->getCenteringBoundary());
1326
}
1327
// iterate over children and add sourceSinkEdge boundaries to make a taz shape
1328
for (const auto& sourceSink : sumoBaseObject->getSumoBaseObjectChildren()) {
1329
// check that child is a source or sink elements (to avoid other elements)
1330
if ((sourceSink->getTag() == SUMO_TAG_TAZSOURCE) || (sourceSink->getTag() == SUMO_TAG_TAZSINK)) {
1331
const GNEEdge* sourceSinkEdge = myNet->getAttributeCarriers()->retrieveEdge(sourceSink->getStringAttribute(SUMO_ATTR_ID), false);
1332
if (sourceSinkEdge) {
1333
TAZBoundary.add(sourceSinkEdge->getCenteringBoundary());
1334
}
1335
}
1336
}
1337
// update TAZShape
1338
TAZShape = TAZBoundary.getShape(true);
1339
}
1340
// check TAZ
1341
const auto element = retrieveAdditionalElement({SUMO_TAG_TAZ}, id);
1342
if (!checkElement(SUMO_TAG_TAZ, element)) {
1343
return false;
1344
} else if (!checkValidAdditionalID(SUMO_TAG_TAZ, id)) {
1345
return false;
1346
} else if (TAZShape.size() == 0) {
1347
return writeError(TLF("Could not build TAZ with ID '%' in netedit; Invalid Shape.", id));
1348
} else {
1349
// build TAZ with the given shape
1350
const Position center2 = center == Position::INVALID ? TAZShape.getCentroid() : center;
1351
GNEAdditional* TAZ = new GNETAZ(id, myNet, myFileBucket, TAZShape, center2, fill, color, name, parameters);
1352
// disable updating geometry of TAZ children during insertion (because in large nets provokes slowdowns)
1353
myNet->disableUpdateGeometry();
1354
// add it depending of allow undoRed
1355
if (myAllowUndoRedo) {
1356
myNet->getUndoList()->begin(TAZ, TL("add TAZ '") + id + "'");
1357
myNet->getUndoList()->add(new GNEChange_Additional(TAZ, true), true);
1358
// create TAZEdges
1359
for (const auto& edge : edges) {
1360
// create TAZ Source using GNEChange_Additional
1361
GNETAZSourceSink* TAZSource = new GNETAZSourceSink(SUMO_TAG_TAZSOURCE, TAZ, edge, 1);
1362
myNet->getUndoList()->add(new GNEChange_TAZSourceSink(TAZSource, true), true);
1363
// create TAZ Sink using GNEChange_Additional
1364
GNETAZSourceSink* TAZSink = new GNETAZSourceSink(SUMO_TAG_TAZSINK, TAZ, edge, 1);
1365
myNet->getUndoList()->add(new GNEChange_TAZSourceSink(TAZSink, true), true);
1366
}
1367
myNet->getUndoList()->end();
1368
} else {
1369
myNet->getAttributeCarriers()->insertAdditional(TAZ);
1370
TAZ->incRef("buildTAZ");
1371
for (const auto& edge : edges) {
1372
// create TAZ Source
1373
GNETAZSourceSink* TAZSource = new GNETAZSourceSink(SUMO_TAG_TAZSOURCE, TAZ, edge, 1);
1374
myNet->getAttributeCarriers()->insertTAZSourceSink(TAZSource);
1375
TAZSource->incRef("buildTAZ");
1376
TAZ->addChildElement(TAZSource);
1377
edge->addChildElement(TAZSource);
1378
// create TAZ Sink
1379
GNETAZSourceSink* TAZSink = new GNETAZSourceSink(SUMO_TAG_TAZSINK, TAZ, edge, 1);
1380
myNet->getAttributeCarriers()->insertTAZSourceSink(TAZSink);
1381
TAZSink->incRef("buildTAZ");
1382
TAZ->addChildElement(TAZSink);
1383
edge->addChildElement(TAZSink);
1384
}
1385
}
1386
// enable updating geometry again and update geometry of TAZ
1387
myNet->enableUpdateGeometry();
1388
// update TAZ parent
1389
TAZ->updateGeometry();
1390
return true;
1391
}
1392
}
1393
}
1394
1395
1396
bool
1397
GNEAdditionalHandler::buildTAZSource(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& edgeID, const double departWeight) {
1398
// get TAZ parent
1399
GNEAdditional* TAZ = getAdditionalParent(sumoBaseObject, SUMO_TAG_TAZ);
1400
// get edge
1401
GNEEdge* edge = myNet->getAttributeCarriers()->retrieveEdge(edgeID, false);
1402
// check parents
1403
if (TAZ == nullptr) {
1404
return writeErrorInvalidParent(SUMO_TAG_SOURCE, edgeID, {SUMO_TAG_TAZ}, sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID));
1405
} else if (edge == nullptr) {
1406
return writeErrorInvalidParent(SUMO_TAG_SOURCE, edgeID, {SUMO_TAG_EDGE}, TAZ->getID());
1407
} else {
1408
// declare TAZ Source
1409
GNETAZSourceSink* existentTAZSource = nullptr;
1410
// first check if already exist a TAZ Source for the given edge and TAZ
1411
for (auto it = edge->getChildTAZSourceSinks().begin(); (it != edge->getChildTAZSourceSinks().end()) && !existentTAZSource; it++) {
1412
if (((*it)->getTagProperty()->getTag() == SUMO_TAG_TAZSOURCE) && ((*it)->getParentAdditionals().front() == TAZ)) {
1413
existentTAZSource = (*it);
1414
}
1415
}
1416
// check if TAZSource has to be created
1417
if (existentTAZSource == nullptr) {
1418
// Create TAZ only with departWeight
1419
GNETAZSourceSink* TAZSource = new GNETAZSourceSink(SUMO_TAG_TAZSOURCE, TAZ, edge, departWeight);
1420
// add it depending of allow undoRed
1421
if (myAllowUndoRedo) {
1422
myNet->getUndoList()->begin(TAZ, TL("add TAZ Source in '") + TAZ->getID() + "'");
1423
myNet->getUndoList()->add(new GNEChange_TAZSourceSink(TAZSource, true), true);
1424
myNet->getUndoList()->end();
1425
} else {
1426
myNet->getAttributeCarriers()->insertTAZSourceSink(TAZSource);
1427
TAZ->addChildElement(TAZSource);
1428
edge->addChildElement(TAZSource);
1429
TAZSource->incRef("buildTAZSource");
1430
}
1431
} else {
1432
// update TAZ Attribute depending of allow undoRed
1433
if (myAllowUndoRedo) {
1434
myNet->getUndoList()->begin(TAZ, TL("update TAZ Source in '") + TAZ->getID() + "'");
1435
existentTAZSource->setAttribute(SUMO_ATTR_WEIGHT, toString(departWeight), myNet->getUndoList());
1436
myNet->getUndoList()->end();
1437
} else {
1438
existentTAZSource->setAttribute(SUMO_ATTR_WEIGHT, toString(departWeight), nullptr);
1439
}
1440
}
1441
return true;
1442
}
1443
}
1444
1445
1446
bool
1447
GNEAdditionalHandler::buildTAZSink(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& edgeID, const double arrivalWeight) {
1448
// get TAZ parent
1449
GNEAdditional* TAZ = getAdditionalParent(sumoBaseObject, SUMO_TAG_TAZ);
1450
// get edge
1451
GNEEdge* edge = myNet->getAttributeCarriers()->retrieveEdge(edgeID, false);
1452
// check parents
1453
if (TAZ == nullptr) {
1454
return writeErrorInvalidParent(SUMO_TAG_SOURCE, edgeID, {SUMO_TAG_TAZ}, sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID));
1455
} else if (edge == nullptr) {
1456
return writeErrorInvalidParent(SUMO_TAG_SOURCE, edgeID, {SUMO_TAG_EDGE}, TAZ->getID());
1457
} else {
1458
// declare TAZ Sink
1459
GNETAZSourceSink* existentTAZSink = nullptr;
1460
// first check if already exist a TAZ Sink for the given edge and TAZ
1461
for (auto it = edge->getChildTAZSourceSinks().begin(); (it != edge->getChildTAZSourceSinks().end()) && !existentTAZSink; it++) {
1462
if (((*it)->getTagProperty()->getTag() == SUMO_TAG_TAZSINK) && ((*it)->getParentAdditionals().front() == TAZ)) {
1463
existentTAZSink = (*it);
1464
}
1465
}
1466
// check if TAZSink has to be created
1467
if (existentTAZSink == nullptr) {
1468
// Create TAZ only with departWeight
1469
GNETAZSourceSink* TAZSink = new GNETAZSourceSink(SUMO_TAG_TAZSINK, TAZ, edge, arrivalWeight);
1470
// add it depending of allow undoRed
1471
if (myAllowUndoRedo) {
1472
myNet->getUndoList()->begin(TAZ, TL("add TAZ Sink in '") + TAZ->getID() + "'");
1473
myNet->getUndoList()->add(new GNEChange_TAZSourceSink(TAZSink, true), true);
1474
myNet->getUndoList()->end();
1475
} else {
1476
myNet->getAttributeCarriers()->insertTAZSourceSink(TAZSink);
1477
TAZ->addChildElement(TAZSink);
1478
edge->addChildElement(TAZSink);
1479
TAZSink->incRef("buildTAZSink");
1480
}
1481
} else {
1482
// update TAZ Attribute depending of allow undoRed
1483
if (myAllowUndoRedo) {
1484
myNet->getUndoList()->begin(TAZ, TL("update TAZ Sink in '") + TAZ->getID() + "'");
1485
existentTAZSink->setAttribute(SUMO_ATTR_WEIGHT, toString(arrivalWeight), myNet->getUndoList());
1486
myNet->getUndoList()->end();
1487
} else {
1488
existentTAZSink->setAttribute(SUMO_ATTR_WEIGHT, toString(arrivalWeight), nullptr);
1489
}
1490
}
1491
return true;
1492
}
1493
}
1494
1495
1496
bool
1497
GNEAdditionalHandler::buildTractionSubstation(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id, const Position& pos,
1498
const double voltage, const double currentLimit, const Parameterised::Map& parameters) {
1499
// check conditions
1500
const auto element = retrieveAdditionalElement({SUMO_TAG_TRACTION_SUBSTATION}, id);
1501
if (!checkElement(SUMO_TAG_TRACTION_SUBSTATION, element)) {
1502
return false;
1503
} else if (!checkValidAdditionalID(SUMO_TAG_TRACTION_SUBSTATION, id)) {
1504
return false;
1505
} else if (!checkNegative(SUMO_TAG_TRACTION_SUBSTATION, id, SUMO_ATTR_VOLTAGE, voltage, true)) {
1506
return false;
1507
} else if (!checkNegative(SUMO_TAG_TRACTION_SUBSTATION, id, SUMO_ATTR_CURRENTLIMIT, currentLimit, true)) {
1508
return false;
1509
} else {
1510
// build traction substation
1511
GNEAdditional* tractionSubstation = new GNETractionSubstation(id, myNet, myFileBucket, pos, voltage, currentLimit, parameters);
1512
// insert depending of allowUndoRedo
1513
if (myAllowUndoRedo) {
1514
myNet->getUndoList()->begin(tractionSubstation, TL("add traction substation '") + id + "'");
1515
myNet->getUndoList()->add(new GNEChange_Additional(tractionSubstation, true), true);
1516
myNet->getUndoList()->end();
1517
} else {
1518
myNet->getAttributeCarriers()->insertAdditional(tractionSubstation);
1519
tractionSubstation->incRef("buildTractionSubstation");
1520
}
1521
return true;
1522
}
1523
}
1524
1525
1526
bool
1527
GNEAdditionalHandler::buildOverheadWire(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id, const std::string& substationId,
1528
const std::vector<std::string>& laneIDs, const double startPos, const double endPos, const bool friendlyPos,
1529
const std::vector<std::string>& forbiddenInnerLanes, const Parameterised::Map& parameters) {
1530
// check conditions
1531
const auto element = retrieveAdditionalElement({SUMO_TAG_OVERHEAD_WIRE_SECTION}, id);
1532
if (!checkElement(SUMO_TAG_OVERHEAD_WIRE_SECTION, element)) {
1533
return false;
1534
} else if (!checkValidAdditionalID(SUMO_TAG_OVERHEAD_WIRE_SECTION, id)) {
1535
return false;
1536
} else {
1537
// get lanes
1538
const auto lanes = parseLanes(SUMO_TAG_OVERHEAD_WIRE_SECTION, id, laneIDs);
1539
// get traction substation
1540
const auto tractionSubstation = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_TRACTION_SUBSTATION, substationId, false);
1541
// check lanes
1542
if (lanes.empty()) {
1543
return false;
1544
} else {
1545
// calculate path
1546
if (!GNEAdditional::areLaneConsecutives(lanes)) {
1547
return writeError(TLF("Could not build overhead wire with ID '%' in netedit; Lanes aren't consecutives.", id));
1548
} else if (!checkMultiLanePosition(
1549
startPos, lanes.front()->getParentEdge()->getNBEdge()->getFinalLength(),
1550
endPos, lanes.back()->getParentEdge()->getNBEdge()->getFinalLength(), friendlyPos)) {
1551
return writeErrorInvalidPosition(SUMO_TAG_OVERHEAD_WIRE_SECTION, id);
1552
} else if (tractionSubstation == nullptr) {
1553
return writeErrorInvalidParent(SUMO_TAG_OVERHEAD_WIRE_SECTION, "", {SUMO_TAG_TRACTION_SUBSTATION}, substationId);
1554
} else {
1555
// build Overhead Wire
1556
GNEAdditional* overheadWire = new GNEOverheadWire(id, myNet, myFileBucket, lanes, tractionSubstation, startPos, endPos, friendlyPos, forbiddenInnerLanes, parameters);
1557
// insert depending of allowUndoRedo
1558
if (myAllowUndoRedo) {
1559
myNet->getUndoList()->begin(overheadWire, TL("add overhead wire '") + id + "'");
1560
myNet->getUndoList()->add(new GNEChange_Additional(overheadWire, true), true);
1561
myNet->getUndoList()->end();
1562
} else {
1563
myNet->getAttributeCarriers()->insertAdditional(overheadWire);
1564
for (const auto& lane : lanes) {
1565
lane->addChildElement(overheadWire);
1566
}
1567
overheadWire->incRef("buildOverheadWire");
1568
}
1569
}
1570
return true;
1571
}
1572
}
1573
}
1574
1575
1576
bool
1577
GNEAdditionalHandler::buildOverheadWireClamp(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& /* id */, const std::string& /* overheadWireIDStartClamp */,
1578
const std::string& /* laneIDStartClamp */, const std::string& /* overheadWireIDEndClamp */, const std::string& /* laneIDEndClamp */,
1579
const Parameterised::Map& /* parameters */) {
1580
//
1581
return false;
1582
}
1583
1584
1585
bool
1586
GNEAdditionalHandler::buildPolygon(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& id, const std::string& type,
1587
const RGBColor& color, double layer, double angle, const std::string& imgFile, const PositionVector& shape,
1588
bool geo, bool fill, double lineWidth, const std::string& name, const Parameterised::Map& parameters) {
1589
// check conditions
1590
if (type == "jupedsim.walkable_area") {
1591
return buildJpsWalkableArea(sumoBaseObject, id, shape, geo, name, parameters);
1592
} else if (type == "jupedsim.obstacle") {
1593
return buildJpsObstacle(sumoBaseObject, id, shape, geo, name, parameters);
1594
} else {
1595
// check conditions
1596
const auto element = retrieveAdditionalElement(NamespaceIDs::polygons, id);
1597
if (!checkElement(SUMO_TAG_POLY, element)) {
1598
return false;
1599
} else if (!checkValidAdditionalID(SUMO_TAG_POLY, id)) {
1600
return false;
1601
} else if (!checkNegative(SUMO_TAG_POLY, id, SUMO_ATTR_LINEWIDTH, lineWidth, true)) {
1602
return false;
1603
} else {
1604
// create poly
1605
GNEPoly* poly = new GNEPoly(id, myNet, myFileBucket, type, shape, geo, fill, lineWidth, color, layer, angle, imgFile, name, parameters);
1606
// add it depending of allow undoRed
1607
if (myAllowUndoRedo) {
1608
myNet->getUndoList()->begin(poly, TL("add polygon '") + id + "'");
1609
myNet->getUndoList()->add(new GNEChange_Additional(poly, true), true);
1610
myNet->getUndoList()->end();
1611
} else {
1612
// insert shape without allowing undo/redo
1613
myNet->getAttributeCarriers()->insertAdditional(poly);
1614
poly->incRef("addPolygon");
1615
}
1616
return true;
1617
}
1618
}
1619
}
1620
1621
1622
bool
1623
GNEAdditionalHandler::buildPOI(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id, const std::string& type,
1624
const RGBColor& color, const double x, const double y, const std::string& icon, double layer, double angle,
1625
const std::string& imgFile, double width, double height, const std::string& name, const Parameterised::Map& parameters) {
1626
// check conditions
1627
const auto element = retrieveAdditionalElement(NamespaceIDs::POIs, id);
1628
if (!checkElement(SUMO_TAG_POI, element)) {
1629
return false;
1630
} else if (!checkValidAdditionalID(SUMO_TAG_POI, id)) {
1631
return false;
1632
} else if (!checkNegative(SUMO_TAG_POI, id, SUMO_ATTR_WIDTH, width, true)) {
1633
return false;
1634
} else if (!checkNegative(SUMO_TAG_POI, id, SUMO_ATTR_HEIGHT, height, true)) {
1635
return false;
1636
} else if (!checkFileName(SUMO_TAG_POI, id, SUMO_ATTR_IMGFILE, imgFile)) {
1637
return false;
1638
} else {
1639
// parse position
1640
const auto pos = Position(x, y);
1641
// parse icon
1642
const POIIcon ic = SUMOXMLDefinitions::POIIcons.hasString(icon) ? SUMOXMLDefinitions::POIIcons.get(icon) : POIIcon::NONE;
1643
// create POI
1644
GNEPOI* POI = new GNEPOI(id, myNet, myFileBucket, type, color, pos, false, ic, layer, angle, imgFile, width, height, name, parameters);
1645
// add it depending of allow undoRed
1646
if (myAllowUndoRedo) {
1647
myNet->getUndoList()->begin(POI, TLF("add POI '%'", id));
1648
myNet->getUndoList()->add(new GNEChange_Additional(POI, true), true);
1649
myNet->getUndoList()->end();
1650
} else {
1651
// insert shape without allowing undo/redo
1652
myNet->getAttributeCarriers()->insertAdditional(POI);
1653
POI->incRef("addPOI");
1654
}
1655
return true;
1656
}
1657
}
1658
1659
1660
bool
1661
GNEAdditionalHandler::buildPOILane(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id, const std::string& type,
1662
const RGBColor& color, const std::string& laneID, double posOverLane, const bool friendlyPos, double posLat,
1663
const std::string& icon, double layer, double angle, const std::string& imgFile, double width, double height,
1664
const std::string& name, const Parameterised::Map& parameters) {
1665
// check conditions
1666
const auto element = retrieveAdditionalElement(NamespaceIDs::POIs, id);
1667
if (!checkElement(GNE_TAG_POILANE, element)) {
1668
return false;
1669
} else if (!checkValidAdditionalID(GNE_TAG_POILANE, id)) {
1670
return false;
1671
} else if (!checkNegative(GNE_TAG_POILANE, id, SUMO_ATTR_WIDTH, width, true)) {
1672
return false;
1673
} else if (!checkNegative(GNE_TAG_POILANE, id, SUMO_ATTR_HEIGHT, height, true)) {
1674
return false;
1675
} else if (!checkFileName(GNE_TAG_POILANE, id, SUMO_ATTR_IMGFILE, imgFile)) {
1676
return false;
1677
} else {
1678
// get lane
1679
GNELane* lane = myNet->getAttributeCarriers()->retrieveLane(laneID, false);
1680
// check lane
1681
if (lane == nullptr) {
1682
return writeErrorInvalidParent(GNE_TAG_POILANE, id, {SUMO_TAG_LANE}, laneID);
1683
} else if (!checkLanePosition(posOverLane, 0, lane->getParentEdge()->getNBEdge()->getFinalLength(), friendlyPos)) {
1684
return writeErrorInvalidPosition(GNE_TAG_POILANE, id);
1685
} else {
1686
// parse icon
1687
const POIIcon ic = SUMOXMLDefinitions::POIIcons.hasString(icon) ? SUMOXMLDefinitions::POIIcons.get(icon) : POIIcon::NONE;
1688
// create POI (use GNEAdditional instead GNEPOI for add child references)
1689
GNEAdditional* POILane = new GNEPOI(id, myNet, myFileBucket, type, color, lane, posOverLane, friendlyPos, posLat, ic, layer,
1690
angle, imgFile, width, height, name, parameters);
1691
// add it depending of allow undoRed
1692
if (myAllowUndoRedo) {
1693
myNet->getUndoList()->begin(POILane, TLF("add POI lane '%'", id));
1694
myNet->getUndoList()->add(new GNEChange_Additional(POILane, true), true);
1695
myNet->getUndoList()->end();
1696
} else {
1697
// insert shape without allowing undo/redo
1698
myNet->getAttributeCarriers()->insertAdditional(POILane);
1699
lane->addChildElement(POILane);
1700
POILane->incRef("buildPOILane");
1701
}
1702
}
1703
return true;
1704
}
1705
}
1706
1707
1708
bool
1709
GNEAdditionalHandler::buildPOIGeo(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id, const std::string& type,
1710
const RGBColor& color, const double lon, const double lat, const std::string& icon, double layer,
1711
double angle, const std::string& imgFile, double width, double height, const std::string& name,
1712
const Parameterised::Map& parameters) {
1713
// check conditions
1714
const auto element = retrieveAdditionalElement(NamespaceIDs::POIs, id);
1715
if (!checkElement(GNE_TAG_POIGEO, element)) {
1716
return false;
1717
} else if (!checkValidAdditionalID(GNE_TAG_POIGEO, id)) {
1718
return false;
1719
} else if (!checkNegative(GNE_TAG_POIGEO, id, SUMO_ATTR_WIDTH, width, true)) {
1720
return false;
1721
} else if (!checkNegative(GNE_TAG_POIGEO, id, SUMO_ATTR_HEIGHT, height, true)) {
1722
return false;
1723
} else if (!checkFileName(GNE_TAG_POIGEO, id, SUMO_ATTR_IMGFILE, imgFile)) {
1724
return false;
1725
} else if (GeoConvHelper::getFinal().getProjString() == "!") {
1726
return writeError(TLF("Could not build POI with ID '%' in netedit", id) + std::string("; ") + TL("Network requires a geo projection."));
1727
} else {
1728
// parse position
1729
const auto pos = Position(lon, lat);
1730
// parse icon
1731
const POIIcon ic = SUMOXMLDefinitions::POIIcons.hasString(icon) ? SUMOXMLDefinitions::POIIcons.get(icon) : POIIcon::NONE;
1732
// create POIGEO
1733
GNEPOI* POIGEO = new GNEPOI(id, myNet, myFileBucket, type, color, pos, true, ic, layer, angle, imgFile, width, height, name, parameters);
1734
// add it depending of allow undoRed
1735
if (myAllowUndoRedo) {
1736
myNet->getUndoList()->begin(POIGEO, TLF("add POI GEO '%'", id));
1737
myNet->getUndoList()->add(new GNEChange_Additional(POIGEO, true), true);
1738
myNet->getUndoList()->end();
1739
} else {
1740
// insert shape without allowing undo/redo
1741
myNet->getAttributeCarriers()->insertAdditional(POIGEO);
1742
POIGEO->incRef("buildPOIGeo");
1743
}
1744
return true;
1745
}
1746
}
1747
1748
1749
bool
1750
GNEAdditionalHandler::buildJpsWalkableArea(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id, const PositionVector& shape,
1751
bool geo, const std::string& name, const Parameterised::Map& parameters) {
1752
// check conditions
1753
const auto element = retrieveAdditionalElement(NamespaceIDs::polygons, id);
1754
if (!checkElement(GNE_TAG_JPS_WALKABLEAREA, element)) {
1755
return false;
1756
} else if (!checkValidAdditionalID(GNE_TAG_JPS_WALKABLEAREA, id)) {
1757
return false;
1758
} else {
1759
// create walkable area
1760
GNEPoly* walkableArea = new GNEPoly(GNE_TAG_JPS_WALKABLEAREA, id, myNet, myFileBucket, shape, geo, name, parameters);
1761
// add it depending of allow undoRed
1762
if (myAllowUndoRedo) {
1763
myNet->getUndoList()->begin(walkableArea, TL("add jps walkable area '") + id + "'");
1764
myNet->getUndoList()->add(new GNEChange_Additional(walkableArea, true), true);
1765
myNet->getUndoList()->end();
1766
} else {
1767
// insert shape without allowing undo/redo
1768
myNet->getAttributeCarriers()->insertAdditional(walkableArea);
1769
walkableArea->incRef("addWalkableArea");
1770
}
1771
return true;
1772
}
1773
}
1774
1775
1776
bool
1777
GNEAdditionalHandler::buildJpsObstacle(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id, const PositionVector& shape,
1778
bool geo, const std::string& name, const Parameterised::Map& parameters) {
1779
// check conditions
1780
const auto element = retrieveAdditionalElement(NamespaceIDs::polygons, id);
1781
if (!checkElement(GNE_TAG_JPS_OBSTACLE, element)) {
1782
return false;
1783
} else if (!checkValidAdditionalID(GNE_TAG_JPS_OBSTACLE, id)) {
1784
return false;
1785
} else {
1786
// create walkable area
1787
GNEPoly* obstacle = new GNEPoly(GNE_TAG_JPS_OBSTACLE, id, myNet, myFileBucket, shape, geo, name, parameters);
1788
// add it depending of allow undoRed
1789
if (myAllowUndoRedo) {
1790
myNet->getUndoList()->begin(obstacle, TL("add jps obstacle '") + id + "'");
1791
myNet->getUndoList()->add(new GNEChange_Additional(obstacle, true), true);
1792
myNet->getUndoList()->end();
1793
} else {
1794
// insert shape without allowing undo/redo
1795
myNet->getAttributeCarriers()->insertAdditional(obstacle);
1796
obstacle->incRef("addObstacle");
1797
}
1798
return true;
1799
}
1800
}
1801
1802
1803
bool
1804
GNEAdditionalHandler::accessExists(const GNEAdditional* stoppingPlaceParent, const GNEEdge* edge) {
1805
// check if exist another access for the same parent in the given edge
1806
for (const auto& access : stoppingPlaceParent->getChildAdditionals()) {
1807
// check tag
1808
if (access->getTagProperty()->getTag() == SUMO_TAG_ACCESS) {
1809
// check all siblings of the lane
1810
for (const auto& lane : edge->getChildLanes()) {
1811
if (access->getAttribute(SUMO_ATTR_LANE) == lane->getID()) {
1812
return false;
1813
}
1814
}
1815
}
1816
}
1817
return true;
1818
}
1819
1820
1821
bool
1822
GNEAdditionalHandler::checkOverlappingRerouterIntervals(GNEAdditional* rerouter, SUMOTime newBegin, SUMOTime newEnd) {
1823
// declare a vector to keep sorted rerouter children
1824
std::vector<std::pair<SUMOTime, SUMOTime>> sortedIntervals;
1825
// iterate over child additional
1826
for (const auto& rerouterChild : rerouter->getChildAdditionals()) {
1827
if (!rerouterChild->getTagProperty()->isSymbol()) {
1828
sortedIntervals.push_back(std::make_pair((SUMOTime)0., (SUMOTime)0.));
1829
// set begin and end
1830
sortedIntervals.back().first = TIME2STEPS(rerouterChild->getAttributeDouble(SUMO_ATTR_BEGIN));
1831
sortedIntervals.back().second = TIME2STEPS(rerouterChild->getAttributeDouble(SUMO_ATTR_END));
1832
}
1833
}
1834
// add new intervals
1835
sortedIntervals.push_back(std::make_pair(newBegin, newEnd));
1836
// sort children
1837
std::sort(sortedIntervals.begin(), sortedIntervals.end());
1838
// check overlapping after sorting
1839
for (int i = 0; i < (int)sortedIntervals.size() - 1; i++) {
1840
if (sortedIntervals.at(i).second > sortedIntervals.at(i + 1).first) {
1841
return false;
1842
}
1843
}
1844
return true;
1845
}
1846
1847
1848
bool
1849
GNEAdditionalHandler::checkLanePosition(double pos, const double length, const double laneLength, const bool friendlyPos) {
1850
if (friendlyPos) {
1851
return true;
1852
}
1853
// adjust from and to (negative means that start at the end of lane and count backward)
1854
if (pos < 0) {
1855
pos += laneLength;
1856
}
1857
// check extremes
1858
if ((pos < 0) || (pos > laneLength)) {
1859
return false;
1860
}
1861
// check pos + length
1862
if ((pos + length) > laneLength) {
1863
return false;
1864
}
1865
// all OK
1866
return true;
1867
}
1868
1869
1870
bool
1871
GNEAdditionalHandler::checkFriendlyPosSmallLanes(double pos, const double length, const double laneLength, const bool friendlyPos) {
1872
if (friendlyPos == true) {
1873
return true;
1874
} else if (OptionsCont::getOptions().getBool("e2.friendlyPos.automatic")) {
1875
// adjust from and to (negative means that start at the end of lane and count backward)
1876
if (pos < 0) {
1877
pos += laneLength;
1878
}
1879
// check extremes
1880
if ((pos < 0) || (pos > laneLength)) {
1881
return true;
1882
}
1883
// check pos + length
1884
if ((pos + length) > laneLength) {
1885
return true;
1886
}
1887
}
1888
return false;
1889
}
1890
1891
1892
bool
1893
GNEAdditionalHandler::checkLaneDoublePosition(double from, double to, const double laneLength, const bool friendlyPos) {
1894
if (friendlyPos) {
1895
return true;
1896
}
1897
// adjust from and to (negative means that start at the end of lane and count backward)
1898
if (from == INVALID_DOUBLE) {
1899
from = 0;
1900
}
1901
if (to == INVALID_DOUBLE) {
1902
to = laneLength;
1903
}
1904
if (from < 0) {
1905
from += laneLength;
1906
}
1907
if (to < 0) {
1908
to += laneLength;
1909
}
1910
if ((to - from) < POSITION_EPS) {
1911
return false;
1912
}
1913
if ((from < 0) || (from > laneLength)) {
1914
return false;
1915
}
1916
if ((to < 0) || (to > laneLength)) {
1917
return false;
1918
}
1919
return true;
1920
}
1921
1922
1923
void
1924
GNEAdditionalHandler::fixLaneDoublePosition(double& from, double& to, const double laneLength) {
1925
// adjust from (negative means that start at the end of lane and count backward)
1926
if (from == INVALID_DOUBLE) {
1927
from = 0;
1928
}
1929
if (to == INVALID_DOUBLE) {
1930
to = laneLength;
1931
}
1932
if (from < 0) {
1933
from += laneLength;
1934
}
1935
if (from < 0) {
1936
from = 0;
1937
} else if (from > laneLength) {
1938
from = laneLength;
1939
}
1940
// adjust to
1941
if (to < 0) {
1942
to += laneLength;
1943
}
1944
if (to < 0) {
1945
to = 0;
1946
} else if (to > laneLength) {
1947
to = laneLength;
1948
}
1949
// to has more priorty as from, and distance between from and to must be >= POSITION_EPS
1950
if ((to - from) < POSITION_EPS) {
1951
if (to >= POSITION_EPS) {
1952
from = to - POSITION_EPS;
1953
} else {
1954
from = 0;
1955
to = POSITION_EPS;
1956
}
1957
}
1958
}
1959
1960
1961
bool
1962
GNEAdditionalHandler::checkMultiLanePosition(double fromPos, const double fromLaneLength, const double toPos, const double tolaneLength, const bool friendlyPos) {
1963
if (friendlyPos) {
1964
return true;
1965
} else {
1966
return (checkLanePosition(fromPos, 0, fromLaneLength, false) && checkLanePosition(toPos, 0, tolaneLength, false));
1967
}
1968
}
1969
1970
1971
GNEAdditional*
1972
GNEAdditionalHandler::getAdditionalParent(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, SumoXMLTag tag) const {
1973
if (sumoBaseObject->getParentSumoBaseObject() == nullptr) {
1974
return nullptr;
1975
} else if (!sumoBaseObject->getParentSumoBaseObject()->hasStringAttribute(SUMO_ATTR_ID)) {
1976
return nullptr;
1977
} else {
1978
return myNet->getAttributeCarriers()->retrieveAdditional(tag, sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID), false);
1979
}
1980
}
1981
1982
1983
GNEAdditional*
1984
GNEAdditionalHandler::getRerouterIntervalParent(const CommonXMLStructure::SumoBaseObject* sumoBaseObject) const {
1985
if (sumoBaseObject->getParentSumoBaseObject() == nullptr) {
1986
// parent interval doesn't exist
1987
return nullptr;
1988
} else if (sumoBaseObject->getParentSumoBaseObject()->getParentSumoBaseObject() == nullptr) {
1989
// rerouter parent doesn't exist
1990
return nullptr;
1991
} else if (!sumoBaseObject->getParentSumoBaseObject()->getParentSumoBaseObject()->hasStringAttribute(SUMO_ATTR_ID) || // rerouter ID
1992
!sumoBaseObject->getParentSumoBaseObject()->hasTimeAttribute(SUMO_ATTR_BEGIN) || // interval begin
1993
!sumoBaseObject->getParentSumoBaseObject()->hasTimeAttribute(SUMO_ATTR_END)) { // interval end
1994
return nullptr;
1995
} else {
1996
return myNet->getAttributeCarriers()->retrieveRerouterInterval(
1997
sumoBaseObject->getParentSumoBaseObject()->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID),
1998
sumoBaseObject->getParentSumoBaseObject()->getTimeAttribute(SUMO_ATTR_BEGIN),
1999
sumoBaseObject->getParentSumoBaseObject()->getTimeAttribute(SUMO_ATTR_END));
2000
}
2001
}
2002
2003
2004
std::vector<GNEEdge*>
2005
GNEAdditionalHandler::parseEdges(const SumoXMLTag tag, const std::string& id, const std::vector<std::string>& edgeIDs) {
2006
std::vector<GNEEdge*> edges;
2007
for (const auto& edgeID : edgeIDs) {
2008
GNEEdge* edge = myNet->getAttributeCarriers()->retrieveEdge(edgeID, false);
2009
// empty edges aren't allowed. If edge is empty, write error, clear edges and stop
2010
if (edge == nullptr) {
2011
writeError(TLF("Could not build % with ID '%' in netedit; % with ID '%' doesn't exist.", toString(tag), id, toString(SUMO_TAG_EDGE), edgeID));
2012
edges.clear();
2013
return edges;
2014
} else {
2015
edges.push_back(edge);
2016
}
2017
}
2018
return edges;
2019
}
2020
2021
2022
std::vector<GNELane*>
2023
GNEAdditionalHandler::parseLanes(const SumoXMLTag tag, const std::string& id, const std::vector<std::string>& laneIDs) {
2024
std::vector<GNELane*> lanes;
2025
for (const auto& laneID : laneIDs) {
2026
GNELane* lane = myNet->getAttributeCarriers()->retrieveLane(laneID, false);
2027
// empty lanes aren't allowed. If lane is empty, write error, clear lanes and stop
2028
if (lane == nullptr) {
2029
writeError(TLF("Could not build % with ID '%' in netedit; % with ID '%' doesn't exist.", toString(tag), id, toString(SUMO_TAG_LANE), laneID));
2030
lanes.clear();
2031
return lanes;
2032
} else {
2033
lanes.push_back(lane);
2034
}
2035
}
2036
return lanes;
2037
}
2038
2039
2040
GNEAdditional*
2041
GNEAdditionalHandler::retrieveAdditionalElement(const std::vector<SumoXMLTag> tags, const std::string& id) {
2042
for (const auto& tag : tags) {
2043
// retrieve additional element
2044
auto additionalElement = myNet->getAttributeCarriers()->retrieveAdditional(tag, id, false);
2045
if (additionalElement) {
2046
return additionalElement;
2047
}
2048
}
2049
return nullptr;
2050
}
2051
2052
2053
bool
2054
GNEAdditionalHandler::checkElement(const SumoXMLTag tag, GNEAdditional* additionalElement) {
2055
if (additionalElement) {
2056
if (myOverwriteElements) {
2057
// delete element
2058
myNet->deleteAdditional(additionalElement, myNet->getUndoList());
2059
} else if (myRemainElements) {
2060
// duplicated demand
2061
return writeWarningDuplicated(tag, additionalElement->getID(), additionalElement->getTagProperty()->getTag());
2062
} else {
2063
// open overwrite dialog
2064
GNEOverwriteElement overwriteElementDialog(this, additionalElement);
2065
// continue depending of result
2066
if (overwriteElementDialog.getResult() == GNEOverwriteElement::Result::ACCEPT) {
2067
// delete element
2068
myNet->deleteAdditional(additionalElement, myNet->getUndoList());
2069
} else if (overwriteElementDialog.getResult() == GNEOverwriteElement::Result::CANCEL) {
2070
// duplicated demand
2071
return writeWarningDuplicated(tag, additionalElement->getID(), additionalElement->getTagProperty()->getTag());
2072
} else {
2073
return false;
2074
}
2075
}
2076
}
2077
return true;
2078
}
2079
2080
/****************************************************************************/
2081
2082