1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2002-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file ShapeContainer.cpp
11 /// @author Daniel Krajzewicz
12 /// @author Sascha Krieg
13 /// @author Michael Behrisch
14 /// @author Jakob Erdmann
15 /// @date Sept 2002
16 /// @version $Id$
17 ///
18 // Storage for geometrical objects, sorted by the layers they are in
19 /****************************************************************************/
20
21
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #include <config.h>
26
27 #include <fstream>
28 #include <stdlib.h>
29 #include <iostream>
30 #include <utility>
31 #include <string>
32 #include <cmath>
33 #include <utils/common/NamedObjectCont.h>
34 #include <utils/common/MsgHandler.h>
35 #include <utils/common/UtilExceptions.h>
36 #include <utils/common/ToString.h>
37 #include <utils/common/StdDefs.h>
38 #include <utils/common/ParametrisedWrappingCommand.h>
39 #include "PolygonDynamics.h"
40 #include "ShapeContainer.h"
41
42
43 // Debug defines
44 //#define DEBUG_DYNAMIC_SHAPES
45
46 // ===========================================================================
47 // method definitions
48 // ===========================================================================
ShapeContainer()49 ShapeContainer::ShapeContainer() {}
50
~ShapeContainer()51 ShapeContainer::~ShapeContainer() {
52 for (auto& p : myPolygonUpdateCommands) {
53 p.second->deschedule();
54 }
55 myPolygonUpdateCommands.clear();
56
57 for (auto& p : myPolygonDynamics) {
58 delete p.second;
59 }
60 myPolygonDynamics.clear();
61
62 }
63
64 bool
addPolygon(const std::string & id,const std::string & type,const RGBColor & color,double layer,double angle,const std::string & imgFile,bool relativePath,const PositionVector & shape,bool geo,bool fill,double lineWidth,bool ignorePruning)65 ShapeContainer::addPolygon(const std::string& id, const std::string& type,
66 const RGBColor& color, double layer,
67 double angle, const std::string& imgFile, bool relativePath,
68 const PositionVector& shape, bool geo, bool fill, double lineWidth, bool ignorePruning) {
69 return add(new SUMOPolygon(id, type, color, shape, geo, fill, lineWidth, layer, angle, imgFile, relativePath), ignorePruning);
70 }
71
72
73 PolygonDynamics*
addPolygonDynamics(double simtime,std::string polyID,SUMOTrafficObject * trackedObject,const std::vector<double> & timeSpan,const std::vector<double> & alphaSpan,bool looped,bool rotate)74 ShapeContainer::addPolygonDynamics(double simtime,
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 assigne dynamics
94 removePolygonDynamics(polyID);
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
113 bool
removePolygonDynamics(const std::string & polyID)114 ShapeContainer::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);
133 }
134 delete d->second;
135 myPolygonDynamics.erase(d);
136 // Clear existing polygon dynamics commands before adding new dynamics
137 cleanupPolygonDynamics(polyID);
138 return true;
139 } else {
140 return false;
141 }
142 }
143
144
145 bool
addPOI(const std::string & id,const std::string & type,const RGBColor & color,const Position & pos,bool geo,const std::string & lane,double posOverLane,double posLat,double layer,double angle,const std::string & imgFile,bool relativePath,double width,double height,bool ignorePruning)146 ShapeContainer::addPOI(const std::string& id, const std::string& type, const RGBColor& color, const Position& pos, bool geo,
147 const std::string& lane, double posOverLane, double posLat, double layer, double angle,
148 const std::string& imgFile, bool relativePath, double width, double height, bool ignorePruning) {
149 return add(new PointOfInterest(id, type, color, pos, geo, lane, posOverLane, posLat, layer, angle, imgFile, relativePath, width, height), ignorePruning);
150 }
151
152
153 bool
removePolygon(const std::string & id,bool)154 ShapeContainer::removePolygon(const std::string& id, bool /* useLock */) {
155 #ifdef DEBUG_DYNAMIC_SHAPES
156 std::cout << "ShapeContainer: Removing Polygon '" << id << "'" << std::endl;
157 #endif
158 removePolygonDynamics(id);
159 return myPolygons.remove(id);
160 }
161
162
163 bool
removePOI(const std::string & id)164 ShapeContainer::removePOI(const std::string& id) {
165 return myPOIs.remove(id);
166 }
167
168
169 void
movePOI(const std::string & id,const Position & pos)170 ShapeContainer::movePOI(const std::string& id, const Position& pos) {
171 PointOfInterest* p = myPOIs.get(id);
172 if (p != nullptr) {
173 static_cast<Position*>(p)->set(pos);
174 }
175 }
176
177
178 void
reshapePolygon(const std::string & id,const PositionVector & shape)179 ShapeContainer::reshapePolygon(const std::string& id, const PositionVector& shape) {
180 SUMOPolygon* p = myPolygons.get(id);
181 if (p != nullptr) {
182 p->setShape(shape);
183 }
184 }
185
186
187 bool
add(SUMOPolygon * poly,bool)188 ShapeContainer::add(SUMOPolygon* poly, bool /* ignorePruning */) {
189 if (!myPolygons.add(poly->getID(), poly)) {
190 delete poly;
191 return false;
192 }
193 return true;
194 }
195
196
197 bool
add(PointOfInterest * poi,bool)198 ShapeContainer::add(PointOfInterest* poi, bool /* ignorePruning */) {
199 if (!myPOIs.add(poi->getID(), poi)) {
200 delete poi;
201 return false;
202 }
203 return true;
204 }
205
206
207 void
cleanupPolygonDynamics(const std::string & id)208 ShapeContainer::cleanupPolygonDynamics(const std::string& id) {
209 auto j = myPolygonUpdateCommands.find(id);
210 if (j != myPolygonUpdateCommands.end()) {
211 j->second->deschedule();
212 myPolygonUpdateCommands.erase(j);
213 }
214 }
215
216
217 SUMOTime
polygonDynamicsUpdate(SUMOTime t,PolygonDynamics * pd)218 ShapeContainer::polygonDynamicsUpdate(SUMOTime t, PolygonDynamics* pd) {
219 SUMOTime next = pd->update(t);
220 if (next == 0) {
221 // Dynamics have expired => remove polygon
222 myPolygonUpdateCommands[pd->getPolygonID()]->deschedule();
223 // Don't aquire lock (in GUI case GUIShapeContainer::polygonDynamicsUpdate() does this)
224 removePolygon(pd->getPolygonID(), false);
225 }
226 return next;
227 }
228
229 void
registerHighlight(const std::string & objectID,const int type,const std::string & polygonID)230 ShapeContainer::registerHighlight(const std::string& objectID, const int type, const std::string& polygonID) {
231 std::string toRemove = "";
232 clearHighlight(objectID, type, toRemove);
233 if (toRemove != "") {
234 removePolygon(toRemove);
235 }
236 auto i = myHighlightPolygons.find(objectID);
237 if (i == myHighlightPolygons.end()) {
238 myHighlightPolygons.insert(std::make_pair(objectID, std::map<int, std::string>({std::make_pair(type, polygonID)})));
239 } else {
240 i->second.insert(std::make_pair(type, polygonID));
241 }
242 myHighlightedObjects.insert(std::make_pair(polygonID, objectID));
243 }
244
245 void
clearHighlight(const std::string & objectID,const int type,std::string & toRemove)246 ShapeContainer::clearHighlight(const std::string& objectID, const int type, std::string& toRemove) {
247 auto i = myHighlightPolygons.find(objectID);
248 if (i != myHighlightPolygons.end()) {
249 auto j = i->second.find(type);
250 if (j != i->second.end()) {
251 toRemove = j->second;
252 myHighlightedObjects.erase(toRemove);
253 i->second.erase(j);
254 if (i->second.empty()) {
255 myHighlightPolygons.erase(i);
256 }
257 }
258 }
259 }
260
261 void
clearHighlights(const std::string & objectID)262 ShapeContainer::clearHighlights(const std::string& objectID) {
263 auto i = myHighlightPolygons.find(objectID);
264 if (i != myHighlightPolygons.end()) {
265 myHighlightPolygons.erase(i);
266 }
267 }
268
269 void
addPolygonUpdateCommand(std::string polyID,ParametrisedWrappingCommand<ShapeContainer,PolygonDynamics * > * cmd)270 ShapeContainer::addPolygonUpdateCommand(std::string polyID, ParametrisedWrappingCommand<ShapeContainer, PolygonDynamics*>* cmd) {
271 myPolygonUpdateCommands.insert(std::make_pair(polyID, cmd));
272 }
273
274
275 void
removeTrackers(std::string objectID)276 ShapeContainer::removeTrackers(std::string objectID) {
277 auto i = myTrackingPolygons.find(objectID);
278 if (i != myTrackingPolygons.end()) {
279 #ifdef DEBUG_DYNAMIC_SHAPES
280 std::cout << " Removing tracking polygons for object '" << objectID << "'" << std::endl;
281 #endif
282 for (const SUMOPolygon* p : i->second) {
283 removePolygon(p->getID());
284 }
285 myTrackingPolygons.erase(i);
286 }
287 }
288
289 /****************************************************************************/
290
291