Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2024 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 27709 : GUIPerson::GUIPerson(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan, const double speedFactor) :
171 : MSPerson(pars, vtype, plan, speedFactor),
172 27709 : GUIGlObject(GLO_PERSON, pars->id, GUIIconSubSys::getIcon(GUIIcon::PERSON)),
173 27709 : myLock(true)
174 27709 : { }
175 :
176 :
177 55336 : GUIPerson::~GUIPerson() {
178 27668 : myLock.lock();
179 27668 : 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 27668 : myLock.unlock();
186 55336 : }
187 :
188 :
189 : GUIGLObjectPopupMenu*
190 0 : GUIPerson::getPopUpMenu(GUIMainWindow& app, GUISUMOAbstractView& parent) {
191 0 : GUIGLObjectPopupMenu* ret = new GUIPersonPopupMenu(app, parent, *this);
192 0 : buildPopupHeader(ret, app);
193 0 : buildCenterPopupEntry(ret);
194 0 : buildNameCopyPopupEntry(ret);
195 0 : buildSelectionPopupEntry(ret);
196 0 : if (hasActiveAddVisualisation(&parent, VO_SHOW_ROUTE)) {
197 0 : GUIDesigns::buildFXMenuCommand(ret, "Hide Current Route", nullptr, ret, MID_HIDE_CURRENTROUTE);
198 : } else {
199 0 : GUIDesigns::buildFXMenuCommand(ret, "Show Current Route", nullptr, ret, MID_SHOW_CURRENTROUTE);
200 : }
201 0 : if (hasActiveAddVisualisation(&parent, VO_SHOW_WALKINGAREA_PATH)) {
202 0 : GUIDesigns::buildFXMenuCommand(ret, "Hide Walkingarea Path", nullptr, ret, MID_HIDE_WALKINGAREA_PATH);
203 : } else {
204 0 : GUIDesigns::buildFXMenuCommand(ret, "Show Walkingarea Path", nullptr, ret, MID_SHOW_WALKINGAREA_PATH);
205 : }
206 0 : new FXMenuSeparator(ret);
207 0 : if (parent.getTrackedID() != getGlID()) {
208 0 : GUIDesigns::buildFXMenuCommand(ret, "Start Tracking", nullptr, ret, MID_START_TRACK);
209 : } else {
210 0 : GUIDesigns::buildFXMenuCommand(ret, "Stop Tracking", nullptr, ret, MID_STOP_TRACK);
211 : }
212 0 : GUIDesigns::buildFXMenuCommand(ret, "Remove", nullptr, ret, MID_REMOVE_OBJECT);
213 0 : new FXMenuSeparator(ret);
214 : //
215 0 : buildShowParamsPopupEntry(ret);
216 0 : buildShowTypeParamsPopupEntry(ret);
217 0 : GUIDesigns::buildFXMenuCommand(ret, "Show Plan", GUIIconSubSys::getIcon(GUIIcon::APP_TABLE), ret, MID_SHOWPLAN);
218 0 : new FXMenuSeparator(ret);
219 0 : buildPositionCopyEntry(ret, app);
220 0 : return ret;
221 : }
222 :
223 :
224 : GUIParameterTableWindow*
225 0 : GUIPerson::getParameterWindow(GUIMainWindow& app,
226 : GUISUMOAbstractView&) {
227 0 : GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
228 : // add items
229 0 : ret->mkItem(TL("stage"), true, new FunctionBindingString<GUIPerson>(this, &MSTransportable::getCurrentStageDescription));
230 : // there is always the "start" stage which we do not count here because it is not strictly part of the plan
231 0 : ret->mkItem(TL("stage index"), true, new FunctionBindingString<GUIPerson>(this, &GUIPerson::getStageIndexDescription));
232 0 : ret->mkItem(TL("start edge [id]"), true, new FunctionBindingString<GUIPerson>(this, &GUIPerson::getFromEdgeID));
233 0 : ret->mkItem(TL("dest edge [id]"), true, new FunctionBindingString<GUIPerson>(this, &GUIPerson::getDestinationEdgeID));
234 0 : ret->mkItem(TL("dest stop [id]"), true, new FunctionBindingString<GUIPerson>(this, &GUIPerson::getDestinationStopID));
235 0 : ret->mkItem(TL("arrival position [m]"), true, new FunctionBinding<GUIPerson, double>(this, &GUIPerson::getStageArrivalPos));
236 0 : ret->mkItem(TL("edge [id]"), true, new FunctionBindingString<GUIPerson>(this, &GUIPerson::getEdgeID));
237 0 : ret->mkItem(TL("position [m]"), true, new FunctionBinding<GUIPerson, double>(this, &GUIPerson::getEdgePos));
238 0 : ret->mkItem(TL("speed [m/s]"), true, new FunctionBinding<GUIPerson, double>(this, &GUIPerson::getSpeed));
239 0 : ret->mkItem(TL("speed factor"), false, getChosenSpeedFactor());
240 0 : ret->mkItem(TL("angle [degree]"), true, new FunctionBinding<GUIPerson, double>(this, &GUIPerson::getNaviDegree));
241 0 : ret->mkItem(TL("waiting time [s]"), true, new FunctionBinding<GUIPerson, double>(this, &GUIPerson::getWaitingSeconds));
242 0 : ret->mkItem(TL("vehicle [id]"), true, new FunctionBindingString<GUIPerson>(this, &GUIPerson::getVehicleID));
243 0 : ret->mkItem(TL("stop duration [s]"), true, new FunctionBinding<GUIPerson, double>(this, &GUIPerson::getStopDuration));
244 0 : ret->mkItem(TL("desired depart [s]"), false, time2string(getParameter().depart));
245 : // close building
246 0 : ret->closeBuilding(&getParameter());
247 0 : return ret;
248 : }
249 :
250 :
251 : GUIParameterTableWindow*
252 0 : GUIPerson::getTypeParameterWindow(GUIMainWindow& app, GUISUMOAbstractView&) {
253 0 : GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this, "vType:" + myVType->getID());
254 0 : ret->mkItem(TL("length"), false, myVType->getLength());
255 0 : ret->mkItem(TL("width"), false, myVType->getWidth());
256 0 : ret->mkItem(TL("height"), false, myVType->getHeight());
257 0 : ret->mkItem(TL("minGap"), false, myVType->getMinGap());
258 0 : ret->mkItem(TL("mass [kg]"), false, myVType->getMass());
259 0 : ret->mkItem(TL("desired max speed [m/s]"), false, myVType->getDesiredMaxSpeed());
260 0 : ret->mkItem(TL("maximum speed [m/s]"), false, myVType->getMaxSpeed());
261 0 : ret->closeBuilding(&(myVType->getParameter()));
262 0 : return ret;
263 : }
264 :
265 :
266 : double
267 1703707 : GUIPerson::getExaggeration(const GUIVisualizationSettings& s) const {
268 3407414 : return s.personSize.getExaggeration(s, this, s.personQuality == 1 ? 40 : 80);
269 : }
270 :
271 :
272 : Boundary
273 0 : GUIPerson::getCenteringBoundary() const {
274 0 : Boundary b;
275 : // ensure that the vehicle is drawn, otherwise myPositionInVehicle will not be updated
276 0 : b.add(getGUIPosition());
277 0 : b.grow(MAX2(getVehicleType().getWidth(), getVehicleType().getLength()));
278 0 : return b;
279 0 : }
280 :
281 :
282 : void
283 1703707 : GUIPerson::drawGL(const GUIVisualizationSettings& s) const {
284 1703707 : GLHelper::pushName(getGlID());
285 1703707 : GLHelper::pushMatrix();
286 1703707 : Position p1 = getGUIPosition(&s);
287 1703707 : double angle = getGUIAngle();
288 1703707 : glTranslated(p1.x(), p1.y(), getType());
289 : // set person color
290 1703707 : setColor(s);
291 : // scale
292 1703707 : const double exaggeration = getExaggeration(s);
293 1703707 : glScaled(exaggeration, exaggeration, 1);
294 1703707 : switch (s.personQuality) {
295 1650469 : case 0:
296 1650469 : GUIBasePersonHelper::drawAction_drawAsTriangle(angle, getVehicleType().getLength(), getVehicleType().getWidth());
297 : break;
298 0 : case 1:
299 0 : GUIBasePersonHelper::drawAction_drawAsCircle(angle, getVehicleType().getLength(), getVehicleType().getWidth(), s.scale * exaggeration);
300 : break;
301 53238 : case 2:
302 53238 : GUIBasePersonHelper::drawAction_drawAsPoly(angle, getVehicleType().getLength(), getVehicleType().getWidth());
303 : break;
304 0 : case 3:
305 : default:
306 0 : GUIBasePersonHelper::drawAction_drawAsImage(angle, getVehicleType().getLength(), getVehicleType().getWidth(),
307 0 : getVehicleType().getImgFile(), getVehicleType().getGuiShape(), 1);
308 0 : break;
309 : }
310 1703707 : GLHelper::popMatrix();
311 : #ifdef GUIPerson_DEBUG_DRAW_WALKINGAREA_PATHS
312 : drawAction_drawWalkingareaPath(s);
313 : #endif
314 1703707 : drawName(p1, s.scale, s.personName, s.angle);
315 1703707 : if (s.personValue.show(this)) {
316 0 : Position p2 = p1 + Position(0, 0.6 * s.personName.scaledSize(s.scale));
317 0 : const double value = getColorValue(s, s.personColorer.getActive());
318 0 : GLHelper::drawTextSettings(s.personValue, toString(value), p2, s.scale, s.angle, GLO_MAX - getType());
319 : }
320 1703707 : GLHelper::popName();
321 1703707 : }
322 :
323 :
324 : void
325 0 : GUIPerson::drawAction_drawWalkingareaPath(const GUIVisualizationSettings& s) const {
326 0 : MSStageWalking* stage = dynamic_cast<MSStageWalking*>(getCurrentStage());
327 0 : if (stage != nullptr) {
328 0 : setColor(s);
329 0 : MSPModel_Striping::PState* stripingState = dynamic_cast<MSPModel_Striping::PState*>(stage->getPState());
330 0 : if (stripingState != nullptr) {
331 0 : const MSPModel_Striping::WalkingAreaPath* waPath = stripingState->myWalkingAreaPath;
332 0 : if (waPath != nullptr) {
333 0 : GLHelper::pushMatrix();
334 0 : glTranslated(0, 0, getType());
335 0 : GLHelper::drawBoxLines(waPath->shape, 0.05);
336 0 : GLHelper::popMatrix();
337 : }
338 : }
339 : }
340 0 : }
341 :
342 : void
343 0 : GUIPerson::drawGLAdditional(GUISUMOAbstractView* const parent, const GUIVisualizationSettings& s) const {
344 0 : GLHelper::pushName(getGlID());
345 0 : GLHelper::pushMatrix();
346 0 : glTranslated(0, 0, getType() - .1); // don't draw on top of other cars
347 0 : if (hasActiveAddVisualisation(parent, VO_SHOW_WALKINGAREA_PATH)) {
348 0 : drawAction_drawWalkingareaPath(s);
349 : }
350 0 : if (hasActiveAddVisualisation(parent, VO_SHOW_ROUTE)) {
351 0 : if (getCurrentStageType() == MSStageType::WALKING) {
352 0 : setColor(s);
353 0 : RGBColor current = GLHelper::getColor();
354 0 : RGBColor darker = current.changedBrightness(-51);
355 0 : GLHelper::setColor(darker);
356 0 : MSStageWalking* stage = dynamic_cast<MSStageWalking*>(getCurrentStage());
357 : assert(stage != 0);
358 0 : const double exaggeration = getExaggeration(s);
359 : const ConstMSEdgeVector& edges = stage->getRoute();
360 0 : const bool s2 = s.secondaryShape;
361 0 : for (ConstMSEdgeVector::const_iterator it = edges.begin(); it != edges.end(); ++it) {
362 0 : GUILane* lane = static_cast<GUILane*>((*it)->getLanes()[0]);
363 0 : GLHelper::drawBoxLines(lane->getShape(s2), lane->getShapeRotations(s2), lane->getShapeLengths(s2), exaggeration);
364 : }
365 : }
366 : }
367 0 : GLHelper::popMatrix();
368 0 : GLHelper::popName();
369 0 : }
370 :
371 :
372 : void
373 214021 : GUIPerson::setPositionInVehicle(const GUIBaseVehicle::Seat& pos) {
374 214021 : myPositionInVehicle = pos;
375 214021 : }
376 :
377 :
378 : void
379 1703707 : GUIPerson::setColor(const GUIVisualizationSettings& s) const {
380 1703707 : RGBColor col;
381 : const GUIColorer& c = s.personColorer;
382 1703707 : if (!setFunctionalColor(c.getActive(), this, col)) {
383 1129525 : col = c.getScheme().getColor(getColorValue(s, c.getActive()));
384 : }
385 1703707 : GLHelper::setColor(col);
386 1703707 : }
387 :
388 :
389 : bool
390 1706971 : GUIPerson::setFunctionalColor(int activeScheme, const MSPerson* person, RGBColor& col) {
391 1706971 : switch (activeScheme) {
392 1237779 : case 0: {
393 1237779 : if (person->getParameter().wasSet(VEHPARS_COLOR_SET)) {
394 126280 : col = person->getParameter().color;
395 126280 : return true;
396 : }
397 1111499 : if (person->getVehicleType().wasSet(VTYPEPARS_COLOR_SET)) {
398 447910 : col = person->getVehicleType().getColor();
399 447910 : return true;
400 : }
401 : return false;
402 : }
403 0 : case 2: {
404 0 : if (person->getParameter().wasSet(VEHPARS_COLOR_SET)) {
405 0 : col = person->getParameter().color;
406 0 : return true;
407 : }
408 : return false;
409 : }
410 0 : case 3: {
411 0 : if (person->getVehicleType().wasSet(VTYPEPARS_COLOR_SET)) {
412 0 : col = person->getVehicleType().getColor();
413 0 : return true;
414 : }
415 : return false;
416 : }
417 0 : case 9: { // color by angle
418 0 : double hue = GeomHelper::naviDegree(person->getAngle());
419 0 : col = RGBColor::fromHSV(hue, 1., 1.);
420 0 : return true;
421 : }
422 0 : case 10: { // color randomly (by pointer)
423 0 : const double hue = (double)((long long int)person % 360); // [0-360]
424 0 : const double sat = (double)(((long long int)person / 360) % 67) / 100. + 0.33; // [0.33-1]
425 0 : col = RGBColor::fromHSV(hue, sat, 1.);
426 0 : return true;
427 : }
428 : default:
429 : return false;
430 : }
431 : }
432 :
433 :
434 : double
435 1132781 : GUIPerson::getColorValue(const GUIVisualizationSettings& /* s */, int activeScheme) const {
436 1132781 : switch (activeScheme) {
437 0 : case 4:
438 0 : switch (getCurrentStageType()) {
439 : case MSStageType::WAITING:
440 : return -1;
441 0 : case MSStageType::WAITING_FOR_DEPART:
442 0 : return -2;
443 0 : default:
444 0 : return getSpeed();
445 : }
446 469192 : case 5:
447 469192 : if (isWaiting4Vehicle()) {
448 : return 5;
449 : } else {
450 179808 : return (double)getCurrentStageType();
451 : }
452 0 : case 6:
453 0 : return getWaitingSeconds();
454 0 : case 7:
455 0 : return isJammed() ? 1 : 0;
456 0 : case 8:
457 0 : return gSelected.isSelected(GLO_PERSON, getGlID());
458 : }
459 : return 0;
460 : }
461 :
462 :
463 : double
464 472187 : GUIPerson::getEdgePos() const {
465 472187 : FXMutexLock locker(myLock);
466 472187 : if (hasArrived()) {
467 : return -1;
468 : }
469 472187 : return MSPerson::getEdgePos();
470 : }
471 :
472 : int
473 92710 : GUIPerson::getDirection() const {
474 92710 : FXMutexLock locker(myLock);
475 92710 : if (hasArrived()) {
476 0 : return MSPModel::UNDEFINED_DIRECTION;
477 : }
478 92710 : return MSPerson::getDirection();
479 : }
480 :
481 :
482 : Position
483 1078546 : GUIPerson::getPosition() const {
484 1078546 : FXMutexLock locker(myLock);
485 1078546 : if (hasArrived()) {
486 0 : return Position::INVALID;
487 : }
488 1078546 : return MSPerson::getPosition();
489 : }
490 :
491 :
492 : Position
493 1703707 : GUIPerson::getGUIPosition(const GUIVisualizationSettings* s) const {
494 1703707 : FXMutexLock locker(myLock);
495 1703707 : if (hasArrived()) {
496 0 : return Position::INVALID;
497 : }
498 1703707 : if (getCurrentStageType() == MSStageType::DRIVING) {
499 521521 : if (!isWaiting4Vehicle() && myPositionInVehicle.pos != Position::INVALID) {
500 213870 : if (s != nullptr) {
501 213870 : return myPositionInVehicle.pos;
502 : } else {
503 : // centering boundary must cover the vehicle regardless of exaggeration and zoom
504 0 : SUMOVehicle* veh = getCurrentStage()->getVehicle();
505 0 : if (veh == nullptr) {
506 : // should not happen
507 0 : return myPositionInVehicle.pos;
508 : }
509 0 : PositionVector b = veh->getBoundingBox();
510 0 : if (b.around(myPositionInVehicle.pos)) {
511 0 : return myPositionInVehicle.pos;
512 : } else {
513 0 : return b.getCentroid();
514 : }
515 0 : }
516 : } else if (isWaiting4Vehicle()
517 307500 : && s != nullptr
518 307500 : && s->gaming
519 0 : && getCurrentStage()->getOriginStop() != nullptr
520 307651 : && s->addSize.getExaggeration(*s, nullptr) > 1) {
521 : // shift position away from stop center
522 0 : Position pos = MSPerson::getPosition();
523 0 : Position ref = getCurrentStage()->getOriginStop()->getCenterPos();
524 0 : Position shifted = ref + (pos - ref) * s->personSize.getExaggeration(*s, this);
525 0 : return shifted;
526 : }
527 : }
528 1489837 : return MSPerson::getPosition();
529 : }
530 :
531 :
532 : double
533 1703707 : GUIPerson::getGUIAngle() const {
534 1703707 : FXMutexLock locker(myLock);
535 1703707 : if (hasArrived()) {
536 : return INVALID_DOUBLE;
537 : }
538 2225228 : if (getCurrentStageType() == MSStageType::DRIVING && !isWaiting4Vehicle() && myPositionInVehicle.pos != Position::INVALID) {
539 213870 : return myPositionInVehicle.angle;
540 : } else {
541 1489837 : return MSPerson::getAngle();
542 : }
543 : }
544 :
545 :
546 : double
547 0 : GUIPerson::getNaviDegree() const {
548 0 : FXMutexLock locker(myLock);
549 0 : if (hasArrived()) {
550 : return INVALID_DOUBLE;
551 : }
552 0 : return GeomHelper::naviDegree(MSPerson::getAngle());
553 : }
554 :
555 :
556 : double
557 2 : GUIPerson::getWaitingSeconds() const {
558 2 : FXMutexLock locker(myLock);
559 2 : if (hasArrived()) {
560 : return -1;
561 : }
562 2 : return MSPerson::getWaitingSeconds();
563 : }
564 :
565 :
566 : double
567 250279 : GUIPerson::getSpeed() const {
568 250279 : FXMutexLock locker(myLock);
569 250279 : if (hasArrived()) {
570 : return -1;
571 : }
572 250279 : return MSPerson::getSpeed();
573 : }
574 :
575 :
576 : std::string
577 0 : GUIPerson::getStageIndexDescription() const {
578 0 : FXMutexLock locker(myLock);
579 0 : if (hasArrived()) {
580 0 : return "arrived";
581 : }
582 : // there is always the "start" stage which we do not count here because it is not strictly part of the plan
583 0 : return toString(getCurrentStageIndex()) + " of " + toString(getNumStages() - 1);
584 : }
585 :
586 :
587 : std::string
588 0 : GUIPerson::getEdgeID() const {
589 0 : FXMutexLock locker(myLock);
590 0 : if (hasArrived()) {
591 0 : return "arrived";
592 : }
593 0 : return getEdge()->getID();
594 : }
595 :
596 :
597 : std::string
598 0 : GUIPerson::getFromEdgeID() const {
599 0 : FXMutexLock locker(myLock);
600 0 : if (hasArrived()) {
601 0 : return "arrived";
602 : }
603 : return getFromEdge()->getID();
604 : }
605 :
606 :
607 : std::string
608 0 : GUIPerson::getDestinationEdgeID() const {
609 0 : FXMutexLock locker(myLock);
610 0 : if (hasArrived()) {
611 0 : return "arrived";
612 : }
613 : return getDestination()->getID();
614 : }
615 :
616 :
617 : std::string
618 0 : GUIPerson::getDestinationStopID() const {
619 0 : FXMutexLock locker(myLock);
620 0 : if (hasArrived()) {
621 0 : return "";
622 : }
623 : MSStoppingPlace* destStop = getCurrentStage()->getDestinationStop();
624 0 : if (destStop != nullptr) {
625 : return destStop->getID();
626 : } else {
627 0 : return "";
628 : }
629 : }
630 :
631 :
632 : std::string
633 0 : GUIPerson::getVehicleID() const {
634 0 : FXMutexLock locker(myLock);
635 0 : if (hasArrived()) {
636 0 : return "";
637 : }
638 0 : SUMOVehicle* veh = getCurrentStage()->getVehicle();
639 0 : if (veh != nullptr) {
640 : return veh->getID();
641 : } else {
642 0 : return "";
643 : }
644 : }
645 :
646 :
647 : double
648 0 : GUIPerson::getStopDuration() const {
649 0 : FXMutexLock locker(myLock);
650 0 : if (hasArrived()) {
651 : return -1;
652 : }
653 0 : if (getCurrentStage()->getStageType() == MSStageType::WAITING) {
654 0 : return STEPS2TIME(dynamic_cast<MSStageWaiting*>(getCurrentStage())->getStopEnd() - SIMSTEP);
655 : } else {
656 : return -1;
657 : }
658 : }
659 :
660 :
661 : double
662 0 : GUIPerson::getStageArrivalPos() const {
663 0 : FXMutexLock locker(myLock);
664 0 : if (hasArrived()) {
665 : return INVALID_DOUBLE;
666 : }
667 0 : return getCurrentStage()->getArrivalPos();
668 : }
669 :
670 : bool
671 55551 : GUIPerson::proceed(MSNet* net, SUMOTime time, const bool vehicleArrived) {
672 : // acquire lock before locking the person to avoid mutual deadlock (#9468)
673 55551 : ScopedLocker<const MSEdge, true> edgeLocker(*getEdge());
674 55551 : FXMutexLock locker(myLock);
675 111083 : return MSTransportable::proceed(net, time, vehicleArrived);
676 : }
677 :
678 : // -------------------------------------------------------------------------
679 : // GUIPerson - Additional Visualsation methods
680 : // -------------------------------------------------------------------------
681 :
682 : bool
683 0 : GUIPerson::hasActiveAddVisualisation(GUISUMOAbstractView* const parent, int which) const {
684 0 : return myAdditionalVisualizations.find(parent) != myAdditionalVisualizations.end() && (myAdditionalVisualizations.find(parent)->second & which) != 0;
685 : }
686 :
687 :
688 : void
689 0 : GUIPerson::addActiveAddVisualisation(GUISUMOAbstractView* const parent, int which) {
690 0 : if (myAdditionalVisualizations.find(parent) == myAdditionalVisualizations.end()) {
691 0 : myAdditionalVisualizations[parent] = 0;
692 : }
693 0 : myAdditionalVisualizations[parent] |= which;
694 0 : parent->addAdditionalGLVisualisation(this);
695 0 : }
696 :
697 :
698 : void
699 0 : GUIPerson::removeActiveAddVisualisation(GUISUMOAbstractView* const parent, int which) {
700 0 : myAdditionalVisualizations[parent] &= ~which;
701 0 : parent->removeAdditionalGLVisualisation(this);
702 0 : }
703 :
704 : bool
705 33311680 : GUIPerson::isSelected() const {
706 33311680 : return gSelected.isSelected(GLO_PERSON, getGlID());
707 : }
708 :
709 :
710 : /****************************************************************************/
|