Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/elements/additional/GNEDetector.cpp
193699 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 GNEDetector.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Nov 2015
17
///
18
//
19
/****************************************************************************/
20
#include <config.h>
21
22
#include <netedit/GNENet.h>
23
#include <netedit/GNETagProperties.h>
24
#include <netedit/GNESegment.h>
25
#include <netedit/changes/GNEChange_Attribute.h>
26
#include <utils/gui/div/GLHelper.h>
27
28
#include "GNEDetector.h"
29
30
// ===========================================================================
31
// member method definitions
32
// ===========================================================================
33
34
GNEDetector::GNEDetector(GNENet* net, SumoXMLTag tag) :
35
GNEAdditional(net, tag) {
36
}
37
38
39
GNEDetector::GNEDetector(const std::string& id, GNENet* net, FileBucket* fileBucket, SumoXMLTag tag,
40
const SUMOTime period, const std::string& outputFilename, const std::vector<std::string>& vehicleTypes,
41
const std::vector<std::string>& nextEdges, const std::string& detectPersons, const std::string& name,
42
const Parameterised::Map& parameters) :
43
GNEAdditional(id, net, tag, fileBucket, name),
44
Parameterised(parameters),
45
myPeriod(period),
46
myOutputFilename(outputFilename),
47
myVehicleTypes(vehicleTypes),
48
myNextEdges(nextEdges),
49
myDetectPersons(detectPersons) {
50
// update output filename
51
if (outputFilename.empty()) {
52
myOutputFilename = id + ".xml";
53
}
54
}
55
56
57
GNEDetector::GNEDetector(GNEAdditional* additionalParent, SumoXMLTag tag, const SUMOTime period,
58
const std::string& outputFilename, const std::string& name,
59
const Parameterised::Map& parameters) :
60
GNEAdditional(additionalParent, tag, name),
61
Parameterised(parameters),
62
myPeriod(period),
63
myOutputFilename(outputFilename) {
64
// set parents
65
setParent<GNEAdditional*>(additionalParent);
66
}
67
68
69
GNEDetector::~GNEDetector() {}
70
71
72
Parameterised*
73
GNEDetector::getParameters() {
74
return this;
75
}
76
77
78
const Parameterised*
79
GNEDetector::getParameters() const {
80
return this;
81
}
82
83
84
bool
85
GNEDetector::checkDrawMoveContour() const {
86
// get edit modes
87
const auto& editModes = myNet->getViewNet()->getEditModes();
88
// check if we're in move mode
89
if (!myNet->getViewNet()->isCurrentlyMovingElements() && editModes.isCurrentSupermodeNetwork() &&
90
!myNet->getViewNet()->getEditNetworkElementShapes().getEditedNetworkElement() &&
91
(editModes.networkEditMode == NetworkEditMode::NETWORK_MOVE) && myNet->getViewNet()->checkOverLockedElement(this, mySelected)) {
92
// only move the first element
93
if (myNet->getViewNet()->getViewObjectsSelector().getGUIGlObjectFront() == this) {
94
// special case for multiple lane area detectors
95
if (myTagProperty->getTag() == GNE_TAG_MULTI_LANE_AREA_DETECTOR) {
96
auto segment = gViewObjectsHandler.getSelectedSegment(this);
97
if (segment && segment->getJunction()) {
98
return false;
99
} else if (segment && segment->getLane()) {
100
// ensure that is the first or the last lane
101
if (segment->getLaneIndex() == 0) {
102
return true;
103
} else if (segment->getLaneIndex() == ((int)getParentLanes().size() - 1)) {
104
return true;
105
}
106
} else {
107
// this is the start or end point
108
return true;
109
}
110
} else {
111
return true;
112
}
113
}
114
}
115
return false;
116
}
117
118
119
Position
120
GNEDetector::getPositionInView() const {
121
return myAdditionalGeometry.getShape().getPolygonCenter();
122
}
123
124
125
void
126
GNEDetector::updateCenteringBoundary(const bool /*updateGrid*/) {
127
// nothing to update
128
}
129
130
131
void
132
GNEDetector::splitEdgeGeometry(const double splitPosition, const GNENetworkElement* originalElement,
133
const GNENetworkElement* newElement, GNEUndoList* undoList) {
134
// only split geometry of E2 multilane detectors
135
if (myTagProperty->getTag() == GNE_TAG_MULTI_LANE_AREA_DETECTOR) {
136
// obtain new list of E2 lanes
137
std::string newE2Lanes = getNewListOfParents(originalElement, newElement);
138
// update E2 Lanes
139
if (newE2Lanes.size() > 0) {
140
setAttribute(SUMO_ATTR_LANES, newE2Lanes, undoList);
141
}
142
} else if (splitPosition < getAttributeDouble(SUMO_ATTR_POSITION)) {
143
// change lane
144
setAttribute(SUMO_ATTR_LANE, newElement->getID(), undoList);
145
// now adjust start position
146
setAttribute(SUMO_ATTR_POSITION, toString(getAttributeDouble(SUMO_ATTR_POSITION) - splitPosition), undoList);
147
}
148
}
149
150
151
std::string
152
GNEDetector::getParentName() const {
153
return getParentLanes().front()->getID();
154
}
155
156
157
PositionVector GNEDetector::getAttributePositionVector(SumoXMLAttr key) const {
158
return getCommonAttributePositionVector(key);
159
}
160
161
162
std::string
163
GNEDetector::getPopUpID() const {
164
return getTagStr() + ": " + getID();
165
}
166
167
168
std::string
169
GNEDetector::getHierarchyName() const {
170
return getTagStr();
171
}
172
173
174
std::string
175
GNEDetector::getDetectorAttribute(SumoXMLAttr key) const {
176
switch (key) {
177
case SUMO_ATTR_ID:
178
return getMicrosimID();
179
case SUMO_ATTR_PERIOD:
180
if (myPeriod == SUMOTime_MAX_PERIOD) {
181
return "";
182
} else {
183
return time2string(myPeriod);
184
}
185
case SUMO_ATTR_NAME:
186
return myAdditionalName;
187
case SUMO_ATTR_FILE:
188
return myOutputFilename;
189
case SUMO_ATTR_VTYPES:
190
return toString(myVehicleTypes);
191
case SUMO_ATTR_NEXT_EDGES:
192
return toString(myNextEdges);
193
case SUMO_ATTR_DETECT_PERSONS:
194
return toString(myDetectPersons);
195
case GNE_ATTR_SHIFTLANEINDEX:
196
return "";
197
default:
198
return getMoveElement()->getMovingAttribute(key);
199
}
200
}
201
202
203
double
204
GNEDetector::getDetectorAttributeDouble(SumoXMLAttr key) const {
205
return getMoveElement()->getMovingAttributeDouble(key);
206
}
207
208
209
Position
210
GNEDetector::getDetectorAttributePosition(SumoXMLAttr key) const {
211
return getMoveElement()->getMovingAttributePosition(key);
212
}
213
214
215
void
216
GNEDetector::setDetectorAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
217
switch (key) {
218
case SUMO_ATTR_ID:
219
case SUMO_ATTR_PERIOD:
220
case SUMO_ATTR_NAME:
221
case SUMO_ATTR_FILE:
222
case SUMO_ATTR_VTYPES:
223
case SUMO_ATTR_NEXT_EDGES:
224
case SUMO_ATTR_DETECT_PERSONS:
225
case GNE_ATTR_SHIFTLANEINDEX:
226
GNEChange_Attribute::changeAttribute(this, key, value, undoList);
227
break;
228
default:
229
getMoveElement()->setMovingAttribute(key, value, undoList);
230
break;
231
}
232
}
233
234
235
236
bool
237
GNEDetector::isDetectorValid(SumoXMLAttr key, const std::string& value) {
238
switch (key) {
239
case SUMO_ATTR_ID:
240
return isValidDetectorID(value);
241
case SUMO_ATTR_PERIOD:
242
if (value.empty()) {
243
return true;
244
} else {
245
return (canParse<double>(value) && (parse<double>(value) >= 0));
246
}
247
case SUMO_ATTR_NAME:
248
return SUMOXMLDefinitions::isValidAttribute(value);
249
case SUMO_ATTR_FILE:
250
return SUMOXMLDefinitions::isValidFilename(value);
251
case SUMO_ATTR_VTYPES:
252
if (value.empty()) {
253
return true;
254
} else {
255
return SUMOXMLDefinitions::isValidListOfTypeID(value);
256
}
257
case SUMO_ATTR_NEXT_EDGES:
258
if (value.empty()) {
259
return true;
260
} else {
261
return SUMOXMLDefinitions::isValidListOfNetIDs(value);
262
}
263
case SUMO_ATTR_DETECT_PERSONS:
264
if (value.empty()) {
265
return true;
266
} else {
267
return SUMOXMLDefinitions::PersonModeValues.hasString(value);
268
}
269
default:
270
return getMoveElement()->isMovingAttributeValid(key, value);
271
}
272
}
273
274
275
void
276
GNEDetector::writeDetectorValues(OutputDevice& device) const {
277
if ((myPeriod > 0) && (myPeriod != SUMOTime_MAX_PERIOD)) {
278
device.writeAttr(SUMO_ATTR_PERIOD, time2string(myPeriod));
279
}
280
if (myOutputFilename.size() > 0) {
281
device.writeAttr(SUMO_ATTR_FILE, myOutputFilename);
282
}
283
if (myVehicleTypes.size() > 0) {
284
device.writeAttr(SUMO_ATTR_VTYPES, myVehicleTypes);
285
}
286
if (myNextEdges.size() > 0) {
287
device.writeAttr(SUMO_ATTR_NEXT_EDGES, myNextEdges);
288
}
289
if ((myDetectPersons.size() > 0) && (myDetectPersons != SUMOXMLDefinitions::PersonModeValues.getString(PersonMode::NONE))) {
290
device.writeAttr(SUMO_ATTR_DETECT_PERSONS, myDetectPersons);
291
}
292
}
293
294
295
void
296
GNEDetector::setDetectorAttribute(SumoXMLAttr key, const std::string& value) {
297
switch (key) {
298
case SUMO_ATTR_ID:
299
// update microsimID
300
setAdditionalID(value);
301
break;
302
case SUMO_ATTR_PERIOD:
303
if (value.empty()) {
304
myPeriod = SUMOTime_MAX_PERIOD;
305
} else {
306
myPeriod = string2time(value);
307
}
308
break;
309
case SUMO_ATTR_FILE:
310
myOutputFilename = value;
311
break;
312
case SUMO_ATTR_NAME:
313
myAdditionalName = value;
314
break;
315
case SUMO_ATTR_VTYPES:
316
myVehicleTypes = parse<std::vector<std::string> >(value);
317
break;
318
case SUMO_ATTR_NEXT_EDGES:
319
myNextEdges = parse<std::vector<std::string> >(value);
320
break;
321
case SUMO_ATTR_DETECT_PERSONS:
322
myDetectPersons = value;
323
break;
324
case GNE_ATTR_SHIFTLANEINDEX:
325
shiftLaneIndex();
326
break;
327
default:
328
getMoveElement()->setMovingAttribute(key, value);
329
break;
330
}
331
}
332
333
334
void
335
GNEDetector::drawE1Shape(const GUIVisualizationSettings::Detail d, const double exaggeration,
336
const RGBColor& mainColor, const RGBColor& secondColor) const {
337
// push matrix
338
GLHelper::pushMatrix();
339
// set line width
340
glLineWidth(1.0);
341
// translate to center geometry
342
glTranslated(myAdditionalGeometry.getShape().front().x(), myAdditionalGeometry.getShape().front().y(), 0);
343
// rotate over lane
344
GUIGeometry::rotateOverLane(myAdditionalGeometry.getShapeRotations().front() + 90);
345
// scale
346
glScaled(exaggeration, exaggeration, 1);
347
// set main color
348
GLHelper::setColor(mainColor);
349
// begin draw square
350
glBegin(GL_QUADS);
351
// draw square
352
glVertex2d(-1.0, 2);
353
glVertex2d(-1.0, -2);
354
glVertex2d(1.0, -2);
355
glVertex2d(1.0, 2);
356
// end draw square
357
glEnd();
358
// move top
359
glTranslated(0, 0, .01);
360
// begin draw line
361
glBegin(GL_LINES);
362
// draw lines
363
glVertex2d(0, 2 - .1);
364
glVertex2d(0, -2 + .1);
365
// end draw line
366
glEnd();
367
// draw center only in draw in level 2
368
if (d <= GUIVisualizationSettings::Detail::AdditionalDetails) {
369
// set main color
370
GLHelper::setColor(secondColor);
371
// set polygon mode
372
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
373
// begin draw square
374
glBegin(GL_QUADS);
375
// draw square
376
glVertex2f(-1.0, 2);
377
glVertex2f(-1.0, -2);
378
glVertex2f(1.0, -2);
379
glVertex2f(1.0, 2);
380
// end draw square
381
glEnd();
382
// rotate 90 degrees
383
glRotated(90, 0, 0, -1);
384
//set polygon mode
385
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
386
// begin draw line
387
glBegin(GL_LINES);
388
// draw line
389
glVertex2d(0, 1.7);
390
glVertex2d(0, -1.7);
391
// end draw line
392
glEnd();
393
//arrow
394
glTranslated(2, 0, 0);
395
GLHelper::setColor(mainColor);
396
GLHelper::drawTriangleAtEnd(Position(0, 0), Position(0.5, 0), (double) 0.5, (double) 1);
397
}
398
// pop matrix
399
GLHelper::popMatrix();
400
}
401
402
403
void
404
GNEDetector::drawE1DetectorLogo(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
405
const double exaggeration, const std::string& logo, const RGBColor& textColor) const {
406
// only draw in level 2
407
if (d <= GUIVisualizationSettings::Detail::Text) {
408
// calculate position
409
const Position pos = myAdditionalGeometry.getShape().front();
410
// calculate rotation
411
const double rot = s.getTextAngle(myAdditionalGeometry.getShapeRotations().front() + 90);
412
// Start pushing matrix
413
GLHelper::pushMatrix();
414
// Traslate to position
415
glTranslated(pos.x(), pos.y(), 0.1);
416
// scale text
417
glScaled(exaggeration, exaggeration, 1);
418
// draw E1 logo
419
GLHelper::drawText(logo + " ", Position(), .1, 1.5, textColor, rot);
420
// pop matrix
421
GLHelper::popMatrix();
422
}
423
}
424
425
426
void
427
GNEDetector::drawE2DetectorLogo(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
428
const double exaggeration, const std::string& logo, const RGBColor& textColor) const {
429
// only draw in level 2
430
if (d <= GUIVisualizationSettings::Detail::Text) {
431
// calculate middle point
432
const double middlePoint = (myAdditionalGeometry.getShape().length2D() * 0.5);
433
// calculate position
434
const Position pos = myAdditionalGeometry.getShape().positionAtOffset2D(middlePoint);
435
// calculate rotation
436
const double rot = s.getTextAngle(myAdditionalGeometry.getShape().rotationDegreeAtOffset(middlePoint) + 90);
437
// Start pushing matrix
438
GLHelper::pushMatrix();
439
// Traslate to position
440
glTranslated(pos.x(), pos.y(), 0.1);
441
// scale text
442
glScaled(exaggeration, exaggeration, 1);
443
// draw E1 logo
444
GLHelper::drawText(logo, Position(), .1, 1.5, textColor, rot);
445
// pop matrix
446
GLHelper::popMatrix();
447
}
448
}
449
450
/****************************************************************************/
451
452