LCOV - code coverage report
Current view: top level - src/guisim - GUIInductLoop.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 65.3 % 173 113
Test Date: 2024-11-22 15:46:21 Functions: 85.7 % 14 12

            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    GUIInductLoop.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Michael Behrisch
      18              : /// @date    Aug 2003
      19              : ///
      20              : // The gui-version of the MSInductLoop, together with the according
      21              : /****************************************************************************/
      22              : #include <config.h>
      23              : 
      24              : #include <utils/common/MsgHandler.h>
      25              : #include <utils/gui/globjects/GUIGlObject.h>
      26              : #include <utils/geom/PositionVector.h>
      27              : #include <utils/gui/div/GLHelper.h>
      28              : #include <utils/gui/div/GUIParameterTableWindow.h>
      29              : #include <utils/gui/globjects/GLIncludes.h>
      30              : #include <microsim/logging/FunctionBinding.h>
      31              : #include <microsim/logging/FuncBinding_IntParam.h>
      32              : #include <microsim/logging/CastingFunctionBinding_Param.h>
      33              : #include <microsim/MSLane.h>
      34              : #include <microsim/output/MSInductLoop.h>
      35              : #include "GUIEdge.h"
      36              : #include "Command_Hotkey_InductionLoop.h"
      37              : #include "GUIInductLoop.h"
      38              : 
      39              : 
      40              : // ===========================================================================
      41              : // method definitions
      42              : // ===========================================================================
      43              : /* -------------------------------------------------------------------------
      44              :  * GUIInductLoop-methods
      45              :  * ----------------------------------------------------------------------- */
      46          472 : GUIInductLoop::GUIInductLoop(const std::string& id, MSLane* const lane,
      47              :                              double position, double length,
      48              :                              std::string name, const std::string& vTypes,
      49              :                              const std::string& nextEdges,
      50          472 :                              int detectPersons, bool show) :
      51              :     MSInductLoop(id, lane, position, length, name, vTypes, nextEdges, detectPersons, true),
      52          471 :     myWrapper(nullptr),
      53          472 :     myShow(show) {
      54          471 : }
      55              : 
      56              : 
      57          938 : GUIInductLoop::~GUIInductLoop() {}
      58              : 
      59              : 
      60              : GUIDetectorWrapper*
      61          470 : GUIInductLoop::buildDetectorGUIRepresentation() {
      62          940 :     if (hasParameter("hotkey")) {
      63            0 :         Command_Hotkey_InductionLoop::registerHotkey(getParameter("hotkey"), this);
      64              :     }
      65              :     // caller (GUINet) takes responsibility for pointer
      66          470 :     myWrapper = new MyWrapper(*this, myPosition);
      67          470 :     return myWrapper;
      68              : }
      69              : 
      70              : 
      71              : void
      72        26975 : GUIInductLoop::setSpecialColor(const RGBColor* color) {
      73        26975 :     if (myWrapper != nullptr) {
      74              :         myWrapper->setSpecialColor(color);
      75              :     }
      76        26975 : }
      77              : 
      78              : 
      79              : // -------------------------------------------------------------------------
      80              : // GUIInductLoop::MyWrapper-methods
      81              : // -------------------------------------------------------------------------
      82              : 
      83          470 : GUIInductLoop::MyWrapper::MyWrapper(GUIInductLoop& detector, double pos) :
      84              :     GUIDetectorWrapper(GLO_E1DETECTOR, detector.getID(), GUIIconSubSys::getIcon(GUIIcon::E1)),
      85          470 :     myDetector(detector), myPosition(pos),
      86          470 :     myHaveLength(myPosition != detector.getEndPosition()),
      87          470 :     mySpecialColor(nullptr) {
      88          470 :     mySupportsOverride = true;
      89          470 :     myFGPosition = detector.getLane()->geometryPositionAtOffset(pos);
      90          470 :     myBoundary.add(myFGPosition.x() + (double) 5.5, myFGPosition.y() + (double) 5.5);
      91          470 :     myBoundary.add(myFGPosition.x() - (double) 5.5, myFGPosition.y() - (double) 5.5);
      92          470 :     myFGRotation = -detector.getLane()->getShape().rotationDegreeAtOffset(pos);
      93              : 
      94          470 :     if (myHaveLength) {
      95              :         const MSLane& lane = *detector.getLane();
      96              :         const double endPos = detector.getEndPosition();
      97              :         myFGShape = lane.getShape();
      98            4 :         myFGShape = myFGShape.getSubpart(
      99              :                         lane.interpolateLanePosToGeometryPos(pos),
     100              :                         lane.interpolateLanePosToGeometryPos(endPos));
     101            2 :         myFGShapeRotations.reserve(myFGShape.size() - 1);
     102            2 :         myFGShapeLengths.reserve(myFGShape.size() - 1);
     103            2 :         int e = (int) myFGShape.size() - 1;
     104            6 :         for (int i = 0; i < e; ++i) {
     105            4 :             const Position& f = myFGShape[i];
     106            4 :             const Position& s = myFGShape[i + 1];
     107            4 :             myFGShapeLengths.push_back(f.distanceTo(s));
     108            4 :             myFGShapeRotations.push_back((double) atan2((s.x() - f.x()), (f.y() - s.y())) * (double) 180.0 / (double) PI);
     109              :         }
     110            2 :         myOutline.push_back(lane.geometryPositionAtOffset(pos, -1));
     111            2 :         myOutline.push_back(lane.geometryPositionAtOffset(pos, 1));
     112            2 :         myOutline.push_back(lane.geometryPositionAtOffset(endPos, 1));
     113            2 :         myOutline.push_back(lane.geometryPositionAtOffset(endPos, -1));
     114            2 :         myIndicators.push_back(lane.geometryPositionAtOffset(pos, -1.7));
     115            2 :         myIndicators.push_back(lane.geometryPositionAtOffset(pos, 1.7));
     116            2 :         myIndicators.push_back(lane.geometryPositionAtOffset(endPos, 1.7));
     117            2 :         myIndicators.push_back(lane.geometryPositionAtOffset(endPos, -1.7));
     118              :     }
     119          470 : }
     120              : 
     121              : 
     122          936 : GUIInductLoop::MyWrapper::~MyWrapper() {}
     123              : 
     124              : 
     125              : Boundary
     126        33677 : GUIInductLoop::MyWrapper::getCenteringBoundary() const {
     127              :     Boundary b(myBoundary);
     128        33677 :     b.grow(20);
     129        33677 :     return b;
     130            0 : }
     131              : 
     132              : 
     133              : 
     134              : GUIParameterTableWindow*
     135            0 : GUIInductLoop::MyWrapper::getParameterWindow(GUIMainWindow& app,
     136              :         GUISUMOAbstractView& /*parent !!! recheck this - never needed?*/) {
     137            0 :     GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
     138              :     // add items
     139              :     // parameter
     140            0 :     ret->mkItem(TL("name"), false, myDetector.getName());
     141            0 :     ret->mkItem(TL("position [m]"), false, myPosition);
     142            0 :     if (myDetector.getEndPosition() != myPosition) {
     143            0 :         ret->mkItem(TL("end position [m]"), false, myDetector.getEndPosition());
     144              :     }
     145            0 :     ret->mkItem(TL("lane"), false, myDetector.getLane()->getID());
     146            0 :     if (myDetector.isTyped()) {
     147            0 :         ret->mkItem(TL("vTypes"), false, toString(myDetector.getVehicleTypes()));
     148              :     }
     149              :     // values
     150            0 :     ret->mkItem(TL("entered vehicles [-]"), true,
     151            0 :                 new FuncBinding_IntParam<GUIInductLoop, double>(&myDetector, &GUIInductLoop::getEnteredNumber, 0));
     152            0 :     ret->mkItem(TL("speed [m/s]"), true,
     153            0 :                 new FuncBinding_IntParam<GUIInductLoop, double>(&myDetector, &GUIInductLoop::getSpeed, 0));
     154            0 :     ret->mkItem(TL("occupancy [%]"), true,
     155            0 :                 new FunctionBinding<GUIInductLoop, double>(&myDetector, &GUIInductLoop::getOccupancy));
     156            0 :     ret->mkItem(TL("vehicle length [m]"), true,
     157            0 :                 new FuncBinding_IntParam<GUIInductLoop, double>(&myDetector, &GUIInductLoop::getVehicleLength, 0));
     158            0 :     ret->mkItem(TL("empty time [s]"), true,
     159            0 :                 new FunctionBinding<GUIInductLoop, double>(&myDetector, &GUIInductLoop::getTimeSinceLastDetection));
     160            0 :     ret->mkItem(TL("occupied time [s]"), true,
     161            0 :                 new FunctionBinding<GUIInductLoop, double>(&myDetector, &GUIInductLoop::getOccupancyTime));
     162            0 :     ret->mkItem(TL("interval entered vehicles [#]"), true,
     163            0 :                 new CastingFunctionBinding_Param<GUIInductLoop, double, int, bool>(&myDetector, &GUIInductLoop::getIntervalVehicleNumber, false));
     164            0 :     ret->mkItem(TL("interval speed [m/s]"), true,
     165            0 :                 new CastingFunctionBinding_Param<GUIInductLoop, double, double, bool>(&myDetector, &GUIInductLoop::getIntervalMeanSpeed, false));
     166            0 :     ret->mkItem(TL("interval occupancy [%]"), true,
     167            0 :                 new CastingFunctionBinding_Param<GUIInductLoop, double, double, bool>(&myDetector, &GUIInductLoop::getIntervalOccupancy, false));
     168            0 :     ret->mkItem(TL("last interval entered vehicles [#]"), true,
     169            0 :                 new CastingFunctionBinding_Param<GUIInductLoop, double, int, bool>(&myDetector, &GUIInductLoop::getIntervalVehicleNumber, true));
     170            0 :     ret->mkItem(TL("last interval speed [m/s]"), true,
     171            0 :                 new CastingFunctionBinding_Param<GUIInductLoop, double, double, bool>(&myDetector, &GUIInductLoop::getIntervalMeanSpeed, true));
     172            0 :     ret->mkItem(TL("last interval occupancy [%]"), true,
     173            0 :                 new CastingFunctionBinding_Param<GUIInductLoop, double, double, bool>(&myDetector, &GUIInductLoop::getIntervalOccupancy, true));
     174              :     // close building
     175            0 :     ret->closeBuilding(&myDetector);
     176            0 :     return ret;
     177              : }
     178              : 
     179              : 
     180              : void
     181        63578 : GUIInductLoop::MyWrapper::drawGL(const GUIVisualizationSettings& s) const {
     182        63578 :     if (!myDetector.isVisible()) {
     183              :         return;
     184              :     }
     185        33207 :     GLHelper::pushName(getGlID());
     186        33207 :     double width = (double) 2.0 * s.scale;
     187        33207 :     glLineWidth(1.0);
     188        33207 :     const double exaggeration = getExaggeration(s);
     189        33207 :     glColor3d(1, 1, 0);
     190        33207 :     if (myHaveLength) {
     191           14 :         GLHelper::pushMatrix();
     192           14 :         glTranslated(0, 0, GLO_JUNCTION + 0.4); // do not draw on top of linkRules
     193           14 :         GLHelper::drawBoxLines(myFGShape, myFGShapeRotations, myFGShapeLengths, MIN2(1.0, exaggeration), 0, 0);
     194           14 :         if (width * exaggeration > 1) {
     195              : 
     196              :             // outline
     197           14 :             setOutlineColor();
     198           14 :             glTranslated(0, 0, .01);
     199           14 :             glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
     200           14 :             glBegin(GL_QUADS);
     201           70 :             for (const Position& p : myOutline) {
     202           56 :                 glVertex2d(p.x(), p.y());
     203              :             }
     204           14 :             glEnd();
     205           14 :             glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
     206              : 
     207              :             // position indicator
     208           14 :             glBegin(GL_LINES);
     209           14 :             glVertex2d(myIndicators[0].x(), myIndicators[0].y());
     210           14 :             glVertex2d(myIndicators[1].x(), myIndicators[1].y());
     211           14 :             glEnd();
     212           14 :             glBegin(GL_LINES);
     213           14 :             glVertex2d(myIndicators[2].x(), myIndicators[2].y());
     214           14 :             glVertex2d(myIndicators[3].x(), myIndicators[3].y());
     215           14 :             glEnd();
     216              : 
     217              :             // jammed actuated-tls detector, draw crossed-out:
     218           14 :             if (mySpecialColor != nullptr  && *mySpecialColor == RGBColor::ORANGE) {
     219            0 :                 glBegin(GL_LINES);
     220            0 :                 glVertex2d(myOutline[0].x(), myOutline[0].y());
     221            0 :                 glVertex2d(myOutline[2].x(), myOutline[2].y());
     222            0 :                 glEnd();
     223            0 :                 glBegin(GL_LINES);
     224            0 :                 glVertex2d(myOutline[1].x(), myOutline[1].y());
     225            0 :                 glVertex2d(myOutline[3].x(), myOutline[3].y());
     226            0 :                 glEnd();
     227              :             }
     228              :         }
     229           14 :         GLHelper::popMatrix();
     230              :     } else {
     231              :         // classic shape
     232        33193 :         GLHelper::pushMatrix();
     233        33193 :         glTranslated(0, 0, GLO_JUNCTION + 0.4); // do not draw on top of linkRules
     234        33193 :         glTranslated(myFGPosition.x(), myFGPosition.y(), 0);
     235        33193 :         glRotated(myFGRotation, 0, 0, 1);
     236        33193 :         glScaled(exaggeration, exaggeration, 1);
     237        33193 :         glBegin(GL_QUADS);
     238        33193 :         glVertex2d(0 - 1.0, 2);
     239        33193 :         glVertex2d(-1.0, -2);
     240        33193 :         glVertex2d(1.0, -2);
     241        33193 :         glVertex2d(1.0, 2);
     242        33193 :         glEnd();
     243        33193 :         glTranslated(0, 0, .01);
     244        33193 :         setOutlineColor();
     245              : 
     246        33193 :         if (width * exaggeration > 1) {
     247              :             // outline
     248        18714 :             glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
     249        18714 :             glBegin(GL_QUADS);
     250        18714 :             glVertex2d(0 - 1.0, 2);
     251        18714 :             glVertex2d(-1.0, -2);
     252        18714 :             glVertex2d(1.0, -2);
     253        18714 :             glVertex2d(1.0, 2);
     254        18714 :             glEnd();
     255        18714 :             glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
     256              : 
     257              :             // position indicator
     258        18714 :             glRotated(90, 0, 0, -1);
     259        18714 :             glBegin(GL_LINES);
     260        18714 :             glVertex2d(0, 1.7);
     261        18714 :             glVertex2d(0, -1.7);
     262        18714 :             glEnd();
     263              : 
     264              :             // jammed actuated-tls detector, draw crossed-out:
     265        18714 :             if (mySpecialColor != nullptr  && *mySpecialColor == RGBColor::ORANGE) {
     266            0 :                 glBegin(GL_LINES);
     267            0 :                 glVertex2d(-1.0, 2);
     268            0 :                 glVertex2d(1.0, -2);
     269            0 :                 glEnd();
     270            0 :                 glBegin(GL_LINES);
     271            0 :                 glVertex2d(-1.0, -2);
     272            0 :                 glVertex2d(1.0, 2);
     273            0 :                 glEnd();
     274              :             }
     275              :         }
     276        33193 :         GLHelper::popMatrix();
     277              :     }
     278        33207 :     drawName(getCenteringBoundary().getCenter(), s.scale, s.addName);
     279        33207 :     GLHelper::popName();
     280              : }
     281              : 
     282              : 
     283              : void
     284        33207 : GUIInductLoop::MyWrapper::setOutlineColor() const {
     285        33207 :     if (haveOverride()) {
     286            0 :         glColor3d(1, 0, 1);
     287        33207 :     } else if (mySpecialColor == nullptr) {
     288        33207 :         glColor3d(1, 1, 1);
     289              :     } else {
     290            0 :         GLHelper::setColor(*mySpecialColor);
     291              :     }
     292        33207 : }
     293              : 
     294              : bool
     295        33207 : GUIInductLoop::MyWrapper::haveOverride() const {
     296        33207 :     return myDetector.getOverrideTime() >= 0;
     297              : }
     298              : 
     299              : 
     300              : void
     301            0 : GUIInductLoop::MyWrapper::toggleOverride() const {
     302            0 :     if (haveOverride()) {
     303            0 :         myDetector.overrideTimeSinceDetection(-1);
     304              :     } else {
     305            0 :         myDetector.overrideTimeSinceDetection(0);
     306              :     }
     307            0 : }
     308              : 
     309              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1