Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
ShapeContainer.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2002-2026 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/****************************************************************************/
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>
37
38#include "PolygonDynamics.h"
39#include "ShapeContainer.h"
40
41// Debug defines
42//#define DEBUG_DYNAMIC_SHAPES
43
44// ===========================================================================
45// method definitions
46// ===========================================================================
47
49
50
52 for (auto& p : myPolygonUpdateCommands) {
53 p.second->deschedule();
54 }
56
57 for (auto& p : myPolygonDynamics) {
58 delete p.second;
59 }
60 myPolygonDynamics.clear();
61
62}
63
64
65bool
66ShapeContainer::addPolygon(const std::string& id, const std::string& type, const RGBColor& color,
67 double layer, double angle, const std::string& imgFile, const PositionVector& shape,
68 bool geo, bool fill, double lineWidth, bool ignorePruning, const std::string& name) {
69 return add(new SUMOPolygon(id, type, color, shape, geo, fill, lineWidth, layer, angle, imgFile, name), ignorePruning);
70}
71
72
75 std::string polyID,
76 SUMOTrafficObject* trackedObject,
77 const std::vector<double>& timeSpan,
78 const std::vector<double>& alphaSpan,
79 bool looped,
80 bool rotate) {
81
82#ifdef DEBUG_DYNAMIC_SHAPES
83 std::cout << simtime << " ShapeContainer::addPolygonDynamics() called for polygon '" << polyID << "'" << std::endl;
84#endif
85
86 SUMOPolygon* p = myPolygons.get(polyID);
87 if (p == nullptr) {
88#ifdef DEBUG_DYNAMIC_SHAPES
89 std::cout << " polygon '" << polyID << "' doesn't exist!" << std::endl;
90#endif
91 return nullptr;
92 }
93 // remove eventually existent previously
95
96 // Add new dynamics
97 PolygonDynamics* pd = new PolygonDynamics(simtime, p, trackedObject, timeSpan, alphaSpan, looped, rotate);
98 myPolygonDynamics.insert(std::make_pair(polyID, pd));
99
100 // Add tracking information
101 if (trackedObject != nullptr) {
102 auto i = myTrackingPolygons.find(pd->getTrackedObjectID());
103 if (i == myTrackingPolygons.end()) {
104 myTrackingPolygons.insert(std::make_pair(pd->getTrackedObjectID(), std::set<const SUMOPolygon*>({p})));
105 } else {
106 i->second.insert(p);
107 }
108 }
109 return pd;
110}
111
112
113bool
114ShapeContainer::removePolygonDynamics(const std::string& polyID) {
115 SUMOPolygon* p = myPolygons.get(polyID);
116 if (p == nullptr) {
117 return false;
118 }
119 auto d = myPolygonDynamics.find(polyID);
120 if (d != myPolygonDynamics.end()) {
121#ifdef DEBUG_DYNAMIC_SHAPES
122 std::cout << " Removing dynamics of polygon '" << polyID << "'" << std::endl;
123#endif
124 const std::string& trackedObjID = d->second->getTrackedObjectID();
125 if (trackedObjID != "") {
126 // Remove tracking information
127 auto i = myTrackingPolygons.find(trackedObjID);
128 assert(i != myTrackingPolygons.end());
129 assert(i->second.find(p) != i->second.end());
130 i->second.erase(p);
131 // Remove highlighting information
132 clearHighlights(trackedObjID, p);
133 }
134 delete d->second;
135 myPolygonDynamics.erase(d);
136 // Clear existing polygon dynamics commands before adding new dynamics
138 return true;
139 } else {
140 return false;
141 }
142}
143
144
145bool
146ShapeContainer::addPOI(const std::string& id, const std::string& type, const RGBColor& color, const Position& pos, bool geo,
147 const std::string& lane, double posOverLane, bool friendlyPos, double posLat, const std::string& icon, double layer,
148 double angle, const std::string& imgFile, double width, double height, bool ignorePruning) {
149 return add(new PointOfInterest(id, type, color, pos, geo, lane, posOverLane, friendlyPos, posLat, icon, layer, angle, imgFile, width, height), ignorePruning);
150}
151
152
153bool
154ShapeContainer::removePolygon(const std::string& id, bool /* useLock */) {
155#ifdef DEBUG_DYNAMIC_SHAPES
156 std::cout << "ShapeContainer: Removing Polygon '" << id << "'" << std::endl;
157#endif
159 SUMOPolygon* p = myPolygons.get(id);
160 if (p != nullptr) {
161 for (ShapeListener* listener : myListeners) {
162 listener->polygonChanged(p, false, true);
163 }
164 }
165 return myPolygons.remove(id);
166}
167
168
169bool
170ShapeContainer::removePOI(const std::string& id) {
171 PointOfInterest* p = myPOIs.get(id);
172 if (p != nullptr) {
173 for (ShapeListener* listener : myListeners) {
174 listener->poiChanged(p, false, true);
175 }
176 }
177 return myPOIs.remove(id);
178}
179
180
181void
182ShapeContainer::movePOI(const std::string& id, const Position& pos) {
183 PointOfInterest* p = myPOIs.get(id);
184 if (p != nullptr) {
185 static_cast<Position*>(p)->set(pos);
186 for (ShapeListener* listener : myListeners) {
187 listener->poiChanged(p, false, false);
188 }
189 }
190}
191
192
193void
194ShapeContainer::reshapePolygon(const std::string& id, const PositionVector& shape) {
195 SUMOPolygon* p = myPolygons.get(id);
196 if (p != nullptr) {
197 p->setShape(shape);
198 for (ShapeListener* listener : myListeners) {
199 listener->polygonChanged(p, false, false);
200 }
201 }
202}
203
204
205bool
206ShapeContainer::add(SUMOPolygon* poly, bool /* ignorePruning */) {
207 if (!myPolygons.add(poly->getID(), poly)) {
208 delete poly;
209 return false;
210 }
211 for (ShapeListener* listener : myListeners) {
212 listener->polygonChanged(poly, true, false);
213 }
214 return true;
215}
216
217
218bool
219ShapeContainer::add(PointOfInterest* poi, bool /* ignorePruning */) {
220 if (!myPOIs.add(poi->getID(), poi)) {
221 delete poi;
222 return false;
223 }
224 for (ShapeListener* listener : myListeners) {
225 listener->poiChanged(poi, true, false);
226 }
227 return true;
228}
229
230void
232 for (auto& item : myPolygonUpdateCommands) {
233 item.second->deschedule();
234 }
236}
237
238void
240 auto j = myPolygonUpdateCommands.find(id);
241 if (j != myPolygonUpdateCommands.end()) {
242 j->second->deschedule();
244 }
245}
246
247
250 SUMOTime next = pd->update(t);
251 if (next == 0) {
252 // Dynamics have expired => remove polygon
253 myPolygonUpdateCommands[pd->getPolygonID()]->deschedule();
254 // Don't aquire lock (in GUI case GUIShapeContainer::polygonDynamicsUpdate() does this)
255 removePolygon(pd->getPolygonID(), false);
256 }
257 return next;
258}
259
260void
261ShapeContainer::registerHighlight(const std::string& objectID, const int type, const std::string& polygonID) {
262 std::string toRemove = "";
263 clearHighlight(objectID, type, toRemove);
264 if (toRemove != "") {
265 removePolygon(toRemove);
266 }
267 auto i = myHighlightPolygons.find(objectID);
268 if (i == myHighlightPolygons.end()) {
269 myHighlightPolygons.insert(std::make_pair(objectID, std::map<int, std::string>({std::make_pair(type, polygonID)})));
270 } else {
271 i->second.insert(std::make_pair(type, polygonID));
272 }
273 myHighlightedObjects.insert(std::make_pair(polygonID, objectID));
274}
275
276void
277ShapeContainer::clearHighlight(const std::string& objectID, const int type, std::string& toRemove) {
278 auto i = myHighlightPolygons.find(objectID);
279 if (i != myHighlightPolygons.end()) {
280 auto j = i->second.find(type);
281 if (j != i->second.end()) {
282 toRemove = j->second;
283 myHighlightedObjects.erase(toRemove);
284 i->second.erase(j);
285 if (i->second.empty()) {
286 myHighlightPolygons.erase(i);
287 }
288 }
289 }
290}
291
292void
293ShapeContainer::clearHighlights(const std::string& objectID, SUMOPolygon* p) {
294 auto i = myHighlightPolygons.find(objectID);
295 if (i != myHighlightPolygons.end()) {
296 auto j = i->second.begin();
297 while (j != i->second.end()) {
298 if (j->second == p->getID()) {
299 i->second.erase(j);
300 break;
301 } else {
302 ++j;
303 }
304 }
305 if (i->second.empty()) {
306 myHighlightPolygons.erase(i);
307 }
308 }
309}
310
311void
315
316
317void
318ShapeContainer::removeTrackers(std::string objectID) {
319 auto i = myTrackingPolygons.find(objectID);
320 if (i != myTrackingPolygons.end()) {
321#ifdef DEBUG_DYNAMIC_SHAPES
322 std::cout << " Removing tracking polygons for object '" << objectID << "'" << std::endl;
323#endif
324 while (!i->second.empty()) {
325 removePolygon((*i->second.begin())->getID());
326 }
327 myTrackingPolygons.erase(i);
328 }
329}
330
331
332/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
const std::string & getID() const
Returns the id.
Definition Named.h:74
T get(const std::string &id) const
Retrieves an item.
bool remove(const std::string &id, const bool del=true)
Removes an item.
bool add(const std::string &id, T item)
Adds an item.
A wrapper for a Command function with parameter.
A point-of-interest.
const std::string & getTrackedObjectID() const
SUMOTime update(SUMOTime t)
Updates the polygon according to its timeSpan and follows the tracked object.
const std::string & getPolygonID() const
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
A list of positions.
virtual void setShape(const PositionVector &shape)
Sets the shape of the polygon.
Representation of a vehicle, person, or container.
virtual bool removePolygonDynamics(const std::string &polyID)
Remove dynamics (animation / tracking) for the given polygon.
virtual void clearHighlight(const std::string &objectID, const int type, std::string &toRemove)
virtual void cleanupPolygonDynamics(const std::string &id)
Unschedules the removal and update commands of the given polygon.
virtual bool removePOI(const std::string &id)
Removes a PoI from the container.
virtual SUMOTime polygonDynamicsUpdate(SUMOTime t, PolygonDynamics *pd)
Regular update event for updating polygon dynamics.
virtual void reshapePolygon(const std::string &id, const PositionVector &shape)
Assigns a shape to the named polygon.
std::map< std::string, std::map< int, std::string > > myHighlightPolygons
maps objects to a map of highlight types to highlighting polygons
std::map< std::string, PolygonDynamics * > myPolygonDynamics
stored PolygonDynamics
virtual bool removePolygon(const std::string &id, bool useLock=true)
Removes a polygon from the container.
virtual void removeTrackers(std::string objectID)
Remove all tracking polygons for the given object.
virtual void movePOI(const std::string &id, const Position &pos)
Assigns a new position to the named PoI.
std::map< const std::string, ParametrisedWrappingCommand< ShapeContainer, PolygonDynamics * > * > myPolygonUpdateCommands
Command pointers for scheduled polygon update. Maps PolyID->Command.
virtual ~ShapeContainer()
Destructor.
POIs myPOIs
stored POIs
std::map< std::string, std::string > myHighlightedObjects
inverse map to myHighlightPolygons saves the highlighted object for each polygon
std::vector< ShapeListener * > myListeners
std::map< const std::string, std::set< const SUMOPolygon * > > myTrackingPolygons
Information about tracked objects.
virtual PolygonDynamics * addPolygonDynamics(double simtime, std::string polyID, SUMOTrafficObject *trackedObject, const std::vector< double > &timeSpan, const std::vector< double > &alphaSpan, bool looped, bool rotate)
Adds dynamics (animation / tracking) to the given polygon.
ShapeContainer()
Constructor.
virtual void addPolygonUpdateCommand(std::string polyID, ParametrisedWrappingCommand< ShapeContainer, PolygonDynamics * > *cmd)
Register update command (for descheduling at removal)
virtual bool add(SUMOPolygon *poly, bool ignorePruning=false)
add polygon
virtual void clearHighlights(const std::string &objectID, SUMOPolygon *p)
Clears all highlight information from the maps when the object leaves the net (Highlight polygons and...
virtual void registerHighlight(const std::string &objectID, const int type, const std::string &polygonID)
register highlight of the specified type if the given id
virtual bool addPOI(const std::string &id, const std::string &type, const RGBColor &color, const Position &pos, bool geo, const std::string &lane, double posOverLane, bool friendlyPos, double posLat, const std::string &icon, double layer, double angle, const std::string &imgFile, double width, double height, bool ignorePruning=false)
Builds a POI using the given values and adds it to the container.
void clearState()
Remove all dynamics before quick-loading state.
Polygons myPolygons
stored Polygons
virtual bool addPolygon(const std::string &id, const std::string &type, const RGBColor &color, double layer, double angle, const std::string &imgFile, const PositionVector &shape, bool geo, bool fill, double lineWidth, bool ignorePruning=false, const std::string &name=Shape::DEFAULT_NAME)
Builds a polygon using the given values and adds it to the container.
Interface for objects which want to be notified about shape updates.