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    GUIPerson.cpp
11 /// @author  Daniel Krajzewicz
12 /// @author  Jakob Erdmann
13 /// @author  Michael Behrisch
14 /// @date    Sept 2002
15 /// @version $Id$
16 ///
17 // A MSPerson extended by some values for usage within the gui
18 /****************************************************************************/
19 
20 
21 // ===========================================================================
22 // included modules
23 // ===========================================================================
24 #include <config.h>
25 
26 #include <cmath>
27 #include <vector>
28 #include <string>
29 #include <microsim/MSVehicleControl.h>
30 #include <microsim/MSVehicleType.h>
31 #include <microsim/pedestrians/MSPerson.h>
32 #include <microsim/pedestrians/MSPModel_Striping.h>
33 #include <microsim/logging/CastingFunctionBinding.h>
34 #include <microsim/logging/FunctionBinding.h>
35 #include <microsim/devices/MSDevice_Vehroutes.h>
36 #include <utils/common/StringUtils.h>
37 #include <utils/vehicle/SUMOVehicleParameter.h>
38 #include <utils/geom/GeomHelper.h>
39 #include <utils/gui/images/GUITexturesHelper.h>
40 #include <utils/gui/windows/GUISUMOAbstractView.h>
41 #include <utils/gui/windows/GUIAppEnum.h>
42 #include <utils/gui/div/GUIParameterTableWindow.h>
43 #include <utils/gui/div/GUIGlobalSelection.h>
44 #include <utils/gui/div/GLHelper.h>
45 #include <utils/gui/div/GLObjectValuePassConnector.h>
46 #include <utils/gui/globjects/GLIncludes.h>
47 #include <utils/gui/images/GUIIconSubSys.h>
48 #include <gui/GUIApplicationWindow.h>
49 #include <gui/GUIGlobals.h>
50 #include "GUILane.h"
51 #include "GUINet.h"
52 #include "GUIEdge.h"
53 #include "GUIPerson.h"
54 
55 //#define GUIPerson_DEBUG_DRAW_WALKINGAREA_PATHS 1
56 
57 // ===========================================================================
58 // FOX callback mapping
59 // ===========================================================================
60 FXDEFMAP(GUIPerson::GUIPersonPopupMenu) GUIPersonPopupMenuMap[] = {
61     FXMAPFUNC(SEL_COMMAND, MID_SHOW_CURRENTROUTE,     GUIPerson::GUIPersonPopupMenu::onCmdShowCurrentRoute),
62     FXMAPFUNC(SEL_COMMAND, MID_HIDE_CURRENTROUTE,     GUIPerson::GUIPersonPopupMenu::onCmdHideCurrentRoute),
63     FXMAPFUNC(SEL_COMMAND, MID_SHOW_WALKINGAREA_PATH, GUIPerson::GUIPersonPopupMenu::onCmdShowWalkingareaPath),
64     FXMAPFUNC(SEL_COMMAND, MID_HIDE_WALKINGAREA_PATH, GUIPerson::GUIPersonPopupMenu::onCmdHideWalkingareaPath),
65     FXMAPFUNC(SEL_COMMAND, MID_SHOWPLAN,              GUIPerson::GUIPersonPopupMenu::onCmdShowPlan),
66     FXMAPFUNC(SEL_COMMAND, MID_START_TRACK,           GUIPerson::GUIPersonPopupMenu::onCmdStartTrack),
67     FXMAPFUNC(SEL_COMMAND, MID_STOP_TRACK,            GUIPerson::GUIPersonPopupMenu::onCmdStopTrack),
68 };
69 
70 // Object implementation
FXIMPLEMENT(GUIPerson::GUIPersonPopupMenu,GUIGLObjectPopupMenu,GUIPersonPopupMenuMap,ARRAYNUMBER (GUIPersonPopupMenuMap))71 FXIMPLEMENT(GUIPerson::GUIPersonPopupMenu, GUIGLObjectPopupMenu, GUIPersonPopupMenuMap, ARRAYNUMBER(GUIPersonPopupMenuMap))
72 
73 
74 
75 // ===========================================================================
76 // method definitions
77 // ===========================================================================
78 /* -------------------------------------------------------------------------
79  * GUIPerson::GUIPersonPopupMenu - methods
80  * ----------------------------------------------------------------------- */
81 GUIPerson::GUIPersonPopupMenu::GUIPersonPopupMenu(
82     GUIMainWindow& app, GUISUMOAbstractView& parent,
83     GUIGlObject& o, std::map<GUISUMOAbstractView*, int>& additionalVisualizations) :
84     GUIGLObjectPopupMenu(app, parent, o),
85     myVehiclesAdditionalVisualizations(additionalVisualizations) {
86 }
87 
88 
~GUIPersonPopupMenu()89 GUIPerson::GUIPersonPopupMenu::~GUIPersonPopupMenu() {}
90 
91 long
onCmdShowCurrentRoute(FXObject *,FXSelector,void *)92 GUIPerson::GUIPersonPopupMenu::onCmdShowCurrentRoute(FXObject*, FXSelector, void*) {
93     assert(myObject->getType() == GLO_PERSON);
94     if (!static_cast<GUIPerson*>(myObject)->hasActiveAddVisualisation(myParent, VO_SHOW_ROUTE)) {
95         static_cast<GUIPerson*>(myObject)->addActiveAddVisualisation(myParent, VO_SHOW_ROUTE);
96     }
97     return 1;
98 }
99 
100 long
onCmdHideCurrentRoute(FXObject *,FXSelector,void *)101 GUIPerson::GUIPersonPopupMenu::onCmdHideCurrentRoute(FXObject*, FXSelector, void*) {
102     assert(myObject->getType() == GLO_PERSON);
103     static_cast<GUIPerson*>(myObject)->removeActiveAddVisualisation(myParent, VO_SHOW_ROUTE);
104     return 1;
105 }
106 
107 
108 
109 long
onCmdShowWalkingareaPath(FXObject *,FXSelector,void *)110 GUIPerson::GUIPersonPopupMenu::onCmdShowWalkingareaPath(FXObject*, FXSelector, void*) {
111     assert(myObject->getType() == GLO_PERSON);
112     if (!static_cast<GUIPerson*>(myObject)->hasActiveAddVisualisation(myParent, VO_SHOW_WALKINGAREA_PATH)) {
113         static_cast<GUIPerson*>(myObject)->addActiveAddVisualisation(myParent, VO_SHOW_WALKINGAREA_PATH);
114     }
115     return 1;
116 }
117 
118 long
onCmdHideWalkingareaPath(FXObject *,FXSelector,void *)119 GUIPerson::GUIPersonPopupMenu::onCmdHideWalkingareaPath(FXObject*, FXSelector, void*) {
120     assert(myObject->getType() == GLO_PERSON);
121     static_cast<GUIPerson*>(myObject)->removeActiveAddVisualisation(myParent, VO_SHOW_WALKINGAREA_PATH);
122     return 1;
123 }
124 
125 
126 long
onCmdShowPlan(FXObject *,FXSelector,void *)127 GUIPerson::GUIPersonPopupMenu::onCmdShowPlan(FXObject*, FXSelector, void*) {
128     GUIPerson* p = dynamic_cast<GUIPerson*>(myObject);
129     if (p == nullptr) {
130         return 1;
131     }
132     GUIParameterTableWindow* ret = new GUIParameterTableWindow(*myApplication, *p, p->getNumStages());
133     // add items
134     for (int stage = 1; stage < p->getNumStages(); stage++) {
135         ret->mkItem(toString(stage).c_str(), false, p->getStageSummary(stage));
136     }
137     // close building (use an object that is not Parameterised as argument)
138     Parameterised dummy;
139     ret->closeBuilding(&dummy);
140     return 1;
141 }
142 
143 
144 long
onCmdStartTrack(FXObject *,FXSelector,void *)145 GUIPerson::GUIPersonPopupMenu::onCmdStartTrack(FXObject*, FXSelector, void*) {
146     assert(myObject->getType() == GLO_PERSON);
147     if (myParent->getTrackedID() != static_cast<GUIPerson*>(myObject)->getGlID()) {
148         myParent->startTrack(static_cast<GUIPerson*>(myObject)->getGlID());
149     }
150     return 1;
151 }
152 
153 long
onCmdStopTrack(FXObject *,FXSelector,void *)154 GUIPerson::GUIPersonPopupMenu::onCmdStopTrack(FXObject*, FXSelector, void*) {
155     assert(myObject->getType() == GLO_PERSON);
156     myParent->stopTrack();
157     return 1;
158 }
159 
160 
161 
162 
163 /* -------------------------------------------------------------------------
164  * GUIPerson - methods
165  * ----------------------------------------------------------------------- */
GUIPerson(const SUMOVehicleParameter * pars,MSVehicleType * vtype,MSTransportable::MSTransportablePlan * plan,const double speedFactor)166 GUIPerson::GUIPerson(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan, const double speedFactor) :
167     MSPerson(pars, vtype, plan, speedFactor),
168     GUIGlObject(GLO_PERSON, pars->id),
169     myPositionInVehicle(Position::INVALID) {
170 }
171 
172 
~GUIPerson()173 GUIPerson::~GUIPerson() {
174     myLock.lock();
175     for (std::map<GUISUMOAbstractView*, int>::iterator i = myAdditionalVisualizations.begin(); i != myAdditionalVisualizations.end(); ++i) {
176         if (i->first->getTrackedID() == getGlID()) {
177             i->first->stopTrack();
178         }
179         while (i->first->removeAdditionalGLVisualisation(this));
180     }
181     myLock.unlock();
182 }
183 
184 
185 GUIGLObjectPopupMenu*
getPopUpMenu(GUIMainWindow & app,GUISUMOAbstractView & parent)186 GUIPerson::getPopUpMenu(GUIMainWindow& app,
187                         GUISUMOAbstractView& parent) {
188     GUIGLObjectPopupMenu* ret = new GUIPersonPopupMenu(app, parent, *this, myAdditionalVisualizations);
189     buildPopupHeader(ret, app);
190     buildCenterPopupEntry(ret);
191     buildNameCopyPopupEntry(ret);
192     buildSelectionPopupEntry(ret);
193     if (hasActiveAddVisualisation(&parent, VO_SHOW_ROUTE)) {
194         new FXMenuCommand(ret, "Hide Current Route", nullptr, ret, MID_HIDE_CURRENTROUTE);
195     } else {
196         new FXMenuCommand(ret, "Show Current Route", nullptr, ret, MID_SHOW_CURRENTROUTE);
197     }
198     if (hasActiveAddVisualisation(&parent, VO_SHOW_WALKINGAREA_PATH)) {
199         new FXMenuCommand(ret, "Hide Walkingarea Path", nullptr, ret, MID_HIDE_WALKINGAREA_PATH);
200     } else {
201         new FXMenuCommand(ret, "Show Walkingarea Path", nullptr, ret, MID_SHOW_WALKINGAREA_PATH);
202     }
203     new FXMenuSeparator(ret);
204     if (parent.getTrackedID() != getGlID()) {
205         new FXMenuCommand(ret, "Start Tracking", nullptr, ret, MID_START_TRACK);
206     } else {
207         new FXMenuCommand(ret, "Stop Tracking", nullptr, ret, MID_STOP_TRACK);
208     }
209     new FXMenuSeparator(ret);
210     //
211     buildShowParamsPopupEntry(ret);
212     buildShowTypeParamsPopupEntry(ret);
213     new FXMenuCommand(ret, "Show Plan", GUIIconSubSys::getIcon(ICON_APP_TABLE), ret, MID_SHOWPLAN);
214     new FXMenuSeparator(ret);
215     buildPositionCopyEntry(ret, false);
216     return ret;
217 }
218 
219 
220 GUIParameterTableWindow*
getParameterWindow(GUIMainWindow & app,GUISUMOAbstractView &)221 GUIPerson::getParameterWindow(GUIMainWindow& app,
222                               GUISUMOAbstractView&) {
223     GUIParameterTableWindow* ret =
224         new GUIParameterTableWindow(app, *this, 12 + (int)getParameter().getParametersMap().size());
225     // add items
226     ret->mkItem("stage", false, getCurrentStageDescription());
227     // there is always the "start" stage which we do not count here because it is not strictly part of the plan
228     ret->mkItem("stage index", false, toString(getNumStages() - getNumRemainingStages()) + " of " + toString(getNumStages() - 1));
229     ret->mkItem("start edge [id]", false, getFromEdge()->getID());
230     ret->mkItem("dest edge [id]", false, getDestination()->getID());
231     ret->mkItem("arrivalPos [m]", false, toString(getCurrentStage()->getArrivalPos()));
232     ret->mkItem("edge [id]", false, getEdge()->getID());
233     ret->mkItem("position [m]", true, new FunctionBinding<GUIPerson, double>(this, &GUIPerson::getEdgePos));
234     ret->mkItem("speed [m/s]", true, new FunctionBinding<GUIPerson, double>(this, &GUIPerson::getSpeed));
235     ret->mkItem("speed factor", false, getSpeedFactor());
236     ret->mkItem("angle [degree]", true, new FunctionBinding<GUIPerson, double>(this, &GUIPerson::getNaviDegree));
237     ret->mkItem("waiting time [s]", true, new FunctionBinding<GUIPerson, double>(this, &GUIPerson::getWaitingSeconds));
238     ret->mkItem("desired depart [s]", false, time2string(getParameter().depart));
239     // close building
240     ret->closeBuilding(&getParameter());
241     return ret;
242 }
243 
244 
245 GUIParameterTableWindow*
getTypeParameterWindow(GUIMainWindow & app,GUISUMOAbstractView &)246 GUIPerson::getTypeParameterWindow(GUIMainWindow& app,
247                                   GUISUMOAbstractView&) {
248     GUIParameterTableWindow* ret =
249         new GUIParameterTableWindow(app, *this, 8 + (int)myVType->getParameter().getParametersMap().size());
250     // add items
251     ret->mkItem("Type Information:", false, "");
252     ret->mkItem("type [id]", false, myVType->getID());
253     ret->mkItem("length", false, myVType->getLength());
254     ret->mkItem("width", false, myVType->getWidth());
255     ret->mkItem("height", false, myVType->getHeight());
256     ret->mkItem("minGap", false, myVType->getMinGap());
257     ret->mkItem("maximum speed [m/s]", false, myVType->getMaxSpeed());
258     // close building
259     ret->closeBuilding(&(myVType->getParameter()));
260     return ret;
261 }
262 
263 
264 Boundary
getCenteringBoundary() const265 GUIPerson::getCenteringBoundary() const {
266     Boundary b;
267     // ensure that the vehicle is drawn, otherwise myPositionInVehicle will not be updated
268     b.add(getGUIPosition());
269     b.grow(MAX2(getVehicleType().getWidth(), getVehicleType().getLength()));
270     return b;
271 }
272 
273 
274 void
drawGL(const GUIVisualizationSettings & s) const275 GUIPerson::drawGL(const GUIVisualizationSettings& s) const {
276     glPushName(getGlID());
277     glPushMatrix();
278     Position p1 = getGUIPosition();
279     glTranslated(p1.x(), p1.y(), getType());
280     glRotated(90, 0, 0, 1);
281     // set person color
282     setColor(s);
283     // scale
284     const double upscale = s.personSize.getExaggeration(s, this, 80);
285     glScaled(upscale, upscale, 1);
286     switch (s.personQuality) {
287         case 0:
288             drawAction_drawAsTriangle(s);
289             break;
290         case 1:
291             drawAction_drawAsCircle(s);
292             break;
293         case 2:
294             drawAction_drawAsPoly(s);
295             break;
296         case 3:
297         default:
298             drawAction_drawAsImage(s);
299             break;
300     }
301     glPopMatrix();
302 #ifdef GUIPerson_DEBUG_DRAW_WALKINGAREA_PATHS
303     drawAction_drawWalkingareaPath(s);
304 #endif
305     drawName(p1, s.scale, s.personName, s.angle);
306     if (s.personValue.show) {
307         Position p2 = p1 + Position(0, 0.6 * s.personName.scaledSize(s.scale));
308         const double value = getColorValue(s.personColorer.getActive());
309         GLHelper::drawTextSettings(s.personValue, toString(value), p2, s.scale, s.angle, GLO_MAX - getType());
310     }
311     glPopName();
312 }
313 
314 void
drawAction_drawWalkingareaPath(const GUIVisualizationSettings & s) const315 GUIPerson::drawAction_drawWalkingareaPath(const GUIVisualizationSettings& s) const {
316     MSPersonStage_Walking* stage = dynamic_cast<MSPersonStage_Walking*>(getCurrentStage());
317     if (stage != nullptr) {
318         setColor(s);
319         MSPModel_Striping::PState* stripingState = dynamic_cast<MSPModel_Striping::PState*>(stage->getPedestrianState());
320         if (stripingState != nullptr) {
321             MSPModel_Striping::WalkingAreaPath* waPath = stripingState->myWalkingAreaPath;
322             if (waPath != nullptr) {
323                 glPushMatrix();
324                 glTranslated(0, 0, getType());
325                 GLHelper::drawBoxLines(waPath->shape, 0.05);
326                 glPopMatrix();
327             }
328         }
329     }
330 }
331 
332 void
drawGLAdditional(GUISUMOAbstractView * const parent,const GUIVisualizationSettings & s) const333 GUIPerson::drawGLAdditional(GUISUMOAbstractView* const parent, const GUIVisualizationSettings& s) const {
334     glPushName(getGlID());
335     glPushMatrix();
336     glTranslated(0, 0, getType() - .1); // don't draw on top of other cars
337     if (hasActiveAddVisualisation(parent, VO_SHOW_WALKINGAREA_PATH)) {
338         drawAction_drawWalkingareaPath(s);
339     }
340     if (hasActiveAddVisualisation(parent, VO_SHOW_ROUTE)) {
341         if (getCurrentStageType() == MOVING_WITHOUT_VEHICLE) {
342             setColor(s);
343             RGBColor current = GLHelper::getColor();
344             RGBColor darker = current.changedBrightness(-51);
345             GLHelper::setColor(darker);
346             MSPersonStage_Walking* stage = dynamic_cast<MSPersonStage_Walking*>(getCurrentStage());
347             assert(stage != 0);
348             const double exaggeration = s.personSize.getExaggeration(s, this);
349             const ConstMSEdgeVector& edges = stage->getRoute();
350             for (ConstMSEdgeVector::const_iterator it = edges.begin(); it != edges.end(); ++it) {
351                 GUILane* lane = static_cast<GUILane*>((*it)->getLanes()[0]);
352                 GLHelper::drawBoxLines(lane->getShape(), lane->getShapeRotations(), lane->getShapeLengths(), exaggeration);
353             }
354         }
355     }
356     glPopMatrix();
357     glPopName();
358 }
359 
360 
361 
362 
363 void
setColor(const GUIVisualizationSettings & s) const364 GUIPerson::setColor(const GUIVisualizationSettings& s) const {
365     const GUIColorer& c = s.personColorer;
366     if (!setFunctionalColor(c.getActive())) {
367         GLHelper::setColor(c.getScheme().getColor(getColorValue(c.getActive())));
368     }
369 }
370 
371 
372 bool
setFunctionalColor(int activeScheme) const373 GUIPerson::setFunctionalColor(int activeScheme) const {
374     switch (activeScheme) {
375         case 0: {
376             if (getParameter().wasSet(VEHPARS_COLOR_SET)) {
377                 GLHelper::setColor(getParameter().color);
378                 return true;
379             }
380             if (getVehicleType().wasSet(VTYPEPARS_COLOR_SET)) {
381                 GLHelper::setColor(getVehicleType().getColor());
382                 return true;
383             }
384             return false;
385         }
386         case 2: {
387             if (getParameter().wasSet(VEHPARS_COLOR_SET)) {
388                 GLHelper::setColor(getParameter().color);
389                 return true;
390             }
391             return false;
392         }
393         case 3: {
394             if (getVehicleType().wasSet(VTYPEPARS_COLOR_SET)) {
395                 GLHelper::setColor(getVehicleType().getColor());
396                 return true;
397             }
398             return false;
399         }
400         case 8: { // color by angle
401             double hue = GeomHelper::naviDegree(getAngle());
402             GLHelper::setColor(RGBColor::fromHSV(hue, 1., 1.));
403             return true;
404         }
405         case 9: { // color randomly (by pointer)
406             const double hue = (long)this % 360; // [0-360]
407             const double sat = (((long)this / 360) % 67) / 100.0 + 0.33; // [0.33-1]
408             GLHelper::setColor(RGBColor::fromHSV(hue, sat, 1.));
409             return true;
410         }
411         default:
412             return false;
413     }
414 }
415 
416 
417 double
getColorValue(int activeScheme) const418 GUIPerson::getColorValue(int activeScheme) const {
419     switch (activeScheme) {
420         case 4:
421             return getSpeed();
422         case 5:
423             if (isWaiting4Vehicle()) {
424                 return 5;
425             } else {
426                 return (double)getCurrentStageType();
427             }
428         case 6:
429             return getWaitingSeconds();
430         case 7:
431             return gSelected.isSelected(GLO_PERSON, getGlID());
432     }
433     return 0;
434 }
435 
436 
437 double
getEdgePos() const438 GUIPerson::getEdgePos() const {
439     FXMutexLock locker(myLock);
440     return MSPerson::getEdgePos();
441 }
442 
443 
444 Position
getPosition() const445 GUIPerson::getPosition() const {
446     FXMutexLock locker(myLock);
447     return MSPerson::getPosition();
448 }
449 
450 
451 Position
getGUIPosition() const452 GUIPerson::getGUIPosition() const {
453     FXMutexLock locker(myLock);
454     if (getCurrentStageType() == DRIVING && !isWaiting4Vehicle() && myPositionInVehicle != Position::INVALID) {
455         return myPositionInVehicle;
456     } else {
457         return MSPerson::getPosition();
458     }
459 }
460 
461 
462 double
getNaviDegree() const463 GUIPerson::getNaviDegree() const {
464     FXMutexLock locker(myLock);
465     return GeomHelper::naviDegree(MSPerson::getAngle());
466 }
467 
468 
469 double
getWaitingSeconds() const470 GUIPerson::getWaitingSeconds() const {
471     FXMutexLock locker(myLock);
472     return MSPerson::getWaitingSeconds();
473 }
474 
475 
476 double
getSpeed() const477 GUIPerson::getSpeed() const {
478     FXMutexLock locker(myLock);
479     return MSPerson::getSpeed();
480 }
481 
482 
483 void
drawAction_drawAsTriangle(const GUIVisualizationSettings &) const484 GUIPerson::drawAction_drawAsTriangle(const GUIVisualizationSettings& /* s */) const {
485     // draw triangle pointing forward
486     glRotated(RAD2DEG(getAngle() + M_PI / 2.), 0, 0, 1);
487     glScaled(getVehicleType().getLength(), getVehicleType().getWidth(), 1);
488     glBegin(GL_TRIANGLES);
489     glVertex2d(0., 0.);
490     glVertex2d(1, -0.5);
491     glVertex2d(1, 0.5);
492     glEnd();
493     // draw a smaller triangle to indicate facing
494     GLHelper::setColor(GLHelper::getColor().changedBrightness(-64));
495     glTranslated(0, 0, .045);
496     glBegin(GL_TRIANGLES);
497     glVertex2d(0., 0.);
498     glVertex2d(0.5, -0.25);
499     glVertex2d(0.5, 0.25);
500     glEnd();
501     glTranslated(0, 0, -.045);
502 }
503 
504 
505 void
drawAction_drawAsCircle(const GUIVisualizationSettings &) const506 GUIPerson::drawAction_drawAsCircle(const GUIVisualizationSettings& /* s */) const {
507     glScaled(getVehicleType().getLength(), getVehicleType().getLength(), 1);
508     GLHelper::drawFilledCircle(0.8);
509 }
510 
511 
512 void
drawAction_drawAsPoly(const GUIVisualizationSettings &) const513 GUIPerson::drawAction_drawAsPoly(const GUIVisualizationSettings& /* s */) const {
514     // draw pedestrian shape
515     glRotated(GeomHelper::naviDegree(getAngle()) - 180, 0, 0, -1);
516     glScaled(getVehicleType().getLength(), getVehicleType().getWidth(), 1);
517     RGBColor lighter = GLHelper::getColor().changedBrightness(51);
518     glTranslated(0, 0, .045);
519     // head
520     glScaled(1, 0.5, 1.);
521     GLHelper::drawFilledCircle(0.5);
522     // nose
523     glBegin(GL_TRIANGLES);
524     glVertex2d(0.0, -0.2);
525     glVertex2d(0.0, 0.2);
526     glVertex2d(-0.6, 0.0);
527     glEnd();
528     glTranslated(0, 0, -.045);
529     // body
530     glScaled(0.9, 2.0, 1);
531     glTranslated(0, 0, .04);
532     GLHelper::setColor(lighter);
533     GLHelper::drawFilledCircle(0.5);
534     glTranslated(0, 0, -.04);
535 }
536 
537 
538 void
drawAction_drawAsImage(const GUIVisualizationSettings & s) const539 GUIPerson::drawAction_drawAsImage(const GUIVisualizationSettings& s) const {
540     const std::string& file = getVehicleType().getImgFile();
541     if (file != "") {
542         if (getVehicleType().getGuiShape() == SVS_PEDESTRIAN) {
543             glRotated(RAD2DEG(getAngle() + M_PI / 2.), 0, 0, 1);
544         }
545         int textureID = GUITexturesHelper::getTextureID(file);
546         if (textureID > 0) {
547             const double exaggeration = s.personSize.getExaggeration(s, this);
548             const double halfLength = getVehicleType().getLength() / 2.0 * exaggeration;
549             const double halfWidth = getVehicleType().getWidth() / 2.0 * exaggeration;
550             GUITexturesHelper::drawTexturedBox(textureID, -halfWidth, -halfLength, halfWidth, halfLength);
551         }
552     } else {
553         // fallback if no image is defined
554         drawAction_drawAsPoly(s);
555     }
556 }
557 
558 
559 // ------------ Additional visualisations
560 bool
hasActiveAddVisualisation(GUISUMOAbstractView * const parent,int which) const561 GUIPerson::hasActiveAddVisualisation(GUISUMOAbstractView* const parent, int which) const {
562     return myAdditionalVisualizations.find(parent) != myAdditionalVisualizations.end() && (myAdditionalVisualizations.find(parent)->second & which) != 0;
563 }
564 
565 
566 void
addActiveAddVisualisation(GUISUMOAbstractView * const parent,int which)567 GUIPerson::addActiveAddVisualisation(GUISUMOAbstractView* const parent, int which) {
568     if (myAdditionalVisualizations.find(parent) == myAdditionalVisualizations.end()) {
569         myAdditionalVisualizations[parent] = 0;
570     }
571     myAdditionalVisualizations[parent] |= which;
572     parent->addAdditionalGLVisualisation(this);
573 }
574 
575 
576 void
removeActiveAddVisualisation(GUISUMOAbstractView * const parent,int which)577 GUIPerson::removeActiveAddVisualisation(GUISUMOAbstractView* const parent, int which) {
578     myAdditionalVisualizations[parent] &= ~which;
579     parent->removeAdditionalGLVisualisation(this);
580 }
581 
582 bool
isSelected() const583 GUIPerson::isSelected() const {
584     return gSelected.isSelected(GLO_PERSON, getGlID());
585 }
586 
587 /****************************************************************************/
588 
589