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