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