LCOV - code coverage report
Current view: top level - src/libsumo - Polygon.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 94.4 % 161 152
Test Date: 2024-12-21 15:45:41 Functions: 88.9 % 36 32

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2017-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    Polygon.cpp
      15              : /// @author  Gregor Laemmel
      16              : /// @date    15.03.2017
      17              : ///
      18              : // C++ TraCI client API implementation
      19              : /****************************************************************************/
      20              : #include <microsim/MSNet.h>
      21              : #include <microsim/MSEventControl.h>
      22              : #include <microsim/MSVehicleControl.h>
      23              : #include <microsim/transportables/MSTransportableControl.h>
      24              : #include <microsim/MSDynamicShapeUpdater.h>
      25              : #include <libsumo/TraCIConstants.h>
      26              : #include <utils/shapes/SUMOPolygon.h>
      27              : #include <utils/shapes/PolygonDynamics.h>
      28              : #include <utils/shapes/ShapeContainer.h>
      29              : #include <utils/common/ParametrisedWrappingCommand.h>
      30              : 
      31              : #include "Polygon.h"
      32              : #include "Helper.h"
      33              : 
      34              : 
      35              : namespace libsumo {
      36              : // ===========================================================================
      37              : // static member initializations
      38              : // ===========================================================================
      39              : SubscriptionResults Polygon::mySubscriptionResults;
      40              : ContextSubscriptionResults Polygon::myContextSubscriptionResults;
      41              : NamedRTree* Polygon::myTree(nullptr);
      42              : 
      43              : 
      44              : // ===========================================================================
      45              : // static member definitions
      46              : // ===========================================================================
      47              : std::vector<std::string>
      48          533 : Polygon::getIDList() {
      49              :     std::vector<std::string> ids;
      50          533 :     MSNet::getInstance()->getShapeContainer().getPolygons().insertIDs(ids);
      51          531 :     return ids;
      52            2 : }
      53              : 
      54              : 
      55              : int
      56          136 : Polygon::getIDCount() {
      57          136 :     return (int)getIDList().size();
      58              : }
      59              : 
      60              : 
      61              : std::string
      62          101 : Polygon::getType(const std::string& polygonID) {
      63          101 :     return getPolygon(polygonID)->getShapeType();
      64              : }
      65              : 
      66              : 
      67              : TraCIPositionVector
      68         8116 : Polygon::getShape(const std::string& polygonID) {
      69         8116 :     SUMOPolygon* p = getPolygon(polygonID);
      70         8116 :     return Helper::makeTraCIPositionVector(p->getShape());
      71              : }
      72              : 
      73              : 
      74              : bool
      75          101 : Polygon::getFilled(const std::string& polygonID) {
      76          101 :     return getPolygon(polygonID)->getFill();
      77              : }
      78              : 
      79              : double
      80           11 : Polygon::getLineWidth(const std::string& polygonID) {
      81           11 :     return getPolygon(polygonID)->getLineWidth();
      82              : }
      83              : 
      84              : TraCIColor
      85          109 : Polygon::getColor(const std::string& polygonID) {
      86          109 :     SUMOPolygon* p = getPolygon(polygonID);
      87          107 :     return Helper::makeTraCIColor(p->getShapeColor());
      88              : }
      89              : 
      90              : 
      91              : std::string
      92           12 : Polygon::getParameter(const std::string& polygonID, const std::string& key) {
      93           24 :     return getPolygon(polygonID)->getParameter(key, "");
      94              : }
      95              : 
      96              : 
      97            0 : LIBSUMO_GET_PARAMETER_WITH_KEY_IMPLEMENTATION(Polygon)
      98              : 
      99              : 
     100              : void
     101            7 : Polygon::setType(const std::string& polygonID, const std::string& polygonType) {
     102            7 :     getPolygon(polygonID)->setShapeType(polygonType);
     103            6 : }
     104              : 
     105              : 
     106              : void
     107            8 : Polygon::setShape(const std::string& polygonID, const TraCIPositionVector& shape) {
     108            8 :     PositionVector positionVector = Helper::makePositionVector(shape);
     109            8 :     getPolygon(polygonID); // just to check whether it exists
     110            7 :     ShapeContainer& shapeCont = MSNet::getInstance()->getShapeContainer();
     111            7 :     shapeCont.reshapePolygon(polygonID, positionVector);
     112            8 : }
     113              : 
     114              : 
     115              : void
     116           12 : Polygon::setColor(const std::string& polygonID, const TraCIColor& c) {
     117           12 :     getPolygon(polygonID)->setShapeColor(Helper::makeRGBColor(c));
     118           11 : }
     119              : 
     120              : 
     121              : void
     122          216 : Polygon::add(const std::string& polygonID, const TraCIPositionVector& shape, const TraCIColor& color, bool fill, const std::string& polygonType, int layer, double lineWidth) {
     123          216 :     ShapeContainer& shapeCont = MSNet::getInstance()->getShapeContainer();
     124          216 :     PositionVector pShape = Helper::makePositionVector(shape);
     125          214 :     RGBColor col = Helper::makeRGBColor(color);
     126          214 :     if (!shapeCont.addPolygon(polygonID, polygonType, col, (double)layer, Shape::DEFAULT_ANGLE, Shape::DEFAULT_IMG_FILE, Shape::DEFAULT_RELATIVEPATH, pShape, false, fill, lineWidth)) {
     127            0 :         throw TraCIException("Could not add polygon '" + polygonID + "'");
     128              :     }
     129          214 :     if (myTree != nullptr) {
     130              :         SUMOPolygon* p = shapeCont.getPolygons().get(polygonID);
     131            5 :         Boundary b = p->getShape().getBoxBoundary();
     132            5 :         const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
     133            5 :         const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
     134            5 :         myTree->Insert(cmin, cmax, p);
     135            5 :     }
     136          214 : }
     137              : 
     138              : 
     139              : void
     140           69 : Polygon::addHighlightPolygon(const std::string& objectID, const int type, const std::string& polygonID, const TraCIPositionVector& shape, const TraCIColor& color, bool fill, const std::string& polygonType, int layer, double lineWidth) {
     141           69 :     add(polygonID, shape, color, fill, polygonType, layer, lineWidth);
     142           69 :     MSNet::getInstance()->getShapeContainer().registerHighlight(objectID, type, polygonID);
     143           69 : }
     144              : 
     145              : 
     146              : void
     147          204 : Polygon::addDynamics(const std::string& polygonID, const std::string& trackedObjectID, const std::vector<double>& timeSpan, const std::vector<double>& alphaSpan, bool looped, bool rotate) {
     148          204 :     if (timeSpan.empty()) {
     149           63 :         if (trackedObjectID == "") {
     150           16 :             throw TraCIException("Could not add polygon dynamics for polygon '" + polygonID + "': dynamics underspecified (either a tracked object ID or a time span have to be provided).");
     151              :         }
     152           55 :         if (looped) {
     153           16 :             throw TraCIException("Could not add polygon dynamics for polygon '" + polygonID + "': looped==true requires time line of positive length.");
     154              :         }
     155              :     }
     156          188 :     if (timeSpan.size() == 1) {
     157           16 :         throw TraCIException("Could not add polygon dynamics for polygon '" + polygonID + "': time span cannot have length one.");
     158          180 :     } else if (timeSpan.size() > 0 && timeSpan[0] != 0.0) {
     159           16 :         throw TraCIException("Could not add polygon dynamics for polygon '" + polygonID + "': first element of time span must be zero.");
     160              :     }
     161          172 :     if (timeSpan.size() != alphaSpan.size() && alphaSpan.size() != 0) {
     162           16 :         throw TraCIException("Could not add polygon dynamics for polygon '" + polygonID + "': alpha span must have length zero or equal to time span length.");
     163              :     }
     164          164 :     if (timeSpan.size() >= 2) {
     165          612 :         for (unsigned int i = 1; i < timeSpan.size(); ++i) {
     166          503 :             if (timeSpan[i - 1] > timeSpan[i]) {
     167           16 :                 throw TraCIException("Could not add polygon dynamics for polygon '" + polygonID + "': entries of time span must be ordered ascendingly.");
     168              :             }
     169              :         }
     170              :     }
     171              : 
     172          156 :     SUMOTrafficObject* obj = getTrafficObject(trackedObjectID);
     173          156 :     ShapeContainer& shapeCont = MSNet::getInstance()->getShapeContainer();
     174          312 :     PolygonDynamics* pd = shapeCont.addPolygonDynamics(SIMTIME, polygonID, obj, timeSpan, alphaSpan, looped, rotate);
     175          156 :     if (pd == nullptr) {
     176            0 :         throw TraCIException("Could not add polygon dynamics for polygon '" + polygonID + "': polygon doesn't exist.");
     177              :     }
     178              :     // Ensure existence of a DynamicShapeUpdater
     179          156 :     if (MSNet::getInstance()->getDynamicShapeUpdater() == nullptr) {
     180           24 :         MSNet::VehicleStateListener* listener = dynamic_cast<MSNet::VehicleStateListener*>(MSNet::getInstance()->makeDynamicShapeUpdater());
     181           24 :         MSNet::getInstance()->addVehicleStateListener(listener);
     182              :     }
     183              : 
     184              :     // Schedule the regular polygon update
     185          156 :     auto cmd = new ParametrisedWrappingCommand<ShapeContainer, PolygonDynamics*>(&shapeCont, pd, &ShapeContainer::polygonDynamicsUpdate);
     186          312 :     shapeCont.addPolygonUpdateCommand(pd->getPolygonID(), cmd);
     187          156 :     MSNet::getInstance()->getEndOfTimestepEvents()->addEvent(cmd, SIMSTEP);
     188          156 : }
     189              : 
     190              : 
     191              : void
     192           27 : Polygon::remove(const std::string& polygonID, int /* layer */) {
     193              :     // !!! layer not used yet (shouldn't the id be enough?)
     194           27 :     ShapeContainer& shapeCont = MSNet::getInstance()->getShapeContainer();
     195           27 :     if (myTree != nullptr) {
     196              :         SUMOPolygon* p = shapeCont.getPolygons().get(polygonID);
     197            5 :         if (p != nullptr) {
     198            5 :             Boundary b = p->getShape().getBoxBoundary();
     199            5 :             const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
     200            5 :             const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
     201            5 :             myTree->Remove(cmin, cmax, p);
     202            5 :         }
     203              :     }
     204           27 :     if (!shapeCont.removePolygon(polygonID)) {
     205            2 :         throw TraCIException("Could not remove polygon '" + polygonID + "'");
     206              :     }
     207           26 : }
     208              : 
     209              : 
     210              : void
     211            7 : Polygon::setFilled(std::string polygonID, bool filled) {
     212            7 :     SUMOPolygon* p = getPolygon(polygonID);
     213            6 :     p->setFill(filled);
     214            6 : }
     215              : 
     216              : void
     217            6 : Polygon::setLineWidth(std::string polygonID, double lineWidth) {
     218            6 :     SUMOPolygon* p = getPolygon(polygonID);
     219            6 :     p->setLineWidth(lineWidth);
     220            6 : }
     221              : 
     222              : 
     223              : SUMOPolygon*
     224        24851 : Polygon::getPolygon(const std::string& id) {
     225        24851 :     SUMOPolygon* p = MSNet::getInstance()->getShapeContainer().getPolygons().get(id);
     226        24845 :     if (p == nullptr) {
     227           12 :         throw TraCIException("Polygon '" + id + "' is not known");
     228              :     }
     229        24845 :     return p;
     230              : }
     231              : 
     232              : 
     233              : SUMOTrafficObject*
     234          156 : Polygon::getTrafficObject(const std::string& id) {
     235          156 :     if (id == "") {
     236              :         return nullptr;
     237              :     }
     238          111 :     MSNet* net = MSNet::getInstance();
     239              :     // First try to find a vehicle with the given id
     240          111 :     SUMOVehicle* sumoVehicle = net->getVehicleControl().getVehicle(id);
     241          111 :     if (sumoVehicle != nullptr) {
     242              :         return static_cast<SUMOTrafficObject*>(sumoVehicle);
     243              :     }
     244            0 :     MSTransportable* transportable = net->getPersonControl().get(id);
     245            0 :     if (transportable != nullptr) {
     246              :         return static_cast<SUMOTrafficObject*>(transportable);
     247              :     } else {
     248            0 :         throw TraCIException("Traffic object '" + id + "' is not known");
     249              :     }
     250              : }
     251              : 
     252              : 
     253              : void
     254            6 : Polygon::setParameter(const std::string& polygonID, const std::string& key, const std::string& value) {
     255            6 :     SUMOPolygon* p = getPolygon(polygonID);
     256            6 :     p->setParameter(key, value);
     257            6 : }
     258              : 
     259              : 
     260         8298 : LIBSUMO_SUBSCRIPTION_IMPLEMENTATION(Polygon, POLYGON)
     261              : 
     262              : 
     263              : NamedRTree*
     264          352 : Polygon::getTree() {
     265          352 :     if (myTree == nullptr) {
     266           17 :         myTree = new NamedRTree();
     267           17 :         ShapeContainer& shapeCont = MSNet::getInstance()->getShapeContainer();
     268           58 :         for (const auto& i : shapeCont.getPolygons()) {
     269           41 :             Boundary b = i.second->getShape().getBoxBoundary();
     270           41 :             const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
     271           41 :             const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
     272           41 :             myTree->Insert(cmin, cmax, i.second);
     273           41 :         }
     274              :     }
     275          352 :     return myTree;
     276              : }
     277              : 
     278              : void
     279        40516 : Polygon::cleanup() {
     280        40516 :     delete myTree;
     281        40516 :     myTree = nullptr;
     282        40516 : }
     283              : 
     284              : void
     285        16355 : Polygon::storeShape(const std::string& id, PositionVector& shape) {
     286        16355 :     shape = getPolygon(id)->getShape();
     287        16355 : }
     288              : 
     289              : 
     290              : std::shared_ptr<VariableWrapper>
     291          264 : Polygon::makeWrapper() {
     292          264 :     return std::make_shared<Helper::SubscriptionWrapper>(handleVariable, mySubscriptionResults, myContextSubscriptionResults);
     293              : }
     294              : 
     295              : 
     296              : bool
     297         4695 : Polygon::handleVariable(const std::string& objID, const int variable, VariableWrapper* wrapper, tcpip::Storage* paramData) {
     298         4695 :     switch (variable) {
     299          253 :         case TRACI_ID_LIST:
     300          253 :             return wrapper->wrapStringList(objID, variable, getIDList());
     301          102 :         case ID_COUNT:
     302          102 :             return wrapper->wrapInt(objID, variable, getIDCount());
     303           75 :         case VAR_TYPE:
     304          150 :             return wrapper->wrapString(objID, variable, getType(objID));
     305           81 :         case VAR_COLOR:
     306           81 :             return wrapper->wrapColor(objID, variable, getColor(objID));
     307           75 :         case VAR_FILL:
     308           75 :             return wrapper->wrapInt(objID, variable, getFilled(objID));
     309            7 :         case VAR_WIDTH:
     310            7 :             return wrapper->wrapDouble(objID, variable, getLineWidth(objID));
     311         4084 :         case VAR_SHAPE:
     312         8168 :             return wrapper->wrapPositionVector(objID, variable, getShape(objID));
     313            8 :         case libsumo::VAR_PARAMETER:
     314            8 :             paramData->readUnsignedByte();
     315           16 :             return wrapper->wrapString(objID, variable, getParameter(objID, paramData->readString()));
     316            0 :         case libsumo::VAR_PARAMETER_WITH_KEY:
     317            0 :             paramData->readUnsignedByte();
     318            0 :             return wrapper->wrapStringPair(objID, variable, getParameterWithKey(objID, paramData->readString()));
     319              :         default:
     320              :             return false;
     321              :     }
     322              : }
     323              : 
     324              : 
     325              : bool
     326           85 : Polygon::exists(std::string polyID) {
     327           85 :     SUMOPolygon* p = MSNet::getInstance()->getShapeContainer().getPolygons().get(polyID);
     328           85 :     return p != nullptr;
     329              : }
     330              : }
     331              : 
     332              : 
     333              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1