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    GUIContainer.cpp
11 /// @author  Melanie Weber
12 /// @author  Andreas Kendziorra
13 /// @date    Wed, 01.08.2014
14 /// @version $Id$
15 ///
16 // A MSContainer extended by some values for usage within the gui
17 /****************************************************************************/
18 
19 
20 // ===========================================================================
21 // included modules
22 // ===========================================================================
23 #include <config.h>
24 
25 #include <cmath>
26 #include <vector>
27 #include <string>
28 #include <microsim/MSContainer.h>
29 #include <microsim/MSCModel_NonInteracting.h>
30 #include <microsim/logging/CastingFunctionBinding.h>
31 #include <microsim/logging/FunctionBinding.h>
32 #include <microsim/MSVehicleControl.h>
33 #include <microsim/lcmodels/MSAbstractLaneChangeModel.h>
34 #include <microsim/devices/MSDevice_Vehroutes.h>
35 #include <utils/common/StringUtils.h>
36 #include <utils/vehicle/SUMOVehicleParameter.h>
37 #include <utils/geom/GeomHelper.h>
38 #include <utils/gui/images/GUITexturesHelper.h>
39 #include <utils/gui/windows/GUISUMOAbstractView.h>
40 #include <utils/gui/windows/GUIAppEnum.h>
41 #include <utils/gui/div/GUIParameterTableWindow.h>
42 #include <utils/gui/div/GUIGlobalSelection.h>
43 #include <utils/gui/div/GLHelper.h>
44 #include <utils/gui/div/GLObjectValuePassConnector.h>
45 #include <utils/geom/PositionVector.h>
46 #include <gui/GUIApplicationWindow.h>
47 #include <gui/GUIGlobals.h>
48 #include "GUIContainer.h"
49 #include "GUINet.h"
50 #include "GUIEdge.h"
51 #include <utils/gui/globjects/GLIncludes.h>
52 
53 //#define GUIContainer_DEBUG_DRAW_WALKING_AREA_SHAPE
54 
55 // ===========================================================================
56 // FOX callback mapping
57 // ===========================================================================
58 /*
59 FXDEFMAP(GUIContainer::GUIContainerPopupMenu) GUIContainerPopupMenuMap[] = {
60     FXMAPFUNC(SEL_COMMAND, MID_SHOW_ALLROUTES, GUIContainer::GUIContainerPopupMenu::onCmdShowAllRoutes),
61     FXMAPFUNC(SEL_COMMAND, MID_HIDE_ALLROUTES, GUIContainer::GUIContainerPopupMenu::onCmdHideAllRoutes),
62     FXMAPFUNC(SEL_COMMAND, MID_SHOW_CURRENTROUTE, GUIContainer::GUIContainerPopupMenu::onCmdShowCurrentRoute),
63     FXMAPFUNC(SEL_COMMAND, MID_HIDE_CURRENTROUTE, GUIContainer::GUIContainerPopupMenu::onCmdHideCurrentRoute),
64     FXMAPFUNC(SEL_COMMAND, MID_SHOW_BEST_LANES, GUIContainer::GUIContainerPopupMenu::onCmdShowBestLanes),
65     FXMAPFUNC(SEL_COMMAND, MID_HIDE_BEST_LANES, GUIContainer::GUIContainerPopupMenu::onCmdHideBestLanes),
66     FXMAPFUNC(SEL_COMMAND, MID_START_TRACK, GUIContainer::GUIContainerPopupMenu::onCmdStartTrack),
67     FXMAPFUNC(SEL_COMMAND, MID_STOP_TRACK, GUIContainer::GUIContainerPopupMenu::onCmdStopTrack),
68     FXMAPFUNC(SEL_COMMAND, MID_SHOW_LFLINKITEMS, GUIContainer::GUIContainerPopupMenu::onCmdShowLFLinkItems),
69     FXMAPFUNC(SEL_COMMAND, MID_HIDE_LFLINKITEMS, GUIContainer::GUIContainerPopupMenu::onCmdHideLFLinkItems),
70 };
71 
72 // Object implementation
73 FXIMPLEMENT(GUIContainer::GUIContainerPopupMenu, GUIGLObjectPopupMenu, GUIContainerPopupMenuMap, ARRAYNUMBER(GUIContainerPopupMenuMap))
74 */
75 
76 #define WATER_WAY_OFFSET 6.0
77 
78 // ===========================================================================
79 // method definitions
80 // ===========================================================================
81 /* -------------------------------------------------------------------------
82  * GUIContainer::GUIContainerPopupMenu - methods
83  * ----------------------------------------------------------------------- */
GUIContainerPopupMenu(GUIMainWindow & app,GUISUMOAbstractView & parent,GUIGlObject & o,std::map<GUISUMOAbstractView *,int> & additionalVisualizations)84 GUIContainer::GUIContainerPopupMenu::GUIContainerPopupMenu(
85     GUIMainWindow& app, GUISUMOAbstractView& parent,
86     GUIGlObject& o, std::map<GUISUMOAbstractView*, int>& additionalVisualizations)
87     : GUIGLObjectPopupMenu(app, parent, o), myVehiclesAdditionalVisualizations(additionalVisualizations) {
88 }
89 
90 
~GUIContainerPopupMenu()91 GUIContainer::GUIContainerPopupMenu::~GUIContainerPopupMenu() {}
92 
93 
94 
95 /* -------------------------------------------------------------------------
96  * GUIContainer - methods
97  * ----------------------------------------------------------------------- */
GUIContainer(const SUMOVehicleParameter * pars,MSVehicleType * vtype,MSTransportable::MSTransportablePlan * plan)98 GUIContainer::GUIContainer(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan) :
99     MSContainer(pars, vtype, plan),
100     GUIGlObject(GLO_CONTAINER, pars->id) {
101 }
102 
103 
~GUIContainer()104 GUIContainer::~GUIContainer() {
105 }
106 
107 
108 GUIGLObjectPopupMenu*
getPopUpMenu(GUIMainWindow & app,GUISUMOAbstractView & parent)109 GUIContainer::getPopUpMenu(GUIMainWindow& app,
110                            GUISUMOAbstractView& parent) {
111     GUIGLObjectPopupMenu* ret = new GUIContainerPopupMenu(app, parent, *this, myAdditionalVisualizations);
112     buildPopupHeader(ret, app);
113     buildCenterPopupEntry(ret);
114     buildNameCopyPopupEntry(ret);
115     buildSelectionPopupEntry(ret);
116     //
117     buildShowParamsPopupEntry(ret);
118     buildPositionCopyEntry(ret, false);
119     return ret;
120 }
121 
122 
123 GUIParameterTableWindow*
getParameterWindow(GUIMainWindow & app,GUISUMOAbstractView &)124 GUIContainer::getParameterWindow(GUIMainWindow& app,
125                                  GUISUMOAbstractView&) {
126     GUIParameterTableWindow* ret =
127         new GUIParameterTableWindow(app, *this, 12 + (int)getParameter().getParametersMap().size());
128     // add items
129     ret->mkItem("stage", false, getCurrentStageDescription());
130     ret->mkItem("start edge [id]", false, getFromEdge()->getID());
131     ret->mkItem("dest edge [id]", false, getDestination()->getID());
132     ret->mkItem("edge [id]", false, getEdge()->getID());
133     ret->mkItem("position [m]", true, new FunctionBinding<GUIContainer, double>(this, &GUIContainer::getEdgePos));
134     ret->mkItem("speed [m/s]", true, new FunctionBinding<GUIContainer, double>(this, &GUIContainer::getSpeed));
135     ret->mkItem("speed factor", false, getSpeedFactor());
136     ret->mkItem("angle [degree]", true, new FunctionBinding<GUIContainer, double>(this, &GUIContainer::getAngle));
137     ret->mkItem("waiting time [s]", true, new FunctionBinding<GUIContainer, double>(this, &GUIContainer::getWaitingSeconds));
138     ret->mkItem("desired depart [s]", false, time2string(getParameter().depart));
139     // close building
140     ret->closeBuilding(&getParameter());
141     return ret;
142 }
143 
144 
145 GUIParameterTableWindow*
getTypeParameterWindow(GUIMainWindow & app,GUISUMOAbstractView &)146 GUIContainer::getTypeParameterWindow(GUIMainWindow& app,
147                                      GUISUMOAbstractView&) {
148     GUIParameterTableWindow* ret =
149         new GUIParameterTableWindow(app, *this, 8 + (int)myVType->getParameter().getParametersMap().size());
150     // add items
151     ret->mkItem("Type Information:", false, "");
152     ret->mkItem("type [id]", false, myVType->getID());
153     ret->mkItem("length", false, myVType->getLength());
154     ret->mkItem("width", false, myVType->getWidth());
155     ret->mkItem("height", false, myVType->getHeight());
156     ret->mkItem("minGap", false, myVType->getMinGap());
157     ret->mkItem("maximum speed [m/s]", false, myVType->getMaxSpeed());
158     // close building
159     ret->closeBuilding(&(myVType->getParameter()));
160     return ret;
161 }
162 
163 
164 Boundary
getCenteringBoundary() const165 GUIContainer::getCenteringBoundary() const {
166     Boundary b;
167     // ensure that the vehicle is drawn, otherwise myPositionInVehicle will not be updated
168     b.add(getPosition());
169     b.grow(20);
170     return b;
171 }
172 
173 
174 void
drawGL(const GUIVisualizationSettings & s) const175 GUIContainer::drawGL(const GUIVisualizationSettings& s) const {
176     glPushName(getGlID());
177     glPushMatrix();
178     Position p1 = getPosition();
179     if (getCurrentStageType() == DRIVING && !isWaiting4Vehicle()) {
180         p1 = myPositionInVehicle;
181     }
182     glTranslated(p1.x(), p1.y(), getType());
183     glRotated(90, 0, 0, 1);
184     // XXX use container specific gui settings
185     // set container color
186     setColor(s);
187     // scale
188     const double upscale = s.containerSize.getExaggeration(s, this);
189     glScaled(upscale, upscale, 1);
190     switch (s.containerQuality) {
191         case 0:
192         case 1:
193         case 2:
194             drawAction_drawAsPoly(s);
195             break;
196         case 3:
197         default:
198             drawAction_drawAsImage(s);
199             break;
200     }
201     glPopMatrix();
202 
203     drawName(p1, s.scale, s.containerName, s.angle);
204     glPopName();
205 }
206 
207 
208 void
drawGLAdditional(GUISUMOAbstractView * const,const GUIVisualizationSettings &) const209 GUIContainer::drawGLAdditional(GUISUMOAbstractView* const /* parent */, const GUIVisualizationSettings& /* s */) const {
210     glPushName(getGlID());
211     glPushMatrix();
212     /*
213     glTranslated(0, 0, getType() - .1); // don't draw on top of other cars
214     if (hasActiveAddVisualisation(parent, VO_SHOW_BEST_LANES)) {
215         drawBestLanes();
216     }
217     if (hasActiveAddVisualisation(parent, VO_SHOW_ROUTE)) {
218         drawRoute(s, 0, 0.25);
219     }
220     if (hasActiveAddVisualisation(parent, VO_SHOW_ALL_ROUTES)) {
221         if (getNumberReroutes() > 0) {
222             const int noReroutePlus1 = getNumberReroutes() + 1;
223             for (int i = noReroutePlus1 - 1; i >= 0; i--) {
224                 double darken = double(0.4) / double(noReroutePlus1) * double(i);
225                 drawRoute(s, i, darken);
226             }
227         } else {
228             drawRoute(s, 0, 0.25);
229         }
230     }
231     if (hasActiveAddVisualisation(parent, VO_SHOW_LFLINKITEMS)) {
232         for (DriveItemVector::const_iterator i = myLFLinkLanes.begin(); i != myLFLinkLanes.end(); ++i) {
233             if((*i).myLink==0) {
234                 continue;
235             }
236             MSLink* link = (*i).myLink;
237             MSLane *via = link->getViaLane();
238             if (via == 0) {
239                 via = link->getLane();
240             }
241             if (via != 0) {
242                 Position p = via->getShape()[0];
243                 if((*i).mySetRequest) {
244                     glColor3f(0, 1, 0);
245                 } else {
246                     glColor3f(1, 0, 0);
247                 }
248                 glTranslated(p.x(), p.y(), -.1);
249                 GLHelper::drawFilledCircle(1);
250                 glTranslated(-p.x(), -p.y(), .1);
251             }
252         }
253     }
254     */
255     glPopMatrix();
256     glPopName();
257 }
258 
259 
260 
261 
262 void
setColor(const GUIVisualizationSettings & s) const263 GUIContainer::setColor(const GUIVisualizationSettings& s) const {
264     const GUIColorer& c = s.containerColorer;
265     if (!setFunctionalColor(c.getActive())) {
266         GLHelper::setColor(c.getScheme().getColor(getColorValue(c.getActive())));
267     }
268 }
269 
270 
271 bool
setFunctionalColor(int activeScheme) const272 GUIContainer::setFunctionalColor(int activeScheme) const {
273     switch (activeScheme) {
274         case 0: {
275             if (getParameter().wasSet(VEHPARS_COLOR_SET)) {
276                 GLHelper::setColor(getParameter().color);
277                 return true;
278             }
279             if (getVehicleType().wasSet(VTYPEPARS_COLOR_SET)) {
280                 GLHelper::setColor(getVehicleType().getColor());
281                 return true;
282             }
283             return false;
284         }
285         case 2: {
286             if (getParameter().wasSet(VEHPARS_COLOR_SET)) {
287                 GLHelper::setColor(getParameter().color);
288                 return true;
289             }
290             return false;
291         }
292         case 3: {
293             if (getVehicleType().wasSet(VTYPEPARS_COLOR_SET)) {
294                 GLHelper::setColor(getVehicleType().getColor());
295                 return true;
296             }
297             return false;
298         }
299         case 8: {
300             double hue = GeomHelper::naviDegree(getAngle());
301             GLHelper::setColor(RGBColor::fromHSV(hue, 1., 1.));
302             return true;
303         }
304         default:
305             return false;
306     }
307 }
308 
309 
310 double
getColorValue(int activeScheme) const311 GUIContainer::getColorValue(int activeScheme) const {
312     switch (activeScheme) {
313         case 4:
314             return getSpeed();
315         case 5:
316             if (isWaiting4Vehicle()) {
317                 return 5;
318             } else {
319                 return (double)getCurrentStageType();
320             }
321         case 6:
322             return getWaitingSeconds();
323         case 7:
324             return gSelected.isSelected(GLO_CONTAINER, getGlID());
325     }
326     return 0;
327 }
328 
329 
330 double
getEdgePos() const331 GUIContainer::getEdgePos() const {
332     FXMutexLock locker(myLock);
333     return MSContainer::getEdgePos();
334 }
335 
336 
337 Position
getPosition() const338 GUIContainer::getPosition() const {
339     FXMutexLock locker(myLock);
340     if (getCurrentStageType() == WAITING && getEdge()->getPermissions() == SVC_SHIP) {
341         MSLane* lane = getEdge()->getLanes().front();   //the most right lane of the water way
342         PositionVector laneShape = lane->getShape();
343         return laneShape.positionAtOffset2D(getEdgePos(), WATER_WAY_OFFSET);
344     }
345     return MSContainer::getPosition();
346 }
347 
348 
349 double
getAngle() const350 GUIContainer::getAngle() const {
351     FXMutexLock locker(myLock);
352     return MSContainer::getAngle();
353 }
354 
355 
356 double
getWaitingSeconds() const357 GUIContainer::getWaitingSeconds() const {
358     FXMutexLock locker(myLock);
359     return MSContainer::getWaitingSeconds();
360 }
361 
362 
363 double
getSpeed() const364 GUIContainer::getSpeed() const {
365     FXMutexLock locker(myLock);
366     return MSContainer::getSpeed();
367 }
368 
369 
370 void
drawAction_drawAsPoly(const GUIVisualizationSettings &) const371 GUIContainer::drawAction_drawAsPoly(const GUIVisualizationSettings& /* s */) const {
372     // draw pedestrian shape
373     glRotated(RAD2DEG(getAngle() + M_PI / 2.), 0, 0, 1);
374     glScaled(getVehicleType().getLength(), getVehicleType().getWidth(), 1);
375     glBegin(GL_QUADS);
376     glVertex2d(0, 0.5);
377     glVertex2d(0, -0.5);
378     glVertex2d(-1, -0.5);
379     glVertex2d(-1, 0.5);
380     glEnd();
381     GLHelper::setColor(GLHelper::getColor().changedBrightness(-30));
382     glTranslated(0, 0, .045);
383     glBegin(GL_QUADS);
384     glVertex2d(-0.1, 0.4);
385     glVertex2d(-0.1, -0.4);
386     glVertex2d(-0.9, -0.4);
387     glVertex2d(-0.9, 0.4);
388     glEnd();
389 }
390 
391 
392 void
drawAction_drawAsImage(const GUIVisualizationSettings & s) const393 GUIContainer::drawAction_drawAsImage(const GUIVisualizationSettings& s) const {
394     const std::string& file = getVehicleType().getImgFile();
395     if (file != "") {
396         // @todo invent an option for controlling whether images should be rotated or not
397         //if (getVehicleType().getGuiShape() == SVS_CONTAINER) {
398         //    glRotated(RAD2DEG(getAngle() + M_PI / 2.), 0, 0, 1);
399         //}
400         int textureID = GUITexturesHelper::getTextureID(file);
401         if (textureID > 0) {
402             const double exaggeration = s.personSize.getExaggeration(s, this);
403             const double halfLength = getVehicleType().getLength() / 2.0 * exaggeration;
404             const double halfWidth = getVehicleType().getWidth() / 2.0 * exaggeration;
405             GUITexturesHelper::drawTexturedBox(textureID, -halfWidth, -halfLength, halfWidth, halfLength);
406         }
407     } else {
408         // fallback if no image is defined
409         drawAction_drawAsPoly(s);
410     }
411 }
412 /****************************************************************************/
413 
414