Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/utils/shapes/ShapeContainer.cpp
169678 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2002-2025 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
38
#include "PolygonDynamics.h"
39
#include "ShapeContainer.h"
40
41
// Debug defines
42
//#define DEBUG_DYNAMIC_SHAPES
43
44
// ===========================================================================
45
// method definitions
46
// ===========================================================================
47
48
ShapeContainer::ShapeContainer() {}
49
50
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
65
bool
66
ShapeContainer::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
73
PolygonDynamics*
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
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
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, p);
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
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, 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
153
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
164
ShapeContainer::removePOI(const std::string& id) {
165
return myPOIs.remove(id);
166
}
167
168
169
void
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
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
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
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
void
207
ShapeContainer::clearState() {
208
for (auto& item : myPolygonUpdateCommands) {
209
item.second->deschedule();
210
}
211
myPolygonUpdateCommands.clear();
212
}
213
214
void
215
ShapeContainer::cleanupPolygonDynamics(const std::string& id) {
216
auto j = myPolygonUpdateCommands.find(id);
217
if (j != myPolygonUpdateCommands.end()) {
218
j->second->deschedule();
219
myPolygonUpdateCommands.erase(j);
220
}
221
}
222
223
224
SUMOTime
225
ShapeContainer::polygonDynamicsUpdate(SUMOTime t, PolygonDynamics* pd) {
226
SUMOTime next = pd->update(t);
227
if (next == 0) {
228
// Dynamics have expired => remove polygon
229
myPolygonUpdateCommands[pd->getPolygonID()]->deschedule();
230
// Don't aquire lock (in GUI case GUIShapeContainer::polygonDynamicsUpdate() does this)
231
removePolygon(pd->getPolygonID(), false);
232
}
233
return next;
234
}
235
236
void
237
ShapeContainer::registerHighlight(const std::string& objectID, const int type, const std::string& polygonID) {
238
std::string toRemove = "";
239
clearHighlight(objectID, type, toRemove);
240
if (toRemove != "") {
241
removePolygon(toRemove);
242
}
243
auto i = myHighlightPolygons.find(objectID);
244
if (i == myHighlightPolygons.end()) {
245
myHighlightPolygons.insert(std::make_pair(objectID, std::map<int, std::string>({std::make_pair(type, polygonID)})));
246
} else {
247
i->second.insert(std::make_pair(type, polygonID));
248
}
249
myHighlightedObjects.insert(std::make_pair(polygonID, objectID));
250
}
251
252
void
253
ShapeContainer::clearHighlight(const std::string& objectID, const int type, std::string& toRemove) {
254
auto i = myHighlightPolygons.find(objectID);
255
if (i != myHighlightPolygons.end()) {
256
auto j = i->second.find(type);
257
if (j != i->second.end()) {
258
toRemove = j->second;
259
myHighlightedObjects.erase(toRemove);
260
i->second.erase(j);
261
if (i->second.empty()) {
262
myHighlightPolygons.erase(i);
263
}
264
}
265
}
266
}
267
268
void
269
ShapeContainer::clearHighlights(const std::string& objectID, SUMOPolygon* p) {
270
auto i = myHighlightPolygons.find(objectID);
271
if (i != myHighlightPolygons.end()) {
272
auto j = i->second.begin();
273
while (j != i->second.end()) {
274
if (j->second == p->getID()) {
275
i->second.erase(j);
276
break;
277
} else {
278
++j;
279
}
280
}
281
if (i->second.empty()) {
282
myHighlightPolygons.erase(i);
283
}
284
}
285
}
286
287
void
288
ShapeContainer::addPolygonUpdateCommand(std::string polyID, ParametrisedWrappingCommand<ShapeContainer, PolygonDynamics*>* cmd) {
289
myPolygonUpdateCommands.insert(std::make_pair(polyID, cmd));
290
}
291
292
293
void
294
ShapeContainer::removeTrackers(std::string objectID) {
295
auto i = myTrackingPolygons.find(objectID);
296
if (i != myTrackingPolygons.end()) {
297
#ifdef DEBUG_DYNAMIC_SHAPES
298
std::cout << " Removing tracking polygons for object '" << objectID << "'" << std::endl;
299
#endif
300
while (!i->second.empty()) {
301
removePolygon((*i->second.begin())->getID());
302
}
303
myTrackingPolygons.erase(i);
304
}
305
}
306
307
308
/****************************************************************************/
309
310