Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file GUIPerson.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date Sept 2002
19 : ///
20 : // A MSPerson extended by some values for usage within the gui
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <gui/GUIApplicationWindow.h>
25 : #include <microsim/MSStoppingPlace.h>
26 : #include <microsim/transportables/MSTransportableControl.h>
27 : #include <microsim/logging/FunctionBinding.h>
28 : #include <microsim/transportables/MSPModel_Striping.h>
29 : #include <microsim/transportables/MSStageWaiting.h>
30 : #include <microsim/transportables/MSStageWalking.h>
31 : #include <utils/common/MsgHandler.h>
32 : #include <utils/common/ScopedLocker.h>
33 : #include <utils/gui/div/GLHelper.h>
34 : #include <utils/gui/div/GUIGlobalSelection.h>
35 : #include <utils/gui/div/GUIParameterTableWindow.h>
36 : #include <utils/gui/globjects/GLIncludes.h>
37 : #include <utils/gui/div/GUIBasePersonHelper.h>
38 : #include <utils/gui/div/GUIDesigns.h>
39 :
40 : #include "GUILane.h"
41 : #include "GUIPerson.h"
42 :
43 : //#define GUIPerson_DEBUG_DRAW_WALKINGAREA_PATHS 1
44 :
45 : // ===========================================================================
46 : // FOX callback mapping
47 : // ===========================================================================
48 :
49 : FXDEFMAP(GUIPerson::GUIPersonPopupMenu) GUIPersonPopupMenuMap[] = {
50 : FXMAPFUNC(SEL_COMMAND, MID_SHOW_CURRENTROUTE, GUIPerson::GUIPersonPopupMenu::onCmdShowCurrentRoute),
51 : FXMAPFUNC(SEL_COMMAND, MID_HIDE_CURRENTROUTE, GUIPerson::GUIPersonPopupMenu::onCmdHideCurrentRoute),
52 : FXMAPFUNC(SEL_COMMAND, MID_SHOW_WALKINGAREA_PATH, GUIPerson::GUIPersonPopupMenu::onCmdShowWalkingareaPath),
53 : FXMAPFUNC(SEL_COMMAND, MID_HIDE_WALKINGAREA_PATH, GUIPerson::GUIPersonPopupMenu::onCmdHideWalkingareaPath),
54 : FXMAPFUNC(SEL_COMMAND, MID_SHOWPLAN, GUIPerson::GUIPersonPopupMenu::onCmdShowPlan),
55 : FXMAPFUNC(SEL_COMMAND, MID_START_TRACK, GUIPerson::GUIPersonPopupMenu::onCmdStartTrack),
56 : FXMAPFUNC(SEL_COMMAND, MID_STOP_TRACK, GUIPerson::GUIPersonPopupMenu::onCmdStopTrack),
57 : FXMAPFUNC(SEL_COMMAND, MID_REMOVE_OBJECT, GUIPerson::GUIPersonPopupMenu::onCmdRemoveObject),
58 : };
59 :
60 : // Object implementation
61 0 : FXIMPLEMENT(GUIPerson::GUIPersonPopupMenu, GUIGLObjectPopupMenu, GUIPersonPopupMenuMap, ARRAYNUMBER(GUIPersonPopupMenuMap))
62 :
63 : // ===========================================================================
64 : // method definitions
65 : // ===========================================================================
66 :
67 : // -------------------------------------------------------------------------
68 : // GUIPerson::GUIPersonPopupMenu - methods
69 : // -------------------------------------------------------------------------
70 :
71 0 : GUIPerson::GUIPersonPopupMenu::GUIPersonPopupMenu(
72 0 : GUIMainWindow& app, GUISUMOAbstractView& parent, GUIGlObject* o) :
73 0 : GUIGLObjectPopupMenu(app, parent, o) {
74 0 : }
75 :
76 :
77 0 : GUIPerson::GUIPersonPopupMenu::~GUIPersonPopupMenu() {}
78 :
79 :
80 : long
81 0 : GUIPerson::GUIPersonPopupMenu::onCmdShowCurrentRoute(FXObject*, FXSelector, void*) {
82 : assert(myObject->getType() == GLO_PERSON);
83 0 : if (!static_cast<GUIPerson*>(myObject)->hasActiveAddVisualisation(myParent, VO_SHOW_ROUTE)) {
84 0 : static_cast<GUIPerson*>(myObject)->addActiveAddVisualisation(myParent, VO_SHOW_ROUTE);
85 : }
86 0 : return 1;
87 : }
88 :
89 :
90 : long
91 0 : GUIPerson::GUIPersonPopupMenu::onCmdHideCurrentRoute(FXObject*, FXSelector, void*) {
92 : assert(myObject->getType() == GLO_PERSON);
93 0 : static_cast<GUIPerson*>(myObject)->removeActiveAddVisualisation(myParent, VO_SHOW_ROUTE);
94 0 : return 1;
95 : }
96 :
97 :
98 : long
99 0 : GUIPerson::GUIPersonPopupMenu::onCmdShowWalkingareaPath(FXObject*, FXSelector, void*) {
100 : assert(myObject->getType() == GLO_PERSON);
101 0 : if (!static_cast<GUIPerson*>(myObject)->hasActiveAddVisualisation(myParent, VO_SHOW_WALKINGAREA_PATH)) {
102 0 : static_cast<GUIPerson*>(myObject)->addActiveAddVisualisation(myParent, VO_SHOW_WALKINGAREA_PATH);
103 : }
104 0 : return 1;
105 : }
106 :
107 :
108 : long
109 0 : GUIPerson::GUIPersonPopupMenu::onCmdHideWalkingareaPath(FXObject*, FXSelector, void*) {
110 : assert(myObject->getType() == GLO_PERSON);
111 0 : static_cast<GUIPerson*>(myObject)->removeActiveAddVisualisation(myParent, VO_SHOW_WALKINGAREA_PATH);
112 0 : return 1;
113 : }
114 :
115 :
116 : long
117 0 : GUIPerson::GUIPersonPopupMenu::onCmdShowPlan(FXObject*, FXSelector, void*) {
118 0 : GUIPerson* p = dynamic_cast<GUIPerson*>(myObject);
119 0 : if (p == nullptr) {
120 : return 1;
121 : }
122 0 : GUIParameterTableWindow* ret = new GUIParameterTableWindow(*myApplication, *p);
123 : // add items
124 0 : for (int stage = 1; stage < p->getNumStages(); stage++) {
125 0 : ret->mkItem(toString(stage).c_str(), false, p->getStageSummary(stage));
126 : }
127 : // close building (use an object that is not Parameterised as argument)
128 0 : Parameterised dummyParameterised;
129 0 : ret->closeBuilding(&dummyParameterised);
130 : return 1;
131 0 : }
132 :
133 :
134 : long
135 0 : GUIPerson::GUIPersonPopupMenu::onCmdStartTrack(FXObject*, FXSelector, void*) {
136 : assert(myObject->getType() == GLO_PERSON);
137 0 : if (myParent->getTrackedID() != static_cast<GUIPerson*>(myObject)->getGlID()) {
138 0 : myParent->startTrack(static_cast<GUIPerson*>(myObject)->getGlID());
139 : }
140 0 : return 1;
141 : }
142 :
143 :
144 : long
145 0 : GUIPerson::GUIPersonPopupMenu::onCmdStopTrack(FXObject*, FXSelector, void*) {
146 : assert(myObject->getType() == GLO_PERSON);
147 0 : myParent->stopTrack();
148 0 : return 1;
149 : }
150 :
151 :
152 : long
153 0 : GUIPerson::GUIPersonPopupMenu::onCmdRemoveObject(FXObject*, FXSelector, void*) {
154 0 : GUIPerson* person = static_cast<GUIPerson*>(myObject);
155 : MSStage* stage = person->getCurrentStage();
156 0 : stage->abort(person);
157 0 : stage->getEdge()->removeTransportable(person);
158 0 : if (stage->getDestinationStop() != nullptr) {
159 0 : stage->getDestinationStop()->removeTransportable(person);
160 : }
161 0 : MSNet::getInstance()->getPersonControl().erase(person);
162 0 : myParent->update();
163 0 : return 1;
164 : }
165 :
166 : // -------------------------------------------------------------------------
167 : // GUIPerson - methods
168 : // -------------------------------------------------------------------------
169 :
170 29148 : GUIPerson::GUIPerson(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan, const double speedFactor) :
171 : MSPerson(pars, vtype, plan, speedFactor),
172 29148 : GUIGlObject(GLO_PERSON, pars->id, GUIIconSubSys::getIcon(GUIIcon::PERSON)),
173 29148 : myLock(true)
174 29148 : { }
175 :
176 :
177 58214 : GUIPerson::~GUIPerson() {
178 29107 : myLock.lock();
179 29107 : for (std::map<GUISUMOAbstractView*, int>::iterator i = myAdditionalVisualizations.begin(); i != myAdditionalVisualizations.end(); ++i) {
180 0 : if (i->first->getTrackedID() == getGlID()) {
181 0 : i->first->stopTrack();
182 : }
183 0 : while (i->first->removeAdditionalGLVisualisation(this));
184 : }
185 29107 : gSelected.deselect(GLO_PERSON, getGlID());
186 29107 : myLock.unlock();
187 58214 : }
188 :
189 :
190 : GUIGLObjectPopupMenu*
191 0 : GUIPerson::getPopUpMenu(GUIMainWindow& app, GUISUMOAbstractView& parent) {
192 0 : GUIGLObjectPopupMenu* ret = new GUIPersonPopupMenu(app, parent, this);
193 0 : buildPopupHeader(ret, app);
194 0 : buildCenterPopupEntry(ret);
195 0 : buildNameCopyPopupEntry(ret);
196 0 : buildSelectionPopupEntry(ret);
197 0 : if (hasActiveAddVisualisation(&parent, VO_SHOW_ROUTE)) {
198 0 : GUIDesigns::buildFXMenuCommand(ret, "Hide Current Route", nullptr, ret, MID_HIDE_CURRENTROUTE);
199 : } else {
200 0 : GUIDesigns::buildFXMenuCommand(ret, "Show Current Route", nullptr, ret, MID_SHOW_CURRENTROUTE);
201 : }
202 0 : if (hasActiveAddVisualisation(&parent, VO_SHOW_WALKINGAREA_PATH)) {
203 0 : GUIDesigns::buildFXMenuCommand(ret, "Hide Walkingarea Path", nullptr, ret, MID_HIDE_WALKINGAREA_PATH);
204 : } else {
205 0 : GUIDesigns::buildFXMenuCommand(ret, "Show Walkingarea Path", nullptr, ret, MID_SHOW_WALKINGAREA_PATH);
206 : }
207 0 : new FXMenuSeparator(ret);
208 0 : if (parent.getTrackedID() != getGlID()) {
209 0 : GUIDesigns::buildFXMenuCommand(ret, "Start Tracking", nullptr, ret, MID_START_TRACK);
210 : } else {
211 0 : GUIDesigns::buildFXMenuCommand(ret, "Stop Tracking", nullptr, ret, MID_STOP_TRACK);
212 : }
213 0 : GUIDesigns::buildFXMenuCommand(ret, "Remove", nullptr, ret, MID_REMOVE_OBJECT);
214 0 : new FXMenuSeparator(ret);
215 : //
216 0 : buildShowParamsPopupEntry(ret);
217 0 : buildShowTypeParamsPopupEntry(ret);
218 0 : GUIDesigns::buildFXMenuCommand(ret, "Show Plan", GUIIconSubSys::getIcon(GUIIcon::APP_TABLE), ret, MID_SHOWPLAN);
219 0 : new FXMenuSeparator(ret);
220 0 : buildPositionCopyEntry(ret, app);
221 0 : return ret;
222 : }
223 :
224 :
225 : GUIParameterTableWindow*
226 0 : GUIPerson::getParameterWindow(GUIMainWindow& app,
227 : GUISUMOAbstractView&) {
228 0 : GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
229 : // add items
230 0 : ret->mkItem(TL("stage"), true, new FunctionBindingString<GUIPerson>(this, &MSTransportable::getCurrentStageDescription));
231 : // there is always the "start" stage which we do not count here because it is not strictly part of the plan
232 0 : ret->mkItem(TL("stage index"), true, new FunctionBindingString<GUIPerson>(this, &GUIPerson::getStageIndexDescription));
233 0 : ret->mkItem(TL("start edge [id]"), true, new FunctionBindingString<GUIPerson>(this, &GUIPerson::getFromEdgeID));
234 0 : ret->mkItem(TL("dest edge [id]"), true, new FunctionBindingString<GUIPerson>(this, &GUIPerson::getDestinationEdgeID));
235 0 : ret->mkItem(TL("dest stop [id]"), true, new FunctionBindingString<GUIPerson>(this, &GUIPerson::getDestinationStopID));
236 0 : ret->mkItem(TL("arrival position [m]"), true, new FunctionBinding<GUIPerson, double>(this, &GUIPerson::getStageArrivalPos));
237 0 : ret->mkItem(TL("edge [id]"), true, new FunctionBindingString<GUIPerson>(this, &GUIPerson::getEdgeID));
238 0 : ret->mkItem(TL("lane [id]"), true, new FunctionBindingString<GUIPerson>(this, &GUIPerson::getLaneID));
239 0 : ret->mkItem(TL("position [m]"), true, new FunctionBinding<GUIPerson, double>(this, &GUIPerson::getEdgePos));
240 0 : ret->mkItem(TL("speed [m/s]"), true, new FunctionBinding<GUIPerson, double>(this, &GUIPerson::getSpeed));
241 0 : ret->mkItem(TL("speed factor"), false, getChosenSpeedFactor());
242 0 : ret->mkItem(TL("angle [degree]"), true, new FunctionBinding<GUIPerson, double>(this, &GUIPerson::getNaviDegree));
243 0 : ret->mkItem(TL("waiting time [s]"), true, new FunctionBinding<GUIPerson, double>(this, &GUIPerson::getWaitingSeconds));
244 0 : ret->mkItem(TL("vehicle [id]"), true, new FunctionBindingString<GUIPerson>(this, &GUIPerson::getVehicleID));
245 0 : ret->mkItem(TL("stop duration [s]"), true, new FunctionBinding<GUIPerson, double>(this, &GUIPerson::getStopDuration));
246 0 : ret->mkItem(TL("desired depart [s]"), false, time2string(getParameter().depart));
247 : // close building
248 0 : ret->closeBuilding(&getParameter());
249 0 : return ret;
250 : }
251 :
252 :
253 : GUIParameterTableWindow*
254 0 : GUIPerson::getTypeParameterWindow(GUIMainWindow& app, GUISUMOAbstractView&) {
255 0 : GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this, "vType:" + myVType->getID());
256 0 : ret->mkItem(TL("length"), false, myVType->getLength());
257 0 : ret->mkItem(TL("width"), false, myVType->getWidth());
258 0 : ret->mkItem(TL("height"), false, myVType->getHeight());
259 0 : ret->mkItem(TL("minGap"), false, myVType->getMinGap());
260 0 : ret->mkItem(TL("mass [kg]"), false, myVType->getMass());
261 0 : ret->mkItem(TL("desired max speed [m/s]"), false, myVType->getDesiredMaxSpeed());
262 0 : ret->mkItem(TL("maximum speed [m/s]"), false, myVType->getMaxSpeed());
263 0 : ret->closeBuilding(&(myVType->getParameter()));
264 0 : return ret;
265 : }
266 :
267 :
268 : double
269 1194678 : GUIPerson::getExaggeration(const GUIVisualizationSettings& s) const {
270 2389356 : return s.personSize.getExaggeration(s, this, s.personQuality == 1 ? 40 : 80);
271 : }
272 :
273 :
274 : Boundary
275 0 : GUIPerson::getCenteringBoundary() const {
276 0 : Boundary b;
277 : // ensure that the vehicle is drawn, otherwise myPositionInVehicle will not be updated
278 0 : b.add(getGUIPosition());
279 0 : b.grow(MAX2(getVehicleType().getWidth(), getVehicleType().getLength()));
280 0 : return b;
281 : }
282 :
283 :
284 : void
285 1194678 : GUIPerson::drawGL(const GUIVisualizationSettings& s) const {
286 1194678 : GLHelper::pushName(getGlID());
287 1194678 : GLHelper::pushMatrix();
288 1194678 : Position p1 = getGUIPosition(&s);
289 1194678 : double angle = getGUIAngle();
290 1194678 : glTranslated(p1.x(), p1.y(), getType());
291 : // set person color
292 1194678 : setColor(s);
293 : // scale
294 1194678 : const double exaggeration = getExaggeration(s);
295 1194678 : glScaled(exaggeration, exaggeration, 1);
296 1194678 : switch (s.personQuality) {
297 1143771 : case 0:
298 1143771 : GUIBasePersonHelper::drawAction_drawAsTriangle(angle, getVehicleType().getLength(), getVehicleType().getWidth());
299 : break;
300 0 : case 1:
301 0 : GUIBasePersonHelper::drawAction_drawAsCircle(angle, getVehicleType().getLength(), getVehicleType().getWidth(), s.scale * exaggeration);
302 : break;
303 50907 : case 2:
304 50907 : GUIBasePersonHelper::drawAction_drawAsPoly(angle, getVehicleType().getLength(), getVehicleType().getWidth());
305 : break;
306 0 : case 3:
307 : default:
308 0 : GUIBasePersonHelper::drawAction_drawAsImage(angle, getVehicleType().getLength(), getVehicleType().getWidth(),
309 0 : getVehicleType().getImgFile(), getVehicleType().getGuiShape(), 1);
310 0 : break;
311 : }
312 1194678 : GLHelper::popMatrix();
313 : #ifdef GUIPerson_DEBUG_DRAW_WALKINGAREA_PATHS
314 : drawAction_drawWalkingareaPath(s);
315 : #endif
316 1194678 : drawName(p1, s.scale, s.personName, s.angle);
317 1194678 : if (s.personValue.show(this)) {
318 0 : Position p2 = p1 + Position(0, 0.6 * s.personName.scaledSize(s.scale));
319 0 : const double value = getColorValue(s, s.personColorer.getActive());
320 0 : GLHelper::drawTextSettings(s.personValue, toString(value), p2, s.scale, s.angle, GLO_MAX - getType());
321 : }
322 1194678 : GLHelper::popName();
323 1194678 : }
324 :
325 :
326 : void
327 0 : GUIPerson::drawAction_drawWalkingareaPath(const GUIVisualizationSettings& s) const {
328 0 : MSStageWalking* stage = dynamic_cast<MSStageWalking*>(getCurrentStage());
329 0 : if (stage != nullptr) {
330 0 : setColor(s);
331 0 : MSPModel_Striping::PState* stripingState = dynamic_cast<MSPModel_Striping::PState*>(stage->getPState());
332 0 : if (stripingState != nullptr) {
333 0 : const MSPModel_Striping::WalkingAreaPath* waPath = stripingState->myWalkingAreaPath;
334 0 : if (waPath != nullptr) {
335 0 : GLHelper::pushMatrix();
336 0 : glTranslated(0, 0, getType());
337 0 : GLHelper::drawBoxLines(waPath->shape, 0.05);
338 0 : GLHelper::popMatrix();
339 : }
340 : }
341 : }
342 0 : }
343 :
344 : void
345 0 : GUIPerson::drawGLAdditional(GUISUMOAbstractView* const parent, const GUIVisualizationSettings& s) const {
346 0 : GLHelper::pushName(getGlID());
347 0 : GLHelper::pushMatrix();
348 0 : glTranslated(0, 0, getType() - .1); // don't draw on top of other cars
349 0 : if (hasActiveAddVisualisation(parent, VO_SHOW_WALKINGAREA_PATH)) {
350 0 : drawAction_drawWalkingareaPath(s);
351 : }
352 0 : if (hasActiveAddVisualisation(parent, VO_SHOW_ROUTE)) {
353 0 : if (getCurrentStageType() == MSStageType::WALKING) {
354 0 : setColor(s);
355 0 : RGBColor current = GLHelper::getColor();
356 0 : RGBColor darker = current.changedBrightness(-51);
357 0 : GLHelper::setColor(darker);
358 0 : MSStageWalking* stage = dynamic_cast<MSStageWalking*>(getCurrentStage());
359 : assert(stage != 0);
360 0 : const double exaggeration = getExaggeration(s);
361 : const ConstMSEdgeVector& edges = stage->getRoute();
362 0 : const bool s2 = s.secondaryShape;
363 0 : for (ConstMSEdgeVector::const_iterator it = edges.begin(); it != edges.end(); ++it) {
364 0 : GUILane* lane = static_cast<GUILane*>((*it)->getLanes()[0]);
365 0 : GLHelper::drawBoxLines(lane->getShape(s2), lane->getShapeRotations(s2), lane->getShapeLengths(s2), exaggeration);
366 : }
367 : }
368 : }
369 0 : GLHelper::popMatrix();
370 0 : GLHelper::popName();
371 0 : }
372 :
373 :
374 : void
375 210566 : GUIPerson::setPositionInVehicle(const GUIBaseVehicle::Seat& pos) {
376 210566 : myPositionInVehicle = pos;
377 210566 : }
378 :
379 :
380 : void
381 1194678 : GUIPerson::setColor(const GUIVisualizationSettings& s) const {
382 1194678 : RGBColor col;
383 : const GUIColorer& c = s.personColorer;
384 1194678 : if (!setFunctionalColor(c.getActive(), this, col)) {
385 894933 : col = c.getScheme().getColor(getColorValue(s, c.getActive()));
386 : }
387 1194678 : GLHelper::setColor(col);
388 1194678 : }
389 :
390 :
391 : bool
392 1197904 : GUIPerson::setFunctionalColor(int activeScheme, const MSPerson* person, RGBColor& col) {
393 1197904 : switch (activeScheme) {
394 728714 : case 0: {
395 728714 : if (person->getParameter().wasSet(VEHPARS_COLOR_SET)) {
396 39133 : col = person->getParameter().color;
397 39133 : return true;
398 : }
399 689581 : if (person->getVehicleType().wasSet(VTYPEPARS_COLOR_SET)) {
400 260686 : col = person->getVehicleType().getColor();
401 260686 : return true;
402 : }
403 : return false;
404 : }
405 0 : case 2: {
406 0 : if (person->getParameter().wasSet(VEHPARS_COLOR_SET)) {
407 0 : col = person->getParameter().color;
408 0 : return true;
409 : }
410 : return false;
411 : }
412 0 : case 3: {
413 0 : if (person->getVehicleType().wasSet(VTYPEPARS_COLOR_SET)) {
414 0 : col = person->getVehicleType().getColor();
415 0 : return true;
416 : }
417 : return false;
418 : }
419 0 : case 9: { // color by angle
420 0 : double hue = GeomHelper::naviDegree(person->getAngle());
421 0 : col = RGBColor::fromHSV(hue, 1., 1.);
422 0 : return true;
423 : }
424 0 : case 10: { // color randomly (by pointer)
425 0 : const double hue = (double)((long long int)person % 360); // [0-360]
426 0 : const double sat = (double)(((long long int)person / 360) % 67) / 100. + 0.33; // [0.33-1]
427 0 : col = RGBColor::fromHSV(hue, sat, 1.);
428 0 : return true;
429 : }
430 : default:
431 : return false;
432 : }
433 : }
434 :
435 :
436 : double
437 898085 : GUIPerson::getColorValue(const GUIVisualizationSettings& /* s */, int activeScheme) const {
438 898085 : switch (activeScheme) {
439 0 : case 4:
440 0 : switch (getCurrentStageType()) {
441 : case MSStageType::WAITING:
442 : return -1;
443 0 : case MSStageType::WAITING_FOR_DEPART:
444 0 : return -2;
445 0 : default:
446 0 : return getSpeed();
447 : }
448 469190 : case 5:
449 469190 : if (isWaiting4Vehicle()) {
450 : return 5;
451 : } else {
452 179820 : return (double)getCurrentStageType();
453 : }
454 0 : case 6:
455 0 : return getWaitingSeconds();
456 0 : case 7:
457 0 : return isJammed() ? 1 : 0;
458 0 : case 8:
459 0 : return gSelected.isSelected(GLO_PERSON, getGlID());
460 : }
461 : return 0;
462 : }
463 :
464 :
465 : double
466 478848 : GUIPerson::getEdgePos() const {
467 478848 : FXMutexLock locker(myLock);
468 478848 : if (hasArrived()) {
469 : return -1;
470 : }
471 478848 : return MSPerson::getEdgePos();
472 : }
473 :
474 : int
475 92712 : GUIPerson::getDirection() const {
476 92712 : FXMutexLock locker(myLock);
477 92712 : if (hasArrived()) {
478 0 : return MSPModel::UNDEFINED_DIRECTION;
479 : }
480 92712 : return MSPerson::getDirection();
481 : }
482 :
483 :
484 : Position
485 1126239 : GUIPerson::getPosition() const {
486 1126239 : FXMutexLock locker(myLock);
487 1126239 : if (hasArrived()) {
488 0 : return Position::INVALID;
489 : }
490 1126239 : return MSPerson::getPosition();
491 : }
492 :
493 :
494 : Position
495 1194678 : GUIPerson::getGUIPosition(const GUIVisualizationSettings* s) const {
496 1194678 : FXMutexLock locker(myLock);
497 1194678 : if (hasArrived()) {
498 0 : return Position::INVALID;
499 : }
500 1194678 : if (getCurrentStageType() == MSStageType::DRIVING) {
501 517974 : if (!isWaiting4Vehicle() && myPositionInVehicle.pos != Position::INVALID) {
502 210417 : if (s != nullptr) {
503 210417 : return myPositionInVehicle.pos;
504 : } else {
505 : // centering boundary must cover the vehicle regardless of exaggeration and zoom
506 0 : SUMOVehicle* veh = getCurrentStage()->getVehicle();
507 0 : if (veh == nullptr) {
508 : // should not happen
509 0 : return myPositionInVehicle.pos;
510 : }
511 0 : PositionVector b = veh->getBoundingBox();
512 0 : if (b.around(myPositionInVehicle.pos)) {
513 0 : return myPositionInVehicle.pos;
514 : } else {
515 0 : return b.getCentroid();
516 : }
517 0 : }
518 : } else if (isWaiting4Vehicle()
519 307408 : && s != nullptr
520 307408 : && s->gaming
521 0 : && getCurrentStage()->getOriginStop() != nullptr
522 307557 : && s->addSize.getExaggeration(*s, nullptr) > 1) {
523 : // shift position away from stop center
524 0 : Position pos = MSPerson::getPosition();
525 0 : Position ref = getCurrentStage()->getOriginStop()->getCenterPos();
526 0 : Position shifted = ref + (pos - ref) * s->personSize.getExaggeration(*s, this);
527 0 : return shifted;
528 : }
529 : }
530 984261 : return MSPerson::getPosition();
531 : }
532 :
533 :
534 : double
535 1194678 : GUIPerson::getGUIAngle() const {
536 1194678 : FXMutexLock locker(myLock);
537 1194678 : if (hasArrived()) {
538 : return INVALID_DOUBLE;
539 : }
540 1712652 : if (getCurrentStageType() == MSStageType::DRIVING && !isWaiting4Vehicle() && myPositionInVehicle.pos != Position::INVALID) {
541 210417 : return myPositionInVehicle.angle;
542 : } else {
543 984261 : return MSPerson::getAngle();
544 : }
545 : }
546 :
547 :
548 : double
549 0 : GUIPerson::getNaviDegree() const {
550 0 : FXMutexLock locker(myLock);
551 0 : if (hasArrived()) {
552 : return INVALID_DOUBLE;
553 : }
554 0 : return GeomHelper::naviDegree(MSPerson::getAngle());
555 : }
556 :
557 :
558 : double
559 2 : GUIPerson::getWaitingSeconds() const {
560 2 : FXMutexLock locker(myLock);
561 2 : if (hasArrived()) {
562 : return -1;
563 : }
564 2 : return MSPerson::getWaitingSeconds();
565 : }
566 :
567 :
568 : double
569 251617 : GUIPerson::getSpeed() const {
570 251617 : FXMutexLock locker(myLock);
571 251617 : if (hasArrived()) {
572 : return -1;
573 : }
574 251617 : return MSPerson::getSpeed();
575 : }
576 :
577 :
578 : std::string
579 0 : GUIPerson::getStageIndexDescription() const {
580 0 : FXMutexLock locker(myLock);
581 0 : if (hasArrived()) {
582 0 : return "arrived";
583 : }
584 : // there is always the "start" stage which we do not count here because it is not strictly part of the plan
585 0 : return toString(getCurrentStageIndex()) + " of " + toString(getNumStages() - 1);
586 : }
587 :
588 :
589 : std::string
590 0 : GUIPerson::getEdgeID() const {
591 0 : FXMutexLock locker(myLock);
592 0 : if (hasArrived()) {
593 0 : return "arrived";
594 : }
595 0 : return getEdge()->getID();
596 : }
597 :
598 :
599 : std::string
600 0 : GUIPerson::getLaneID() const {
601 0 : FXMutexLock locker(myLock);
602 0 : if (hasArrived()) {
603 0 : return "arrived";
604 : }
605 0 : return getLane() != nullptr ? getLane()->getID() : "";
606 : }
607 :
608 :
609 : std::string
610 0 : GUIPerson::getFromEdgeID() const {
611 0 : FXMutexLock locker(myLock);
612 0 : if (hasArrived()) {
613 0 : return "arrived";
614 : }
615 : return getFromEdge()->getID();
616 : }
617 :
618 :
619 : std::string
620 0 : GUIPerson::getDestinationEdgeID() const {
621 0 : FXMutexLock locker(myLock);
622 0 : if (hasArrived()) {
623 0 : return "arrived";
624 : }
625 : return getDestination()->getID();
626 : }
627 :
628 :
629 : std::string
630 0 : GUIPerson::getDestinationStopID() const {
631 0 : FXMutexLock locker(myLock);
632 0 : if (hasArrived()) {
633 0 : return "";
634 : }
635 : MSStoppingPlace* destStop = getCurrentStage()->getDestinationStop();
636 0 : if (destStop != nullptr) {
637 : return destStop->getID();
638 : } else {
639 0 : return "";
640 : }
641 : }
642 :
643 :
644 : std::string
645 0 : GUIPerson::getVehicleID() const {
646 0 : FXMutexLock locker(myLock);
647 0 : if (hasArrived()) {
648 0 : return "";
649 : }
650 0 : SUMOVehicle* veh = getCurrentStage()->getVehicle();
651 0 : if (veh != nullptr) {
652 : return veh->getID();
653 : } else {
654 0 : return "";
655 : }
656 : }
657 :
658 :
659 : double
660 0 : GUIPerson::getStopDuration() const {
661 0 : FXMutexLock locker(myLock);
662 0 : if (hasArrived()) {
663 : return -1;
664 : }
665 0 : if (getCurrentStage()->getStageType() == MSStageType::WAITING) {
666 0 : return STEPS2TIME(dynamic_cast<MSStageWaiting*>(getCurrentStage())->getStopEnd() - SIMSTEP);
667 : } else {
668 : return -1;
669 : }
670 : }
671 :
672 :
673 : double
674 0 : GUIPerson::getStageArrivalPos() const {
675 0 : FXMutexLock locker(myLock);
676 0 : if (hasArrived()) {
677 : return INVALID_DOUBLE;
678 : }
679 0 : return getCurrentStage()->getArrivalPos();
680 : }
681 :
682 : bool
683 59368 : GUIPerson::proceed(MSNet* net, SUMOTime time, const bool vehicleArrived) {
684 : // acquire lock before locking the person to avoid mutual deadlock (#9468)
685 59368 : ScopedLocker<const MSEdge, true> edgeLocker(*getEdge());
686 59368 : FXMutexLock locker(myLock);
687 118711 : return MSTransportable::proceed(net, time, vehicleArrived);
688 : }
689 :
690 : // -------------------------------------------------------------------------
691 : // GUIPerson - Additional Visualsation methods
692 : // -------------------------------------------------------------------------
693 :
694 : bool
695 0 : GUIPerson::hasActiveAddVisualisation(GUISUMOAbstractView* const parent, int which) const {
696 0 : return myAdditionalVisualizations.find(parent) != myAdditionalVisualizations.end() && (myAdditionalVisualizations.find(parent)->second & which) != 0;
697 : }
698 :
699 :
700 : void
701 0 : GUIPerson::addActiveAddVisualisation(GUISUMOAbstractView* const parent, int which) {
702 0 : if (myAdditionalVisualizations.find(parent) == myAdditionalVisualizations.end()) {
703 0 : myAdditionalVisualizations[parent] = 0;
704 : }
705 0 : myAdditionalVisualizations[parent] |= which;
706 0 : parent->addAdditionalGLVisualisation(this);
707 0 : }
708 :
709 :
710 : void
711 0 : GUIPerson::removeActiveAddVisualisation(GUISUMOAbstractView* const parent, int which) {
712 0 : myAdditionalVisualizations[parent] &= ~which;
713 0 : parent->removeAdditionalGLVisualisation(this);
714 0 : }
715 :
716 : bool
717 32955357 : GUIPerson::isSelected() const {
718 32955357 : return gSelected.isSelected(GLO_PERSON, getGlID());
719 : }
720 :
721 :
722 : /****************************************************************************/
|