Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2017-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 POI.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Mario Krumnow
17 : /// @author Jakob Erdmann
18 : /// @author Michael Behrisch
19 : /// @author Robert Hilbrich
20 : /// @date 30.05.2012
21 : ///
22 : // C++ TraCI client API implementation
23 : /****************************************************************************/
24 : #include <config.h>
25 :
26 : #include <utils/shapes/PointOfInterest.h>
27 : #include <utils/shapes/ShapeContainer.h>
28 : #include <utils/geom/GeomHelper.h>
29 : #include <microsim/MSNet.h>
30 : #include <libsumo/TraCIConstants.h>
31 : #include "Polygon.h"
32 : #include "POI.h"
33 : #include "Helper.h"
34 :
35 :
36 : namespace libsumo {
37 : // ===========================================================================
38 : // static member initializations
39 : // ===========================================================================
40 : SubscriptionResults POI::mySubscriptionResults;
41 : ContextSubscriptionResults POI::myContextSubscriptionResults;
42 : NamedRTree* POI::myTree(nullptr);
43 :
44 :
45 : // ===========================================================================
46 : // static member definitions
47 : // ===========================================================================
48 : std::vector<std::string>
49 362 : POI::getIDList() {
50 : std::vector<std::string> ids;
51 362 : MSNet::getInstance()->getShapeContainer().getPOIs().insertIDs(ids);
52 360 : return ids;
53 2 : }
54 :
55 :
56 : int
57 57 : POI::getIDCount() {
58 57 : return (int)getIDList().size();
59 : }
60 :
61 :
62 : std::string
63 36 : POI::getType(const std::string& poiID) {
64 36 : return getPoI(poiID)->getShapeType();
65 : }
66 :
67 :
68 : TraCIColor
69 39 : POI::getColor(const std::string& poiID) {
70 39 : return Helper::makeTraCIColor(getPoI(poiID)->getShapeColor());
71 : }
72 :
73 :
74 : TraCIPosition
75 8050 : POI::getPosition(const std::string& poiID, const bool includeZ) {
76 8050 : return Helper::makeTraCIPosition(*getPoI(poiID), includeZ);
77 : }
78 :
79 :
80 : double
81 30 : POI::getWidth(const std::string& poiID) {
82 30 : return getPoI(poiID)->getWidth();
83 : }
84 :
85 :
86 : double
87 30 : POI::getHeight(const std::string& poiID) {
88 30 : return getPoI(poiID)->getHeight();
89 : }
90 :
91 :
92 : double
93 30 : POI::getAngle(const std::string& poiID) {
94 30 : return getPoI(poiID)->getShapeNaviDegree();
95 : }
96 :
97 :
98 : std::string
99 15 : POI::getImageFile(const std::string& poiID) {
100 15 : return getPoI(poiID)->getShapeImgFile();
101 : }
102 :
103 :
104 : std::string
105 46 : POI::getParameter(const std::string& poiID, const std::string& key) {
106 92 : return getPoI(poiID)->getParameter(key, "");
107 : }
108 :
109 :
110 20 : LIBSUMO_GET_PARAMETER_WITH_KEY_IMPLEMENTATION(POI)
111 :
112 :
113 : void
114 7 : POI::setType(const std::string& poiID, const std::string& poiType) {
115 7 : getPoI(poiID)->setShapeType(poiType);
116 6 : }
117 :
118 :
119 : void
120 51 : POI::setPosition(const std::string& poiID, double x, double y) {
121 : // try to retrieve so that the correct error is generated for unknown poiIDs
122 51 : getPoI(poiID);
123 50 : MSNet::getInstance()->getShapeContainer().movePOI(poiID, Position(x, y));
124 50 : }
125 :
126 :
127 : void
128 7 : POI::setColor(const std::string& poiID, const TraCIColor& c) {
129 7 : getPoI(poiID)->setShapeColor(Helper::makeRGBColor(c));
130 6 : }
131 :
132 :
133 : void
134 5 : POI::setWidth(const std::string& poiID, double width) {
135 5 : getPoI(poiID)->setWidth(width);
136 5 : }
137 :
138 :
139 : void
140 5 : POI::setHeight(const std::string& poiID, double height) {
141 5 : getPoI(poiID)->setHeight(height);
142 5 : }
143 :
144 :
145 : void
146 5 : POI::setAngle(const std::string& poiID, double angle) {
147 5 : getPoI(poiID)->setShapeNaviDegree(angle);
148 5 : }
149 :
150 :
151 : void
152 5 : POI::setImageFile(const std::string& poiID, const std::string& imageFile) {
153 5 : getPoI(poiID)->setShapeImgFile(imageFile);
154 5 : }
155 :
156 :
157 : bool
158 108 : POI::add(const std::string& poiID, double x, double y, const TraCIColor& color, const std::string& poiType,
159 : int layer, const std::string& imgFile, double width, double height, double angle, const std::string& icon) {
160 108 : ShapeContainer& shapeCont = MSNet::getInstance()->getShapeContainer();
161 108 : bool ok = shapeCont.addPOI(poiID, poiType, Helper::makeRGBColor(color),
162 108 : Position(x, y), false, "", 0, false, 0, icon, layer,
163 : angle, imgFile, width, height);
164 108 : if (ok && myTree != nullptr) {
165 : PointOfInterest* p = shapeCont.getPOIs().get(poiID);
166 10 : const float cmin[2] = {(float)p->x(), (float)p->y()};
167 10 : const float cmax[2] = {(float)p->x(), (float)p->y()};
168 10 : myTree->Insert(cmin, cmax, p);
169 : }
170 108 : return ok;
171 : }
172 :
173 :
174 : bool
175 12 : POI::remove(const std::string& poiID, int /* layer */) {
176 12 : ShapeContainer& shapeCont = MSNet::getInstance()->getShapeContainer();
177 : PointOfInterest* p = shapeCont.getPOIs().get(poiID);
178 11 : if (p != nullptr && myTree != nullptr) {
179 5 : const float cmin[2] = {(float)p->x(), (float)p->y()};
180 5 : const float cmax[2] = {(float)p->x(), (float)p->y()};
181 5 : myTree->Remove(cmin, cmax, p);
182 : }
183 12 : return shapeCont.removePOI(poiID);
184 : }
185 :
186 :
187 : void
188 29 : POI::highlight(const std::string& poiID, const TraCIColor& col, double size, const int alphaMax, const double duration, const int type) {
189 : // NOTE: Code is duplicated in large parts in Vehicle.cpp
190 29 : PointOfInterest* poi = getPoI(poiID);
191 :
192 : // Center of the highlight circle
193 29 : Position* center = dynamic_cast<Position*>(poi);
194 : // Size of the highlight circle
195 29 : if (size <= 0) {
196 21 : size = sqrt(poi->getHeight() * poi->getHeight() + poi->getWidth() * poi->getWidth()) * 0.7;
197 : }
198 : // Make polygon shape
199 : const unsigned int nPoints = 34;
200 29 : const PositionVector circlePV = GeomHelper::makeRing(size, size + 1., *center, nPoints);
201 29 : TraCIPositionVector circle = Helper::makeTraCIPositionVector(circlePV);
202 :
203 : #ifdef DEBUG_DYNAMIC_SHAPES
204 : std::cout << SIMTIME << " Vehicle::highlight() for vehicle '" << vehicleID << "'\n"
205 : << " circle: " << circlePV << std::endl;
206 : #endif
207 :
208 : // Find a free polygon id
209 29 : int i = 0;
210 58 : std::string polyID = poi->getID() + "_hl" + toString(i);
211 103 : while (Polygon::exists(polyID)) {
212 16 : polyID = poi->getID() + "_hl" + toString(++i);
213 : }
214 : // Line width
215 : double lw = 0.;
216 : // Layer
217 : double lyr = 0.;
218 29 : if (MSNet::getInstance()->isGUINet()) {
219 : lyr = poi->getShapeLayer();
220 13 : lyr += (type + 1) / 257.;
221 : }
222 : // Make Polygon
223 58 : Polygon::addHighlightPolygon(poiID, type, polyID, circle, col, true, "highlight", (int)lyr, lw);
224 :
225 : // Animation time line
226 : double maxAttack = 1.0; // maximal fade-in time
227 : std::vector<double> timeSpan;
228 29 : if (duration > 0.) {
229 58 : timeSpan = {0, MIN2(maxAttack, duration / 3.), 2.*duration / 3., duration};
230 : }
231 : // Alpha time line
232 : std::vector<double> alphaSpan;
233 29 : if (alphaMax > 0.) {
234 58 : alphaSpan = {0., (double) alphaMax, ((double) alphaMax) / 3., 0.};
235 : }
236 : // Attach dynamics
237 29 : Polygon::addDynamics(polyID, "", timeSpan, alphaSpan, false, false);
238 58 : }
239 :
240 :
241 : void
242 329 : POI::setParameter(const std::string& poiID, const std::string& key, const std::string& value) {
243 329 : PointOfInterest* p = getPoI(poiID);
244 329 : p->setParameter(key, value);
245 329 : }
246 :
247 :
248 :
249 8348 : LIBSUMO_SUBSCRIPTION_IMPLEMENTATION(POI, POI)
250 :
251 :
252 : PointOfInterest*
253 25206 : POI::getPoI(const std::string& id) {
254 25206 : PointOfInterest* sumoPoi = MSNet::getInstance()->getShapeContainer().getPOIs().get(id);
255 25201 : if (sumoPoi == nullptr) {
256 10 : throw TraCIException("POI '" + id + "' is not known");
257 : }
258 25201 : return sumoPoi;
259 : }
260 :
261 :
262 : NamedRTree*
263 407 : POI::getTree() {
264 407 : if (myTree == nullptr) {
265 18 : myTree = new NamedRTree();
266 18 : ShapeContainer& shapeCont = MSNet::getInstance()->getShapeContainer();
267 62 : for (const auto& i : shapeCont.getPOIs()) {
268 44 : const float cmin[2] = {(float)i.second->x(), (float)i.second->y()};
269 44 : const float cmax[2] = {(float)i.second->x(), (float)i.second->y()};
270 44 : myTree->Insert(cmin, cmax, i.second);
271 : }
272 : }
273 407 : return myTree;
274 : }
275 :
276 : void
277 41336 : POI::cleanup() {
278 41336 : delete myTree;
279 41336 : myTree = nullptr;
280 41336 : }
281 :
282 :
283 : void
284 16487 : POI::storeShape(const std::string& id, PositionVector& shape) {
285 16487 : shape.push_back(*getPoI(id));
286 16487 : }
287 :
288 :
289 : std::shared_ptr<VariableWrapper>
290 273 : POI::makeWrapper() {
291 273 : return std::make_shared<Helper::SubscriptionWrapper>(handleVariable, mySubscriptionResults, myContextSubscriptionResults);
292 : }
293 :
294 :
295 : bool
296 4451 : POI::handleVariable(const std::string& objID, const int variable, VariableWrapper* wrapper, tcpip::Storage* paramData) {
297 4451 : switch (variable) {
298 191 : case TRACI_ID_LIST:
299 191 : return wrapper->wrapStringList(objID, variable, getIDList());
300 43 : case ID_COUNT:
301 43 : return wrapper->wrapInt(objID, variable, getIDCount());
302 28 : case VAR_TYPE:
303 56 : return wrapper->wrapString(objID, variable, getType(objID));
304 31 : case VAR_COLOR:
305 31 : return wrapper->wrapColor(objID, variable, getColor(objID));
306 4036 : case VAR_POSITION:
307 4036 : return wrapper->wrapPosition(objID, variable, getPosition(objID));
308 0 : case VAR_POSITION3D:
309 0 : return wrapper->wrapPosition(objID, variable, getPosition(objID, true));
310 22 : case VAR_WIDTH:
311 22 : return wrapper->wrapDouble(objID, variable, getWidth(objID));
312 22 : case VAR_HEIGHT:
313 22 : return wrapper->wrapDouble(objID, variable, getHeight(objID));
314 22 : case VAR_ANGLE:
315 22 : return wrapper->wrapDouble(objID, variable, getAngle(objID));
316 13 : case VAR_IMAGEFILE:
317 26 : return wrapper->wrapString(objID, variable, getImageFile(objID));
318 26 : case libsumo::VAR_PARAMETER:
319 26 : paramData->readUnsignedByte();
320 52 : return wrapper->wrapString(objID, variable, getParameter(objID, paramData->readString()));
321 10 : case libsumo::VAR_PARAMETER_WITH_KEY:
322 10 : paramData->readUnsignedByte();
323 20 : return wrapper->wrapStringPair(objID, variable, getParameterWithKey(objID, paramData->readString()));
324 : default:
325 : return false;
326 : }
327 : }
328 :
329 :
330 : }
331 :
332 :
333 : /****************************************************************************/
|