1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file GUIJunctionWrapper.cpp
11 /// @author Daniel Krajzewicz
12 /// @author Jakob Erdmann
13 /// @author Michael Behrisch
14 /// @author Laura Bieker
15 /// @author Andreas Gaubatz
16 /// @date Mon, 1 Jul 2003
17 /// @version $Id$
18 ///
19 // }
20 /****************************************************************************/
21
22
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #include <config.h>
27
28 #include <string>
29 #include <utility>
30 #ifdef HAVE_OSG
31 #include <osg/Geometry>
32 #endif
33 #include <microsim/MSLane.h>
34 #include <microsim/MSEdge.h>
35 #include <microsim/MSJunction.h>
36 #include <utils/geom/Position.h>
37 #include <utils/geom/GeomHelper.h>
38 #include <microsim/MSNet.h>
39 #include <microsim/MSInternalJunction.h>
40 #include <microsim/traffic_lights/MSTrafficLightLogic.h>
41 #include <microsim/traffic_lights/MSTLLogicControl.h>
42 #include <gui/GUIApplicationWindow.h>
43 #include <gui/GUIGlobals.h>
44 #include <utils/gui/windows/GUIAppEnum.h>
45 #include <utils/gui/windows/GUISUMOAbstractView.h>
46 #include "GUIJunctionWrapper.h"
47 #include <utils/gui/globjects/GUIGLObjectPopupMenu.h>
48 #include <utils/gui/div/GUIGlobalSelection.h>
49 #include <utils/gui/div/GUIParameterTableWindow.h>
50 #include <utils/gui/div/GLHelper.h>
51 #include <utils/gui/globjects/GLIncludes.h>
52
53 //#define GUIJunctionWrapper_DEBUG_DRAW_NODE_SHAPE_VERTICES
54
55 // ===========================================================================
56 // method definitions
57 // ===========================================================================
GUIJunctionWrapper(MSJunction & junction,const std::string & tllID)58 GUIJunctionWrapper::GUIJunctionWrapper(MSJunction& junction, const std::string& tllID):
59 GUIGlObject(GLO_JUNCTION, junction.getID()),
60 myJunction(junction),
61 myTLLID(tllID) {
62 if (myJunction.getShape().size() == 0) {
63 Position pos = myJunction.getPosition();
64 myBoundary = Boundary(pos.x() - 1., pos.y() - 1., pos.x() + 1., pos.y() + 1.);
65 } else {
66 myBoundary = myJunction.getShape().getBoxBoundary();
67 }
68 myMaxSize = MAX2(myBoundary.getWidth(), myBoundary.getHeight());
69 myIsInternal = myJunction.getType() == NODETYPE_INTERNAL;
70 myAmWaterway = myJunction.getIncoming().size() + myJunction.getOutgoing().size() > 0;
71 myAmRailway = myJunction.getIncoming().size() + myJunction.getOutgoing().size() > 0;
72 for (auto it = myJunction.getIncoming().begin(); it != myJunction.getIncoming().end() && (myAmWaterway || myAmRailway); ++it) {
73 if (!(*it)->isInternal()) {
74 if (!isWaterway((*it)->getPermissions())) {
75 myAmWaterway = false;
76 }
77 if (!isRailway((*it)->getPermissions())) {
78 myAmRailway = false;
79 }
80 }
81 }
82 for (auto it = myJunction.getOutgoing().begin(); it != myJunction.getOutgoing().end() && (myAmWaterway || myAmRailway); ++it) {
83 if (!(*it)->isInternal()) {
84 if (!isWaterway((*it)->getPermissions())) {
85 myAmWaterway = false;
86 }
87 if (!isRailway((*it)->getPermissions())) {
88 myAmRailway = false;
89 }
90 }
91 }
92 }
93
94
~GUIJunctionWrapper()95 GUIJunctionWrapper::~GUIJunctionWrapper() {}
96
97
98 GUIGLObjectPopupMenu*
getPopUpMenu(GUIMainWindow & app,GUISUMOAbstractView & parent)99 GUIJunctionWrapper::getPopUpMenu(GUIMainWindow& app,
100 GUISUMOAbstractView& parent) {
101 GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
102 buildPopupHeader(ret, app);
103 buildCenterPopupEntry(ret);
104 buildNameCopyPopupEntry(ret);
105 buildSelectionPopupEntry(ret);
106 buildShowParamsPopupEntry(ret);
107 buildPositionCopyEntry(ret, false);
108 return ret;
109 }
110
111
112 GUIParameterTableWindow*
getParameterWindow(GUIMainWindow & app,GUISUMOAbstractView &)113 GUIJunctionWrapper::getParameterWindow(GUIMainWindow& app, GUISUMOAbstractView&) {
114 GUIParameterTableWindow* ret =
115 new GUIParameterTableWindow(app, *this, 12 + (int)myJunction.getParametersMap().size());
116 // add items
117 ret->mkItem("type", false, toString(myJunction.getType()));
118 // close building
119 ret->closeBuilding(&myJunction);
120 return ret;
121 }
122
123
124 Boundary
getCenteringBoundary() const125 GUIJunctionWrapper::getCenteringBoundary() const {
126 Boundary b = myBoundary;
127 b.grow(1);
128 return b;
129 }
130
131
132 void
drawGL(const GUIVisualizationSettings & s) const133 GUIJunctionWrapper::drawGL(const GUIVisualizationSettings& s) const {
134 if (!myIsInternal && s.drawJunctionShape) {
135 // check whether it is not too small
136 const double exaggeration = s.junctionSize.getExaggeration(s, this, 4);
137 if (s.scale * exaggeration >= s.junctionSize.minSize) {
138 glPushMatrix();
139 glPushName(getGlID());
140 const double colorValue = getColorValue(s);
141 const RGBColor color = s.junctionColorer.getScheme().getColor(colorValue);
142 GLHelper::setColor(color);
143
144 // recognize full transparency and simply don't draw
145 if (color.alpha() != 0) {
146 PositionVector shape = myJunction.getShape();
147 shape.closePolygon();
148 if (exaggeration > 1) {
149 shape.scaleRelative(exaggeration);
150 }
151 glTranslated(0, 0, getType());
152 if (s.scale * myMaxSize < 40.) {
153 GLHelper::drawFilledPoly(shape, true);
154 } else {
155 GLHelper::drawFilledPolyTesselated(shape, true);
156 }
157 #ifdef GUIJunctionWrapper_DEBUG_DRAW_NODE_SHAPE_VERTICES
158 GLHelper::debugVertices(shape, 80 / s.scale);
159 #endif
160 // make small junctions more visible when coloring by type
161 if (myJunction.getType() == NODETYPE_RAIL_SIGNAL && s.junctionColorer.getActive() == 2) {
162 glTranslated(myJunction.getPosition().x(), myJunction.getPosition().y(), getType() + 0.05);
163 GLHelper::drawFilledCircle(2 * exaggeration, 12);
164 }
165 }
166 glPopName();
167 glPopMatrix();
168 }
169 }
170 if (myIsInternal) {
171 drawName(myJunction.getPosition(), s.scale, s.internalJunctionName, s.angle);
172 } else {
173 drawName(myJunction.getPosition(), s.scale, s.junctionName, s.angle);
174 if (s.tlsPhaseIndex.show && myTLLID != "") {
175 const MSTrafficLightLogic* active = MSNet::getInstance()->getTLSControl().getActive(myTLLID);
176 const int index = active->getCurrentPhaseIndex();
177 const std::string& name = active->getCurrentPhaseDef().getName();
178 GLHelper::drawTextSettings(s.tlsPhaseIndex, toString(index), myJunction.getPosition(), s.scale, s.angle);
179 if (name != "") {
180 const Position offset = Position(0, 0.8 * s.tlsPhaseIndex.scaledSize(s.scale)).rotateAround2D(DEG2RAD(-s.angle), Position(0, 0));
181 GLHelper::drawTextSettings(s.tlsPhaseIndex, name, myJunction.getPosition() - offset, s.scale, s.angle);
182 }
183 }
184 }
185 }
186
187
188 double
getColorValue(const GUIVisualizationSettings & s) const189 GUIJunctionWrapper::getColorValue(const GUIVisualizationSettings& s) const {
190 switch (s.junctionColorer.getActive()) {
191 case 0:
192 if (myAmWaterway) {
193 return 1;
194 } else if (myAmRailway && MSNet::getInstance()->hasInternalLinks()) {
195 return 2;
196 } else {
197 return 0;
198 }
199 case 1:
200 return gSelected.isSelected(getType(), getGlID()) ? 1 : 0;
201 case 2:
202 switch (myJunction.getType()) {
203 case NODETYPE_TRAFFIC_LIGHT:
204 return 0;
205 case NODETYPE_TRAFFIC_LIGHT_NOJUNCTION:
206 return 1;
207 case NODETYPE_PRIORITY:
208 return 2;
209 case NODETYPE_PRIORITY_STOP:
210 return 3;
211 case NODETYPE_RIGHT_BEFORE_LEFT:
212 return 4;
213 case NODETYPE_ALLWAY_STOP:
214 return 5;
215 case NODETYPE_DISTRICT:
216 return 6;
217 case NODETYPE_NOJUNCTION:
218 return 7;
219 case NODETYPE_DEAD_END:
220 case NODETYPE_DEAD_END_DEPRECATED:
221 return 8;
222 case NODETYPE_UNKNOWN:
223 case NODETYPE_INTERNAL:
224 assert(false);
225 return 8;
226 case NODETYPE_RAIL_SIGNAL:
227 return 9;
228 case NODETYPE_ZIPPER:
229 return 10;
230 case NODETYPE_TRAFFIC_LIGHT_RIGHT_ON_RED:
231 return 11;
232 case NODETYPE_RAIL_CROSSING:
233 return 12;
234 }
235 case 3:
236 return myJunction.getPosition().z();
237 default:
238 assert(false);
239 return 0;
240 }
241 }
242
243 #ifdef HAVE_OSG
244 void
updateColor(const GUIVisualizationSettings & s)245 GUIJunctionWrapper::updateColor(const GUIVisualizationSettings& s) {
246 const double colorValue = getColorValue(s);
247 const RGBColor& col = s.junctionColorer.getScheme().getColor(colorValue);
248 osg::Vec4ubArray* colors = dynamic_cast<osg::Vec4ubArray*>(myGeom->getColorArray());
249 (*colors)[0].set(col.red(), col.green(), col.blue(), col.alpha());
250 myGeom->setColorArray(colors);
251 }
252 #endif
253
254
255 /****************************************************************************/
256
257