LCOV - code coverage report
Current view: top level - src/guisim - GUITriggeredRerouter.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 55.6 % 286 159
Test Date: 2025-11-13 15:38:19 Functions: 27.8 % 36 10

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    GUITriggeredRerouter.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Michael Behrisch
      18              : /// @date    Mon, 25.07.2005
      19              : ///
      20              : // Reroutes vehicles passing an edge (gui version)
      21              : /****************************************************************************/
      22              : #include <config.h>
      23              : 
      24              : #include <string>
      25              : #include <utils/common/MsgHandler.h>
      26              : #include <utils/geom/PositionVector.h>
      27              : #include <utils/geom/Boundary.h>
      28              : #include <utils/gui/div/GLHelper.h>
      29              : #include <utils/common/ToString.h>
      30              : #include <utils/common/Command.h>
      31              : #include <microsim/MSNet.h>
      32              : #include <microsim/MSLane.h>
      33              : #include <microsim/MSEdge.h>
      34              : #include <microsim/MSRoute.h>
      35              : #include <microsim/MSVehicle.h>
      36              : #include <guisim/GUINet.h>
      37              : #include <guisim/GUIEdge.h>
      38              : #include "GUITriggeredRerouter.h"
      39              : #include <utils/gui/globjects/GUIGLObjectPopupMenu.h>
      40              : #include <utils/gui/windows/GUIAppEnum.h>
      41              : #include <gui/GUIGlobals.h>
      42              : #include <utils/gui/div/GUIParameterTableWindow.h>
      43              : #include <gui/GUIApplicationWindow.h>
      44              : #include <microsim/logging/FunctionBinding.h>
      45              : #include <utils/gui/div/GUIGlobalSelection.h>
      46              : #include <utils/gui/globjects/GLIncludes.h>
      47              : #include <utils/gui/globjects/GLIncludes.h>
      48              : #include <utils/gui/div/GUIDesigns.h>
      49              : 
      50              : 
      51              : // ===========================================================================
      52              : // FOX callback mapping
      53              : // ===========================================================================
      54              : /* -------------------------------------------------------------------------
      55              :  * GUITriggeredRerouter::GUITriggeredRerouterPopupMenu - mapping
      56              :  * ----------------------------------------------------------------------- */
      57              : FXDEFMAP(GUITriggeredRerouter::GUITriggeredRerouterPopupMenu)
      58              : GUITriggeredRerouterPopupMenuMap[] = {
      59              :     FXMAPFUNC(SEL_COMMAND,  MID_MANIP,         GUITriggeredRerouter::GUITriggeredRerouterPopupMenu::onCmdOpenManip),
      60              : 
      61              : };
      62              : 
      63              : // Object implementation
      64            0 : FXIMPLEMENT(GUITriggeredRerouter::GUITriggeredRerouterPopupMenu, GUIGLObjectPopupMenu, GUITriggeredRerouterPopupMenuMap, ARRAYNUMBER(GUITriggeredRerouterPopupMenuMap))
      65              : 
      66              : 
      67              : /* -------------------------------------------------------------------------
      68              :  * GUITriggeredRerouter::GUIManip_TriggeredRerouter - mapping
      69              :  * ----------------------------------------------------------------------- */
      70              : FXDEFMAP(GUITriggeredRerouter::GUIManip_TriggeredRerouter) GUIManip_TriggeredRerouterMap[] = {
      71              :     FXMAPFUNC(SEL_COMMAND,  GUITriggeredRerouter::GUIManip_TriggeredRerouter::MID_USER_DEF, GUITriggeredRerouter::GUIManip_TriggeredRerouter::onCmdUserDef),
      72              :     FXMAPFUNC(SEL_UPDATE,   GUITriggeredRerouter::GUIManip_TriggeredRerouter::MID_USER_DEF, GUITriggeredRerouter::GUIManip_TriggeredRerouter::onUpdUserDef),
      73              :     FXMAPFUNC(SEL_COMMAND,  GUITriggeredRerouter::GUIManip_TriggeredRerouter::MID_OPTION,   GUITriggeredRerouter::GUIManip_TriggeredRerouter::onCmdChangeOption),
      74              :     FXMAPFUNC(SEL_COMMAND,  GUITriggeredRerouter::GUIManip_TriggeredRerouter::MID_SHIFT_PROBS,  GUITriggeredRerouter::GUIManip_TriggeredRerouter::onCmdShiftProbs),
      75              :     FXMAPFUNC(SEL_COMMAND,  GUITriggeredRerouter::GUIManip_TriggeredRerouter::MID_CLOSE,    GUITriggeredRerouter::GUIManip_TriggeredRerouter::onCmdClose),
      76              : };
      77              : 
      78            0 : FXIMPLEMENT(GUITriggeredRerouter::GUIManip_TriggeredRerouter, GUIManipulator, GUIManip_TriggeredRerouterMap, ARRAYNUMBER(GUIManip_TriggeredRerouterMap))
      79              : 
      80              : 
      81              : // ===========================================================================
      82              : // method definitions
      83              : // ===========================================================================
      84              : /* -------------------------------------------------------------------------
      85              :  * GUITriggeredRerouter::GUIManip_TriggeredRerouter - methods
      86              :  * ----------------------------------------------------------------------- */
      87            0 : GUITriggeredRerouter::GUIManip_TriggeredRerouter::GUIManip_TriggeredRerouter(
      88            0 :     GUIMainWindow& app, const std::string& name, GUITriggeredRerouter& o) :
      89            0 :     GUIManipulator(app, name, 0, 0), myParent(&app),
      90            0 :     myChosenValue(0), myChosenTarget(myChosenValue, nullptr, MID_OPTION),
      91            0 :     myUsageProbability(o.getProbability()), myUsageProbabilityTarget(myUsageProbability),
      92            0 :     myObject(&o) {
      93            0 :     myChosenTarget.setTarget(this);
      94              :     FXVerticalFrame* f1 =
      95            0 :         new FXVerticalFrame(this, LAYOUT_FILL_X | LAYOUT_FILL_Y, 0, 0, 0, 0, 0, 0, 0, 0);
      96              : 
      97              :     FXGroupBox* gp = new FXGroupBox(f1, "Change Trigger Probability",
      98              :                                     GROUPBOX_TITLE_LEFT | FRAME_SUNKEN | FRAME_RIDGE,
      99            0 :                                     0, 0, 0, 0,  4, 4, 1, 1, 2, 0);
     100              :     {
     101              :         // default
     102              :         FXHorizontalFrame* gf1 =
     103            0 :             new FXHorizontalFrame(gp, LAYOUT_TOP | LAYOUT_LEFT, 0, 0, 0, 0, 10, 10, 5, 5);
     104              :         new FXRadioButton(gf1, "Default", &myChosenTarget, FXDataTarget::ID_OPTION + 0,
     105              :                           ICON_BEFORE_TEXT | LAYOUT_SIDE_TOP,
     106            0 :                           0, 0, 0, 0,   2, 2, 0, 0);
     107              :     }
     108              :     {
     109              :         // free
     110              :         FXHorizontalFrame* gf12 =
     111            0 :             new FXHorizontalFrame(gp, LAYOUT_TOP | LAYOUT_LEFT, 0, 0, 0, 0, 10, 10, 5, 5);
     112              :         new FXRadioButton(gf12, "User Given: ", &myChosenTarget, FXDataTarget::ID_OPTION + 1,
     113              :                           ICON_BEFORE_TEXT | LAYOUT_SIDE_TOP | LAYOUT_CENTER_Y,
     114            0 :                           0, 0, 0, 0,   2, 2, 0, 0);
     115            0 :         myUsageProbabilityDial =
     116              :             new FXRealSpinner(gf12, 10, this, MID_USER_DEF,
     117            0 :                               LAYOUT_TOP | FRAME_SUNKEN | FRAME_THICK);
     118              :         //myUsageProbabilityDial->setFormatString("%.2f");
     119              :         //myUsageProbabilityDial->setIncrements(.1, .1, .1);
     120            0 :         myUsageProbabilityDial->setIncrement(.1);
     121            0 :         myUsageProbabilityDial->setRange(0, 1);
     122            0 :         myUsageProbabilityDial->setValue(myObject->getUserProbability());
     123              :     }
     124              :     {
     125              :         // off
     126              :         FXHorizontalFrame* gf13 =
     127            0 :             new FXHorizontalFrame(gp, LAYOUT_TOP | LAYOUT_LEFT, 0, 0, 0, 0, 10, 10, 5, 5);
     128              :         new FXRadioButton(gf13, "Off", &myChosenTarget, FXDataTarget::ID_OPTION + 2,
     129              :                           ICON_BEFORE_TEXT | LAYOUT_SIDE_TOP,
     130            0 :                           0, 0, 0, 0,   2, 2, 0, 0);
     131              :     }
     132            0 :     myChosenValue = myObject->inUserMode()
     133            0 :                     ? myObject->getUserProbability() > 0
     134            0 :                     ? 1 : 2
     135              :                     : 0;
     136              : 
     137              :     FXGroupBox* gp2 = new FXGroupBox(f1, "Change Route Probability",
     138              :                                      GROUPBOX_TITLE_LEFT | FRAME_SUNKEN | FRAME_RIDGE,
     139            0 :                                      0, 0, 0, 0,  4, 4, 1, 1, 2, 0);
     140            0 :     GUIDesigns::buildFXButton(gp2, "Shift", "", "", nullptr, this, MID_SHIFT_PROBS,
     141              :                               BUTTON_INITIAL | BUTTON_DEFAULT | FRAME_RAISED | FRAME_THICK | LAYOUT_TOP | LAYOUT_LEFT | LAYOUT_CENTER_X, 0, 0, 0, 0, 30, 30, 4, 4);
     142              : 
     143            0 :     GUIDesigns::buildFXButton(f1, "Close", "", "", nullptr, this, MID_CLOSE,
     144              :                               BUTTON_INITIAL | BUTTON_DEFAULT | FRAME_RAISED | FRAME_THICK | LAYOUT_TOP | LAYOUT_LEFT | LAYOUT_CENTER_X, 0, 0, 0, 0, 30, 30, 4, 4);
     145              : 
     146            0 : }
     147              : 
     148              : 
     149            0 : GUITriggeredRerouter::GUIManip_TriggeredRerouter::~GUIManip_TriggeredRerouter() {}
     150              : 
     151              : 
     152              : long
     153            0 : GUITriggeredRerouter::GUIManip_TriggeredRerouter::onCmdClose(FXObject*, FXSelector, void*) {
     154            0 :     destroy();
     155            0 :     return 1;
     156              : }
     157              : 
     158              : 
     159              : long
     160            0 : GUITriggeredRerouter::GUIManip_TriggeredRerouter::onCmdUserDef(FXObject*, FXSelector, void*) {
     161            0 :     myUsageProbability = (double)(myUsageProbabilityDial->getValue());
     162            0 :     static_cast<GUITriggeredRerouter*>(myObject)->setUserUsageProbability(myUsageProbability);
     163            0 :     static_cast<GUITriggeredRerouter*>(myObject)->setUserMode(true);
     164            0 :     myParent->updateChildren();
     165            0 :     return 1;
     166              : }
     167              : 
     168              : 
     169              : long
     170            0 : GUITriggeredRerouter::GUIManip_TriggeredRerouter::onUpdUserDef(FXObject* sender, FXSelector, void* ptr) {
     171            0 :     sender->handle(this,
     172            0 :                    myChosenValue != 1 ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
     173              :                    ptr);
     174            0 :     myParent->updateChildren();
     175            0 :     return 1;
     176              : }
     177              : 
     178              : 
     179              : long
     180            0 : GUITriggeredRerouter::GUIManip_TriggeredRerouter::onCmdChangeOption(FXObject*, FXSelector, void*) {
     181            0 :     static_cast<GUITriggeredRerouter*>(myObject)->setUserUsageProbability(myUsageProbability);
     182            0 :     switch (myChosenValue) {
     183            0 :         case 0:
     184            0 :             static_cast<GUITriggeredRerouter*>(myObject)->setUserMode(false);
     185            0 :             break;
     186            0 :         case 1:
     187            0 :             static_cast<GUITriggeredRerouter*>(myObject)->setUserMode(true);
     188            0 :             break;
     189            0 :         case 2:
     190            0 :             static_cast<GUITriggeredRerouter*>(myObject)->setUserUsageProbability(0);
     191            0 :             static_cast<GUITriggeredRerouter*>(myObject)->setUserMode(true);
     192            0 :             break;
     193            0 :         default:
     194            0 :             throw 1;
     195              :     }
     196            0 :     myParent->updateChildren();
     197            0 :     return 1;
     198              : }
     199              : 
     200              : long
     201            0 : GUITriggeredRerouter::GUIManip_TriggeredRerouter::onCmdShiftProbs(FXObject*, FXSelector, void*) {
     202            0 :     static_cast<GUITriggeredRerouter*>(myObject)->shiftProbs();
     203            0 :     myParent->updateChildren();
     204            0 :     return 1;
     205              : }
     206              : 
     207              : /* -------------------------------------------------------------------------
     208              :  * GUITriggeredRerouter::GUITriggeredRerouterPopupMenu - methods
     209              :  * ----------------------------------------------------------------------- */
     210              : 
     211            0 : GUITriggeredRerouter::GUITriggeredRerouterPopupMenu::GUITriggeredRerouterPopupMenu(
     212            0 :     GUIMainWindow& app, GUISUMOAbstractView& parent, GUIGlObject* o) :
     213            0 :     GUIGLObjectPopupMenu(app, parent, o) {}
     214              : 
     215              : 
     216            0 : GUITriggeredRerouter::GUITriggeredRerouterPopupMenu::~GUITriggeredRerouterPopupMenu() {}
     217              : 
     218              : 
     219              : long
     220            0 : GUITriggeredRerouter::GUITriggeredRerouterPopupMenu::onCmdOpenManip(FXObject*,
     221              :         FXSelector,
     222              :         void*) {
     223            0 :     static_cast<GUITriggeredRerouter*>(myObject)->openManipulator(
     224            0 :         *myApplication, *myParent);
     225            0 :     return 1;
     226              : }
     227              : 
     228              : // -------------------------------------------------------------------------
     229              : // GUITriggeredRerouter - methods
     230              : // -------------------------------------------------------------------------
     231              : 
     232          703 : GUITriggeredRerouter::GUITriggeredRerouter(const std::string& id, const MSEdgeVector& edges, double prob,
     233          703 :         bool off, bool optional, SUMOTime timeThreshold, const std::string& vTypes, const Position& pos, const double radius, SUMORTree& rtree) :
     234              :     MSTriggeredRerouter(id, edges, prob, off, optional, timeThreshold, vTypes, pos, radius),
     235              :     GUIGlObject_AbstractAdd(GLO_REROUTER, id, GUIIconSubSys::getIcon(GUIIcon::REROUTER)),
     236          703 :     myShiftProbDistIndex(0) {
     237              :     // add visualisation objects for edges which trigger the rerouter
     238         1602 :     for (MSEdgeVector::const_iterator it = edges.begin(); it != edges.end(); ++it) {
     239          899 :         myEdgeVisualizations.push_back(new GUITriggeredRerouterEdge(dynamic_cast<GUIEdge*>(*it), this, REROUTER_TRIGGER_EDGE, -1, pos, radius));
     240          899 :         rtree.addAdditionalGLObject(myEdgeVisualizations.back());
     241          899 :         myBoundary.add(myEdgeVisualizations.back()->getCenteringBoundary());
     242           18 :         if (pos != Position::INVALID && radius != std::numeric_limits<double>::max()) {
     243              :             break;
     244              :         }
     245              :     }
     246          703 : }
     247              : 
     248              : 
     249         1406 : GUITriggeredRerouter::~GUITriggeredRerouter() {
     250         1841 :     for (std::vector<GUITriggeredRerouterEdge*>::iterator it = myEdgeVisualizations.begin(); it != myEdgeVisualizations.end(); ++it) {
     251         1138 :         delete *it;
     252              :     }
     253              :     myEdgeVisualizations.clear();
     254         1406 : }
     255              : 
     256              : 
     257              : void
     258         4487 : GUITriggeredRerouter::myEndElement(int element) {
     259         4487 :     MSTriggeredRerouter::myEndElement(element);
     260         4487 :     if (element == SUMO_TAG_INTERVAL) {
     261              :         // add visualisation objects for closed edges
     262              :         const RerouteInterval& ri = myIntervals.back();
     263          919 :         for (auto item : ri.getClosed()) {
     264          214 :             const GUIEdge* edge = dynamic_cast<const GUIEdge*>(item.first);
     265          214 :             myEdgeVisualizations.push_back(new GUITriggeredRerouterEdge(const_cast<GUIEdge*>(edge), this, REROUTER_CLOSED_EDGE));
     266          214 :             dynamic_cast<GUINet*>(GUINet::getInstance())->getVisualisationSpeedUp().addAdditionalGLObject(myEdgeVisualizations.back());
     267          214 :             myBoundary.add(myEdgeVisualizations.back()->getCenteringBoundary());
     268              :         }
     269              :         // add visualisation objects for switches
     270          705 :         if (ri.routeProbs.getProbs().size() > 1) {
     271              :             // find last common edge of all routes
     272              :             ConstMSRoutePtr route0 = ri.routeProbs.getVals()[0];
     273              :             const MSEdge* lastEdge = nullptr;
     274              :             int nextIndex = 0;
     275           20 :             for (int i = 0; i < (int)route0->getEdges().size(); i++) {
     276           20 :                 const MSEdge* cand = route0->getEdges()[i];
     277           74 :                 for (ConstMSRoutePtr route : ri.routeProbs.getVals()) {
     278           54 :                     const MSEdge* nextEdge = i < (int)route->getEdges().size() ? route->getEdges()[i] : nullptr;
     279           54 :                     if (nextEdge != cand) {
     280              :                         cand = nullptr;
     281              :                     }
     282              :                 }
     283           20 :                 if (cand != nullptr) {
     284              :                     lastEdge = cand;
     285              :                 } else {
     286              :                     nextIndex = i;
     287              :                     break;
     288              :                 }
     289              :             }
     290            9 :             if (lastEdge != nullptr) {
     291            9 :                 double maxProb = ri.routeProbs.getProbs()[myShiftProbDistIndex];
     292           34 :                 for (int i = 0; i < (int)ri.routeProbs.getVals().size(); i++) {
     293           25 :                     const ConstMSEdgeVector& edges = ri.routeProbs.getVals()[i]->getEdges();
     294           25 :                     if (nextIndex < (int)edges.size()) {
     295           25 :                         GUIEdge* edge = dynamic_cast<GUIEdge*>(const_cast<MSEdge*>(edges[nextIndex]));
     296           25 :                         myEdgeVisualizations.push_back(new GUITriggeredRerouterEdge(edge, this, REROUTER_SWITCH_EDGE, i));
     297           25 :                         dynamic_cast<GUINet*>(GUINet::getInstance())->getVisualisationSpeedUp().addAdditionalGLObject(myEdgeVisualizations.back());
     298           25 :                         myBoundary.add(myEdgeVisualizations.back()->getCenteringBoundary());
     299              :                     }
     300           25 :                     double prob = ri.routeProbs.getProbs()[i];
     301           25 :                     if (prob > maxProb) {
     302              :                         maxProb = prob;
     303            1 :                         myShiftProbDistIndex = i;
     304              :                     }
     305              :                 }
     306              :             }
     307              :         }
     308              :     }
     309         4487 : }
     310              : 
     311              : 
     312              : GUIGLObjectPopupMenu*
     313            0 : GUITriggeredRerouter::getPopUpMenu(GUIMainWindow& app, GUISUMOAbstractView& parent) {
     314            0 :     GUIGLObjectPopupMenu* ret = new GUITriggeredRerouterPopupMenu(app, parent, this);
     315            0 :     buildPopupHeader(ret, app);
     316            0 :     buildCenterPopupEntry(ret);
     317            0 :     buildShowManipulatorPopupEntry(ret, false);
     318            0 :     buildNameCopyPopupEntry(ret);
     319            0 :     buildSelectionPopupEntry(ret);
     320            0 :     buildPositionCopyEntry(ret, app);
     321            0 :     return ret;
     322              : }
     323              : 
     324              : 
     325              : GUIParameterTableWindow*
     326            0 : GUITriggeredRerouter::getParameterWindow(GUIMainWindow&,
     327              :         GUISUMOAbstractView&) {
     328            0 :     return nullptr;
     329              : }
     330              : 
     331              : 
     332              : void
     333            0 : GUITriggeredRerouter::drawGL(const GUIVisualizationSettings& s) const {
     334              :     UNUSED_PARAMETER(s);
     335            0 : }
     336              : 
     337              : 
     338              : Boundary
     339            0 : GUITriggeredRerouter::getCenteringBoundary() const {
     340              :     Boundary b(myBoundary);
     341            0 :     b.grow(20);
     342            0 :     return b;
     343              : }
     344              : 
     345              : 
     346              : double
     347            0 : GUITriggeredRerouter::getExaggeration(const GUIVisualizationSettings& s) const {
     348            0 :     return s.addSize.getExaggeration(s, this);
     349              : }
     350              : 
     351              : 
     352              : GUIManipulator*
     353            0 : GUITriggeredRerouter::openManipulator(GUIMainWindow& app,
     354              :                                       GUISUMOAbstractView&) {
     355            0 :     GUIManip_TriggeredRerouter* gui = new GUIManip_TriggeredRerouter(app, getFullName(), *this);
     356            0 :     gui->create();
     357            0 :     gui->show(PLACEMENT_SCREEN);
     358            0 :     return gui;
     359              : }
     360              : 
     361              : 
     362              : void
     363            0 : GUITriggeredRerouter::shiftProbs() {
     364            0 :     const RerouteInterval* const ri = getCurrentReroute(MSNet::getInstance()->getCurrentTimeStep());
     365            0 :     if (ri != nullptr && ri->routeProbs.getProbs().size() > 1) {
     366            0 :         auto& rp = const_cast<RandomDistributor<ConstMSRoutePtr>&>(ri->routeProbs);
     367            0 :         double prob = rp.getProbs()[myShiftProbDistIndex];
     368            0 :         rp.add(rp.getVals()[myShiftProbDistIndex], -prob);
     369            0 :         myShiftProbDistIndex = (myShiftProbDistIndex + 1) % rp.getProbs().size();
     370            0 :         rp.add(rp.getVals()[myShiftProbDistIndex], prob);
     371              :         // notify vehicles currently on a trigger edge
     372            0 :         for (auto rrEdge : myEdgeVisualizations) {
     373            0 :             if (rrEdge->getRerouterEdgeType() == REROUTER_TRIGGER_EDGE) {
     374            0 :                 if (!MSGlobals::gUseMesoSim) {
     375            0 :                     for (MSLane* lane : rrEdge->getEdge()->getLanes()) {
     376            0 :                         for (const MSVehicle* veh : lane->getVehiclesSecure()) {
     377            0 :                             const_cast<MSVehicle*>(veh)->addReminder(this);
     378              :                         }
     379            0 :                         lane->releaseVehicles();
     380              :                     }
     381              :                 }
     382              :             }
     383              :         }
     384              :     }
     385            0 : }
     386              : 
     387              : 
     388              : /* -------------------------------------------------------------------------
     389              :  * GUITriggeredRerouterEdge - methods
     390              :  * ----------------------------------------------------------------------- */
     391         1138 : GUITriggeredRerouter::GUITriggeredRerouterEdge::GUITriggeredRerouterEdge(GUIEdge* edge, GUITriggeredRerouter* parent, RerouterEdgeType edgeType, int distIndex,
     392         1138 :         const Position& pos, const double radius) :
     393         1138 :     GUIGlObject(GLO_REROUTER_EDGE, parent->getID() + ":" + edge->getID(), GUIIconSubSys::getIcon(GUIIcon::REROUTER)),
     394         1138 :     myParent(parent),
     395         1138 :     myEdge(edge),
     396         1138 :     myEdgeType(edgeType),
     397         3414 :     myDistIndex(distIndex) {
     398              :     const std::vector<MSLane*>& lanes = edge->getLanes();
     399           18 :     if (pos == Position::INVALID || radius == std::numeric_limits<double>::max()) {
     400         2382 :         for (const MSLane* lane : lanes) {
     401         1244 :             if ((lane->getPermissions() & ~SVC_PEDESTRIAN) == 0) {
     402           29 :                 continue;
     403              :             }
     404              :             const PositionVector& v = lane->getShape();
     405              :             double lanePos;
     406              :             double centerPos;
     407         1215 :             switch (edgeType) {
     408          974 :                 case REROUTER_TRIGGER_EDGE:
     409              :                     // U sign at end of edge
     410              :                     // (note: symbol is drawn downstream of lanePos and extends 6m)
     411          974 :                     lanePos = MAX2(0.0, v.length() - 10);
     412          974 :                     centerPos = MIN2(lanePos + 3, v.length());
     413              :                     break;
     414              :                 case REROUTER_SWITCH_EDGE:
     415              :                     // triangle with switch probability
     416              :                     lanePos = 0;
     417              :                     centerPos = lanePos;
     418              :                     break;
     419          216 :                 default:
     420              :                     // closing sign on start of edge
     421          216 :                     lanePos = MIN2(v.length(), 3.0);
     422          216 :                     centerPos = MIN2(lanePos + 3, v.length());
     423              :             }
     424         1215 :             myFGPositions.push_back(v.positionAtOffset(lanePos));
     425         1215 :             myFGRotations.push_back(-v.rotationDegreeAtOffset(lanePos));
     426         1215 :             myBoundary.add(v.positionAtOffset(centerPos));
     427         1215 :             myHalfWidths.push_back(lane->getWidth() * 0.5 * 0.875);
     428              :         }
     429              :     } else {
     430            0 :         myFGPositions.push_back(pos);
     431            0 :         const PositionVector& v = lanes.front()->getShape();
     432            0 :         myFGRotations.push_back(-v.rotationDegreeAtOffset(lanes.front()->getLength()));
     433            0 :         myBoundary.add(myFGPositions.back());
     434            0 :         myHalfWidths.push_back(SUMO_const_halfLaneWidth * 0.875);
     435              :     }
     436         1138 : }
     437              : 
     438              : 
     439         2276 : GUITriggeredRerouter::GUITriggeredRerouterEdge::~GUITriggeredRerouterEdge() {}
     440              : 
     441              : 
     442              : GUIGLObjectPopupMenu*
     443            0 : GUITriggeredRerouter::GUITriggeredRerouterEdge::getPopUpMenu(GUIMainWindow& app,
     444              :         GUISUMOAbstractView& parent) {
     445            0 :     return myParent->getPopUpMenu(app, parent);
     446              : }
     447              : 
     448              : 
     449              : GUIParameterTableWindow*
     450            0 : GUITriggeredRerouter::GUITriggeredRerouterEdge::getParameterWindow(GUIMainWindow&,
     451              :         GUISUMOAbstractView&) {
     452            0 :     return nullptr;
     453              : }
     454              : 
     455              : 
     456              : void
     457       201673 : GUITriggeredRerouter::GUITriggeredRerouterEdge::drawGL(const GUIVisualizationSettings& s) const {
     458       201673 :     const double exaggeration = getExaggeration(s);
     459       201673 :     if (s.scale * exaggeration >= 3) {
     460         5375 :         GLHelper::pushName(getGlID());
     461         5375 :         const double prob = myParent->getProbability();
     462         5375 :         if (myEdgeType == REROUTER_CLOSED_EDGE) {
     463              :             // draw closing symbol onto all lanes
     464              :             const RerouteInterval* const ri =
     465           42 :                 myParent->getCurrentReroute(MSNet::getInstance()->getCurrentTimeStep());
     466           42 :             if (ri != nullptr && prob > 0) {
     467              :                 // draw only if the edge is closed at this time
     468           17 :                 const auto& closedEdges = ri->getClosed();
     469           17 :                 if (closedEdges.find(myEdge) != closedEdges.end()) {
     470           17 :                     const int noLanes = (int)myFGPositions.size();
     471           34 :                     for (int j = 0; j < noLanes; ++j) {
     472           17 :                         Position pos = myFGPositions[j];
     473           17 :                         double rot = myFGRotations[j];
     474           17 :                         GLHelper::pushMatrix();
     475           17 :                         glTranslated(pos.x(), pos.y(), 0);
     476           17 :                         glRotated(rot, 0, 0, 1);
     477           17 :                         glTranslated(0, -1.5, 0);
     478              :                         int noPoints = 9;
     479           17 :                         if (s.scale > 25) {
     480            0 :                             noPoints = (int)(9.0 + s.scale / 10.0);
     481            0 :                             if (noPoints > 36) {
     482              :                                 noPoints = 36;
     483              :                             }
     484              :                         }
     485           17 :                         glTranslated(0, 0, getType());
     486              :                         //glScaled(exaggeration, exaggeration, 1);
     487           17 :                         glColor3d(0.7, 0, 0);
     488           17 :                         GLHelper::drawFilledCircle((double) 1.3, noPoints);
     489           17 :                         glTranslated(0, 0, .1);
     490           17 :                         glColor3d(1, 0, 0);
     491           17 :                         GLHelper::drawFilledCircle((double) 1.3, noPoints, 0, prob * 360);
     492           17 :                         glTranslated(0, 0, .1);
     493           17 :                         glColor3d(1, 1, 1);
     494           17 :                         glRotated(-90, 0, 0, 1);
     495           17 :                         glBegin(GL_TRIANGLES);
     496           17 :                         glVertex2d(0 - .3, -1.);
     497           17 :                         glVertex2d(0 - .3, 1.);
     498           17 :                         glVertex2d(0 + .3, 1.);
     499           17 :                         glVertex2d(0 + .3, -1.);
     500           17 :                         glVertex2d(0 - .3, -1.);
     501           17 :                         glVertex2d(0 + .3, 1.);
     502           17 :                         glEnd();
     503           17 :                         GLHelper::popMatrix();
     504              :                     }
     505              :                 }
     506              :             }
     507              : 
     508         5333 :         } else if (myEdgeType == REROUTER_TRIGGER_EDGE) {
     509              :             // draw rerouter symbol onto all lanes
     510        11397 :             for (int i = 0; i < (int)myFGPositions.size(); ++i) {
     511         6532 :                 const Position& pos = myFGPositions[i];
     512         6532 :                 double rot = myFGRotations[i];
     513         6532 :                 const double w = myHalfWidths[i];
     514         6532 :                 GLHelper::pushMatrix();
     515         6532 :                 glTranslated(pos.x(), pos.y(), 0);
     516         6532 :                 glRotated(rot, 0, 0, 1);
     517              :                 // draw the symbol downstream of pos (without touching the older drawing code)
     518         6532 :                 glTranslated(0, -6, 0);
     519         6532 :                 glTranslated(0, 0, getType());
     520         6532 :                 glScaled(exaggeration, exaggeration, 1);
     521         6532 :                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
     522              : 
     523         6532 :                 glBegin(GL_TRIANGLES);
     524         6532 :                 glColor3d(1, .8f, 0);
     525              :                 // base
     526         6532 :                 glVertex2d(0 - w, 0);
     527         6532 :                 glVertex2d(0 - w, 6);
     528         6532 :                 glVertex2d(0 + w, 6);
     529         6532 :                 glVertex2d(0 + w, 0);
     530         6532 :                 glVertex2d(0 - w, 0);
     531         6532 :                 glVertex2d(0 + w, 6);
     532         6532 :                 glEnd();
     533              : 
     534              :                 // draw "U"
     535        13064 :                 GLHelper::drawText("U", Position(0, 2), .1, 3 * (w / 1.4), RGBColor::BLACK, 180);
     536              : 
     537              :                 // draw Probability
     538        13064 :                 GLHelper::drawText((toString((int)(prob * 100)) + "%").c_str(), Position(0, 4), .1, 0.7, RGBColor::BLACK, 180);
     539              : 
     540         6532 :                 GLHelper::popMatrix();
     541              :             }
     542          468 :         } else if (myEdgeType == REROUTER_SWITCH_EDGE) {
     543              :             const RerouteInterval* const ri =
     544          468 :                 myParent->getCurrentReroute(MSNet::getInstance()->getCurrentTimeStep());
     545          468 :             const double routeProb = ri != nullptr && prob > 0 ?  ri->routeProbs.getProbs()[myDistIndex] / ri->routeProbs.getOverallProb() : 0;
     546          468 :             if (routeProb > 0) {
     547          924 :                 for (int i = 0; i < (int)myFGPositions.size(); ++i) {
     548          462 :                     const Position& pos = myFGPositions[i];
     549          462 :                     double rot = myFGRotations[i];
     550          462 :                     const double w = myHalfWidths[i];
     551          462 :                     GLHelper::pushMatrix();
     552          462 :                     glTranslated(pos.x(), pos.y(), 0);
     553          462 :                     glRotated(rot, 0, 0, 1);
     554          462 :                     glTranslated(0, 0, getType());
     555          462 :                     glScaled(exaggeration, exaggeration, 1);
     556          462 :                     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
     557              : 
     558          462 :                     glBegin(GL_TRIANGLES);
     559          462 :                     glColor3d(0, 1, 1);
     560              :                     // base
     561          462 :                     glVertex2d(0 - 0.0, 0);
     562          462 :                     glVertex2d(0 - w, 6);
     563          462 :                     glVertex2d(0 + w, 6);
     564          462 :                     glVertex2d(0 + 0.0, 0);
     565          462 :                     glVertex2d(0 + w, 6);
     566          462 :                     glEnd();
     567              : 
     568              :                     // draw "P"
     569          924 :                     GLHelper::drawText("P", Position(0, 3.5), .1, 2, RGBColor::BLACK, 180);
     570              : 
     571              :                     // draw Probability for this target edge
     572          924 :                     GLHelper::drawText((toString((int)(routeProb * 100)) + "%").c_str(), Position(0, 5), .1, 0.7, RGBColor::BLACK, 180);
     573              : 
     574          462 :                     GLHelper::popMatrix();
     575              :                 }
     576              :             }
     577              :         }
     578         5375 :         GLHelper::popName();
     579              :     }
     580       201673 :     if (myEdgeType == REROUTER_TRIGGER_EDGE && s.addName.show(myParent)) {
     581            0 :         GLHelper::drawTextSettings(s.addName, myParent->getMicrosimID(), myFGPositions.back(), s.scale, s.angle);
     582              :     }
     583       201673 : }
     584              : 
     585              : 
     586              : double
     587       201673 : GUITriggeredRerouter::GUITriggeredRerouterEdge::getExaggeration(const GUIVisualizationSettings& s) const {
     588       201673 :     return s.addSize.getExaggeration(s, this);
     589              : }
     590              : 
     591              : 
     592              : Boundary
     593         2276 : GUITriggeredRerouter::GUITriggeredRerouterEdge::getCenteringBoundary() const {
     594              :     Boundary b(myBoundary);
     595         2276 :     b.grow(20);
     596         2276 :     return b;
     597              : }
     598              : 
     599              : 
     600              : void
     601            0 : GUITriggeredRerouter::GUITriggeredRerouterEdge::onLeftBtnPress(void* /*data*/) {
     602            0 :     myParent->shiftProbs();
     603            0 : }
     604              : 
     605              : 
     606              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1