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 GUITrafficLightLogicWrapper.cpp
11 /// @author Daniel Krajzewicz
12 /// @author Jakob Erdmann
13 /// @author Michael Behrisch
14 /// @author Laura Bieker
15 /// @date Oct/Nov 2003
16 /// @version $Id$
17 ///
18 // A wrapper for tl-logics to allow their visualisation and interaction
19 /****************************************************************************/
20
21
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #include <config.h>
26
27 #include <cassert>
28 #include <utils/geom/GeomHelper.h>
29 #include <utils/gui/globjects/GUIGlObject.h>
30 #include <utils/gui/div/GLObjectValuePassConnector.h>
31 #include <utils/gui/windows/GUIAppEnum.h>
32 #include <utils/gui/images/GUIIconSubSys.h>
33 #include <utils/gui/div/GLHelper.h>
34 #include <utils/gui/div/GUIParameterTableWindow.h>
35 #include <utils/gui/globjects/GUIGLObjectPopupMenu.h>
36 #include <utils/gui/div/GUIGlobalSelection.h>
37 #include <microsim/MSLane.h>
38 #include <microsim/traffic_lights/MSTrafficLightLogic.h>
39 #include <microsim/traffic_lights/MSTLLogicControl.h>
40 #include <microsim/logging/FunctionBinding.h>
41 #include <microsim/logging/FuncBinding_StringParam.h>
42 #include <gui/GUIApplicationWindow.h>
43 #include <gui/GUITLLogicPhasesTrackerWindow.h>
44 #include <gui/GUIGlobals.h>
45 #include "GUITrafficLightLogicWrapper.h"
46 #include "GUINet.h"
47 #include <utils/gui/globjects/GLIncludes.h>
48
49
50 // ===========================================================================
51 // FOX callback mapping
52 // ===========================================================================
53 FXDEFMAP(GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu)
54 GUITrafficLightLogicWrapperPopupMenuMap[] = {
55 FXMAPFUNC(SEL_COMMAND, MID_SHOWPHASES, GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::onCmdShowPhases),
56 FXMAPFUNC(SEL_COMMAND, MID_TRACKPHASES, GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::onCmdBegin2TrackPhases),
57 FXMAPFUNC(SEL_COMMAND, MID_SWITCH_OFF, GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::onCmdSwitchTLS2Off),
58 FXMAPFUNCS(SEL_COMMAND, MID_SWITCH, MID_SWITCH + 20, GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::onCmdSwitchTLSLogic),
59 };
60
61 // Object implementation
FXIMPLEMENT(GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu,GUIGLObjectPopupMenu,GUITrafficLightLogicWrapperPopupMenuMap,ARRAYNUMBER (GUITrafficLightLogicWrapperPopupMenuMap))62 FXIMPLEMENT(GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu, GUIGLObjectPopupMenu, GUITrafficLightLogicWrapperPopupMenuMap, ARRAYNUMBER(GUITrafficLightLogicWrapperPopupMenuMap))
63
64
65 // ===========================================================================
66 // method definitions
67 // ===========================================================================
68 /* -------------------------------------------------------------------------
69 * GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu - methods
70 * ----------------------------------------------------------------------- */
71 GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::GUITrafficLightLogicWrapperPopupMenu(
72 GUIMainWindow& app, GUISUMOAbstractView& parent,
73 GUIGlObject& o)
74 : GUIGLObjectPopupMenu(app, parent, o) {}
75
76
~GUITrafficLightLogicWrapperPopupMenu()77 GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::~GUITrafficLightLogicWrapperPopupMenu() {}
78
79
80
81 long
onCmdBegin2TrackPhases(FXObject *,FXSelector,void *)82 GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::onCmdBegin2TrackPhases(
83 FXObject*, FXSelector, void*) {
84 assert(myObject->getType() == GLO_TLLOGIC);
85 static_cast<GUITrafficLightLogicWrapper*>(myObject)->begin2TrackPhases();
86 return 1;
87 }
88
89
90 long
onCmdShowPhases(FXObject *,FXSelector,void *)91 GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::onCmdShowPhases(
92 FXObject*, FXSelector, void*) {
93 assert(myObject->getType() == GLO_TLLOGIC);
94 static_cast<GUITrafficLightLogicWrapper*>(myObject)->showPhases();
95 return 1;
96 }
97
98
99 long
onCmdSwitchTLS2Off(FXObject *,FXSelector,void *)100 GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::onCmdSwitchTLS2Off(
101 FXObject*, FXSelector /*sel*/, void*) {
102 assert(myObject->getType() == GLO_TLLOGIC);
103 static_cast<GUITrafficLightLogicWrapper*>(myObject)->switchTLSLogic(-1);
104 return 1;
105 }
106
107
108 long
onCmdSwitchTLSLogic(FXObject *,FXSelector sel,void *)109 GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::onCmdSwitchTLSLogic(
110 FXObject*, FXSelector sel, void*) {
111 assert(myObject->getType() == GLO_TLLOGIC);
112 static_cast<GUITrafficLightLogicWrapper*>(myObject)->switchTLSLogic(FXSELID(sel) - MID_SWITCH);
113 return 1;
114 }
115
116
117
118 /* -------------------------------------------------------------------------
119 * GUITrafficLightLogicWrapper - methods
120 * ----------------------------------------------------------------------- */
GUITrafficLightLogicWrapper(MSTLLogicControl & control,MSTrafficLightLogic & tll)121 GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapper(
122 MSTLLogicControl& control, MSTrafficLightLogic& tll) :
123 GUIGlObject(GLO_TLLOGIC, tll.getID()),
124 myTLLogicControl(control), myTLLogic(tll) {}
125
126
~GUITrafficLightLogicWrapper()127 GUITrafficLightLogicWrapper::~GUITrafficLightLogicWrapper() {}
128
129
130 GUIGLObjectPopupMenu*
getPopUpMenu(GUIMainWindow & app,GUISUMOAbstractView & parent)131 GUITrafficLightLogicWrapper::getPopUpMenu(GUIMainWindow& app,
132 GUISUMOAbstractView& parent) {
133 myApp = &app;
134 GUIGLObjectPopupMenu* ret = new GUITrafficLightLogicWrapperPopupMenu(app, parent, *this);
135 buildPopupHeader(ret, app);
136 buildCenterPopupEntry(ret);
137 //
138 const MSTLLogicControl::TLSLogicVariants& vars = myTLLogicControl.get(myTLLogic.getID());
139 std::vector<MSTrafficLightLogic*> logics = vars.getAllLogics();
140 if (logics.size() > 1) {
141 std::vector<MSTrafficLightLogic*>::const_iterator i;
142 int index = 0;
143 for (i = logics.begin(); i != logics.end(); ++i, ++index) {
144 if (!vars.isActive(*i)) {
145 new FXMenuCommand(ret, ("Switch to '" + (*i)->getProgramID() + "'").c_str(),
146 GUIIconSubSys::getIcon(ICON_FLAG_MINUS), ret, (FXSelector)(MID_SWITCH + index));
147 }
148 }
149 new FXMenuSeparator(ret);
150 }
151 new FXMenuCommand(ret, "Switch off", GUIIconSubSys::getIcon(ICON_FLAG_MINUS), ret, MID_SWITCH_OFF);
152 new FXMenuCommand(ret, "Track Phases", nullptr, ret, MID_TRACKPHASES);
153 new FXMenuCommand(ret, "Show Phases", nullptr, ret, MID_SHOWPHASES);
154 new FXMenuSeparator(ret);
155 MSTrafficLightLogic* tll = myTLLogicControl.getActive(myTLLogic.getID());
156 buildNameCopyPopupEntry(ret);
157 buildSelectionPopupEntry(ret);
158 new FXMenuCommand(ret, ("phase: " + toString(tll->getCurrentPhaseIndex())).c_str(), nullptr, nullptr, 0);
159 const std::string& name = myTLLogic.getCurrentPhaseDef().getName();
160 if (name != "") {
161 new FXMenuCommand(ret, ("phase name: " + name).c_str(), nullptr, nullptr, 0);
162 }
163 new FXMenuSeparator(ret);
164 buildShowParamsPopupEntry(ret, false);
165 buildPositionCopyEntry(ret, false);
166 return ret;
167 }
168
169
170 void
begin2TrackPhases()171 GUITrafficLightLogicWrapper::begin2TrackPhases() {
172 GUITLLogicPhasesTrackerWindow* window =
173 new GUITLLogicPhasesTrackerWindow(*myApp, myTLLogic, *this,
174 new FuncBinding_StringParam<MSTLLogicControl, std::pair<SUMOTime, MSPhaseDefinition> >
175 (&MSNet::getInstance()->getTLSControl(), &MSTLLogicControl::getPhaseDef, myTLLogic.getID()));
176 window->create();
177 window->show();
178 }
179
180
181 void
showPhases()182 GUITrafficLightLogicWrapper::showPhases() {
183 GUITLLogicPhasesTrackerWindow* window =
184 new GUITLLogicPhasesTrackerWindow(*myApp, myTLLogic, *this,
185 static_cast<MSSimpleTrafficLightLogic&>(myTLLogic).getPhases());
186 window->setBeginTime(0);
187 window->create();
188 window->show();
189 }
190
191
192 GUIParameterTableWindow*
getParameterWindow(GUIMainWindow & app,GUISUMOAbstractView &)193 GUITrafficLightLogicWrapper::getParameterWindow(GUIMainWindow& app,
194 GUISUMOAbstractView&) {
195 GUIParameterTableWindow* ret =
196 new GUIParameterTableWindow(app, *this, 3 + (int)myTLLogic.getParametersMap().size());
197 ret->mkItem("tlLogic [id]", false, myTLLogic.getID());
198 ret->mkItem("program", false, myTLLogic.getProgramID());
199 // close building
200 ret->closeBuilding(&myTLLogic);
201 return ret;
202 }
203
204
205 Boundary
getCenteringBoundary() const206 GUITrafficLightLogicWrapper::getCenteringBoundary() const {
207 Boundary ret;
208 const MSTrafficLightLogic::LaneVectorVector& lanes = myTLLogic.getLaneVectors();
209 for (MSTrafficLightLogic::LaneVectorVector::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
210 const MSTrafficLightLogic::LaneVector& lanes2 = (*i);
211 for (MSTrafficLightLogic::LaneVector::const_iterator j = lanes2.begin(); j != lanes2.end(); ++j) {
212 ret.add((*j)->getShape()[-1]);
213 }
214 }
215 ret.grow(20);
216 return ret;
217 }
218
219
220 void
switchTLSLogic(int to)221 GUITrafficLightLogicWrapper::switchTLSLogic(int to) {
222 if (to == -1) {
223 myTLLogicControl.switchTo(myTLLogic.getID(), "off");
224 MSTrafficLightLogic* tll = myTLLogicControl.getActive(myTLLogic.getID());
225 GUINet::getGUIInstance()->createTLWrapper(tll);
226 } else {
227 const MSTLLogicControl::TLSLogicVariants& vars = myTLLogicControl.get(myTLLogic.getID());
228 std::vector<MSTrafficLightLogic*> logics = vars.getAllLogics();
229 myTLLogicControl.switchTo(myTLLogic.getID(), logics[to]->getProgramID());
230 }
231 }
232
233
234 int
getLinkIndex(const MSLink * const link) const235 GUITrafficLightLogicWrapper::getLinkIndex(const MSLink* const link) const {
236 return myTLLogic.getLinkIndex(link);
237 }
238
239
240 void
drawGL(const GUIVisualizationSettings & s) const241 GUITrafficLightLogicWrapper::drawGL(const GUIVisualizationSettings& s) const {
242 if (s.gaming) {
243 if (!MSNet::getInstance()->getTLSControl().isActive(&myTLLogic)) {
244 return;
245 };
246 const std::string& curState = myTLLogic.getCurrentPhaseDef().getState();
247 if (curState.find_first_of("gG") == std::string::npos) {
248 // no link is 'green' at the moment. find those that turn green next
249 const MSTrafficLightLogic::Phases& phases = myTLLogic.getPhases();
250 int curPhaseIdx = myTLLogic.getCurrentPhaseIndex();
251 int phaseIdx = (curPhaseIdx + 1) % phases.size();
252 std::vector<int> nextGreen;
253 while (phaseIdx != curPhaseIdx) {
254 const std::string& state = phases[phaseIdx]->getState();
255 for (int linkIdx = 0; linkIdx < (int)state.size(); linkIdx++) {
256 if ((LinkState)state[linkIdx] == LINKSTATE_TL_GREEN_MINOR ||
257 (LinkState)state[linkIdx] == LINKSTATE_TL_GREEN_MAJOR) {
258 nextGreen.push_back(linkIdx);
259 }
260 }
261 if (nextGreen.size() > 0) {
262 break;
263 }
264 phaseIdx = (phaseIdx + 1) % phases.size();
265 }
266 // highlight nextGreen links
267 for (std::vector<int>::iterator it_idx = nextGreen.begin(); it_idx != nextGreen.end(); it_idx++) {
268 const MSTrafficLightLogic::LaneVector& lanes = myTLLogic.getLanesAt(*it_idx);
269 for (MSTrafficLightLogic::LaneVector::const_iterator it_lane = lanes.begin(); it_lane != lanes.end(); it_lane++) {
270 glPushMatrix();
271 // split circle in red and yellow
272 Position pos = (*it_lane)->getShape().back();
273 glTranslated(pos.x(), pos.y(), GLO_MAX);
274 double rot = RAD2DEG((*it_lane)->getShape().angleAt2D((int)(*it_lane)->getShape().size() - 2)) - 90;
275 glRotated(rot, 0, 0, 1);
276 GLHelper::setColor(s.getLinkColor(LINKSTATE_TL_RED));
277 GLHelper::drawFilledCircle((*it_lane)->getWidth() / 2., 8, -90, 90);
278 GLHelper::setColor(s.getLinkColor(LINKSTATE_TL_YELLOW_MAJOR));
279 GLHelper::drawFilledCircle((*it_lane)->getWidth() / 2., 8, 90, 270);
280 glPopMatrix();
281 }
282 }
283 }
284 }
285 }
286
287
288 /****************************************************************************/
289
290