LCOV - code coverage report
Current view: top level - src/guisim - GUIBaseVehicle.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 186 596 31.2 %
Date: 2024-04-27 15:34:54 Functions: 20 53 37.7 %

          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    GUIBaseVehicle.cpp
      15             : /// @author  Daniel Krajzewicz
      16             : /// @author  Jakob Erdmann
      17             : /// @author  Michael Behrisch
      18             : /// @author  Laura Bieker-Walz
      19             : /// @date    Sept 2002
      20             : ///
      21             : // A MSVehicle extended by some values for usage within the gui
      22             : /****************************************************************************/
      23             : #include <config.h>
      24             : 
      25             : #include <cmath>
      26             : #include <vector>
      27             : #include <string>
      28             : #include <functional>
      29             : #include <utils/common/MsgHandler.h>
      30             : #include <utils/common/StringUtils.h>
      31             : #include <utils/common/StringTokenizer.h>
      32             : #include <utils/geom/GeomHelper.h>
      33             : #include <utils/vehicle/SUMOVehicleParameter.h>
      34             : #include <utils/emissions/PollutantsInterface.h>
      35             : #include <utils/gui/globjects/GLIncludes.h>
      36             : #include <utils/gui/windows/GUISUMOAbstractView.h>
      37             : #include <utils/gui/windows/GUIAppEnum.h>
      38             : #include <utils/gui/images/GUITexturesHelper.h>
      39             : #include <utils/gui/div/GUIGlobalSelection.h>
      40             : #include <utils/gui/div/GLHelper.h>
      41             : #include <utils/gui/div/GUIGlobalSelection.h>
      42             : #include <utils/gui/div/GUIBaseVehicleHelper.h>
      43             : #include <mesosim/MEVehicle.h>
      44             : #include <mesosim/MELoop.h>
      45             : #include <microsim/MSVehicle.h>
      46             : #include <microsim/MSLane.h>
      47             : #include <microsim/logging/CastingFunctionBinding.h>
      48             : #include <microsim/logging/FunctionBinding.h>
      49             : #include <microsim/MSVehicleControl.h>
      50             : #include <microsim/MSStop.h>
      51             : #include <microsim/MSTrainHelper.h>
      52             : #include <microsim/lcmodels/MSAbstractLaneChangeModel.h>
      53             : #include <microsim/devices/MSDevice_Vehroutes.h>
      54             : #include <microsim/devices/MSDevice_Transportable.h>
      55             : #include <microsim/devices/MSDevice_BTreceiver.h>
      56             : #include <gui/GUIApplicationWindow.h>
      57             : #include <gui/GUIGlobals.h>
      58             : #include <utils/gui/div/GUIDesigns.h>
      59             : 
      60             : #include "GUIBaseVehicle.h"
      61             : #include "GUIPerson.h"
      62             : #include "GUIContainer.h"
      63             : #include "GUINet.h"
      64             : #include "GUIEdge.h"
      65             : #include "GUILane.h"
      66             : #include "GUIParkingArea.h"
      67             : 
      68             : //#define DRAW_BOUNDING_BOX
      69             : 
      70             : // ===========================================================================
      71             : // FOX callback mapping
      72             : // ===========================================================================
      73             : FXDEFMAP(GUIBaseVehicle::GUIBaseVehiclePopupMenu) GUIBaseVehiclePopupMenuMap[] = {
      74             :     FXMAPFUNC(SEL_COMMAND, MID_SHOW_ALLROUTES, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowAllRoutes),
      75             :     FXMAPFUNC(SEL_COMMAND, MID_HIDE_ALLROUTES, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideAllRoutes),
      76             :     FXMAPFUNC(SEL_COMMAND, MID_SHOW_CURRENTROUTE, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowCurrentRoute),
      77             :     FXMAPFUNC(SEL_COMMAND, MID_HIDE_CURRENTROUTE, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideCurrentRoute),
      78             :     FXMAPFUNC(SEL_COMMAND, MID_SHOW_FUTUREROUTE, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowFutureRoute),
      79             :     FXMAPFUNC(SEL_COMMAND, MID_HIDE_FUTUREROUTE, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideFutureRoute),
      80             :     FXMAPFUNC(SEL_COMMAND, MID_SHOW_ROUTE_NOLOOPS, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowRouteNoLoops),
      81             :     FXMAPFUNC(SEL_COMMAND, MID_HIDE_ROUTE_NOLOOPS, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideRouteNoLoops),
      82             :     FXMAPFUNC(SEL_COMMAND, MID_SHOW_BEST_LANES, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowBestLanes),
      83             :     FXMAPFUNC(SEL_COMMAND, MID_HIDE_BEST_LANES, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideBestLanes),
      84             :     FXMAPFUNC(SEL_COMMAND, MID_START_TRACK, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdStartTrack),
      85             :     FXMAPFUNC(SEL_COMMAND, MID_STOP_TRACK, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdStopTrack),
      86             :     FXMAPFUNC(SEL_COMMAND, MID_SHOW_LFLINKITEMS, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowLFLinkItems),
      87             :     FXMAPFUNC(SEL_COMMAND, MID_HIDE_LFLINKITEMS, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideLFLinkItems),
      88             :     FXMAPFUNC(SEL_COMMAND, MID_SHOW_FOES, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowFoes),
      89             :     FXMAPFUNC(SEL_COMMAND, MID_SELECT_TRANSPORTED, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdSelectTransported),
      90             :     FXMAPFUNC(SEL_COMMAND, MID_REMOVE_OBJECT, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdRemoveObject),
      91             :     FXMAPFUNC(SEL_COMMAND, MID_TOGGLE_STOP, GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdToggleStop),
      92             : };
      93             : 
      94             : // Object implementation
      95           0 : FXIMPLEMENT(GUIBaseVehicle::GUIBaseVehiclePopupMenu, GUIGLObjectPopupMenu, GUIBaseVehiclePopupMenuMap, ARRAYNUMBER(GUIBaseVehiclePopupMenuMap))
      96             : 
      97             : // ===========================================================================
      98             : // method definitions
      99             : // ===========================================================================
     100             : /* -------------------------------------------------------------------------
     101             :  * GUIBaseVehicle::GUIBaseVehiclePopupMenu - methods
     102             :  * ----------------------------------------------------------------------- */
     103           0 : GUIBaseVehicle::GUIBaseVehiclePopupMenu::GUIBaseVehiclePopupMenu(
     104           0 :     GUIMainWindow& app, GUISUMOAbstractView& parent, GUIGlObject& o)
     105           0 :     : GUIGLObjectPopupMenu(app, parent, o) {
     106           0 : }
     107             : 
     108             : 
     109           0 : GUIBaseVehicle::GUIBaseVehiclePopupMenu::~GUIBaseVehiclePopupMenu() {}
     110             : 
     111             : 
     112             : long
     113           0 : GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowAllRoutes(FXObject*, FXSelector, void*) {
     114             :     assert(myObject->getType() == GLO_VEHICLE);
     115           0 :     if (!static_cast<GUIBaseVehicle*>(myObject)->hasActiveAddVisualisation(myParent, VO_SHOW_ALL_ROUTES)) {
     116           0 :         static_cast<GUIBaseVehicle*>(myObject)->addActiveAddVisualisation(myParent, VO_SHOW_ALL_ROUTES);
     117             :     }
     118           0 :     return 1;
     119             : }
     120             : 
     121             : long
     122           0 : GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideAllRoutes(FXObject*, FXSelector, void*) {
     123             :     assert(myObject->getType() == GLO_VEHICLE);
     124           0 :     static_cast<GUIBaseVehicle*>(myObject)->removeActiveAddVisualisation(myParent, VO_SHOW_ALL_ROUTES);
     125           0 :     return 1;
     126             : }
     127             : 
     128             : 
     129             : long
     130           0 : GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowCurrentRoute(FXObject*, FXSelector, void*) {
     131             :     assert(myObject->getType() == GLO_VEHICLE);
     132           0 :     if (!static_cast<GUIBaseVehicle*>(myObject)->hasActiveAddVisualisation(myParent, VO_SHOW_ROUTE)) {
     133           0 :         static_cast<GUIBaseVehicle*>(myObject)->addActiveAddVisualisation(myParent, VO_SHOW_ROUTE);
     134             :     }
     135           0 :     return 1;
     136             : }
     137             : 
     138             : long
     139           0 : GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideCurrentRoute(FXObject*, FXSelector, void*) {
     140             :     assert(myObject->getType() == GLO_VEHICLE);
     141           0 :     static_cast<GUIBaseVehicle*>(myObject)->removeActiveAddVisualisation(myParent, VO_SHOW_ROUTE);
     142           0 :     return 1;
     143             : }
     144             : 
     145             : 
     146             : long
     147           0 : GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowFutureRoute(FXObject*, FXSelector, void*) {
     148             :     assert(myObject->getType() == GLO_VEHICLE);
     149           0 :     if (!static_cast<GUIBaseVehicle*>(myObject)->hasActiveAddVisualisation(myParent, VO_SHOW_FUTURE_ROUTE)) {
     150           0 :         static_cast<GUIBaseVehicle*>(myObject)->addActiveAddVisualisation(myParent, VO_SHOW_FUTURE_ROUTE);
     151             :     }
     152           0 :     return 1;
     153             : }
     154             : 
     155             : long
     156           0 : GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideFutureRoute(FXObject*, FXSelector, void*) {
     157             :     assert(myObject->getType() == GLO_VEHICLE);
     158           0 :     static_cast<GUIBaseVehicle*>(myObject)->removeActiveAddVisualisation(myParent, VO_SHOW_FUTURE_ROUTE);
     159           0 :     return 1;
     160             : }
     161             : 
     162             : 
     163             : long
     164           0 : GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowRouteNoLoops(FXObject*, FXSelector, void*) {
     165             :     assert(myObject->getType() == GLO_VEHICLE);
     166           0 :     if (!static_cast<GUIBaseVehicle*>(myObject)->hasActiveAddVisualisation(myParent, VO_SHOW_ROUTE_NOLOOP)) {
     167           0 :         static_cast<GUIBaseVehicle*>(myObject)->addActiveAddVisualisation(myParent, VO_SHOW_ROUTE_NOLOOP);
     168             :     }
     169           0 :     return 1;
     170             : }
     171             : 
     172             : long
     173           0 : GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideRouteNoLoops(FXObject*, FXSelector, void*) {
     174             :     assert(myObject->getType() == GLO_VEHICLE);
     175           0 :     static_cast<GUIBaseVehicle*>(myObject)->removeActiveAddVisualisation(myParent, VO_SHOW_ROUTE_NOLOOP);
     176           0 :     return 1;
     177             : }
     178             : 
     179             : 
     180             : long
     181           0 : GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowBestLanes(FXObject*, FXSelector, void*) {
     182             :     assert(myObject->getType() == GLO_VEHICLE);
     183           0 :     if (!static_cast<GUIBaseVehicle*>(myObject)->hasActiveAddVisualisation(myParent, VO_SHOW_BEST_LANES)) {
     184           0 :         static_cast<GUIBaseVehicle*>(myObject)->addActiveAddVisualisation(myParent, VO_SHOW_BEST_LANES);
     185             :     }
     186           0 :     return 1;
     187             : }
     188             : 
     189             : long
     190           0 : GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideBestLanes(FXObject*, FXSelector, void*) {
     191             :     assert(myObject->getType() == GLO_VEHICLE);
     192           0 :     static_cast<GUIBaseVehicle*>(myObject)->removeActiveAddVisualisation(myParent, VO_SHOW_BEST_LANES);
     193           0 :     return 1;
     194             : }
     195             : 
     196             : 
     197             : long
     198           0 : GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdStartTrack(FXObject*, FXSelector, void*) {
     199             :     assert(myObject->getType() == GLO_VEHICLE);
     200           0 :     if (myParent->getTrackedID() != static_cast<GUIBaseVehicle*>(myObject)->getGlID()) {
     201           0 :         myParent->startTrack(static_cast<GUIBaseVehicle*>(myObject)->getGlID());
     202             :     }
     203           0 :     return 1;
     204             : }
     205             : 
     206             : long
     207           0 : GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdStopTrack(FXObject*, FXSelector, void*) {
     208             :     assert(myObject->getType() == GLO_VEHICLE);
     209           0 :     myParent->stopTrack();
     210           0 :     return 1;
     211             : }
     212             : 
     213             : 
     214             : long
     215           0 : GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowLFLinkItems(FXObject*, FXSelector, void*) {
     216             :     assert(myObject->getType() == GLO_VEHICLE);
     217           0 :     if (!static_cast<GUIBaseVehicle*>(myObject)->hasActiveAddVisualisation(myParent, VO_SHOW_LFLINKITEMS)) {
     218           0 :         static_cast<GUIBaseVehicle*>(myObject)->addActiveAddVisualisation(myParent, VO_SHOW_LFLINKITEMS);
     219             :     }
     220           0 :     return 1;
     221             : }
     222             : 
     223             : long
     224           0 : GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdHideLFLinkItems(FXObject*, FXSelector, void*) {
     225             :     assert(myObject->getType() == GLO_VEHICLE);
     226           0 :     static_cast<GUIBaseVehicle*>(myObject)->removeActiveAddVisualisation(myParent, VO_SHOW_LFLINKITEMS);
     227           0 :     return 1;
     228             : }
     229             : 
     230             : long
     231           0 : GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdShowFoes(FXObject*, FXSelector, void*) {
     232             :     assert(myObject->getType() == GLO_VEHICLE);
     233           0 :     static_cast<GUIBaseVehicle*>(myObject)->selectBlockingFoes();
     234           0 :     myParent->update();
     235           0 :     return 1;
     236             : }
     237             : 
     238             : 
     239             : long
     240           0 : GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdSelectTransported(FXObject*, FXSelector, void*) {
     241             :     assert(myObject->getType() == GLO_VEHICLE);
     242           0 :     const MSBaseVehicle& veh = static_cast<GUIBaseVehicle*>(myObject)->getVehicle();
     243           0 :     for (const MSTransportable* t : veh.getPersons()) {
     244           0 :         gSelected.select((static_cast<const GUIPerson*>(t))->getGlID());
     245             :     }
     246           0 :     for (MSTransportable* t : veh.getContainers()) {
     247           0 :         gSelected.select((static_cast<const GUIContainer*>(t))->getGlID());
     248             :     }
     249           0 :     myParent->update();
     250           0 :     return 1;
     251             : }
     252             : 
     253             : long
     254           0 : GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdRemoveObject(FXObject*, FXSelector, void*) {
     255           0 :     GUIBaseVehicle* baseVeh = static_cast<GUIBaseVehicle*>(myObject);
     256           0 :     MSVehicle* microVeh = dynamic_cast<MSVehicle*>(&baseVeh->myVehicle);
     257           0 :     if (microVeh != nullptr) {
     258             :         MSLane* lane = microVeh->getMutableLane();
     259           0 :         if (lane != nullptr) {
     260           0 :             lane->getVehiclesSecure();
     261           0 :             lane->removeVehicle(microVeh, MSMoveReminder::NOTIFICATION_VAPORIZED_GUI);
     262             :         }
     263           0 :         microVeh->onRemovalFromNet(MSMoveReminder::NOTIFICATION_VAPORIZED_GUI);
     264           0 :         if (lane != nullptr) {
     265           0 :             lane->releaseVehicles();
     266             :         }
     267             :     } else {
     268           0 :         MEVehicle* mesoVeh = dynamic_cast<MEVehicle*>(&baseVeh->myVehicle);
     269           0 :         MSGlobals::gMesoNet->vaporizeCar(mesoVeh, MSMoveReminder::NOTIFICATION_VAPORIZED_GUI);
     270             :     }
     271           0 :     MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(&baseVeh->myVehicle);
     272           0 :     myParent->destroyPopup();
     273           0 :     myParent->update();
     274           0 :     return 1;
     275             : }
     276             : 
     277             : 
     278             : long
     279           0 : GUIBaseVehicle::GUIBaseVehiclePopupMenu::onCmdToggleStop(FXObject*, FXSelector, void*) {
     280           0 :     GUIBaseVehicle* baseVeh = static_cast<GUIBaseVehicle*>(myObject);
     281           0 :     MSVehicle* microVeh = dynamic_cast<MSVehicle*>(&baseVeh->myVehicle);
     282           0 :     if (microVeh != nullptr) {
     283           0 :         if (microVeh->isStopped()) {
     284           0 :             microVeh->resumeFromStopping();
     285             :         } else {
     286             :             std::string errorOut;
     287           0 :             const double brakeGap = microVeh->getCarFollowModel().brakeGap(microVeh->getSpeed());
     288           0 :             std::pair<const MSLane*, double> stopPos = microVeh->getLanePosAfterDist(brakeGap);
     289           0 :             if (stopPos.first != nullptr) {
     290           0 :                 SUMOVehicleParameter::Stop stop;
     291             :                 stop.lane = stopPos.first->getID();
     292           0 :                 stop.startPos = stopPos.second;
     293           0 :                 stop.endPos = stopPos.second + POSITION_EPS;
     294           0 :                 stop.duration = TIME2STEPS(3600);
     295           0 :                 microVeh->addTraciStop(stop, errorOut);
     296           0 :                 if (errorOut != "") {
     297           0 :                     WRITE_WARNING(errorOut);
     298             :                 }
     299           0 :             }
     300             :         }
     301             :     } else {
     302           0 :         WRITE_WARNING(TL("GUI-triggered stop not implemented for meso"));
     303             :     }
     304           0 :     myParent->update();
     305           0 :     return 1;
     306             : }
     307             : 
     308             : 
     309             : /* -------------------------------------------------------------------------
     310             :  * GUIBaseVehicle - methods
     311             :  * ----------------------------------------------------------------------- */
     312             : 
     313      683010 : GUIBaseVehicle::GUIBaseVehicle(MSBaseVehicle& vehicle) :
     314             :     GUIGlObject(GLO_VEHICLE, vehicle.getID(), GUIIconSubSys::getIcon(GUIIcon::VEHICLE)),
     315      683010 :     myVehicle(vehicle),
     316      683010 :     myPopup(nullptr) {
     317             :     // as it is possible to show all vehicle routes, we have to store them... (bug [ 2519761 ])
     318      683010 :     myRoutes = MSDevice_Vehroutes::buildVehicleDevices(myVehicle, myVehicle.myDevices, 5);
     319      683010 :     myVehicle.myMoveReminders.push_back(std::make_pair(myRoutes, 0.));
     320      683010 :     mySeatPositions.push_back(Seat()); // ensure length 1
     321           0 :     myContainerPositions.push_back(Seat()); // ensure length 1
     322      683010 : }
     323             : 
     324             : 
     325      682964 : GUIBaseVehicle::~GUIBaseVehicle() {
     326      682964 :     myLock.lock();
     327      682977 :     for (std::map<GUISUMOAbstractView*, int>::iterator i = myAdditionalVisualizations.begin(); i != myAdditionalVisualizations.end(); ++i) {
     328          13 :         if (i->first->getTrackedID() == getGlID()) {
     329           4 :             i->first->stopTrack();
     330             :         }
     331          17 :         while (i->first->removeAdditionalGLVisualisation(this));
     332             :     }
     333      682964 :     myLock.unlock();
     334      682964 :     delete myRoutes;
     335      682964 :     if (myPopup != nullptr) {
     336           0 :         myPopup->getParentView()->destroyPopup();
     337             :     }
     338     1365928 : }
     339             : 
     340             : 
     341             : GUIGLObjectPopupMenu*
     342           0 : GUIBaseVehicle::getPopUpMenu(GUIMainWindow& app,
     343             :                              GUISUMOAbstractView& parent) {
     344           0 :     GUIGLObjectPopupMenu* ret = new GUIBaseVehiclePopupMenu(app, parent, *this);
     345           0 :     buildPopupHeader(ret, app);
     346           0 :     buildCenterPopupEntry(ret);
     347           0 :     buildNameCopyPopupEntry(ret);
     348           0 :     buildSelectionPopupEntry(ret);
     349             :     //
     350           0 :     if (hasActiveAddVisualisation(&parent, VO_SHOW_ROUTE)) {
     351           0 :         GUIDesigns::buildFXMenuCommand(ret, TL("Hide Current Route"), nullptr, ret, MID_HIDE_CURRENTROUTE);
     352             :     } else {
     353           0 :         GUIDesigns::buildFXMenuCommand(ret, TL("Show Current Route"), nullptr, ret, MID_SHOW_CURRENTROUTE);
     354             :     }
     355           0 :     if (hasActiveAddVisualisation(&parent, VO_SHOW_FUTURE_ROUTE)) {
     356           0 :         GUIDesigns::buildFXMenuCommand(ret, TL("Hide Future Route"), nullptr, ret, MID_HIDE_FUTUREROUTE);
     357             :     } else {
     358           0 :         GUIDesigns::buildFXMenuCommand(ret, TL("Show Future Route"), nullptr, ret, MID_SHOW_FUTUREROUTE);
     359             :     }
     360           0 :     if (hasActiveAddVisualisation(&parent, VO_SHOW_ALL_ROUTES)) {
     361           0 :         GUIDesigns::buildFXMenuCommand(ret, TL("Hide All Routes"), nullptr, ret, MID_HIDE_ALLROUTES);
     362             :     } else {
     363           0 :         GUIDesigns::buildFXMenuCommand(ret, TL("Show All Routes"), nullptr, ret, MID_SHOW_ALLROUTES);
     364             :     }
     365           0 :     if (hasActiveAddVisualisation(&parent, VO_SHOW_ROUTE_NOLOOP)) {
     366           0 :         FXMenuCheck* showLoops = new FXMenuCheck(ret, TL("Draw looped routes"), ret, MID_HIDE_ROUTE_NOLOOPS);
     367           0 :         showLoops->setCheck(false);
     368             :     } else {
     369           0 :         FXMenuCheck* showLoops = new FXMenuCheck(ret, TL("Draw looped routes"), ret, MID_SHOW_ROUTE_NOLOOPS);
     370           0 :         showLoops->setCheck(true);
     371             :     }
     372           0 :     if (hasActiveAddVisualisation(&parent, VO_SHOW_BEST_LANES)) {
     373           0 :         GUIDesigns::buildFXMenuCommand(ret, TL("Hide Best Lanes"), nullptr, ret, MID_HIDE_BEST_LANES);
     374             :     } else {
     375           0 :         GUIDesigns::buildFXMenuCommand(ret, TL("Show Best Lanes"), nullptr, ret, MID_SHOW_BEST_LANES);
     376             :     }
     377           0 :     if (hasActiveAddVisualisation(&parent, VO_SHOW_LFLINKITEMS)) {
     378           0 :         GUIDesigns::buildFXMenuCommand(ret, TL("Hide Link Items"), nullptr, ret, MID_HIDE_LFLINKITEMS);
     379             :     } else {
     380           0 :         GUIDesigns::buildFXMenuCommand(ret, TL("Show Link Items"), nullptr, ret, MID_SHOW_LFLINKITEMS);
     381             :     }
     382           0 :     new FXMenuSeparator(ret);
     383           0 :     if (parent.getTrackedID() != getGlID()) {
     384           0 :         GUIDesigns::buildFXMenuCommand(ret, TL("Start Tracking"), nullptr, ret, MID_START_TRACK);
     385             :     } else {
     386           0 :         GUIDesigns::buildFXMenuCommand(ret, TL("Stop Tracking"), nullptr, ret, MID_STOP_TRACK);
     387             :     }
     388           0 :     GUIDesigns::buildFXMenuCommand(ret, TL("Select Foes"), nullptr, ret, MID_SHOW_FOES);
     389           0 :     if (myVehicle.getPersons().size() + myVehicle.getContainers().size() > 0) {
     390           0 :         GUIDesigns::buildFXMenuCommand(ret, TL("Select transported"), nullptr, ret, MID_SELECT_TRANSPORTED);
     391             :     }
     392           0 :     GUIDesigns::buildFXMenuCommand(ret, myVehicle.isStopped() ? TL("Abort stop") : TL("Stop"), nullptr, ret, MID_TOGGLE_STOP);
     393           0 :     GUIDesigns::buildFXMenuCommand(ret, TL("Remove"), nullptr, ret, MID_REMOVE_OBJECT);
     394             : 
     395           0 :     new FXMenuSeparator(ret);
     396             :     //
     397           0 :     buildShowParamsPopupEntry(ret, false);
     398           0 :     buildShowTypeParamsPopupEntry(ret);
     399           0 :     buildPositionCopyEntry(ret, app);
     400           0 :     myPopup = ret;
     401           0 :     return ret;
     402             : }
     403             : 
     404             : 
     405             : void
     406           0 : GUIBaseVehicle::removedPopupMenu() {
     407           0 :     myPopup = nullptr;
     408           0 : }
     409             : 
     410             : 
     411             : double
     412     8234608 : GUIBaseVehicle::getExaggeration(const GUIVisualizationSettings& s) const {
     413     8234608 :     return (s.vehicleSize.getExaggeration(s, this) *
     414     8234608 :             s.vehicleScaler.getScheme().getColor(getScaleValue(s, s.vehicleScaler.getActive())));
     415             : }
     416             : 
     417             : 
     418             : Boundary
     419         495 : GUIBaseVehicle::getCenteringBoundary() const {
     420         495 :     Boundary b;
     421         495 :     b.add(getVisualPosition(GUIGlobals::gSecondaryShape));
     422         495 :     b.grow(myVehicle.getVehicleType().getLength());
     423         495 :     return b;
     424           0 : }
     425             : 
     426             : 
     427             : const std::string
     428           0 : GUIBaseVehicle::getOptionalName() const {
     429           0 :     return myVehicle.getParameter().getParameter("name", "");
     430             : }
     431             : 
     432             : 
     433             : void
     434     8881344 : GUIBaseVehicle::drawOnPos(const GUIVisualizationSettings& s, const Position& pos, const double angle) const {
     435     8881344 :     GLHelper::pushName(getGlID());
     436     8881344 :     GLHelper::pushMatrix();
     437     8881344 :     Position p1 = pos;
     438     8881344 :     const double degAngle = RAD2DEG(angle + M_PI / 2.);
     439             :     const double length = getVType().getLength();
     440     8881344 :     glTranslated(p1.x(), p1.y(), getType());
     441     8881344 :     glRotated(degAngle, 0, 0, 1);
     442     8881344 :     RGBColor col = setColor(s);
     443             :     // scale
     444     8881344 :     const double upscale = getExaggeration(s);
     445     8881344 :     const bool s2 = s.secondaryShape;
     446             : 
     447     8881344 :     if (upscale > 1 && s.laneWidthExaggeration > 1 && myVehicle.isOnRoad()) {
     448             :         // optionally shift according to edge exaggeration
     449           0 :         double offsetFromLeftBorder = myVehicle.getCurrentEdge()->getWidth() - myVehicle.getRightSideOnEdge() - myVehicle.getVehicleType().getWidth() / 2;
     450           0 :         glTranslated((s.laneWidthExaggeration - 1) * -offsetFromLeftBorder / 2, 0, 0);
     451             :     }
     452             : 
     453     8881344 :     double upscaleLength = MSTrainHelper::getUpscaleLength(upscale, length, s.vehicleQuality);
     454     8881344 :     glScaled(upscale, upscaleLength, 1);
     455             :     /*
     456             :         MSLaneChangeModel::DK2004 &m2 = static_cast<MSLaneChangeModel::DK2004&>(veh->getLaneChangeModel());
     457             :         if((m2.getState()&LCA_URGENT)!=0) {
     458             :             glColor3d(1, .4, .4);
     459             :         } else if((m2.getState()&LCA_SPEEDGAIN)!=0) {
     460             :             glColor3d(.4, .4, 1);
     461             :         } else {
     462             :             glColor3d(.4, 1, .4);
     463             :         }
     464             :         */
     465             :     // draw the vehicle
     466             :     bool drawCarriages = false;
     467     8881344 :     const double geometryFactor = (s.scaleLength ?
     468     8881344 :                                    ((myVehicle.getLane() != nullptr
     469     8881344 :                                      ? myVehicle.getLane()->getLengthGeometryFactor(s2)
     470      646736 :                                      : (myVehicle.getEdge()->getLanes().size() > 0 ? myVehicle.getEdge()->getLanes()[0]->getLengthGeometryFactor(s2) : 1)))
     471             :                                    : 1);
     472     8881344 :     double scaledLength = length * geometryFactor;
     473     8881344 :     if (col.alpha() != 0) {
     474     8881344 :         switch (s.vehicleQuality) {
     475     8674340 :             case 0:
     476     8674340 :                 GUIBaseVehicleHelper::drawAction_drawVehicleAsTrianglePlus(getVType().getWidth(), scaledLength, drawReversed(s));
     477             :                 break;
     478           0 :             case 1:
     479           0 :                 GUIBaseVehicleHelper::drawAction_drawVehicleAsBoxPlus(getVType().getWidth(), scaledLength, drawReversed(s));
     480             :                 break;
     481      198671 :             case 2:
     482      198671 :                 drawCarriages = drawAction_drawVehicleAsPolyWithCarriagges(s, scaledLength);
     483             :                 // draw flashing blue light for emergency vehicles
     484      198671 :                 if (getVType().getGuiShape() == SUMOVehicleShape::EMERGENCY) {
     485           0 :                     glTranslated(0, 0, .1);
     486           0 :                     drawAction_drawVehicleBlueLight();
     487             :                 }
     488             :                 break;
     489        8333 :             case 3:
     490        8333 :                 drawCarriages = drawAction_drawVehicleAsPolyWithCarriagges(s, scaledLength, true);
     491             :                 break;
     492             :             case 4: {
     493             :                 // do not scale circle radius by lengthGeometryFactor nor length and reduce the effect of width
     494           0 :                 const double w = 1.8 * sqrt(getVType().getWidth() / 1.8);
     495           0 :                 GUIBaseVehicleHelper::drawAction_drawVehicleAsCircle(w, s.scale * upscale);
     496             :                 // display text at circle center
     497             :                 scaledLength = 0;
     498             :                 break;
     499             :             }
     500             :             default:
     501             :                 break;
     502             :         }
     503     8881344 :         if (s.drawMinGap) {
     504           0 :             const double minGap = -getVType().getMinGap();
     505           0 :             glColor3d(0., 1., 0.);
     506           0 :             glBegin(GL_LINES);
     507           0 :             glVertex2d(0., 0);
     508           0 :             glVertex2d(0., minGap);
     509           0 :             glVertex2d(-.5, minGap);
     510           0 :             glVertex2d(.5, minGap);
     511           0 :             glEnd();
     512             :         }
     513           0 :         if (s.drawBrakeGap && !MSGlobals::gUseMesoSim
     514     8881344 :                 && (!s.vehicleSize.constantSizeSelected || myVehicle.isSelected())) {
     515           0 :             const double brakeGap = -static_cast<MSVehicle&>(myVehicle).getCarFollowModel().brakeGap(myVehicle.getSpeed());
     516           0 :             glColor3d(1., 0., 0.);
     517           0 :             glBegin(GL_LINES);
     518           0 :             glVertex2d(0., 0);
     519           0 :             glVertex2d(0., brakeGap);
     520           0 :             glVertex2d(-.5, brakeGap);
     521           0 :             glVertex2d(.5, brakeGap);
     522           0 :             glEnd();
     523             :         }
     524     8881344 :         if (s.showBTRange) {
     525           0 :             MSVehicleDevice_BTreceiver* dev = static_cast<MSVehicleDevice_BTreceiver*>(myVehicle.getDevice(typeid(MSVehicleDevice_BTreceiver)));
     526             :             if (dev != nullptr) {
     527           0 :                 glColor3d(1., 0., 0.);
     528           0 :                 GLHelper::drawOutlineCircle(dev->getRange(), dev->getRange() - .2, 32);
     529             :             }
     530             :         }
     531             :         // draw the blinker and brakelights if wished
     532     8881344 :         if (s.showBlinker) {
     533     8881344 :             glTranslated(0, 0, .1);
     534     8881344 :             switch (getVType().getGuiShape()) {
     535             :                 case SUMOVehicleShape::PEDESTRIAN:
     536             :                 case SUMOVehicleShape::BICYCLE:
     537             :                 case SUMOVehicleShape::SCOOTER:
     538             :                 case SUMOVehicleShape::ANT:
     539             :                 case SUMOVehicleShape::SHIP:
     540             :                 case SUMOVehicleShape::RAIL:
     541             :                 case SUMOVehicleShape::RAIL_CARGO:
     542             :                 case SUMOVehicleShape::RAIL_CAR:
     543             :                 case SUMOVehicleShape::AIRCRAFT:
     544             :                     break;
     545      531547 :                 case SUMOVehicleShape::MOTORCYCLE:
     546             :                 case SUMOVehicleShape::MOPED:
     547      531547 :                     drawAction_drawVehicleBlinker(scaledLength);
     548      531547 :                     drawAction_drawVehicleBrakeLight(scaledLength, true);
     549             :                     break;
     550     8109424 :                 default:
     551             :                     // only SUMOVehicleShape::RAIL_CAR has blinkers and brake lights but they are drawn along with the carriages
     552     8109424 :                     if (!drawCarriages) {
     553     8108035 :                         drawAction_drawVehicleBlinker(scaledLength);
     554     8108035 :                         drawAction_drawVehicleBrakeLight(scaledLength);
     555             :                     }
     556             :                     break;
     557             :             }
     558             :         }
     559             :         // draw the wish to change the lane
     560             :         if (s.drawLaneChangePreference) {
     561             :             /*
     562             :                if(gSelected.isSelected(GLO_VEHICLE, veh->getGlID())) {
     563             :                MSLaneChangeModel::DK2004 &m = static_cast<MSLaneChangeModel::DK2004&>(veh->getLaneChangeModel());
     564             :                glColor3d(.5, .5, 1);
     565             :                glBegin(GL_LINES);
     566             :                glVertex2f(0, 0);
     567             :                glVertex2f(m.getChangeProbability(), .5);
     568             :                glEnd();
     569             : 
     570             :                glColor3d(1, 0, 0);
     571             :                glBegin(GL_LINES);
     572             :                glVertex2f(0.1, 0);
     573             :                glVertex2f(0.1, m.myMaxJam1);
     574             :                glEnd();
     575             : 
     576             :                glColor3d(0, 1, 0);
     577             :                glBegin(GL_LINES);
     578             :                glVertex2f(-0.1, 0);
     579             :                glVertex2f(-0.1, m.myTDist);
     580             :                glEnd();
     581             :                }
     582             :                */
     583             :         }
     584             :     }
     585     8952541 :     glTranslated(0, MIN2(scaledLength / 2, double(5)), -getType()); // drawing name at GLO_MAX fails unless translating z
     586     8881344 :     glScaled(1 / upscale, 1 / upscaleLength, 1);
     587     8881344 :     glRotated(-degAngle, 0, 0, 1);
     588     8881344 :     drawName(Position(0, 0), s.scale, s.vehicleName, s.angle);
     589     8881344 :     if (s.vehicleName.show(this) && myVehicle.getParameter().line != "") {
     590           0 :         glRotated(-s.angle, 0, 0, 1);
     591           0 :         glTranslated(0, 0.7 * s.vehicleName.scaledSize(s.scale), 0);
     592           0 :         glRotated(s.angle, 0, 0, 1);
     593           0 :         GLHelper::drawTextSettings(s.vehicleName, "line:" + myVehicle.getParameter().line, Position(0, 0), s.scale, s.angle);
     594             :     }
     595     8881344 :     if (s.vehicleValue.show(this)) {
     596           0 :         glRotated(-s.angle, 0, 0, 1);
     597           0 :         glTranslated(0, 0.7 * s.vehicleName.scaledSize(s.scale), 0);
     598           0 :         glRotated(s.angle, 0, 0, 1);
     599           0 :         const double value = getColorValue(s, s.vehicleColorer.getActive());
     600           0 :         GLHelper::drawTextSettings(s.vehicleValue, toString(value), Position(0, 0), s.scale, s.angle);
     601             :     }
     602     8881344 :     if (s.vehicleScaleValue.show(this)) {
     603           0 :         glRotated(-s.angle, 0, 0, 1);
     604           0 :         glTranslated(0, 0.7 * s.vehicleName.scaledSize(s.scale), 0);
     605           0 :         glRotated(s.angle, 0, 0, 1);
     606           0 :         const double value = getScaleValue(s, s.vehicleScaler.getActive());
     607           0 :         GLHelper::drawTextSettings(s.vehicleScaleValue, toString(value), Position(0, 0), s.scale, s.angle);
     608             :     }
     609     8881344 :     if (s.vehicleText.show(this)) {
     610             :         std::string error;
     611           0 :         std::string value = myVehicle.getPrefixedParameter(s.vehicleTextParam, error);
     612           0 :         if (value != "") {
     613           0 :             auto lines = StringTokenizer(value, StringTokenizer::NEWLINE).getVector();
     614           0 :             glRotated(-s.angle, 0, 0, 1);
     615           0 :             glTranslated(0, 0.7 * s.vehicleText.scaledSize(s.scale) * (double)lines.size(), 0);
     616           0 :             glRotated(s.angle, 0, 0, 1);
     617           0 :             for (std::string& line : lines) {
     618           0 :                 GLHelper::drawTextSettings(s.vehicleText, line, Position(0, 0), s.scale, s.angle);
     619           0 :                 glRotated(-s.angle, 0, 0, 1);
     620           0 :                 glTranslated(0, -0.7 * s.vehicleText.scaledSize(s.scale), 0);
     621           0 :                 glRotated(s.angle, 0, 0, 1);
     622             :             }
     623           0 :         }
     624             :     }
     625     8881344 :     if (s.showParkingInfo && myAdditionalVisualizations.size() != 0 && hasActiveAddVisualisation(
     626           0 :                 myAdditionalVisualizations.begin()->first, VO_SHOW_ROUTE | VO_SHOW_FUTURE_ROUTE | VO_SHOW_ALL_ROUTES)) {
     627           0 :         glRotated(-s.angle, 0, 0, 1);
     628           0 :         glTranslated(0, 0.7 * s.vehicleName.scaledSize(s.scale), 0);
     629           0 :         glRotated(s.angle, 0, 0, 1);
     630           0 :         const double value = myVehicle.getNumberParkingReroutes();
     631           0 :         GLHelper::drawTextSettings(s.vehicleName, toString(value), Position(0, 0), s.scale, s.angle);
     632             :     }
     633             : 
     634     8881344 :     if (!drawCarriages) {
     635     8877047 :         mySeatPositions.clear();
     636     8877047 :         myContainerPositions.clear();
     637     8877047 :         int requiredSeats = getNumPassengers();
     638     8877047 :         int requiredContainerPositions = getNumContainers();
     639     8877047 :         const Position back = (p1 + Position(-scaledLength * upscaleLength, 0)).rotateAround2D(angle, p1);
     640     8877047 :         double extraOffset = scaledLength * 0.15;
     641     8877047 :         computeSeats(p1, back, SUMO_const_waitingPersonWidth, getVType().getPersonCapacity(), upscale, requiredSeats, mySeatPositions, extraOffset);
     642     8877047 :         computeSeats(p1, back, SUMO_const_waitingContainerWidth, getVType().getContainerCapacity(), upscale, requiredContainerPositions, myContainerPositions, extraOffset);
     643             :     }
     644             : 
     645     8881344 :     GLHelper::popMatrix();
     646     8881344 :     GLHelper::popName();
     647     8881344 :     drawAction_drawPersonsAndContainers(s);
     648     8881344 : }
     649             : 
     650             : 
     651             : void
     652     8234841 : GUIBaseVehicle::drawGL(const GUIVisualizationSettings& s) const {
     653     8234841 :     drawOnPos(s, getVisualPosition(s.secondaryShape), getVisualAngle(s.secondaryShape));
     654     8234841 : }
     655             : 
     656             : 
     657             : void
     658           3 : GUIBaseVehicle::drawGLAdditional(GUISUMOAbstractView* const parent, const GUIVisualizationSettings& s) const {
     659           3 :     if (!myVehicle.isOnRoad()) {
     660           3 :         drawGL(s);
     661             :     }
     662           3 :     GLHelper::pushName(getGlID());
     663           3 :     GLHelper::pushMatrix();
     664           3 :     glTranslated(0, 0, getType() - .1); // don't draw on top of other cars
     665           3 :     if (hasActiveAddVisualisation(parent, VO_SHOW_BEST_LANES)) {
     666           0 :         drawBestLanes();
     667             :     }
     668           3 :     bool noLoop = hasActiveAddVisualisation(parent, VO_SHOW_ROUTE_NOLOOP);
     669           3 :     if (hasActiveAddVisualisation(parent, VO_SHOW_ROUTE)) {
     670           0 :         drawRoute(s, 0, 0.25, false, noLoop);
     671             :     }
     672           3 :     if (hasActiveAddVisualisation(parent, VO_SHOW_FUTURE_ROUTE)) {
     673           0 :         drawRoute(s, 0, 0.25, true, noLoop);
     674             :     }
     675           3 :     if (hasActiveAddVisualisation(parent, VO_SHOW_ALL_ROUTES)) {
     676           0 :         if (myVehicle.getNumberReroutes() > 0) {
     677           0 :             const int noReroutePlus1 = myVehicle.getNumberReroutes() + 1;
     678           0 :             for (int i = noReroutePlus1 - 1; i >= 0; i--) {
     679           0 :                 double darken = double(0.4) / double(noReroutePlus1) * double(i);
     680           0 :                 drawRoute(s, i, darken);
     681             :             }
     682             :         } else {
     683           0 :             drawRoute(s, 0, 0.25, false, noLoop);
     684             :         }
     685             :     }
     686           3 :     if (hasActiveAddVisualisation(parent, VO_SHOW_LFLINKITEMS)) {
     687           0 :         drawAction_drawLinkItems(s);
     688             :     }
     689           3 :     GLHelper::popMatrix();
     690           3 :     GLHelper::popName();
     691           3 : }
     692             : 
     693             : 
     694             : void
     695           0 : GUIBaseVehicle::drawLinkItem(const Position& pos, SUMOTime arrivalTime, SUMOTime leaveTime, double exagerate) {
     696           0 :     glTranslated(pos.x(), pos.y(), -.1);
     697           0 :     GLHelper::drawFilledCircle(1);
     698           0 :     std::string times = toString(STEPS2TIME(arrivalTime)) + "/" + toString(STEPS2TIME(leaveTime));
     699           0 :     GLHelper::drawText(times.c_str(), Position(), .1, 1.6 * exagerate, RGBColor::GREEN, 0);
     700           0 :     glTranslated(-pos.x(), -pos.y(), .1);
     701           0 : }
     702             : 
     703             : 
     704             : RGBColor
     705     8881344 : GUIBaseVehicle::setColor(const GUIVisualizationSettings& s) const {
     706     8881344 :     RGBColor col;
     707             :     const GUIColorer& c = s.vehicleColorer;
     708     8881344 :     if (!setFunctionalColor(c.getActive(), &myVehicle, col)) {
     709     5983741 :         col = c.getScheme().getColor(getColorValue(s, c.getActive()));
     710             :     }
     711     8881344 :     GLHelper::setColor(col);
     712     8881344 :     return col;
     713             : }
     714             : 
     715             : 
     716             : bool
     717    11965319 : GUIBaseVehicle::setFunctionalColor(int activeScheme, const MSBaseVehicle* veh, RGBColor& col) {
     718    11965319 :     switch (activeScheme) {
     719    11792331 :         case 0: {
     720             :             //test for emergency vehicle
     721    11792331 :             if (veh->getVehicleType().getGuiShape() == SUMOVehicleShape::EMERGENCY) {
     722          67 :                 col = RGBColor::WHITE;
     723          67 :                 return true;
     724             :             }
     725             :             //test for firebrigade
     726    11792264 :             if (veh->getVehicleType().getGuiShape() == SUMOVehicleShape::FIREBRIGADE) {
     727           0 :                 col = RGBColor::RED;
     728           0 :                 return true;
     729             :             }
     730             :             //test for police car
     731    11792264 :             if (veh->getVehicleType().getGuiShape() == SUMOVehicleShape::POLICE) {
     732           0 :                 col = RGBColor::BLUE;
     733           0 :                 return true;
     734             :             }
     735    11792264 :             if (veh->getParameter().wasSet(VEHPARS_COLOR_SET)) {
     736     2356298 :                 col = veh->getParameter().color;
     737     2356298 :                 return true;
     738             :             }
     739     9435966 :             if (veh->getVehicleType().wasSet(VTYPEPARS_COLOR_SET)) {
     740      300236 :                 col = veh->getVehicleType().getColor();
     741      300236 :                 return true;
     742             :             }
     743     9135730 :             if (&(veh->getRoute().getColor()) != &RGBColor::DEFAULT_COLOR) {
     744      242557 :                 col = veh->getRoute().getColor();
     745      242557 :                 return true;
     746             :             }
     747             :             return false;
     748             :         }
     749           0 :         case 2: {
     750           0 :             if (veh->getParameter().wasSet(VEHPARS_COLOR_SET)) {
     751           0 :                 col = veh->getParameter().color;
     752           0 :                 return true;
     753             :             }
     754             :             return false;
     755             :         }
     756           0 :         case 3: {
     757           0 :             if (veh->getVehicleType().wasSet(VTYPEPARS_COLOR_SET)) {
     758           0 :                 col = veh->getVehicleType().getColor();
     759           0 :                 return true;
     760             :             }
     761             :             return false;
     762             :         }
     763           0 :         case 4: {
     764           0 :             if (&(veh->getRoute().getColor()) != &RGBColor::DEFAULT_COLOR) {
     765           0 :                 col = veh->getRoute().getColor();
     766           0 :                 return true;
     767             :             }
     768             :             return false;
     769             :         }
     770           0 :         case 5: {
     771           0 :             Position p = veh->getRoute().getEdges()[0]->getLanes()[0]->getShape()[0];
     772           0 :             const Boundary& b = ((GUINet*) MSNet::getInstance())->getBoundary();
     773           0 :             Position center = b.getCenter();
     774           0 :             double hue = 180. + atan2(center.x() - p.x(), center.y() - p.y()) * 180. / M_PI;
     775           0 :             double sat = p.distanceTo(center) / center.distanceTo(Position(b.xmin(), b.ymin()));
     776           0 :             col = RGBColor::fromHSV(hue, sat, 1.);
     777             :             return true;
     778             :         }
     779           0 :         case 6: {
     780           0 :             Position p = veh->getRoute().getEdges().back()->getLanes()[0]->getShape()[-1];
     781           0 :             const Boundary& b = ((GUINet*) MSNet::getInstance())->getBoundary();
     782           0 :             Position center = b.getCenter();
     783           0 :             double hue = 180. + atan2(center.x() - p.x(), center.y() - p.y()) * 180. / M_PI;
     784           0 :             double sat = p.distanceTo(center) / center.distanceTo(Position(b.xmin(), b.ymin()));
     785           0 :             col = RGBColor::fromHSV(hue, sat, 1.);
     786             :             return true;
     787             :         }
     788           0 :         case 7: {
     789           0 :             Position pb = veh->getRoute().getEdges()[0]->getLanes()[0]->getShape()[0];
     790           0 :             Position pe = veh->getRoute().getEdges().back()->getLanes()[0]->getShape()[-1];
     791           0 :             const Boundary& b = ((GUINet*) MSNet::getInstance())->getBoundary();
     792           0 :             double hue = 180. + atan2(pb.x() - pe.x(), pb.y() - pe.y()) * 180. / M_PI;
     793           0 :             Position minp(b.xmin(), b.ymin());
     794           0 :             Position maxp(b.xmax(), b.ymax());
     795           0 :             double sat = pb.distanceTo(pe) / minp.distanceTo(maxp);
     796           0 :             col = RGBColor::fromHSV(hue, sat, 1.);
     797             :             return true;
     798             :         }
     799             :         case 35: { // color randomly (by pointer hash)
     800             :             std::hash<const MSBaseVehicle*> ptr_hash;
     801           0 :             const double hue = (double)(ptr_hash(veh) % 360); // [0-360]
     802           0 :             const double sat = (double)((ptr_hash(veh) / 360) % 67) / 100.0 + 0.33; // [0.33-1]
     803           0 :             col = RGBColor::fromHSV(hue, sat, 1.);
     804             :             return true;
     805             :         }
     806           0 :         case 36: { // color by angle
     807           0 :             double hue = GeomHelper::naviDegree(veh->getAngle());
     808           0 :             col = RGBColor::fromHSV(hue, 1., 1.);
     809           0 :             return true;
     810             :         }
     811             :     }
     812             :     return false;
     813             : }
     814             : 
     815             : 
     816             : double
     817     8238905 : GUIBaseVehicle::getScaleValue(const GUIVisualizationSettings& s, int activeScheme) const {
     818     8238905 :     switch (activeScheme) {
     819             :         case 0: // uniform
     820             :             return 0;
     821           0 :         case 1: // selection
     822           0 :             return myVehicle.isSelected();
     823           0 :         case 2: // by speed
     824           0 :             if (myVehicle.isStopped()) {
     825           0 :                 return myVehicle.isParking() ? -2 : -1;
     826             :             }
     827           0 :             return myVehicle.getSpeed();
     828           0 :         case 3:
     829           0 :             return myVehicle.getWaitingSeconds();
     830           0 :         case 4: {
     831           0 :             MSVehicle* microVeh = dynamic_cast<MSVehicle*>(&myVehicle);
     832           0 :             return (microVeh != nullptr ? microVeh->getAccumulatedWaitingSeconds() : 0);
     833             :         }
     834           0 :         case 5: {
     835           0 :             MSVehicle* microVeh = dynamic_cast<MSVehicle*>(&myVehicle);
     836           0 :             return (microVeh != nullptr ? microVeh->getLane()->getVehicleMaxSpeed(microVeh) : myVehicle.getEdge()->getVehicleMaxSpeed(&myVehicle));
     837             :         }
     838           0 :         case 6:
     839           0 :             return myVehicle.getNumberReroutes();
     840           0 :         case 7: {
     841           0 :             MSVehicle* microVeh = dynamic_cast<MSVehicle*>(&myVehicle);
     842             :             return (microVeh != nullptr
     843           0 :                     ? (microVeh->getLaneChangeModel().isOpposite() ? -100 : microVeh->getBestLaneOffset())
     844           0 :                     : 0);
     845             :         }
     846           0 :         case 8:
     847           0 :             return myVehicle.getAcceleration();
     848           0 :         case 9: {
     849           0 :             MSVehicle* microVeh = dynamic_cast<MSVehicle*>(&myVehicle);
     850           0 :             return (microVeh != nullptr ? microVeh->getTimeGapOnLane() : 0);
     851             :         }
     852           0 :         case 10:
     853           0 :             return STEPS2TIME(myVehicle.getDepartDelay());
     854           0 :         case 11:
     855           0 :             return myVehicle.getTimeLossSeconds();
     856           0 :         case 12:
     857           0 :             return myVehicle.getStopDelay();
     858           0 :         case 13:
     859           0 :             return myVehicle.getStopArrivalDelay();
     860             :         case 14: // by numerical param value
     861             :             std::string error;
     862           0 :             std::string val = myVehicle.getPrefixedParameter(s.vehicleScaleParam, error);
     863             :             try {
     864           0 :                 if (val == "") {
     865             :                     return 0;
     866             :                 } else {
     867           0 :                     return StringUtils::toDouble(val);
     868             :                 }
     869           0 :             } catch (NumberFormatException&) {
     870             :                 try {
     871           0 :                     return StringUtils::toBool(val);
     872           0 :                 } catch (BoolFormatException&) {
     873           0 :                     WRITE_WARNINGF(TL("Vehicle parameter '%' key '%' is not a number for vehicle '%'."),
     874             :                                    myVehicle.getParameter().getParameter(s.vehicleScaleParam, "0"), s.vehicleScaleParam, myVehicle.getID());
     875             :                     return -1;
     876           0 :                 }
     877           0 :             }
     878             :     }
     879             :     return 0;
     880             : }
     881             : 
     882             : 
     883             : // ------------ Additional visualisations
     884             : bool
     885          18 : GUIBaseVehicle::hasActiveAddVisualisation(GUISUMOAbstractView* const parent, int which) const {
     886          36 :     return myAdditionalVisualizations.find(parent) != myAdditionalVisualizations.end() && (myAdditionalVisualizations.find(parent)->second & which) != 0;
     887             : }
     888             : 
     889             : 
     890             : void
     891           4 : GUIBaseVehicle::addActiveAddVisualisation(GUISUMOAbstractView* const parent, int which) {
     892           4 :     if (myAdditionalVisualizations.find(parent) == myAdditionalVisualizations.end()) {
     893           4 :         myAdditionalVisualizations[parent] = 0;
     894             :     }
     895           4 :     myAdditionalVisualizations[parent] |= which;
     896           4 :     if (which != VO_TRACK) {
     897           0 :         parent->addAdditionalGLVisualisation(this);
     898             :     }
     899           4 : }
     900             : 
     901             : 
     902             : void
     903           0 : GUIBaseVehicle::removeActiveAddVisualisation(GUISUMOAbstractView* const parent, int which) {
     904           0 :     myAdditionalVisualizations[parent] &= ~which;
     905           0 :     if (myAdditionalVisualizations[parent] == 0) {
     906             :         myAdditionalVisualizations.erase(parent);
     907             :     }
     908           0 :     parent->removeAdditionalGLVisualisation(this);
     909           0 : }
     910             : 
     911             : 
     912             : void
     913           0 : GUIBaseVehicle::drawRoute(const GUIVisualizationSettings& s, int routeNo, double darken, bool future, bool noLoop) const {
     914           0 :     RGBColor vehColor = setColor(s);
     915           0 :     RGBColor darker = vehColor.changedBrightness((int)(darken * -255));
     916           0 :     if (darker == RGBColor::BLACK) {
     917           0 :         darker = vehColor.multiply(1 - darken);
     918             :     }
     919           0 :     GLHelper::setColor(darker);
     920           0 :     if (routeNo == 0) {
     921           0 :         drawRouteHelper(s, myVehicle.getRoutePtr(), future, noLoop, darker);
     922           0 :         return;
     923             :     }
     924           0 :     ConstMSRoutePtr route = myRoutes->getRoute(routeNo - 1); // only prior routes are stored
     925           0 :     if (route != nullptr) {
     926           0 :         drawRouteHelper(s, route, future, noLoop, darker);
     927             :     }
     928             : }
     929             : 
     930             : 
     931             : void
     932           0 : GUIBaseVehicle::drawStopLabels(const GUIVisualizationSettings& s, bool noLoop, const RGBColor& col) const {
     933             :     // (vertical shift for repeated stops at the same position
     934             :     std::map<const MSLane*, int> repeat; // count repeated occurrences of the same position
     935           0 :     int stopIndex = 0;
     936           0 :     for (const MSStop& stop : myVehicle.getStops()) {
     937             :         double stopLanePos;
     938           0 :         if (stop.getSpeed() > 0) {
     939           0 :             stopLanePos = stop.reached ? stop.pars.endPos : stop.pars.startPos;
     940             :         } else {
     941           0 :             stopLanePos = stop.reached ? myVehicle.getPositionOnLane() : MAX2(0.0, stop.getEndPos(myVehicle));
     942             :         }
     943           0 :         if (stop.isOpposite && !stop.reached) {
     944           0 :             stopLanePos = stop.lane->getLength() - stopLanePos;
     945             :         }
     946           0 :         Position pos = stop.lane->geometryPositionAtOffset(stopLanePos);
     947           0 :         GLHelper::setColor(col);
     948           0 :         GLHelper::drawBoxLines(stop.lane->getShape().getOrthogonal(pos, 10, true, stop.lane->getWidth()), 0.1);
     949           0 :         std::string label = (stop.getSpeed() > 0
     950           0 :                              ? (stop.reached ? "passing waypoint" : "waypoint ")
     951           0 :                              : (stop.reached ? "stopped" : "stop "));
     952           0 :         if (!stop.reached) {
     953           0 :             label += toString(stopIndex);
     954             :         }
     955             : 
     956           0 :         if (stop.isOpposite) {
     957             :             label += " (opposite)";
     958             :         }
     959             : #ifdef _DEBUG
     960             :         label += " (" + toString(stop.edge - myVehicle.getCurrentRouteEdge()) + "e)";
     961             : #endif
     962           0 :         if (myVehicle.isStoppedTriggered()) {
     963             :             label += " triggered:";
     964           0 :             if (stop.triggered) {
     965             :                 label += "person";
     966           0 :                 if (stop.numExpectedPerson > 0) {
     967           0 :                     label += "(" + toString(stop.numExpectedPerson) + ")";
     968             :                 }
     969             :             }
     970           0 :             if (stop.containerTriggered) {
     971             :                 label += "container";
     972           0 :                 if (stop.numExpectedContainer > 0) {
     973           0 :                     label += "(" + toString(stop.numExpectedContainer) + ")";
     974             :                 }
     975             :             }
     976           0 :             if (stop.joinTriggered) {
     977             :                 label += "join";
     978           0 :                 if (stop.pars.join != "") {
     979           0 :                     label += "(" + stop.pars.join + ")";
     980             :                 }
     981             :             }
     982             :         }
     983           0 :         if (stop.pars.ended >= 0 && MSGlobals::gUseStopEnded) {
     984           0 :             label += " ended:" + time2string(stop.pars.ended);
     985           0 :         } else if (stop.pars.until >= 0) {
     986           0 :             label += " until:" + time2string(stop.pars.until);
     987             :         }
     988           0 :         if (stop.duration >= 0 || stop.pars.duration > 0) {
     989           0 :             if (STEPS2TIME(stop.duration) > 3600 * 24) {
     990             :                 label += " duration:1day+";
     991             :             } else {
     992           0 :                 label += " duration:" + time2string(stop.duration);
     993             :             }
     994             :         }
     995           0 :         if (stop.getSpeed() > 0) {
     996           0 :             if (stop.skipOnDemand) {
     997             :                 label += " onDemand (skipped)";
     998             :             } else {
     999           0 :                 label += " speed:" + toString(stop.getSpeed());
    1000             :             }
    1001             :         }
    1002           0 :         if (stop.pars.actType != "") {
    1003           0 :             label += " actType:" + stop.pars.actType;
    1004             :         }
    1005           0 :         const double nameSize = s.vehicleName.size / s.scale;
    1006           0 :         Position pos2 = pos - Position(0, nameSize * repeat[stop.lane]);
    1007           0 :         if (noLoop && repeat[stop.lane] > 0) {
    1008             :             break;
    1009             :         }
    1010           0 :         GLHelper::drawTextSettings(s.vehicleText, label, pos2, s.scale, s.angle, 1.0);
    1011           0 :         repeat[stop.lane]++;
    1012           0 :         stopIndex++;
    1013             :     }
    1014             :     // indicate arrivalPos if set
    1015           0 :     if (myVehicle.getParameter().wasSet(VEHPARS_ARRIVALPOS_SET) || myVehicle.getArrivalLane() >= 0) {
    1016           0 :         const int arrivalEdge = myVehicle.getParameter().arrivalEdge >= 0
    1017           0 :                                 ? myVehicle.getParameter().arrivalEdge
    1018           0 :                                 : (int)myVehicle.getRoute().getEdges().size() - 1;
    1019           0 :         const MSLane* arrivalLane = myVehicle.getRoute().getEdges()[arrivalEdge]->getLanes()[MAX2(0, myVehicle.getArrivalLane())];
    1020           0 :         Position pos = arrivalLane->geometryPositionAtOffset(myVehicle.getArrivalPos());
    1021           0 :         GLHelper::setColor(col);
    1022           0 :         GLHelper::drawBoxLines(arrivalLane->getShape().getOrthogonal(pos, 10, true, arrivalLane->getWidth() * 0.5,  90), 0.1);
    1023           0 :         GLHelper::drawBoxLines(arrivalLane->getShape().getOrthogonal(pos, 10, true, arrivalLane->getWidth() * 0.5, 270), 0.1);
    1024           0 :         GLHelper::drawTextSettings(s.vehicleText, "arrival", pos, s.scale, s.angle, 1.0);
    1025             : 
    1026             :     }
    1027           0 : }
    1028             : 
    1029             : void
    1030           0 : GUIBaseVehicle::drawParkingInfo(const GUIVisualizationSettings& s, const RGBColor& /*col*/) const {
    1031           0 :     if (s.showParkingInfo) {
    1032           0 :         const MSBaseVehicle::ParkingMemory* pm = myVehicle.getParkingMemory();
    1033           0 :         if (pm != nullptr) {
    1034           0 :             for (auto item : *pm) {
    1035           0 :                 const GUIParkingArea* pa = dynamic_cast<const GUIParkingArea*>(item.first);
    1036           0 :                 if (item.second.blockedAtTime >= 0) {
    1037           0 :                     std::string seenAgo = time2string(SIMSTEP - item.second.blockedAtTime);
    1038             :                     //if (item.second.blockedAtTime >= 0) {
    1039             :                     //    seenAgo += ", " + time2string(SIMSTEP - item.second.blockedAtTimeLocal);
    1040             :                     //}
    1041           0 :                     GLHelper::drawTextSettings(s.vehicleValue, seenAgo, pa->getSignPos(), s.scale, s.angle, 1.0);
    1042             :                 }
    1043           0 :                 if (item.second.score != "") {
    1044           0 :                     const double dist = 0.4 * (s.vehicleText.scaledSize(s.scale) + s.vehicleValue.scaledSize(s.scale));
    1045           0 :                     Position shift(0, -dist);
    1046           0 :                     GLHelper::drawTextSettings(s.vehicleText, item.second.score, pa->getSignPos() + shift, s.scale, s.angle, 1.0);
    1047             :                 }
    1048             :             }
    1049             :         }
    1050             :     }
    1051           0 : }
    1052             : 
    1053             : const GUIBaseVehicle::Seat&
    1054      212324 : GUIBaseVehicle::getSeatPosition(int personIndex) const {
    1055             :     /// if there are not enough seats in the vehicle people have to squeeze onto the last seat
    1056      212324 :     return mySeatPositions[MIN2(personIndex, (int)mySeatPositions.size() - 1)];
    1057             : }
    1058             : 
    1059             : const GUIBaseVehicle::Seat&
    1060        5826 : GUIBaseVehicle::getContainerPosition(int containerIndex) const {
    1061             :     /// if there are not enough positions in the vehicle containers have to squeeze onto the last position
    1062        5826 :     return myContainerPositions[MIN2(containerIndex, (int)myContainerPositions.size() - 1)];
    1063             : }
    1064             : 
    1065             : 
    1066             : void
    1067     8881344 : GUIBaseVehicle::drawAction_drawPersonsAndContainers(const GUIVisualizationSettings& s) const {
    1068     8881344 :     if (myVehicle.myPersonDevice != nullptr) {
    1069             :         const std::vector<MSTransportable*>& ps = myVehicle.myPersonDevice->getTransportables();
    1070             :         int personIndex = 0;
    1071      218935 :         for (std::vector<MSTransportable*>::const_iterator i = ps.begin(); i != ps.end(); ++i) {
    1072      212324 :             GUIPerson* person = dynamic_cast<GUIPerson*>(*i);
    1073             :             assert(person != 0);
    1074      212324 :             person->setPositionInVehicle(getSeatPosition(personIndex++));
    1075      212324 :             person->drawGL(s);
    1076             :         }
    1077             :     }
    1078     8881344 :     if (myVehicle.myContainerDevice != nullptr) {
    1079             :         const std::vector<MSTransportable*>& cs = myVehicle.myContainerDevice->getTransportables();
    1080             :         int containerIndex = 0;
    1081       10951 :         for (std::vector<MSTransportable*>::const_iterator i = cs.begin(); i != cs.end(); ++i) {
    1082        5826 :             GUIContainer* container = dynamic_cast<GUIContainer*>(*i);
    1083             :             assert(container != 0);
    1084        5826 :             container->setPositionInVehicle(getContainerPosition(containerIndex++));
    1085        5826 :             container->drawGL(s);
    1086             :         }
    1087             :     }
    1088             : #ifdef DRAW_BOUNDING_BOX
    1089             :     if (!MSGlobals::gUseMesoSim) {
    1090             :         MSVehicle& microVeh = dynamic_cast<MSVehicle&>(myVehicle);
    1091             :         GLHelper::pushName(getGlID());
    1092             :         GLHelper::pushMatrix();
    1093             :         glTranslated(0, 0, getType());
    1094             :         PositionVector smallBB = microVeh.getBoundingPoly();
    1095             :         glColor3d(0.5, .8, 0);
    1096             :         GLHelper::drawBoxLines(smallBB, 0.3);
    1097             :         glTranslated(0, 0, 0.1);
    1098             :         PositionVector boundingBox = microVeh.getBoundingBox();
    1099             :         boundingBox.push_back(boundingBox.front());
    1100             :         glColor3d(1, 0, 0);
    1101             :         GLHelper::drawBoxLines(boundingBox, 0.15);
    1102             :         GLHelper::popMatrix();
    1103             :         GLHelper::popName();
    1104             :     }
    1105             : #endif
    1106     8881344 : }
    1107             : 
    1108             : bool
    1109     8868714 : GUIBaseVehicle::drawReversed(const GUIVisualizationSettings& s) const {
    1110     8868714 :     return myVehicle.isReversed() && s.drawReversed;
    1111             : }
    1112             : 
    1113             : bool
    1114      207004 : GUIBaseVehicle::drawAction_drawVehicleAsPolyWithCarriagges(const GUIVisualizationSettings& s, double scaledLength, bool asImage) const {
    1115      207004 :     if (getVType().getParameter().carriageLength > 0) {
    1116        4297 :         drawAction_drawCarriageClass(s, asImage);
    1117        4297 :         return true;
    1118             :     } else {
    1119      219373 :         if (asImage && GUIBaseVehicleHelper::drawAction_drawVehicleAsImage(
    1120      202707 :                     s, getVType().getImgFile(), this, getVType().getWidth(), scaledLength)) {
    1121             :             return false;
    1122             :         }
    1123      388748 :         GUIBaseVehicleHelper::drawAction_drawVehicleAsPoly(s, getVType().getGuiShape(), getVType().getWidth(), scaledLength, -1, myVehicle.isStopped(), drawReversed(s));
    1124      194374 :         return false;
    1125             :     }
    1126             : }
    1127             : 
    1128             : 
    1129             : int
    1130     8881344 : GUIBaseVehicle::getNumPassengers() const {
    1131     8881344 :     if (myVehicle.getPersonDevice() != nullptr) {
    1132        6611 :         return (int)myVehicle.getPersonDevice()->size();
    1133             :     }
    1134             :     return 0;
    1135             : }
    1136             : 
    1137             : 
    1138             : int
    1139     8881344 : GUIBaseVehicle::getNumContainers() const {
    1140     8881344 :     if (myVehicle.getContainerDevice() != nullptr) {
    1141        5125 :         return (int)myVehicle.getContainerDevice()->size();
    1142             :     }
    1143             :     return 0;
    1144             : }
    1145             : 
    1146             : std::string
    1147           0 : GUIBaseVehicle::getDeviceDescription() {
    1148             :     std::vector<std::string> devs;
    1149           0 :     for (MSDevice* d : myVehicle.getDevices()) {
    1150           0 :         devs.push_back(d->deviceName());
    1151             :     }
    1152           0 :     return joinToString(devs, " ");
    1153           0 : }
    1154             : 
    1155             : 
    1156             : void
    1157    17776309 : GUIBaseVehicle::computeSeats(const Position& front, const Position& back, double seatOffset, int maxSeats, double exaggeration, int& requiredSeats, Seats& into, double extraOffset) const {
    1158    17776309 :     if (requiredSeats <= 0) {
    1159             :         return;
    1160             :     }
    1161             :     maxSeats = MAX2(maxSeats, 1); // compute at least one seat
    1162       11627 :     seatOffset *= exaggeration;
    1163       11627 :     const double vehWidth = getVType().getSeatingWidth() * exaggeration;
    1164             :     const double length = front.distanceTo2D(back);
    1165       11627 :     const int rowSize = MAX2(1, (int)floor(vehWidth / seatOffset));
    1166       11627 :     const double frontSeatPos = getVType().getFrontSeatPos() + extraOffset;
    1167       11627 :     const double rowOffset = MAX2(1.0, (length - frontSeatPos - 1)) / ceil((double)maxSeats / rowSize);
    1168       11627 :     const double sideOffset = (rowSize - 1) / 2.0 * seatOffset;
    1169       11627 :     double rowPos = frontSeatPos - rowOffset;
    1170             :     double angle = back.angleTo2D(front);
    1171       11627 :     const int fillDirection = MSGlobals::gLefthand ? -1 : 1;
    1172             :     //if (myVehicle.getID() == "v0") std::cout << SIMTIME << " seatOffset=" << seatOffset << " max=" << maxSeats << " ex=" << exaggeration << " req=" << requiredSeats << " rowSize=" << rowSize << " sideOffset=" << sideOffset << " front=" << front << " back=" << back << " a=" << angle << " da=" << RAD2DEG(angle) << "\n";
    1173      228332 :     for (int i = 0; requiredSeats > 0 && i < maxSeats; i++) {
    1174      216705 :         int seat = (i % rowSize);
    1175      216705 :         if (seat == 0) {
    1176       79299 :             rowPos += rowOffset;
    1177             :         }
    1178      433410 :         into.push_back(Seat(PositionVector::positionAtOffset2D(front, back, rowPos, (sideOffset - seat * seatOffset) * fillDirection), angle));
    1179      216705 :         requiredSeats--;
    1180             :     }
    1181             : }
    1182             : 
    1183             : 
    1184             : /****************************************************************************/

Generated by: LCOV version 1.14