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