Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/guisim/GUIJunctionWrapper.cpp
169665 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 GUIJunctionWrapper.cpp
15
/// @author Daniel Krajzewicz
16
/// @author Jakob Erdmann
17
/// @author Michael Behrisch
18
/// @author Laura Bieker
19
/// @author Andreas Gaubatz
20
/// @date Mon, 1 Jul 2003
21
///
22
// }
23
/****************************************************************************/
24
#include <config.h>
25
26
#include <string>
27
#include <utility>
28
#include <microsim/MSLane.h>
29
#include <microsim/MSEdge.h>
30
#include <microsim/MSJunction.h>
31
#include <utils/geom/Position.h>
32
#include <utils/geom/GeomHelper.h>
33
#include <microsim/MSNet.h>
34
#include <microsim/MSInternalJunction.h>
35
#include <microsim/traffic_lights/MSTrafficLightLogic.h>
36
#include <microsim/traffic_lights/MSTLLogicControl.h>
37
#include <gui/GUIApplicationWindow.h>
38
#include <gui/GUIGlobals.h>
39
#include <utils/gui/windows/GUIAppEnum.h>
40
#include <utils/gui/windows/GUISUMOAbstractView.h>
41
#include "GUIJunctionWrapper.h"
42
#include <utils/gui/globjects/GUIGLObjectPopupMenu.h>
43
#include <utils/gui/div/GUIGlobalSelection.h>
44
#include <utils/gui/div/GUIParameterTableWindow.h>
45
#include <utils/gui/div/GLHelper.h>
46
#include <utils/gui/globjects/GLIncludes.h>
47
48
#include <osgview/GUIOSGHeader.h>
49
50
// ===========================================================================
51
// method definitions
52
// ===========================================================================
53
GUIJunctionWrapper::GUIJunctionWrapper(MSJunction& junction, const std::string& tllID):
54
GUIGlObject(GLO_JUNCTION, junction.getID(), GUIIconSubSys::getIcon(GUIIcon::JUNCTION)),
55
myJunction(junction),
56
myTesselation(junction.getID(), "", RGBColor::MAGENTA, junction.getShape(), false, true, 0),
57
myExaggeration(1),
58
myTLLID(tllID) {
59
if (myJunction.getShape().size() == 0) {
60
Position pos = myJunction.getPosition();
61
myBoundary = Boundary(pos.x() - 1., pos.y() - 1., pos.x() + 1., pos.y() + 1.);
62
} else {
63
myBoundary = myJunction.getShape().getBoxBoundary();
64
}
65
myMaxSize = MAX2(myBoundary.getWidth(), myBoundary.getHeight());
66
myIsInternal = myJunction.getType() == SumoXMLNodeType::INTERNAL;
67
myAmWaterway = myJunction.getIncoming().size() + myJunction.getOutgoing().size() > 0;
68
myAmRailway = myJunction.getIncoming().size() + myJunction.getOutgoing().size() > 0;
69
myAmAirway = myJunction.getIncoming().size() + myJunction.getOutgoing().size() > 0;
70
for (auto it = myJunction.getIncoming().begin(); it != myJunction.getIncoming().end() && (myAmWaterway || myAmRailway); ++it) {
71
if (!(*it)->isInternal()) {
72
if (!isWaterway((*it)->getPermissions())) {
73
myAmWaterway = false;
74
}
75
if (!isRailway((*it)->getPermissions())) {
76
myAmRailway = false;
77
}
78
if (!isAirway((*it)->getPermissions())) {
79
myAmAirway = false;
80
}
81
}
82
}
83
for (auto it = myJunction.getOutgoing().begin(); it != myJunction.getOutgoing().end() && (myAmWaterway || myAmRailway); ++it) {
84
if (!(*it)->isInternal()) {
85
if (!isWaterway((*it)->getPermissions())) {
86
myAmWaterway = false;
87
}
88
if (!isRailway((*it)->getPermissions())) {
89
myAmRailway = false;
90
}
91
if (!isAirway((*it)->getPermissions())) {
92
myAmAirway = false;
93
}
94
}
95
}
96
myTesselation.getShapeRef().closePolygon();
97
}
98
99
100
GUIJunctionWrapper::~GUIJunctionWrapper() {}
101
102
103
GUIGLObjectPopupMenu*
104
GUIJunctionWrapper::getPopUpMenu(GUIMainWindow& app,
105
GUISUMOAbstractView& parent) {
106
GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, this);
107
buildPopupHeader(ret, app);
108
buildCenterPopupEntry(ret);
109
buildNameCopyPopupEntry(ret);
110
buildSelectionPopupEntry(ret);
111
buildShowParamsPopupEntry(ret);
112
buildPositionCopyEntry(ret, app);
113
return ret;
114
}
115
116
117
GUIParameterTableWindow*
118
GUIJunctionWrapper::getParameterWindow(GUIMainWindow& app, GUISUMOAbstractView&) {
119
GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
120
// add items
121
ret->mkItem(TL("type"), false, toString(myJunction.getType()));
122
ret->mkItem(TL("name"), false, myJunction.getName());
123
// close building
124
ret->closeBuilding(&myJunction);
125
return ret;
126
}
127
128
129
double
130
GUIJunctionWrapper::getExaggeration(const GUIVisualizationSettings& s) const {
131
return s.junctionSize.getExaggeration(s, this, 4);
132
}
133
134
135
Boundary
136
GUIJunctionWrapper::getCenteringBoundary() const {
137
if (GUIGlobals::gSecondaryShape) {
138
const Position& p = myJunction.getPosition(true);
139
return Boundary(p.x() - 1, p.y() - 1, p.x() + 1, p.y() + 1);
140
}
141
Boundary b = myBoundary;
142
b.grow(1);
143
return b;
144
}
145
146
const std::string
147
GUIJunctionWrapper::getOptionalName() const {
148
return myJunction.getName();
149
}
150
151
void
152
GUIJunctionWrapper::drawGL(const GUIVisualizationSettings& s) const {
153
const bool s2 = s.secondaryShape;
154
if (!myIsInternal && s.drawJunctionShape && !s2) {
155
// check whether it is not too small
156
const double exaggeration = getExaggeration(s);
157
if (s.scale * exaggeration >= s.junctionSize.minSize) {
158
GLHelper::pushMatrix();
159
GLHelper::pushName(getGlID());
160
const double colorValue = getColorValue(s, s.junctionColorer.getActive());
161
const RGBColor color = s.junctionColorer.getScheme().getColor(colorValue);
162
GLHelper::setColor(color);
163
164
// recognize full transparency and simply don't draw
165
if (color.alpha() != 0) {
166
if ((exaggeration > 1 || myExaggeration > 1) && exaggeration != myExaggeration) {
167
myExaggeration = exaggeration;
168
myTesselation.setShape(myJunction.getShape());
169
myTesselation.getShapeRef().closePolygon();
170
myTesselation.getShapeRef().scaleRelative(exaggeration);
171
myTesselation.myTesselation.clear();
172
}
173
glTranslated(0, 0, getType());
174
if (s.scale * myMaxSize < 40.) {
175
GLHelper::drawFilledPoly(myTesselation.getShape(), true);
176
} else {
177
myTesselation.drawTesselation(myTesselation.getShape());
178
}
179
// make small junctions more visible when coloring by type
180
if (myJunction.getType() == SumoXMLNodeType::RAIL_SIGNAL && s.junctionColorer.getActive() == 2) {
181
glTranslated(myJunction.getPosition(s2).x(), myJunction.getPosition(s2).y(), getType() + 0.05);
182
GLHelper::drawFilledCircle(2 * exaggeration, 12);
183
}
184
}
185
GLHelper::popName();
186
GLHelper::popMatrix();
187
if (s.geometryIndices.show(this)) {
188
GLHelper::debugVertices(myJunction.getShape(), s.geometryIndices, s.scale);
189
}
190
}
191
}
192
if (myIsInternal) {
193
drawName(myJunction.getPosition(s2), s.scale, s.internalJunctionName, s.angle);
194
} else {
195
drawName(myJunction.getPosition(s2), s.scale, s.junctionID, s.angle);
196
if (s.junctionName.show(this) && myJunction.getName() != "") {
197
GLHelper::drawTextSettings(s.junctionName, myJunction.getName(), myJunction.getPosition(s2), s.scale, s.angle);
198
}
199
if ((s.tlsPhaseIndex.show(this) || s.tlsPhaseName.show(this)) && myTLLID != "") {
200
const MSTrafficLightLogic* active = MSNet::getInstance()->getTLSControl().getActive(myTLLID);
201
if (s.tlsPhaseIndex.show(this)) {
202
const int index = active->getCurrentPhaseIndex();
203
GLHelper::drawTextSettings(s.tlsPhaseIndex, toString(index), myJunction.getPosition(s2), s.scale, s.angle);
204
}
205
if (s.tlsPhaseName.show(this)) {
206
const std::string& name = active->getCurrentPhaseDef().getName();
207
if (name != "") {
208
const Position offset = (s.tlsPhaseIndex.show(this) ?
209
Position(0, 0.8 * s.tlsPhaseIndex.scaledSize(s.scale)).rotateAround2D(DEG2RAD(-s.angle), Position(0, 0))
210
: Position(0, 0));
211
GLHelper::drawTextSettings(s.tlsPhaseName, name, myJunction.getPosition(s2) - offset, s.scale, s.angle);
212
}
213
}
214
}
215
}
216
}
217
218
219
double
220
GUIJunctionWrapper::getColorValue(const GUIVisualizationSettings& /* s */, int activeScheme) const {
221
switch (activeScheme) {
222
case 0:
223
if (myAmWaterway) {
224
return 1;
225
} else if (myAmRailway && MSNet::getInstance()->hasInternalLinks()) {
226
return 2;
227
} else if (myAmAirway) {
228
return 3;
229
} else {
230
return 0;
231
}
232
case 1:
233
return gSelected.isSelected(getType(), getGlID()) ? 1 : 0;
234
case 2:
235
switch (myJunction.getType()) {
236
case SumoXMLNodeType::TRAFFIC_LIGHT:
237
return 0;
238
case SumoXMLNodeType::TRAFFIC_LIGHT_NOJUNCTION:
239
return 1;
240
case SumoXMLNodeType::PRIORITY:
241
return 2;
242
case SumoXMLNodeType::PRIORITY_STOP:
243
return 3;
244
case SumoXMLNodeType::RIGHT_BEFORE_LEFT:
245
return 4;
246
case SumoXMLNodeType::ALLWAY_STOP:
247
return 5;
248
case SumoXMLNodeType::DISTRICT:
249
return 6;
250
case SumoXMLNodeType::NOJUNCTION:
251
return 7;
252
case SumoXMLNodeType::DEAD_END:
253
case SumoXMLNodeType::DEAD_END_DEPRECATED:
254
return 8;
255
case SumoXMLNodeType::UNKNOWN:
256
case SumoXMLNodeType::INTERNAL:
257
assert(false);
258
return 8;
259
case SumoXMLNodeType::RAIL_SIGNAL:
260
return 9;
261
case SumoXMLNodeType::ZIPPER:
262
return 10;
263
case SumoXMLNodeType::TRAFFIC_LIGHT_RIGHT_ON_RED:
264
return 11;
265
case SumoXMLNodeType::RAIL_CROSSING:
266
return 12;
267
case SumoXMLNodeType::LEFT_BEFORE_RIGHT:
268
return 13;
269
default:
270
assert(false);
271
return 0;
272
}
273
case 3:
274
return myJunction.getPosition().z();
275
default:
276
assert(false);
277
return 0;
278
}
279
}
280
281
#ifdef HAVE_OSG
282
void
283
GUIJunctionWrapper::updateColor(const GUIVisualizationSettings& s) {
284
const double colorValue = getColorValue(s, s.junctionColorer.getActive());
285
const RGBColor& col = s.junctionColorer.getScheme().getColor(colorValue);
286
osg::Vec4ubArray* colors = dynamic_cast<osg::Vec4ubArray*>(myGeom->getColorArray());
287
(*colors)[0].set(col.red(), col.green(), col.blue(), col.alpha());
288
myGeom->setColorArray(colors);
289
}
290
#endif
291
292
293
/****************************************************************************/
294
295