Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/elements/additional/GNEEntryExitDetector.cpp
169684 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
4
// This program and the accompanying materials are made available under the
5
// terms of the Eclipse Public License 2.0 which is available at
6
// https://www.eclipse.org/legal/epl-2.0/
7
// This Source Code may also be made available under the following Secondary
8
// Licenses when the conditions for such availability set forth in the Eclipse
9
// Public License 2.0 are satisfied: GNU General Public License, version 2
10
// or later which is available at
11
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
/****************************************************************************/
14
/// @file GNEEntryExitDetector.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Nov 2015
17
///
18
//
19
/****************************************************************************/
20
#include <config.h>
21
22
#include <netedit/GNENet.h>
23
#include <netedit/GNETagProperties.h>
24
#include <netedit/GNEUndoList.h>
25
#include <netedit/GNEViewNet.h>
26
#include <netedit/GNEViewParent.h>
27
#include <netedit/changes/GNEChange_Attribute.h>
28
#include <netedit/frames/network/GNETLSEditorFrame.h>
29
#include <utils/gui/div/GLHelper.h>
30
#include <utils/gui/globjects/GLIncludes.h>
31
#include <utils/gui/div/GUIGlobalViewObjectsHandler.h>
32
33
#include "GNEEntryExitDetector.h"
34
#include "GNEAdditionalHandler.h"
35
36
// ===========================================================================
37
// member method definitions
38
// ===========================================================================
39
40
GNEEntryExitDetector::GNEEntryExitDetector(SumoXMLTag entryExitTag, GNENet* net) :
41
GNEDetector(net, entryExitTag) {
42
}
43
44
45
GNEEntryExitDetector::GNEEntryExitDetector(SumoXMLTag entryExitTag, GNEAdditional* parent, GNELane* lane, const double pos,
46
const bool friendlyPos, const Parameterised::Map& parameters) :
47
GNEDetector(parent, entryExitTag, pos, 0, lane, "", "", friendlyPos, parameters) {
48
// update centering boundary without updating grid
49
updateCenteringBoundary(false);
50
}
51
52
53
GNEEntryExitDetector::~GNEEntryExitDetector() {}
54
55
56
void
57
GNEEntryExitDetector::writeAdditional(OutputDevice& device) const {
58
device.openTag(getTagProperty()->getTag());
59
device.writeAttr(SUMO_ATTR_LANE, getParentLanes().front()->getID());
60
device.writeAttr(SUMO_ATTR_POSITION, myPositionOverLane);
61
// write common detector parameters
62
writeDetectorValues(device);
63
// write parameters
64
writeParams(device);
65
device.closeTag();
66
}
67
68
69
bool
70
GNEEntryExitDetector::isAdditionalValid() const {
71
// with friendly position enabled position are "always fixed"
72
if (myFriendlyPosition) {
73
return true;
74
} else {
75
return fabs(myPositionOverLane) <= getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength();
76
}
77
}
78
79
80
std::string
81
GNEEntryExitDetector::getAdditionalProblem() const {
82
// obtain final length
83
const double len = getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength();
84
// check if detector has a problem
85
if (GNEAdditionalHandler::checkLanePosition(myPositionOverLane, 0, len, myFriendlyPosition)) {
86
return "";
87
} else {
88
// declare variable for error position
89
std::string errorPosition;
90
// check positions over lane
91
if (myPositionOverLane < 0) {
92
errorPosition = (toString(SUMO_ATTR_POSITION) + " < 0");
93
}
94
if (myPositionOverLane > len) {
95
errorPosition = (toString(SUMO_ATTR_POSITION) + TL(" > lanes's length"));
96
}
97
return errorPosition;
98
}
99
}
100
101
102
void
103
GNEEntryExitDetector::fixAdditionalProblem() {
104
// declare new position
105
double newPositionOverLane = myPositionOverLane;
106
// fix pos and length checkAndFixDetectorPosition
107
double length = 0;
108
GNEAdditionalHandler::fixLanePosition(newPositionOverLane, length, getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength());
109
// set new position
110
setAttribute(SUMO_ATTR_POSITION, toString(newPositionOverLane), myNet->getViewNet()->getUndoList());
111
}
112
113
114
void
115
GNEEntryExitDetector::updateGeometry() {
116
// update geometry
117
myAdditionalGeometry.updateGeometry(getParentLanes().front()->getLaneShape(), getGeometryPositionOverLane(), myMoveElementLateralOffset);
118
// update centering boundary without updating grid
119
updateCenteringBoundary(false);
120
}
121
122
123
void
124
GNEEntryExitDetector::drawGL(const GUIVisualizationSettings& s) const {
125
// first check if additional has to be drawn
126
if (myNet->getViewNet()->getDataViewOptions().showAdditionals() &&
127
!myNet->getViewNet()->selectingDetectorsTLSMode()) {
128
// Set initial values
129
const double entryExitExaggeration = getExaggeration(s);
130
// get detail level
131
const auto d = s.getDetailLevel(entryExitExaggeration);
132
// draw geometry only if we'rent in drawForObjectUnderCursor mode
133
if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {
134
// draw parent and child lines
135
drawParentChildLines(s, s.additionalSettings.connectionColor);
136
// Push layer matrix
137
GLHelper::pushMatrix();
138
// translate to front
139
drawInLayer(GLO_DET_ENTRY);
140
// Set color
141
RGBColor color;
142
if (drawUsingSelectColor()) {
143
color = s.colorSettings.selectedAdditionalColor;
144
} else if (myTagProperty->getTag() == SUMO_TAG_DET_ENTRY) {
145
color = s.detectorSettings.E3EntryColor;
146
} else if (myTagProperty->getTag() == SUMO_TAG_DET_EXIT) {
147
color = s.detectorSettings.E3ExitColor;
148
}
149
// draw parts
150
drawBody(d, color, entryExitExaggeration);
151
drawEntryLogo(d, color, entryExitExaggeration);
152
drawE3Logo(d, color, entryExitExaggeration);
153
// pop layer matrix
154
GLHelper::popMatrix();
155
// draw additional name
156
drawAdditionalName(s);
157
// draw lock icon
158
GNEViewNetHelper::LockIcon::drawLockIcon(d, this, getType(), myAdditionalGeometry.getShape().getCentroid(),
159
entryExitExaggeration);
160
// draw dotted contour
161
myAdditionalContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);
162
}
163
// calculate contour
164
myAdditionalContour.calculateContourRectangleShape(s, d, this, myAdditionalGeometry.getShape().front(), 2.7, 1.6,
165
getType(), 2, 0, myAdditionalGeometry.getShapeRotations().front(), entryExitExaggeration,
166
getParentLanes().front()->getParentEdge());
167
}
168
}
169
170
171
std::string
172
GNEEntryExitDetector::getAttribute(SumoXMLAttr key) const {
173
switch (key) {
174
case GNE_ATTR_PARENT:
175
return getParentAdditionals().at(0)->getID();
176
default:
177
return getDetectorAttribute(key);
178
}
179
}
180
181
182
double
183
GNEEntryExitDetector::getAttributeDouble(SumoXMLAttr key) const {
184
switch (key) {
185
case SUMO_ATTR_POSITION:
186
return myPositionOverLane;
187
default:
188
throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
189
}
190
}
191
192
193
void
194
GNEEntryExitDetector::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
195
switch (key) {
196
case GNE_ATTR_PARENT:
197
GNEChange_Attribute::changeAttribute(this, key, value, undoList);
198
break;
199
default:
200
setDetectorAttribute(key, value, undoList);
201
break;
202
}
203
}
204
205
206
bool
207
GNEEntryExitDetector::isValid(SumoXMLAttr key, const std::string& value) {
208
switch (key) {
209
case GNE_ATTR_PARENT:
210
return (myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_ENTRY_EXIT_DETECTOR, value, false) != nullptr);
211
default:
212
return isDetectorValid(key, value);
213
}
214
}
215
216
217
void
218
GNEEntryExitDetector::drawBody(const GUIVisualizationSettings::Detail d,
219
const RGBColor& color, const double exaggeration) const {
220
// check detail level
221
if (d <= GUIVisualizationSettings::Detail::Additionals) {
222
// Push polygon matrix
223
GLHelper::pushMatrix();
224
// set color
225
GLHelper::setColor(color);
226
// set polygon mode
227
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
228
// move to position
229
glTranslated(myAdditionalGeometry.getShape().front().x(), myAdditionalGeometry.getShape().front().y(), 0);
230
// rotate over lane
231
GUIGeometry::rotateOverLane(myAdditionalGeometry.getShapeRotations().front() + 90);
232
// scale
233
glScaled(exaggeration, exaggeration, 1);
234
// check detail level
235
if (d <= GUIVisualizationSettings::Detail::AdditionalDetails) {
236
// Draw polygon
237
glBegin(GL_LINES);
238
glVertex2d(1.7, 0);
239
glVertex2d(-1.7, 0);
240
glEnd();
241
glBegin(GL_QUADS);
242
glVertex2d(-1.7, .5);
243
glVertex2d(-1.7, -.5);
244
glVertex2d(1.7, -.5);
245
glVertex2d(1.7, .5);
246
glEnd();
247
// first Arrow
248
glTranslated(1.5, 0, 0);
249
GLHelper::drawBoxLine(Position(0, 4), 0, 2, .05);
250
GLHelper::drawTriangleAtEnd(Position(0, 4), Position(0, 1), (double) 1, (double) .25);
251
// second Arrow
252
glTranslated(-3, 0, 0);
253
GLHelper::drawBoxLine(Position(0, 4), 0, 2, .05);
254
GLHelper::drawTriangleAtEnd(Position(0, 4), Position(0, 1), (double) 1, (double) .25);
255
} else {
256
// Draw square in drawy for selecting mode
257
glBegin(GL_QUADS);
258
glVertex2d(-1.7, 4.3);
259
glVertex2d(-1.7, -.5);
260
glVertex2d(1.7, -.5);
261
glVertex2d(1.7, 4.3);
262
glEnd();
263
}
264
// Pop polygon matrix
265
GLHelper::popMatrix();
266
}
267
}
268
269
270
void
271
GNEEntryExitDetector::drawEntryLogo(const GUIVisualizationSettings::Detail d,
272
const RGBColor& color, const double exaggeration) const {
273
// check detail level
274
if (d <= GUIVisualizationSettings::Detail::AdditionalDetails) {
275
// Push matrix
276
GLHelper::pushMatrix();
277
// set color
278
GLHelper::setColor(color);
279
// Traslate to center of detector
280
glTranslated(myAdditionalGeometry.getShape().front().x(), myAdditionalGeometry.getShape().front().y(), getType() + 0.1);
281
// rotate over lane
282
GUIGeometry::rotateOverLane(myAdditionalGeometry.getShapeRotations().front());
283
//move to logo position
284
glTranslated(1.9, 0, 0);
285
// scale
286
glScaled(exaggeration, exaggeration, 1);
287
//move to logo position
288
glTranslated(1.7, 0, 0);
289
// rotate 90 degrees lane
290
glRotated(90, 0, 0, 1);
291
// draw Entry or Exit text if isn't being drawn for selecting
292
if (d <= GUIVisualizationSettings::Detail::Text) {
293
if (myTagProperty->getTag() == SUMO_TAG_DET_ENTRY) {
294
GLHelper::drawText("Entry", Position(), .1, 1, color, 180);
295
} else if (myTagProperty->getTag() == SUMO_TAG_DET_EXIT) {
296
GLHelper::drawText("Exit", Position(), .1, 1, color, 180);
297
}
298
} else {
299
GLHelper::drawBoxLine(Position(0, 1), 0, 2, 1);
300
}
301
// pop matrix
302
GLHelper::popMatrix();
303
}
304
}
305
306
307
void
308
GNEEntryExitDetector::drawE3Logo(const GUIVisualizationSettings::Detail d,
309
const RGBColor& color, const double exaggeration) const {
310
// check detail level
311
if (d <= GUIVisualizationSettings::Detail::Text) {
312
// Push matrix
313
GLHelper::pushMatrix();
314
// set color
315
GLHelper::setColor(color);
316
// Traslate to center of detector
317
glTranslated(myAdditionalGeometry.getShape().front().x(), myAdditionalGeometry.getShape().front().y(), getType() + 0.1);
318
// rotate over lane
319
GUIGeometry::rotateOverLane(myAdditionalGeometry.getShapeRotations().front());
320
//move to logo position
321
glTranslated(1.9, 0, 0);
322
// scale
323
glScaled(exaggeration, exaggeration, 1);
324
// draw E3 logo
325
GLHelper::drawText("E3", Position(0, 0), .1, 2.8, color);
326
// pop matrix
327
GLHelper::popMatrix();
328
}
329
}
330
331
332
void
333
GNEEntryExitDetector::setAttribute(SumoXMLAttr key, const std::string& value) {
334
switch (key) {
335
case GNE_ATTR_PARENT:
336
replaceAdditionalParent(SUMO_TAG_ENTRY_EXIT_DETECTOR, value, 0);
337
break;
338
default:
339
setDetectorAttribute(key, value);
340
break;
341
}
342
}
343
344
345
void
346
GNEEntryExitDetector::setMoveShape(const GNEMoveResult& moveResult) {
347
// change position
348
myPositionOverLane = moveResult.newFirstPos;
349
// set lateral offset
350
myMoveElementLateralOffset = moveResult.firstLaneOffset;
351
// update geometry
352
updateGeometry();
353
}
354
355
356
void
357
GNEEntryExitDetector::commitMoveShape(const GNEMoveResult& moveResult, GNEUndoList* undoList) {
358
// reset lateral offset
359
myMoveElementLateralOffset = 0;
360
// begin change attribute
361
undoList->begin(this, "position of " + getTagStr());
362
// set startPosition
363
setAttribute(SUMO_ATTR_POSITION, toString(moveResult.newFirstPos), undoList);
364
// check if lane has to be changed
365
if (moveResult.newFirstLane) {
366
// set new lane
367
setAttribute(SUMO_ATTR_LANE, moveResult.newFirstLane->getID(), undoList);
368
}
369
// end change attribute
370
undoList->end();
371
}
372
373
/****************************************************************************/
374
375