Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/elements/additional/GNEMultiEntryExitDetector.cpp
193671 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.
4
// This program and the accompanying materials are made available under the
5
// terms of the Eclipse Public License 2.0 which is available at
6
// https://www.eclipse.org/legal/epl-2.0/
7
// This Source Code may also be made available under the following Secondary
8
// Licenses when the conditions for such availability set forth in the Eclipse
9
// Public License 2.0 are satisfied: GNU General Public License, version 2
10
// or later which is available at
11
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
/****************************************************************************/
14
/// @file GNEMultiEntryExitDetector.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Nov 2015
17
///
18
// multi entry-exit (E3) detector
19
/****************************************************************************/
20
#include <config.h>
21
22
#include <netedit/changes/GNEChange_Attribute.h>
23
#include <netedit/elements/moving/GNEMoveElementView.h>
24
#include <netedit/GNENet.h>
25
#include <netedit/GNETagProperties.h>
26
27
#include "GNEMultiEntryExitDetector.h"
28
29
// ===========================================================================
30
// member method definitions
31
// ===========================================================================
32
33
GNEMultiEntryExitDetector::GNEMultiEntryExitDetector(GNENet* net) :
34
GNEAdditional(net, SUMO_TAG_ENTRY_EXIT_DETECTOR),
35
GNEAdditionalSquared(this) {
36
}
37
38
39
GNEMultiEntryExitDetector::GNEMultiEntryExitDetector(const std::string& id, GNENet* net, FileBucket* fileBucket, const Position pos, const SUMOTime freq,
40
const std::string& outputFilename, const std::vector<std::string>& vehicleTypes, const std::vector<std::string>& nextEdges, const std::string& detectPersons,
41
const std::string& name, const SUMOTime timeThreshold, const double speedThreshold, const bool openEntry, const bool expectedArrival, const Parameterised::Map& parameters) :
42
GNEAdditional(id, net, SUMO_TAG_ENTRY_EXIT_DETECTOR, fileBucket, name),
43
GNEAdditionalSquared(this, pos),
44
Parameterised(parameters),
45
myPeriod(freq),
46
myOutputFilename(outputFilename),
47
myVehicleTypes(vehicleTypes),
48
myNextEdges(nextEdges),
49
myDetectPersons(detectPersons),
50
myTimeThreshold(timeThreshold),
51
mySpeedThreshold(speedThreshold),
52
myOpenEntry(openEntry),
53
myExpectedArrival(expectedArrival) {
54
// update centering boundary without updating grid
55
updateCenteringBoundary(false);
56
// set default output filename
57
if (outputFilename.empty()) {
58
myOutputFilename = id + ".xml";
59
}
60
}
61
62
63
GNEMultiEntryExitDetector::~GNEMultiEntryExitDetector() {
64
}
65
66
67
GNEMoveElement*
68
GNEMultiEntryExitDetector::getMoveElement() const {
69
return myMoveElementView;
70
}
71
72
73
Parameterised*
74
GNEMultiEntryExitDetector::getParameters() {
75
return this;
76
}
77
78
79
const Parameterised*
80
GNEMultiEntryExitDetector::getParameters() const {
81
return this;
82
}
83
84
85
void
86
GNEMultiEntryExitDetector::writeAdditional(OutputDevice& device) const {
87
bool entry = false;
88
bool exit = false;
89
// first check if E3 has at least one entry and one exit
90
for (const auto& additionalChild : getChildAdditionals()) {
91
if (additionalChild->getTagProperty()->getTag() == SUMO_TAG_DET_ENTRY) {
92
entry = true;
93
} else if (additionalChild->getTagProperty()->getTag() == SUMO_TAG_DET_EXIT) {
94
exit = true;
95
}
96
}
97
// check entry/exits
98
if (entry && exit) {
99
device.openTag(getTagProperty()->getTag());
100
// write common additional attributes
101
writeAdditionalAttributes(device);
102
// write move atributes
103
myMoveElementView->writeMoveAttributes(device);
104
// write specific attributes
105
if (getAttribute(SUMO_ATTR_PERIOD).size() > 0) {
106
device.writeAttr(SUMO_ATTR_PERIOD, time2string(myPeriod));
107
}
108
if (myOutputFilename.size() > 0) {
109
device.writeAttr(SUMO_ATTR_FILE, myOutputFilename);
110
}
111
if (myVehicleTypes.size() > 0) {
112
device.writeAttr(SUMO_ATTR_VTYPES, myVehicleTypes);
113
}
114
if (myTimeThreshold != myTagProperty->getDefaultTimeValue(SUMO_ATTR_HALTING_TIME_THRESHOLD)) {
115
device.writeAttr(SUMO_ATTR_HALTING_TIME_THRESHOLD, time2string(myTimeThreshold));
116
}
117
if (mySpeedThreshold != myTagProperty->getDefaultDoubleValue(SUMO_ATTR_HALTING_SPEED_THRESHOLD)) {
118
device.writeAttr(SUMO_ATTR_HALTING_SPEED_THRESHOLD, mySpeedThreshold);
119
}
120
if (myExpectedArrival != myTagProperty->getDefaultBoolValue(SUMO_ATTR_EXPECT_ARRIVAL)) {
121
device.writeAttr(SUMO_ATTR_EXPECT_ARRIVAL, myExpectedArrival);
122
}
123
if (myOpenEntry != myTagProperty->getDefaultBoolValue(SUMO_ATTR_OPEN_ENTRY)) {
124
device.writeAttr(SUMO_ATTR_OPEN_ENTRY, myOpenEntry);
125
}
126
// write all entry/exits
127
for (const auto& access : getChildAdditionals()) {
128
access->writeAdditional(device);
129
}
130
// write parameters (Always after children to avoid problems with additionals.xsd)
131
writeParams(device);
132
device.closeTag();
133
} else {
134
WRITE_WARNING("E3 '" + getID() + TL("' needs at least one entry and one exit"));
135
}
136
}
137
138
139
bool
140
GNEMultiEntryExitDetector::isAdditionalValid() const {
141
return true;
142
}
143
144
145
std::string
146
GNEMultiEntryExitDetector::getAdditionalProblem() const {
147
return "";
148
}
149
150
151
void
152
GNEMultiEntryExitDetector::fixAdditionalProblem() {
153
// nothing to fix
154
}
155
156
157
bool
158
GNEMultiEntryExitDetector::checkDrawMoveContour() const {
159
// get edit modes
160
const auto& editModes = myNet->getViewNet()->getEditModes();
161
// check if we're in move mode
162
if (!myNet->getViewNet()->isCurrentlyMovingElements() && editModes.isCurrentSupermodeNetwork() &&
163
!myNet->getViewNet()->getEditNetworkElementShapes().getEditedNetworkElement() &&
164
(editModes.networkEditMode == NetworkEditMode::NETWORK_MOVE) && myNet->getViewNet()->checkOverLockedElement(this, mySelected)) {
165
// only move the first element
166
return myNet->getViewNet()->getViewObjectsSelector().getGUIGlObjectFront() == this;
167
} else {
168
return false;
169
}
170
}
171
172
173
void
174
GNEMultiEntryExitDetector::updateGeometry() {
175
updatedSquaredGeometry();
176
}
177
178
179
Position
180
GNEMultiEntryExitDetector::getPositionInView() const {
181
return myPosOverView;
182
}
183
184
185
void
186
GNEMultiEntryExitDetector::updateCenteringBoundary(const bool updateGrid) {
187
updatedSquaredCenteringBoundary(updateGrid);
188
}
189
190
191
void
192
GNEMultiEntryExitDetector::splitEdgeGeometry(const double /*splitPosition*/, const GNENetworkElement* /*originalElement*/, const GNENetworkElement* /*newElement*/, GNEUndoList* /*undoList*/) {
193
// geometry of this element cannot be splitted
194
}
195
196
197
std::string
198
GNEMultiEntryExitDetector::getParentName() const {
199
return myNet->getMicrosimID();
200
}
201
202
203
void
204
GNEMultiEntryExitDetector::drawGL(const GUIVisualizationSettings& s) const {
205
// first check if additional has to be drawn
206
if (myNet->getViewNet()->getDataViewOptions().showAdditionals() &&
207
!myNet->getViewNet()->selectingDetectorsTLSMode()) {
208
// draw parent and child lines
209
drawParentChildLines(s, s.additionalSettings.connectionColor);
210
// draw E3
211
drawSquaredAdditional(s, s.detectorSettings.E3Size, GUITexture::E3, GUITexture::E3_SELECTED);
212
}
213
}
214
215
216
std::string
217
GNEMultiEntryExitDetector::getAttribute(SumoXMLAttr key) const {
218
switch (key) {
219
case SUMO_ATTR_ID:
220
return getMicrosimID();
221
case SUMO_ATTR_PERIOD:
222
if (myPeriod == SUMOTime_MAX_PERIOD) {
223
return "";
224
} else {
225
return time2string(myPeriod);
226
}
227
case SUMO_ATTR_NAME:
228
return myAdditionalName;
229
case SUMO_ATTR_FILE:
230
return myOutputFilename;
231
case SUMO_ATTR_VTYPES:
232
return toString(myVehicleTypes);
233
case SUMO_ATTR_NEXT_EDGES:
234
return toString(myNextEdges);
235
case SUMO_ATTR_DETECT_PERSONS:
236
return toString(myDetectPersons);
237
case SUMO_ATTR_HALTING_TIME_THRESHOLD:
238
return time2string(myTimeThreshold);
239
case SUMO_ATTR_HALTING_SPEED_THRESHOLD:
240
return toString(mySpeedThreshold);
241
case SUMO_ATTR_OPEN_ENTRY:
242
return toString(myOpenEntry);
243
case SUMO_ATTR_EXPECT_ARRIVAL:
244
return toString(myExpectedArrival);
245
default:
246
return myMoveElementView->getMovingAttribute(key);
247
}
248
}
249
250
251
double
252
GNEMultiEntryExitDetector::getAttributeDouble(SumoXMLAttr key) const {
253
return myMoveElementView->getMovingAttributeDouble(key);
254
}
255
256
257
Position
258
GNEMultiEntryExitDetector::getAttributePosition(SumoXMLAttr key) const {
259
return myMoveElementView->getMovingAttributePosition(key);
260
}
261
262
263
PositionVector
264
GNEMultiEntryExitDetector::getAttributePositionVector(SumoXMLAttr key) const {
265
return myMoveElementView->getMovingAttributePositionVector(key);
266
}
267
268
269
void
270
GNEMultiEntryExitDetector::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
271
if (value == getAttribute(key)) {
272
return; //avoid needless changes, later logic relies on the fact that attributes have changed
273
}
274
switch (key) {
275
case SUMO_ATTR_ID:
276
case SUMO_ATTR_PERIOD:
277
case SUMO_ATTR_NAME:
278
case SUMO_ATTR_FILE:
279
case SUMO_ATTR_VTYPES:
280
case SUMO_ATTR_NEXT_EDGES:
281
case SUMO_ATTR_DETECT_PERSONS:
282
case SUMO_ATTR_HALTING_TIME_THRESHOLD:
283
case SUMO_ATTR_HALTING_SPEED_THRESHOLD:
284
case SUMO_ATTR_OPEN_ENTRY:
285
case SUMO_ATTR_EXPECT_ARRIVAL:
286
GNEChange_Attribute::changeAttribute(this, key, value, undoList);
287
break;
288
default:
289
myMoveElementView->setMovingAttribute(key, value, undoList);
290
break;
291
}
292
}
293
294
295
bool
296
GNEMultiEntryExitDetector::isValid(SumoXMLAttr key, const std::string& value) {
297
switch (key) {
298
case SUMO_ATTR_ID:
299
return isValidDetectorID(value);
300
case SUMO_ATTR_PERIOD:
301
if (value.empty()) {
302
return true;
303
} else {
304
return (canParse<double>(value) && (parse<double>(value) >= 0));
305
}
306
case SUMO_ATTR_NAME:
307
return SUMOXMLDefinitions::isValidAttribute(value);
308
case SUMO_ATTR_FILE:
309
return SUMOXMLDefinitions::isValidFilename(value);
310
case SUMO_ATTR_VTYPES:
311
if (value.empty()) {
312
return true;
313
} else {
314
return SUMOXMLDefinitions::isValidListOfTypeID(value);
315
}
316
case SUMO_ATTR_NEXT_EDGES:
317
if (value.empty()) {
318
return true;
319
} else {
320
return SUMOXMLDefinitions::isValidListOfNetIDs(value);
321
}
322
case SUMO_ATTR_DETECT_PERSONS:
323
if (value.empty()) {
324
return true;
325
} else {
326
return SUMOXMLDefinitions::PersonModeValues.hasString(value);
327
}
328
case SUMO_ATTR_HALTING_TIME_THRESHOLD:
329
case SUMO_ATTR_HALTING_SPEED_THRESHOLD:
330
return canParse<double>(value) && (parse<double>(value) >= 0);
331
case SUMO_ATTR_OPEN_ENTRY:
332
case SUMO_ATTR_EXPECT_ARRIVAL:
333
return canParse<bool>(value);
334
default:
335
return myMoveElementView->isMovingAttributeValid(key, value);
336
}
337
}
338
339
340
bool
341
GNEMultiEntryExitDetector::checkChildAdditionalRestriction() const {
342
int numEntrys = 0;
343
int numExits = 0;
344
// iterate over additional chidls and obtain number of entrys and exits
345
for (auto i : getChildAdditionals()) {
346
if (i->getTagProperty()->getTag() == SUMO_TAG_DET_ENTRY) {
347
numEntrys++;
348
} else if (i->getTagProperty()->getTag() == SUMO_TAG_DET_EXIT) {
349
numExits++;
350
}
351
}
352
// write warnings
353
if (numEntrys == 0) {
354
WRITE_WARNING(TL("An entry-exit detector needs at least one entry detector"));
355
}
356
if (numExits == 0) {
357
WRITE_WARNING(TL("An entry-exit detector needs at least one exit detector"));
358
}
359
// return false depending of number of Entrys and Exits
360
return ((numEntrys != 0) && (numExits != 0));
361
}
362
363
364
std::string
365
GNEMultiEntryExitDetector::getPopUpID() const {
366
return getTagStr() + ":" + getID();
367
}
368
369
370
std::string
371
GNEMultiEntryExitDetector::getHierarchyName() const {
372
return getTagStr();
373
}
374
375
// ===========================================================================
376
// private
377
// ===========================================================================
378
379
void
380
GNEMultiEntryExitDetector::setAttribute(SumoXMLAttr key, const std::string& value) {
381
switch (key) {
382
case SUMO_ATTR_ID:
383
// update microsimID
384
setAdditionalID(value);
385
break;
386
case SUMO_ATTR_PERIOD:
387
if (value.empty()) {
388
myPeriod = SUMOTime_MAX_PERIOD;
389
} else {
390
myPeriod = string2time(value);
391
}
392
break;
393
case SUMO_ATTR_NAME:
394
myAdditionalName = value;
395
break;
396
case SUMO_ATTR_FILE:
397
myOutputFilename = value;
398
break;
399
case SUMO_ATTR_VTYPES:
400
myVehicleTypes = parse<std::vector<std::string> >(value);
401
break;
402
case SUMO_ATTR_NEXT_EDGES:
403
myNextEdges = parse<std::vector<std::string> >(value);
404
break;
405
case SUMO_ATTR_DETECT_PERSONS:
406
myDetectPersons = value;
407
break;
408
case SUMO_ATTR_HALTING_TIME_THRESHOLD:
409
myTimeThreshold = parse<SUMOTime>(value);
410
break;
411
case SUMO_ATTR_HALTING_SPEED_THRESHOLD:
412
mySpeedThreshold = parse<double>(value);
413
break;
414
case SUMO_ATTR_OPEN_ENTRY:
415
myOpenEntry = parse<bool>(value);
416
break;
417
case SUMO_ATTR_EXPECT_ARRIVAL:
418
myExpectedArrival = parse<bool>(value);
419
break;
420
default:
421
myMoveElementView->setMovingAttribute(key, value);
422
break;
423
}
424
// update boundary (except for template)
425
if (getID().size() > 0) {
426
updateCenteringBoundary(true);
427
}
428
}
429
430
/****************************************************************************/
431
432