LCOV - code coverage report
Current view: top level - src/guisim - GUIContainer.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 70 198 35.4 %
Date: 2024-04-27 15:34:54 Functions: 13 30 43.3 %

          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    GUIContainer.cpp
      15             : /// @author  Melanie Weber
      16             : /// @author  Andreas Kendziorra
      17             : /// @date    Wed, 01.08.2014
      18             : ///
      19             : // A MSContainer extended by some values for usage within the gui
      20             : /****************************************************************************/
      21             : #include <config.h>
      22             : 
      23             : #include <cmath>
      24             : #include <vector>
      25             : #include <string>
      26             : #include <microsim/logging/CastingFunctionBinding.h>
      27             : #include <microsim/logging/FunctionBinding.h>
      28             : #include <microsim/MSLane.h>
      29             : #include <microsim/MSVehicleControl.h>
      30             : #include <microsim/lcmodels/MSAbstractLaneChangeModel.h>
      31             : #include <microsim/devices/MSDevice_Vehroutes.h>
      32             : #include <utils/common/MsgHandler.h>
      33             : #include <utils/common/StringUtils.h>
      34             : #include <utils/vehicle/SUMOVehicleParameter.h>
      35             : #include <utils/geom/GeomHelper.h>
      36             : #include <utils/gui/images/GUITexturesHelper.h>
      37             : #include <utils/gui/windows/GUISUMOAbstractView.h>
      38             : #include <utils/gui/windows/GUIAppEnum.h>
      39             : #include <utils/gui/div/GUIParameterTableWindow.h>
      40             : #include <utils/gui/div/GUIGlobalSelection.h>
      41             : #include <utils/gui/div/GLHelper.h>
      42             : #include <utils/gui/div/GLObjectValuePassConnector.h>
      43             : #include <utils/geom/PositionVector.h>
      44             : #include <gui/GUIApplicationWindow.h>
      45             : #include <gui/GUIGlobals.h>
      46             : #include <utils/gui/globjects/GLIncludes.h>
      47             : #include <utils/gui/div/GUIDesigns.h>
      48             : 
      49             : #include "GUIContainer.h"
      50             : #include "GUINet.h"
      51             : #include "GUIEdge.h"
      52             : 
      53             : //#define GUIContainer_DEBUG_DRAW_WALKING_AREA_SHAPE
      54             : 
      55             : // ===========================================================================
      56             : // FOX callback mapping
      57             : // ===========================================================================
      58             : FXDEFMAP(GUIContainer::GUIContainerPopupMenu) GUIContainerPopupMenuMap[] = {
      59             :     FXMAPFUNC(SEL_COMMAND, MID_START_TRACK, GUIContainer::GUIContainerPopupMenu::onCmdStartTrack),
      60             :     FXMAPFUNC(SEL_COMMAND, MID_STOP_TRACK,  GUIContainer::GUIContainerPopupMenu::onCmdStopTrack),
      61             :     FXMAPFUNC(SEL_COMMAND, MID_SHOWPLAN,    GUIContainer::GUIContainerPopupMenu::onCmdShowPlan),
      62             : };
      63             : 
      64             : // Object implementation
      65           0 : FXIMPLEMENT(GUIContainer::GUIContainerPopupMenu, GUIGLObjectPopupMenu, GUIContainerPopupMenuMap, ARRAYNUMBER(GUIContainerPopupMenuMap))
      66             : 
      67             : #define WATER_WAY_OFFSET 6.0
      68             : 
      69             : // ===========================================================================
      70             : // method definitions
      71             : // ===========================================================================
      72             : /* -------------------------------------------------------------------------
      73             :  * GUIContainer::GUIContainerPopupMenu - methods
      74             :  * ----------------------------------------------------------------------- */
      75           0 : GUIContainer::GUIContainerPopupMenu::GUIContainerPopupMenu(
      76           0 :     GUIMainWindow& app, GUISUMOAbstractView& parent, GUIGlObject& o)
      77           0 :     : GUIGLObjectPopupMenu(app, parent, o) {
      78           0 : }
      79             : 
      80             : 
      81           0 : GUIContainer::GUIContainerPopupMenu::~GUIContainerPopupMenu() {}
      82             : 
      83             : 
      84             : long
      85           0 : GUIContainer::GUIContainerPopupMenu::onCmdShowPlan(FXObject*, FXSelector, void*) {
      86           0 :     GUIContainer* p = dynamic_cast<GUIContainer*>(myObject);
      87           0 :     if (p == nullptr) {
      88             :         return 1;
      89             :     }
      90           0 :     GUIParameterTableWindow* ret = new GUIParameterTableWindow(*myApplication, *p);
      91             :     // add items
      92           0 :     for (int stage = 1; stage < p->getNumStages(); stage++) {
      93           0 :         ret->mkItem(toString(stage).c_str(), false, p->getStageSummary(stage));
      94             :     }
      95             :     // close building (use an object that is not Parameterised as argument)
      96           0 :     Parameterised dummy;
      97           0 :     ret->closeBuilding(&dummy);
      98             :     return 1;
      99           0 : }
     100             : 
     101             : 
     102             : long
     103           0 : GUIContainer::GUIContainerPopupMenu::onCmdStartTrack(FXObject*, FXSelector, void*) {
     104             :     assert(myObject->getType() == GLO_PERSON);
     105           0 :     if (myParent->getTrackedID() != static_cast<GUIContainer*>(myObject)->getGlID()) {
     106           0 :         myParent->startTrack(static_cast<GUIContainer*>(myObject)->getGlID());
     107             :     }
     108           0 :     return 1;
     109             : }
     110             : 
     111             : long
     112           0 : GUIContainer::GUIContainerPopupMenu::onCmdStopTrack(FXObject*, FXSelector, void*) {
     113             :     assert(myObject->getType() == GLO_PERSON);
     114           0 :     myParent->stopTrack();
     115           0 :     return 1;
     116             : }
     117             : 
     118             : 
     119             : 
     120             : 
     121             : /* -------------------------------------------------------------------------
     122             :  * GUIContainer - methods
     123             :  * ----------------------------------------------------------------------- */
     124         373 : GUIContainer::GUIContainer(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan) :
     125             :     MSTransportable(pars, vtype, plan, false),
     126         373 :     GUIGlObject(GLO_CONTAINER, pars->id, GUIIconSubSys::getIcon(GUIIcon::CONTAINER)) {
     127         373 : }
     128             : 
     129             : 
     130         746 : GUIContainer::~GUIContainer() {
     131        1119 : }
     132             : 
     133             : 
     134             : GUIGLObjectPopupMenu*
     135           0 : GUIContainer::getPopUpMenu(GUIMainWindow& app,
     136             :                            GUISUMOAbstractView& parent) {
     137           0 :     GUIGLObjectPopupMenu* ret = new GUIContainerPopupMenu(app, parent, *this);
     138           0 :     buildPopupHeader(ret, app);
     139           0 :     buildCenterPopupEntry(ret);
     140           0 :     buildNameCopyPopupEntry(ret);
     141           0 :     buildSelectionPopupEntry(ret);
     142           0 :     new FXMenuSeparator(ret);
     143           0 :     if (parent.getTrackedID() != getGlID()) {
     144           0 :         GUIDesigns::buildFXMenuCommand(ret, "Start Tracking", nullptr, ret, MID_START_TRACK);
     145             :     } else {
     146           0 :         GUIDesigns::buildFXMenuCommand(ret, "Stop Tracking", nullptr, ret, MID_STOP_TRACK);
     147             :     }
     148             :     //
     149             : 
     150           0 :     buildShowParamsPopupEntry(ret);
     151           0 :     buildShowTypeParamsPopupEntry(ret);
     152           0 :     GUIDesigns::buildFXMenuCommand(ret, "Show Plan", GUIIconSubSys::getIcon(GUIIcon::APP_TABLE), ret, MID_SHOWPLAN);
     153           0 :     new FXMenuSeparator(ret);
     154           0 :     buildPositionCopyEntry(ret, app);
     155           0 :     return ret;
     156             : }
     157             : 
     158             : 
     159             : GUIParameterTableWindow*
     160           0 : GUIContainer::getParameterWindow(GUIMainWindow& app,
     161             :                                  GUISUMOAbstractView&) {
     162           0 :     GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
     163             :     // add items
     164           0 :     ret->mkItem(TL("stage"), false, getCurrentStageDescription());
     165             :     // there is always the "start" stage which we do not count here because it is not strictly part of the plan
     166           0 :     ret->mkItem(TL("stage index"), false, toString(getCurrentStageIndex()) + " of " + toString(getNumStages() - 1));
     167           0 :     ret->mkItem(TL("start edge [id]"), false, getFromEdge()->getID());
     168           0 :     ret->mkItem(TL("dest edge [id]"), false, getDestination()->getID());
     169           0 :     ret->mkItem(TL("arrivalPos [m]"), false, toString(getCurrentStage()->getArrivalPos()));
     170           0 :     ret->mkItem(TL("edge [id]"), false, getEdge()->getID());
     171           0 :     ret->mkItem(TL("position [m]"), true, new FunctionBinding<GUIContainer, double>(this, &GUIContainer::getEdgePos));
     172           0 :     ret->mkItem(TL("speed [m/s]"), true, new FunctionBinding<GUIContainer, double>(this, &GUIContainer::getSpeed));
     173           0 :     ret->mkItem(TL("speed factor"), false, getChosenSpeedFactor());
     174           0 :     ret->mkItem(TL("angle [degree]"), true, new FunctionBinding<GUIContainer, double>(this, &GUIContainer::getAngle));
     175           0 :     ret->mkItem(TL("waiting time [s]"), true, new FunctionBinding<GUIContainer, double>(this, &GUIContainer::getWaitingSeconds));
     176           0 :     ret->mkItem(TL("desired depart [s]"), false, time2string(getParameter().depart));
     177             :     // close building
     178           0 :     ret->closeBuilding(&getParameter());
     179           0 :     return ret;
     180             : }
     181             : 
     182             : 
     183             : GUIParameterTableWindow*
     184           0 : GUIContainer::getTypeParameterWindow(GUIMainWindow& app, GUISUMOAbstractView&) {
     185           0 :     GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this, "vType:" + myVType->getID());
     186           0 :     ret->mkItem(TL("length"), false, myVType->getLength());
     187           0 :     ret->mkItem(TL("width"), false, myVType->getWidth());
     188           0 :     ret->mkItem(TL("height"), false, myVType->getHeight());
     189           0 :     ret->mkItem(TL("minGap"), false, myVType->getMinGap());
     190           0 :     ret->mkItem(TL("mass [kg]"), false, myVType->getMass());
     191           0 :     ret->mkItem(TL("maximum speed [m/s]"), false, myVType->getMaxSpeed());
     192           0 :     ret->closeBuilding(&(myVType->getParameter()));
     193           0 :     return ret;
     194             : }
     195             : 
     196             : 
     197             : double
     198       21997 : GUIContainer::getExaggeration(const GUIVisualizationSettings& s) const {
     199       21997 :     return s.containerSize.getExaggeration(s, this);
     200             : }
     201             : 
     202             : 
     203             : Boundary
     204           0 : GUIContainer::getCenteringBoundary() const {
     205           0 :     Boundary b;
     206             :     // ensure that the vehicle is drawn, otherwise myPositionInVehicle will not be updated
     207           0 :     b.add(getPosition());
     208           0 :     b.grow(20);
     209           0 :     return b;
     210           0 : }
     211             : 
     212             : 
     213             : void
     214       21997 : GUIContainer::drawGL(const GUIVisualizationSettings& s) const {
     215       21997 :     GLHelper::pushName(getGlID());
     216       21997 :     GLHelper::pushMatrix();
     217       21997 :     Position p1 = getPosition();
     218       21997 :     double angle = getAngle();
     219       43889 :     if (getCurrentStageType() == MSStageType::DRIVING && !isWaiting4Vehicle()) {
     220        5826 :         p1 = myPositionInVehicle.pos;
     221        5826 :         angle = myPositionInVehicle.angle;
     222             :     }
     223       21997 :     glTranslated(p1.x(), p1.y(), getType());
     224       21997 :     glRotated(RAD2DEG(angle), 0, 0, 1);
     225             :     // set container color
     226       21997 :     setColor(s);
     227             :     // scale
     228       21997 :     const double upscale = getExaggeration(s);
     229       21997 :     glScaled(upscale, upscale, 1);
     230       21997 :     switch (s.containerQuality) {
     231       21997 :         case 0:
     232             :         case 1:
     233             :         case 2:
     234       21997 :             drawAction_drawAsPoly(s);
     235             :             break;
     236           0 :         case 3:
     237             :         default:
     238           0 :             drawAction_drawAsImage(s);
     239             :             break;
     240             :     }
     241       21997 :     GLHelper::popMatrix();
     242             : 
     243       21997 :     drawName(p1, s.scale, s.containerName, s.angle);
     244       21997 :     GLHelper::popName();
     245       21997 : }
     246             : 
     247             : 
     248             : void
     249           0 : GUIContainer::drawGLAdditional(GUISUMOAbstractView* const /* parent */, const GUIVisualizationSettings& /* s */) const {
     250           0 :     GLHelper::pushName(getGlID());
     251           0 :     GLHelper::pushMatrix();
     252             :     /*
     253             :     glTranslated(0, 0, getType() - .1); // don't draw on top of other cars
     254             :     if (hasActiveAddVisualisation(parent, VO_SHOW_BEST_LANES)) {
     255             :         drawBestLanes();
     256             :     }
     257             :     if (hasActiveAddVisualisation(parent, VO_SHOW_ROUTE)) {
     258             :         drawRoute(s, 0, 0.25);
     259             :     }
     260             :     if (hasActiveAddVisualisation(parent, VO_SHOW_ALL_ROUTES)) {
     261             :         if (getNumberReroutes() > 0) {
     262             :             const int noReroutePlus1 = getNumberReroutes() + 1;
     263             :             for (int i = noReroutePlus1 - 1; i >= 0; i--) {
     264             :                 double darken = double(0.4) / double(noReroutePlus1) * double(i);
     265             :                 drawRoute(s, i, darken);
     266             :             }
     267             :         } else {
     268             :             drawRoute(s, 0, 0.25);
     269             :         }
     270             :     }
     271             :     if (hasActiveAddVisualisation(parent, VO_SHOW_LFLINKITEMS)) {
     272             :         for (DriveItemVector::const_iterator i = myLFLinkLanes.begin(); i != myLFLinkLanes.end(); ++i) {
     273             :             if((*i).myLink==0) {
     274             :                 continue;
     275             :             }
     276             :             MSLink* link = (*i).myLink;
     277             :             MSLane *via = link->getViaLane();
     278             :             if (via == 0) {
     279             :                 via = link->getLane();
     280             :             }
     281             :             if (via != 0) {
     282             :                 Position p = via->getShape()[0];
     283             :                 if((*i).mySetRequest) {
     284             :                     glColor3f(0, 1, 0);
     285             :                 } else {
     286             :                     glColor3f(1, 0, 0);
     287             :                 }
     288             :                 glTranslated(p.x(), p.y(), -.1);
     289             :                 GLHelper::drawFilledCircle(1);
     290             :                 glTranslated(-p.x(), -p.y(), .1);
     291             :             }
     292             :         }
     293             :     }
     294             :     */
     295           0 :     GLHelper::popMatrix();
     296           0 :     GLHelper::popName();
     297           0 : }
     298             : 
     299             : 
     300             : 
     301             : 
     302             : void
     303       21997 : GUIContainer::setColor(const GUIVisualizationSettings& s) const {
     304             :     const GUIColorer& c = s.containerColorer;
     305       21997 :     if (!setFunctionalColor(c.getActive())) {
     306       19278 :         GLHelper::setColor(c.getScheme().getColor(getColorValue(s, c.getActive())));
     307             :     }
     308       21997 : }
     309             : 
     310             : 
     311             : bool
     312       21997 : GUIContainer::setFunctionalColor(int activeScheme) const {
     313       21997 :     switch (activeScheme) {
     314       21997 :         case 0: {
     315       21997 :             if (getParameter().wasSet(VEHPARS_COLOR_SET)) {
     316        2719 :                 GLHelper::setColor(getParameter().color);
     317        2719 :                 return true;
     318             :             }
     319       19278 :             if (getVehicleType().wasSet(VTYPEPARS_COLOR_SET)) {
     320           0 :                 GLHelper::setColor(getVehicleType().getColor());
     321           0 :                 return true;
     322             :             }
     323             :             return false;
     324             :         }
     325           0 :         case 2: {
     326           0 :             if (getParameter().wasSet(VEHPARS_COLOR_SET)) {
     327           0 :                 GLHelper::setColor(getParameter().color);
     328           0 :                 return true;
     329             :             }
     330             :             return false;
     331             :         }
     332           0 :         case 3: {
     333           0 :             if (getVehicleType().wasSet(VTYPEPARS_COLOR_SET)) {
     334           0 :                 GLHelper::setColor(getVehicleType().getColor());
     335           0 :                 return true;
     336             :             }
     337             :             return false;
     338             :         }
     339           0 :         case 8: { // color by angle
     340           0 :             double hue = GeomHelper::naviDegree(getAngle());
     341           0 :             GLHelper::setColor(RGBColor::fromHSV(hue, 1., 1.));
     342           0 :             return true;
     343             :         }
     344           0 :         case 9: { // color randomly (by pointer)
     345           0 :             const double hue = (double)((long long int)this % 360); // [0-360]
     346           0 :             const double sat = (double)(((long long int)this / 360) % 67) / 100. + 0.33; // [0.33-1]
     347           0 :             GLHelper::setColor(RGBColor::fromHSV(hue, sat, 1.));
     348           0 :             return true;
     349             :         }
     350             :         default:
     351             :             return false;
     352             :     }
     353             : }
     354             : 
     355             : 
     356             : double
     357       19278 : GUIContainer::getColorValue(const GUIVisualizationSettings& /* s */, int activeScheme) const {
     358       19278 :     switch (activeScheme) {
     359           0 :         case 4:
     360           0 :             return getSpeed();
     361           0 :         case 5:
     362           0 :             if (isWaiting4Vehicle()) {
     363             :                 return 5;
     364             :             } else {
     365           0 :                 return (double)getCurrentStageType();
     366             :             }
     367           0 :         case 6:
     368           0 :             return getWaitingSeconds();
     369           0 :         case 7:
     370           0 :             return gSelected.isSelected(GLO_CONTAINER, getGlID());
     371             :     }
     372             :     return 0;
     373             : }
     374             : 
     375             : 
     376             : double
     377        4836 : GUIContainer::getEdgePos() const {
     378        4836 :     FXMutexLock locker(myLock);
     379        9672 :     return MSTransportable::getEdgePos();
     380             : }
     381             : 
     382             : int
     383           0 : GUIContainer::getDirection() const {
     384           0 :     FXMutexLock locker(myLock);
     385           0 :     return MSTransportable::getDirection();
     386             : }
     387             : 
     388             : 
     389             : Position
     390       24161 : GUIContainer::getPosition() const {
     391       24161 :     FXMutexLock locker(myLock);
     392       24161 :     if (getCurrentStageType() == MSStageType::WAITING && getEdge()->getPermissions() == SVC_SHIP) {
     393           0 :         MSLane* lane = getEdge()->getLanes().front();   //the most right lane of the water way
     394             :         PositionVector laneShape = lane->getShape();
     395           0 :         return laneShape.positionAtOffset2D(getEdgePos(), WATER_WAY_OFFSET);
     396           0 :     }
     397       24161 :     return MSTransportable::getPosition();
     398             : }
     399             : 
     400             : 
     401             : double
     402       24475 : GUIContainer::getAngle() const {
     403       24475 :     FXMutexLock locker(myLock);
     404       48950 :     return MSTransportable::getAngle();
     405             : }
     406             : 
     407             : 
     408             : double
     409           0 : GUIContainer::getWaitingSeconds() const {
     410           0 :     FXMutexLock locker(myLock);
     411           0 :     return MSTransportable::getWaitingSeconds();
     412             : }
     413             : 
     414             : 
     415             : double
     416        2164 : GUIContainer::getSpeed() const {
     417        2164 :     FXMutexLock locker(myLock);
     418        4328 :     return MSTransportable::getSpeed();
     419             : }
     420             : 
     421             : 
     422             : void
     423       21997 : GUIContainer::drawAction_drawAsPoly(const GUIVisualizationSettings& /* s */) const {
     424             :     // draw pedestrian shape
     425       21997 :     glScaled(getVehicleType().getLength(), getVehicleType().getWidth(), 1);
     426       21997 :     glBegin(GL_QUADS);
     427       21997 :     glVertex2d(0, 0.5);
     428       21997 :     glVertex2d(0, -0.5);
     429       21997 :     glVertex2d(-1, -0.5);
     430       21997 :     glVertex2d(-1, 0.5);
     431       21997 :     glEnd();
     432       21997 :     GLHelper::setColor(GLHelper::getColor().changedBrightness(-30));
     433       21997 :     glTranslated(0, 0, .045);
     434       21997 :     glBegin(GL_QUADS);
     435       21997 :     glVertex2d(-0.1, 0.4);
     436       21997 :     glVertex2d(-0.1, -0.4);
     437       21997 :     glVertex2d(-0.9, -0.4);
     438       21997 :     glVertex2d(-0.9, 0.4);
     439       21997 :     glEnd();
     440       21997 : }
     441             : 
     442             : 
     443             : void
     444           0 : GUIContainer::drawAction_drawAsImage(const GUIVisualizationSettings& s) const {
     445           0 :     const std::string& file = getVehicleType().getImgFile();
     446           0 :     if (file != "") {
     447             :         // @todo invent an option for controlling whether images should be rotated or not
     448             :         //if (getVehicleType().getGuiShape() == SVS_CONTAINER) {
     449             :         //    glRotated(RAD2DEG(getAngle() + M_PI / 2.), 0, 0, 1);
     450             :         //}
     451           0 :         int textureID = GUITexturesHelper::getTextureID(file);
     452           0 :         if (textureID > 0) {
     453           0 :             const double exaggeration = s.personSize.getExaggeration(s, this);
     454           0 :             const double halfLength = getVehicleType().getLength() / 2.0 * exaggeration;
     455           0 :             const double halfWidth = getVehicleType().getWidth() / 2.0 * exaggeration;
     456           0 :             GUITexturesHelper::drawTexturedBox(textureID, -halfWidth, -halfLength, halfWidth, halfLength);
     457             :         }
     458             :     } else {
     459             :         // fallback if no image is defined
     460           0 :         drawAction_drawAsPoly(s);
     461             :     }
     462           0 : }
     463             : 
     464             : bool
     465           0 : GUIContainer::isSelected() const {
     466           0 :     return gSelected.isSelected(GLO_CONTAINER, getGlID());
     467             : }
     468             : 
     469             : /****************************************************************************/

Generated by: LCOV version 1.14