LCOV - code coverage report
Current view: top level - src/utils/shapes - ShapeContainer.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 91 94 96.8 %
Date: 2024-05-05 15:31:14 Functions: 21 21 100.0 %

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2002-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    ShapeContainer.cpp
      15             : /// @author  Daniel Krajzewicz
      16             : /// @author  Sascha Krieg
      17             : /// @author  Michael Behrisch
      18             : /// @author  Jakob Erdmann
      19             : /// @date    Sept 2002
      20             : ///
      21             : // Storage for geometrical objects, sorted by the layers they are in
      22             : /****************************************************************************/
      23             : #include <config.h>
      24             : 
      25             : #include <fstream>
      26             : #include <stdlib.h>
      27             : #include <iostream>
      28             : #include <utility>
      29             : #include <string>
      30             : #include <cmath>
      31             : #include <utils/common/NamedObjectCont.h>
      32             : #include <utils/common/MsgHandler.h>
      33             : #include <utils/common/UtilExceptions.h>
      34             : #include <utils/common/ToString.h>
      35             : #include <utils/common/StdDefs.h>
      36             : #include <utils/common/ParametrisedWrappingCommand.h>
      37             : #include "PolygonDynamics.h"
      38             : #include "ShapeContainer.h"
      39             : 
      40             : 
      41             : // Debug defines
      42             : //#define DEBUG_DYNAMIC_SHAPES
      43             : 
      44             : // ===========================================================================
      45             : // method definitions
      46             : // ===========================================================================
      47       37839 : ShapeContainer::ShapeContainer() {}
      48             : 
      49       65043 : ShapeContainer::~ShapeContainer() {
      50       37330 :     for (auto& p : myPolygonUpdateCommands) {
      51           6 :         p.second->deschedule();
      52             :     }
      53             :     myPolygonUpdateCommands.clear();
      54             : 
      55       37330 :     for (auto& p : myPolygonDynamics) {
      56           6 :         delete p.second;
      57             :     }
      58             :     myPolygonDynamics.clear();
      59             : 
      60      102367 : }
      61             : 
      62             : bool
      63       10950 : ShapeContainer::addPolygon(const std::string& id, const std::string& type,
      64             :                            const RGBColor& color, double layer,
      65             :                            double angle, const std::string& imgFile, bool relativePath,
      66             :                            const PositionVector& shape, bool geo, bool fill, double lineWidth, bool ignorePruning,
      67             :                            const std::string& name) {
      68       10950 :     return add(new SUMOPolygon(id, type, color, shape, geo, fill, lineWidth, layer, angle, imgFile, relativePath, name), ignorePruning);
      69             : }
      70             : 
      71             : 
      72             : PolygonDynamics*
      73         196 : ShapeContainer::addPolygonDynamics(double simtime,
      74             :                                    std::string polyID,
      75             :                                    SUMOTrafficObject* trackedObject,
      76             :                                    const std::vector<double>& timeSpan,
      77             :                                    const std::vector<double>& alphaSpan,
      78             :                                    bool looped,
      79             :                                    bool rotate) {
      80             : 
      81             : #ifdef DEBUG_DYNAMIC_SHAPES
      82             :     std::cout << simtime << " ShapeContainer::addPolygonDynamics() called for polygon '" << polyID << "'" << std::endl;
      83             : #endif
      84             : 
      85         196 :     SUMOPolygon* p = myPolygons.get(polyID);
      86         196 :     if (p == nullptr) {
      87             : #ifdef DEBUG_DYNAMIC_SHAPES
      88             :         std::cout << "   polygon '" << polyID << "' doesn't exist!" << std::endl;
      89             : #endif
      90             :         return nullptr;
      91             :     }
      92             :     // remove eventually existent previously
      93         196 :     removePolygonDynamics(polyID);
      94             : 
      95             :     // Add new dynamics
      96         196 :     PolygonDynamics* pd = new PolygonDynamics(simtime, p, trackedObject, timeSpan, alphaSpan, looped, rotate);
      97         196 :     myPolygonDynamics.insert(std::make_pair(polyID, pd));
      98             : 
      99             :     // Add tracking information
     100         196 :     if (trackedObject != nullptr) {
     101             :         auto i = myTrackingPolygons.find(pd->getTrackedObjectID());
     102         140 :         if (i == myTrackingPolygons.end()) {
     103         100 :             myTrackingPolygons.insert(std::make_pair(pd->getTrackedObjectID(), std::set<const SUMOPolygon*>({p})));
     104             :         } else {
     105             :             i->second.insert(p);
     106             :         }
     107             :     }
     108             :     return pd;
     109             : }
     110             : 
     111             : 
     112             : bool
     113         370 : ShapeContainer::removePolygonDynamics(const std::string& polyID) {
     114         370 :     SUMOPolygon* p = myPolygons.get(polyID);
     115         370 :     if (p == nullptr) {
     116             :         return false;
     117             :     }
     118             :     auto d = myPolygonDynamics.find(polyID);
     119         369 :     if (d != myPolygonDynamics.end()) {
     120             : #ifdef DEBUG_DYNAMIC_SHAPES
     121             :         std::cout << "   Removing dynamics of polygon '" << polyID << "'" << std::endl;
     122             : #endif
     123         190 :         const std::string& trackedObjID = d->second->getTrackedObjectID();
     124         190 :         if (trackedObjID != "") {
     125             :             // Remove tracking information
     126             :             auto i = myTrackingPolygons.find(trackedObjID);
     127             :             assert(i != myTrackingPolygons.end());
     128             :             assert(i->second.find(p) != i->second.end());
     129             :             i->second.erase(p);
     130             :             // Remove highlighting information
     131         140 :             clearHighlights(trackedObjID, p);
     132             :         }
     133         190 :         delete d->second;
     134             :         myPolygonDynamics.erase(d);
     135             :         // Clear existing polygon dynamics commands before adding new dynamics
     136         190 :         cleanupPolygonDynamics(polyID);
     137         190 :         return true;
     138             :     } else {
     139             :         return false;
     140             :     }
     141             : }
     142             : 
     143             : 
     144             : bool
     145       12156 : ShapeContainer::addPOI(const std::string& id, const std::string& type, const RGBColor& color, const Position& pos, bool geo,
     146             :                        const std::string& lane, double posOverLane, bool friendlyPos, double posLat, const std::string& icon, double layer,
     147             :                        double angle, const std::string& imgFile, bool relativePath, double width, double height, bool ignorePruning) {
     148       12156 :     return add(new PointOfInterest(id, type, color, pos, geo, lane, posOverLane, friendlyPos, posLat, icon, layer, angle, imgFile, relativePath, width, height), ignorePruning);
     149             : }
     150             : 
     151             : 
     152             : bool
     153         174 : ShapeContainer::removePolygon(const std::string& id, bool /* useLock */) {
     154             : #ifdef DEBUG_DYNAMIC_SHAPES
     155             :     std::cout << "ShapeContainer: Removing Polygon '" << id << "'" << std::endl;
     156             : #endif
     157         174 :     removePolygonDynamics(id);
     158         174 :     return myPolygons.remove(id);
     159             : }
     160             : 
     161             : 
     162             : bool
     163          12 : ShapeContainer::removePOI(const std::string& id) {
     164          12 :     return myPOIs.remove(id);
     165             : }
     166             : 
     167             : 
     168             : void
     169           6 : ShapeContainer::movePOI(const std::string& id, const Position& pos) {
     170             :     PointOfInterest* p = myPOIs.get(id);
     171           6 :     if (p != nullptr) {
     172           6 :         static_cast<Position*>(p)->set(pos);
     173             :     }
     174           6 : }
     175             : 
     176             : 
     177             : void
     178           7 : ShapeContainer::reshapePolygon(const std::string& id, const PositionVector& shape) {
     179             :     SUMOPolygon* p = myPolygons.get(id);
     180           7 :     if (p != nullptr) {
     181           7 :         p->setShape(shape);
     182             :     }
     183           7 : }
     184             : 
     185             : 
     186             : bool
     187       17008 : ShapeContainer::add(SUMOPolygon* poly, bool /* ignorePruning */) {
     188       17008 :     if (!myPolygons.add(poly->getID(), poly)) {
     189           0 :         delete poly;
     190           0 :         return false;
     191             :     }
     192             :     return true;
     193             : }
     194             : 
     195             : 
     196             : bool
     197       17658 : ShapeContainer::add(PointOfInterest* poi, bool /* ignorePruning */) {
     198       17658 :     if (!myPOIs.add(poi->getID(), poi)) {
     199           1 :         delete poi;
     200           1 :         return false;
     201             :     }
     202             :     return true;
     203             : }
     204             : 
     205             : void
     206         222 : ShapeContainer::clearState() {
     207         222 :     for (auto& item : myPolygonUpdateCommands) {
     208           0 :         item.second->deschedule();
     209             :     }
     210             :     myPolygonUpdateCommands.clear();
     211             : }
     212             : 
     213             : void
     214         190 : ShapeContainer::cleanupPolygonDynamics(const std::string& id) {
     215             :     auto j = myPolygonUpdateCommands.find(id);
     216         190 :     if (j != myPolygonUpdateCommands.end()) {
     217         190 :         j->second->deschedule();
     218             :         myPolygonUpdateCommands.erase(j);
     219             :     }
     220         190 : }
     221             : 
     222             : 
     223             : SUMOTime
     224        4386 : ShapeContainer::polygonDynamicsUpdate(SUMOTime t, PolygonDynamics* pd) {
     225        4386 :     SUMOTime next = pd->update(t);
     226        4386 :     if (next == 0) {
     227             :         // Dynamics have expired => remove polygon
     228         106 :         myPolygonUpdateCommands[pd->getPolygonID()]->deschedule();
     229             :         // Don't aquire lock (in GUI case GUIShapeContainer::polygonDynamicsUpdate() does this)
     230         106 :         removePolygon(pd->getPolygonID(), false);
     231             :     }
     232        4386 :     return next;
     233             : }
     234             : 
     235             : void
     236          86 : ShapeContainer::registerHighlight(const std::string& objectID, const int type, const std::string& polygonID) {
     237          86 :     std::string toRemove = "";
     238          86 :     clearHighlight(objectID, type, toRemove);
     239          86 :     if (toRemove != "") {
     240          14 :         removePolygon(toRemove);
     241             :     }
     242             :     auto i = myHighlightPolygons.find(objectID);
     243          86 :     if (i == myHighlightPolygons.end()) {
     244         240 :         myHighlightPolygons.insert(std::make_pair(objectID, std::map<int, std::string>({std::make_pair(type, polygonID)})));
     245             :     } else {
     246           6 :         i->second.insert(std::make_pair(type, polygonID));
     247             :     }
     248          86 :     myHighlightedObjects.insert(std::make_pair(polygonID, objectID));
     249          86 : }
     250             : 
     251             : void
     252          86 : ShapeContainer::clearHighlight(const std::string& objectID, const int type, std::string& toRemove) {
     253             :     auto i = myHighlightPolygons.find(objectID);
     254          86 :     if (i != myHighlightPolygons.end()) {
     255             :         auto j = i->second.find(type);
     256          20 :         if (j != i->second.end()) {
     257          14 :             toRemove = j->second;
     258             :             myHighlightedObjects.erase(toRemove);
     259             :             i->second.erase(j);
     260          14 :             if (i->second.empty()) {
     261             :                 myHighlightPolygons.erase(i);
     262             :             }
     263             :         }
     264             :     }
     265          86 : }
     266             : 
     267             : void
     268         140 : ShapeContainer::clearHighlights(const std::string& objectID, SUMOPolygon* p) {
     269             :     auto i = myHighlightPolygons.find(objectID);
     270         140 :     if (i != myHighlightPolygons.end()) {
     271             :         auto j = i->second.begin();
     272          98 :         while (j != i->second.end()) {
     273          69 :             if (j->second == p->getID()) {
     274             :                 i->second.erase(j);
     275             :                 break;
     276             :             } else {
     277             :                 ++j;
     278             :             }
     279             :         }
     280          69 :         if (i->second.empty()) {
     281             :             myHighlightPolygons.erase(i);
     282             :         }
     283             :     }
     284         140 : }
     285             : 
     286             : void
     287         196 : ShapeContainer::addPolygonUpdateCommand(std::string polyID, ParametrisedWrappingCommand<ShapeContainer, PolygonDynamics*>* cmd) {
     288         196 :     myPolygonUpdateCommands.insert(std::make_pair(polyID, cmd));
     289         196 : }
     290             : 
     291             : 
     292             : void
     293          40 : ShapeContainer::removeTrackers(std::string objectID) {
     294             :     auto i = myTrackingPolygons.find(objectID);
     295          40 :     if (i != myTrackingPolygons.end()) {
     296             : #ifdef DEBUG_DYNAMIC_SHAPES
     297             :         std::cout << " Removing tracking polygons for object '" << objectID << "'" << std::endl;
     298             : #endif
     299          60 :         while (!i->second.empty()) {
     300          20 :             removePolygon((*i->second.begin())->getID());
     301             :         }
     302             :         myTrackingPolygons.erase(i);
     303             :     }
     304          40 : }
     305             : 
     306             : 
     307             : /****************************************************************************/

Generated by: LCOV version 1.14