1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-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 GUINet.cpp
11 /// @author Daniel Krajzewicz
12 /// @author Jakob Erdmann
13 /// @author Michael Behrisch
14 /// @author Laura Bieker
15 /// @date Sept 2002
16 /// @version $Id$
17 ///
18 // A MSNet extended by some values for usage within the gui
19 /****************************************************************************/
20 // ===========================================================================
21 // included modules
22 // ===========================================================================
23 #include <config.h>
24
25 #include <utility>
26 #include <set>
27 #include <vector>
28 #include <map>
29 #include <utils/shapes/ShapeContainer.h>
30 #include <utils/gui/globjects/GUIPolygon.h>
31 #include <utils/gui/globjects/GUIPointOfInterest.h>
32 #include <utils/gui/globjects/GUIGLObjectPopupMenu.h>
33 #include <utils/gui/div/GUIParameterTableWindow.h>
34 #include <utils/gui/div/GUIGlobalSelection.h>
35 #include <utils/gui/globjects/GUIShapeContainer.h>
36 #include <utils/xml/XMLSubSys.h>
37 #include <utils/common/StringUtils.h>
38 #include <utils/common/RGBColor.h>
39 #include <utils/gui/div/GLObjectValuePassConnector.h>
40 #include <microsim/MSNet.h>
41 #include <microsim/MSEdgeWeightsStorage.h>
42 #include <microsim/MSJunction.h>
43 #include <microsim/output/MSDetectorControl.h>
44 #include <microsim/MSEdge.h>
45 #include <microsim/pedestrians/MSPModel.h>
46 #include <microsim/MSInsertionControl.h>
47 #include <microsim/traffic_lights/MSTrafficLightLogic.h>
48 #include <microsim/traffic_lights/MSTLLogicControl.h>
49 #include <microsim/MSJunctionControl.h>
50 #include <guisim/GUIEdge.h>
51 #include <guisim/GUILane.h>
52 #include <guisim/GUITransportableControl.h>
53 #include <guisim/GUILaneSpeedTrigger.h>
54 #include <guisim/GUIDetectorWrapper.h>
55 #include <guisim/GUITrafficLightLogicWrapper.h>
56 #include <guisim/GUIJunctionWrapper.h>
57 #include <guisim/GUIVehicleControl.h>
58 #include <gui/GUIGlobals.h>
59 #include "GUINet.h"
60
61 #include <mesogui/GUIMEVehicleControl.h>
62
63
64 // ===========================================================================
65 // definition of static variables used for visualisation of objects' values
66 // ===========================================================================
67 template std::vector< GLObjectValuePassConnector<double>* > GLObjectValuePassConnector<double>::myContainer;
68 template FXMutex GLObjectValuePassConnector<double>::myLock;
69
70 template std::vector< GLObjectValuePassConnector<std::pair<int, class MSPhaseDefinition> >* > GLObjectValuePassConnector<std::pair<int, class MSPhaseDefinition> >::myContainer;
71 template FXMutex GLObjectValuePassConnector<std::pair<int, class MSPhaseDefinition> >::myLock;
72
73
74 // ===========================================================================
75 // member method definitions
76 // ===========================================================================
GUINet(MSVehicleControl * vc,MSEventControl * beginOfTimestepEvents,MSEventControl * endOfTimestepEvents,MSEventControl * insertionEvents)77 GUINet::GUINet(MSVehicleControl* vc, MSEventControl* beginOfTimestepEvents,
78 MSEventControl* endOfTimestepEvents,
79 MSEventControl* insertionEvents) :
80 MSNet(vc, beginOfTimestepEvents, endOfTimestepEvents, insertionEvents, new GUIShapeContainer(myGrid)),
81 GUIGlObject(GLO_NETWORK, ""),
82 myLastSimDuration(0), /*myLastVisDuration(0),*/ myLastIdleDuration(0),
83 myLastVehicleMovementCount(0), myOverallVehicleCount(0), myOverallSimDuration(0) {
84 GUIGlObjectStorage::gIDStorage.setNetObject(this);
85 }
86
87
~GUINet()88 GUINet::~GUINet() {
89 if (myLock.locked()) {
90 myLock.unlock();
91 }
92 // delete allocated wrappers
93 // of junctions
94 for (std::vector<GUIJunctionWrapper*>::iterator i1 = myJunctionWrapper.begin(); i1 != myJunctionWrapper.end(); i1++) {
95 delete (*i1);
96 }
97 // of additional structures
98 GUIGlObject_AbstractAdd::clearDictionary();
99 // of tl-logics
100 for (Logics2WrapperMap::iterator i3 = myLogics2Wrapper.begin(); i3 != myLogics2Wrapper.end(); i3++) {
101 delete (*i3).second;
102 }
103 // of detectors
104 for (std::vector<GUIDetectorWrapper*>::iterator i = myDetectorWrapper.begin(); i != myDetectorWrapper.end(); ++i) {
105 delete *i;
106 }
107 for (auto& item : myLoadedEdgeData) {
108 delete item.second;
109 }
110 }
111
112
113 const Boundary&
getBoundary() const114 GUINet::getBoundary() const {
115 return myBoundary;
116 }
117
118
119 MSTransportableControl&
getPersonControl()120 GUINet::getPersonControl() {
121 if (myPersonControl == nullptr) {
122 myPersonControl = new GUITransportableControl();
123 }
124 return *myPersonControl;
125 }
126
127
128 MSTransportableControl&
getContainerControl()129 GUINet::getContainerControl() {
130 if (myContainerControl == nullptr) {
131 myContainerControl = new GUITransportableControl();
132 }
133 return *myContainerControl;
134 }
135
136
137 void
initTLMap()138 GUINet::initTLMap() {
139 // get the list of loaded tl-logics
140 const std::vector<MSTrafficLightLogic*>& logics = getTLSControl().getAllLogics();
141 // go through the logics
142 for (std::vector<MSTrafficLightLogic*>::const_iterator i = logics.begin(); i != logics.end(); ++i) {
143 createTLWrapper(*i);
144 }
145 }
146
147
148 void
createTLWrapper(MSTrafficLightLogic * tll)149 GUINet::createTLWrapper(MSTrafficLightLogic* tll) {
150 if (myLogics2Wrapper.count(tll) > 0) {
151 return;
152 }
153 // get the links
154 const MSTrafficLightLogic::LinkVectorVector& links = tll->getLinks();
155 if (links.size() == 0) { // @legacy this should never happen in 0.13.0+ networks
156 return;
157 }
158 // build the wrapper
159 GUITrafficLightLogicWrapper* tllw =
160 new GUITrafficLightLogicWrapper(*myLogics, *tll);
161 // build the association link->wrapper
162 MSTrafficLightLogic::LinkVectorVector::const_iterator j;
163 for (j = links.begin(); j != links.end(); ++j) {
164 MSTrafficLightLogic::LinkVector::const_iterator j2;
165 for (j2 = (*j).begin(); j2 != (*j).end(); ++j2) {
166 myLinks2Logic[*j2] = tll->getID();
167 }
168 }
169 myGrid.addAdditionalGLObject(tllw);
170 myLogics2Wrapper[tll] = tllw;
171 return;
172 }
173
174
175 Position
getJunctionPosition(const std::string & name) const176 GUINet::getJunctionPosition(const std::string& name) const {
177 // !!! no check for existance!
178 return myJunctions->get(name)->getPosition();
179 }
180
181
182 bool
vehicleExists(const std::string & name) const183 GUINet::vehicleExists(const std::string& name) const {
184 return myVehicleControl->getVehicle(name) != nullptr;
185 }
186
187
188 int
getLinkTLID(MSLink * link) const189 GUINet::getLinkTLID(MSLink* link) const {
190 if (myLinks2Logic.count(link) == 0) {
191 assert(false);
192 return 0;
193 }
194 MSTrafficLightLogic* tll = myLogics->getActive(myLinks2Logic.find(link)->second);
195 if (myLogics2Wrapper.count(tll) == 0) {
196 // tll may have been added via traci. @see ticket #459
197 return 0;
198 }
199 return myLogics2Wrapper.find(tll)->second->getGlID();
200 }
201
202
203 int
getLinkTLIndex(MSLink * link) const204 GUINet::getLinkTLIndex(MSLink* link) const {
205 Links2LogicMap::const_iterator i = myLinks2Logic.find(link);
206 if (i == myLinks2Logic.end()) {
207 return -1;
208 }
209 if (myLogics2Wrapper.find(myLogics->getActive((*i).second)) == myLogics2Wrapper.end()) {
210 return -1;
211 }
212 return myLogics2Wrapper.find(myLogics->getActive((*i).second))->second->getLinkIndex(link);
213 }
214
215
216 void
guiSimulationStep()217 GUINet::guiSimulationStep() {
218 GLObjectValuePassConnector<double>::updateAll();
219 GLObjectValuePassConnector<std::pair<SUMOTime, MSPhaseDefinition> >::updateAll();
220 }
221
222
223 void
simulationStep()224 GUINet::simulationStep() {
225 FXMutexLock locker(myLock);
226 MSNet::simulationStep();
227 }
228
229
230 std::vector<GUIGlID>
getJunctionIDs(bool includeInternal) const231 GUINet::getJunctionIDs(bool includeInternal) const {
232 std::vector<GUIGlID> ret;
233 for (std::vector<GUIJunctionWrapper*>::const_iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
234 if (!(*i)->isInternal() || includeInternal) {
235 ret.push_back((*i)->getGlID());
236 }
237 }
238 return ret;
239 }
240
241
242 std::vector<GUIGlID>
getTLSIDs() const243 GUINet::getTLSIDs() const {
244 std::vector<GUIGlID> ret;
245 std::vector<std::string> ids;
246 for (std::map<MSTrafficLightLogic*, GUITrafficLightLogicWrapper*>::const_iterator i = myLogics2Wrapper.begin(); i != myLogics2Wrapper.end(); ++i) {
247 std::string sid = (*i).second->getMicrosimID();
248 if (find(ids.begin(), ids.end(), sid) == ids.end()) {
249 ret.push_back((*i).second->getGlID());
250 ids.push_back(sid);
251 }
252 }
253 return ret;
254 }
255
256
257 void
initGUIStructures()258 GUINet::initGUIStructures() {
259 // initialise detector storage for gui
260 const std::vector<SumoXMLTag> types = myDetectorControl->getAvailableTypes();
261 for (std::vector<SumoXMLTag>::const_iterator i = types.begin(); i != types.end(); ++i) {
262 for (const auto& j : myDetectorControl->getTypedDetectors(*i)) {
263 GUIDetectorWrapper* wrapper = j.second->buildDetectorGUIRepresentation();
264 if (wrapper != nullptr) {
265 myDetectorWrapper.push_back(wrapper);
266 myGrid.addAdditionalGLObject(wrapper);
267 }
268 }
269 }
270 // initialise the tl-map
271 initTLMap();
272 // initialise edge storage for gui
273 const MSEdgeVector& edges = MSEdge::getAllEdges();
274 myEdgeWrapper.reserve(edges.size());
275 for (MSEdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
276 // VISIM connector edges shall be drawn (they have lanes)
277 if (!(*i)->isTazConnector() || (*i)->getLanes().size() > 0) {
278 myEdgeWrapper.push_back(static_cast<GUIEdge*>(*i));
279 }
280 }
281 // initialise junction storage for gui
282 int size = myJunctions->size();
283 myJunctionWrapper.reserve(size);
284 std::map<MSJunction*, std::string> junction2TLL;
285 for (const auto tls : getTLSControl().getAllLogics()) {
286 for (const auto& links : tls->getLinks()) {
287 for (const MSLink* l : links) {
288 junction2TLL[l->getJunction()] = l->getTLLogic()->getID();
289 }
290 }
291 }
292 for (const auto& i : *myJunctions) {
293 myJunctionWrapper.push_back(new GUIJunctionWrapper(*i.second, junction2TLL[i.second]));
294 }
295 // build the visualization tree
296 for (std::vector<GUIEdge*>::iterator i = myEdgeWrapper.begin(); i != myEdgeWrapper.end(); ++i) {
297 GUIEdge* edge = *i;
298 Boundary b;
299 const std::vector<MSLane*>& lanes = edge->getLanes();
300 for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
301 b.add((*j)->getShape().getBoxBoundary());
302 }
303 // make sure persons are always drawn and selectable since they depend on their edge being drawn
304 b.grow(MSPModel::SIDEWALK_OFFSET + 1);
305 const float cmin[2] = { (float)b.xmin(), (float)b.ymin() };
306 const float cmax[2] = { (float)b.xmax(), (float)b.ymax() };
307 myGrid.Insert(cmin, cmax, edge);
308 myBoundary.add(b);
309 if (myBoundary.getWidth() > 10e16 || myBoundary.getHeight() > 10e16) {
310 throw ProcessError("Network size exceeds 1 Lightyear. Please reconsider your inputs.\n");
311 }
312 }
313 for (std::vector<GUIJunctionWrapper*>::iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
314 GUIJunctionWrapper* junction = *i;
315 Boundary b = junction->getBoundary();
316 b.grow(2.);
317 const float cmin[2] = { (float)b.xmin(), (float)b.ymin() };
318 const float cmax[2] = { (float)b.xmax(), (float)b.ymax() };
319 myGrid.Insert(cmin, cmax, junction);
320 myBoundary.add(b);
321 }
322 myGrid.add(myBoundary);
323 }
324
325
326 int
getWholeDuration() const327 GUINet::getWholeDuration() const {
328 return myLastSimDuration +/*myLastVisDuration+*/myLastIdleDuration;
329 }
330
331
332 int
getSimDuration() const333 GUINet::getSimDuration() const {
334 return myLastSimDuration;
335 }
336
337 /*
338 int
339 GUINet::getVisDuration() const
340 {
341 return myLastVisDuration;
342 }
343 */
344
345
346 double
getRTFactor() const347 GUINet::getRTFactor() const {
348 if (myLastSimDuration == 0) {
349 return -1;
350 }
351 return (double)DELTA_T / (double)myLastSimDuration;
352 }
353
354
355 double
getUPS() const356 GUINet::getUPS() const {
357 if (myLastSimDuration == 0) {
358 return -1;
359 }
360 return (double) myLastVehicleMovementCount / (double) myLastSimDuration * (double) 1000.;
361 }
362
363
364 double
getMeanRTFactor(int duration) const365 GUINet::getMeanRTFactor(int duration) const {
366 if (myOverallSimDuration == 0) {
367 return -1;
368 }
369 return ((double)(duration) * (double) 1000. / (double)myOverallSimDuration);
370 }
371
372
373 double
getMeanUPS() const374 GUINet::getMeanUPS() const {
375 if (myOverallSimDuration == 0) {
376 return -1;
377 }
378 return ((double)myVehiclesMoved / (double)myOverallSimDuration * (double) 1000.);
379 }
380
381
382 int
getIdleDuration() const383 GUINet::getIdleDuration() const {
384 return myLastIdleDuration;
385 }
386
387
388 void
setSimDuration(int val)389 GUINet::setSimDuration(int val) {
390 myLastSimDuration = val;
391 myOverallSimDuration += val;
392 myLastVehicleMovementCount = getVehicleControl().getRunningVehicleNo();
393 myOverallVehicleCount += myLastVehicleMovementCount;
394 }
395
396 /*
397 void
398 GUINet::setVisDuration(int val)
399 {
400 myLastVisDuration = val;
401 }
402 */
403
404 void
setIdleDuration(int val)405 GUINet::setIdleDuration(int val) {
406 myLastIdleDuration = val;
407 }
408
409
410 GUIGLObjectPopupMenu*
getPopUpMenu(GUIMainWindow & app,GUISUMOAbstractView & parent)411 GUINet::getPopUpMenu(GUIMainWindow& app,
412 GUISUMOAbstractView& parent) {
413 GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
414 buildPopupHeader(ret, app);
415 buildCenterPopupEntry(ret);
416 buildShowParamsPopupEntry(ret);
417 buildPositionCopyEntry(ret, false);
418 return ret;
419 }
420
421
422 GUIParameterTableWindow*
getParameterWindow(GUIMainWindow & app,GUISUMOAbstractView & parent)423 GUINet::getParameterWindow(GUIMainWindow& app,
424 GUISUMOAbstractView& parent) {
425 GUIParameterTableWindow* ret =
426 new GUIParameterTableWindow(app, *this, 36);
427 // add items
428 ret->mkItem("loaded vehicles [#]", true,
429 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getLoadedVehicleNo));
430 ret->mkItem("insertion-backlogged vehicles [#]", true,
431 new FunctionBinding<MSInsertionControl, int>(&getInsertionControl(), &MSInsertionControl::getWaitingVehicleNo));
432 ret->mkItem("departed vehicles [#]", true,
433 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getDepartedVehicleNo));
434 ret->mkItem("running vehicles [#]", true,
435 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getRunningVehicleNo));
436 ret->mkItem("arrived vehicles [#]", true,
437 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getArrivedVehicleNo));
438 ret->mkItem("discarded vehicles [#]", true,
439 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getDiscardedVehicleNo));
440 ret->mkItem("collisions [#]", true,
441 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getCollisionCount));
442 ret->mkItem("teleports [#]", true,
443 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getTeleportCount));
444 ret->mkItem("halting [#]", true,
445 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getHaltingVehicleNo));
446 ret->mkItem("avg. speed [m/s]", true,
447 new FunctionBinding<MSVehicleControl, double>(&getVehicleControl(), &MSVehicleControl::getVehicleMeanSpeed));
448 ret->mkItem("avg. relative speed", true,
449 new FunctionBinding<MSVehicleControl, double>(&getVehicleControl(), &MSVehicleControl::getVehicleMeanSpeedRelative));
450 if (myPersonControl != nullptr) {
451 ret->mkItem("loaded persons [#]", true,
452 new FunctionBinding<MSTransportableControl, int>(&getPersonControl(), &MSTransportableControl::getLoadedNumber));
453 ret->mkItem("running persons [#]", true,
454 new FunctionBinding<MSTransportableControl, int>(&getPersonControl(), &MSTransportableControl::getRunningNumber));
455 ret->mkItem("jammed persons [#]", true,
456 new FunctionBinding<MSTransportableControl, int>(&getPersonControl(), &MSTransportableControl::getJammedNumber));
457 }
458 ret->mkItem("end time [s]", false, OptionsCont::getOptions().getString("end"));
459 ret->mkItem("begin time [s]", false, OptionsCont::getOptions().getString("begin"));
460 // ret->mkItem("time step [s]", true, new FunctionBinding<GUINet, SUMOTime>(this, &GUINet::getCurrentTimeStep));
461 if (logSimulationDuration()) {
462 ret->mkItem("step duration [ms]", true, new FunctionBinding<GUINet, int>(this, &GUINet::getWholeDuration));
463 ret->mkItem("FPS", true, new FunctionBinding<GUISUMOAbstractView, double>(&parent, &GUISUMOAbstractView::getFPS));
464 ret->mkItem("simulation duration [ms]", true, new FunctionBinding<GUINet, int>(this, &GUINet::getSimDuration));
465 /*
466 ret->mkItem("visualisation duration [ms]", true,
467 new CastingFunctionBinding<GUINet, double, int>(
468 &(getNet()), &GUINet::getVisDuration));
469 */
470 ret->mkItem("idle duration [ms]", true, new FunctionBinding<GUINet, int>(this, &GUINet::getIdleDuration));
471 ret->mkItem("duration factor", true, new FunctionBinding<GUINet, double>(this, &GUINet::getRTFactor));
472 /*
473 ret->mkItem("mean duration factor []", true,
474 new FuncBinding_IntParam<GUINet, double>(
475 &(getNet()), &GUINet::getMeanRTFactor), 1);
476 */
477 ret->mkItem("updates per second", true, new FunctionBinding<GUINet, double>(this, &GUINet::getUPS));
478 ret->mkItem("avg. updates per second", true, new FunctionBinding<GUINet, double>(this, &GUINet::getMeanUPS));
479 if (OptionsCont::getOptions().getBool("duration-log.statistics")) {
480 ret->mkItem("avg. trip length [m]", true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgRouteLength));
481 ret->mkItem("avg. trip duration [s]", true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgDuration));
482 ret->mkItem("avg. trip waiting time [s]", true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgWaitingTime));
483 ret->mkItem("avg. trip time loss [s]", true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgTimeLoss));
484 ret->mkItem("avg. trip depart delay [s]", true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgDepartDelay));
485 ret->mkItem("avg. trip speed [m/s]", true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgTripSpeed));
486 if (myPersonControl != nullptr) {
487 ret->mkItem("avg. walk length [m]", true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgWalkRouteLength));
488 ret->mkItem("avg. walk duration [s]", true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgWalkDuration));
489 ret->mkItem("avg. walk time loss [s]", true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgWalkTimeLoss));
490 }
491 }
492 }
493 ret->mkItem("nodes [#]", false, (int)getJunctionIDs(false).size());
494 ret->mkItem("edges [#]", false, (int)GUIEdge::getIDs(false).size());
495 ret->mkItem("total edge length [km]", false, GUIEdge::getTotalLength(false, false) / 1000);
496 ret->mkItem("total lane length [km]", false, GUIEdge::getTotalLength(false, true) / 1000);
497 ret->mkItem("network version ", false, toString(myVersion));
498
499 // close building
500 ret->closeBuilding();
501 return ret;
502 }
503
504
505 void
drawGL(const GUIVisualizationSettings &) const506 GUINet::drawGL(const GUIVisualizationSettings& /*s*/) const {
507 }
508
509 Boundary
getCenteringBoundary() const510 GUINet::getCenteringBoundary() const {
511 return getBoundary();
512 }
513
514
515 GUINet*
getGUIInstance()516 GUINet::getGUIInstance() {
517 GUINet* net = dynamic_cast<GUINet*>(MSNet::getInstance());
518 if (net != nullptr) {
519 return net;
520 }
521 throw ProcessError("A gui-network was not yet constructed.");
522 }
523
524
525 GUIVehicleControl*
getGUIVehicleControl()526 GUINet::getGUIVehicleControl() {
527 return dynamic_cast<GUIVehicleControl*>(myVehicleControl);
528 }
529
530
531 void
lock()532 GUINet::lock() {
533 myLock.lock();
534 }
535
536
537 void
unlock()538 GUINet::unlock() {
539 myLock.unlock();
540 }
541
542 GUIMEVehicleControl*
getGUIMEVehicleControl()543 GUINet::getGUIMEVehicleControl() {
544 return dynamic_cast<GUIMEVehicleControl*>(myVehicleControl);
545 }
546
547
548 double
getEdgeData(const MSEdge * edge,const std::string & attr)549 GUINet::getEdgeData(const MSEdge* edge, const std::string& attr) {
550 auto it = myLoadedEdgeData.find(attr);
551 if (it != myLoadedEdgeData.end()) {
552 double value;
553 bool found = it->second->retrieveExistingEffort(edge, STEPS2TIME(getCurrentTimeStep()), value);
554 if (found) {
555 return value;
556 } else {
557 return -1;
558 }
559 } else {
560 return -2;
561 }
562 }
563
564
565 void
myStartElement(int element,const SUMOSAXAttributes & attrs)566 GUINet::DiscoverAttributes::myStartElement(int element, const SUMOSAXAttributes& attrs) {
567 if (element == SUMO_TAG_EDGE || element == SUMO_TAG_LANE) {
568 std::vector<std::string> tmp = attrs.getAttributeNames();
569 edgeAttrs.insert(tmp.begin(), tmp.end());
570 } else if (element == SUMO_TAG_INTERVAL) {
571 bool ok;
572 lastIntervalEnd = MAX2(lastIntervalEnd, attrs.getSUMOTimeReporting(SUMO_ATTR_END, nullptr, ok));
573 }
574 }
575
576 std::vector<std::string>
getEdgeAttrs()577 GUINet::DiscoverAttributes::getEdgeAttrs() {
578 edgeAttrs.erase(toString(SUMO_ATTR_ID));
579 return std::vector<std::string>(edgeAttrs.begin(), edgeAttrs.end());
580 }
581
582 void
addEdgeWeight(const std::string & id,double value,double begTime,double endTime) const583 GUINet::EdgeFloatTimeLineRetriever_GUI::addEdgeWeight(const std::string& id,
584 double value, double begTime, double endTime) const {
585 MSEdge* edge = MSEdge::dictionary(id);
586 if (edge != nullptr) {
587 myWeightStorage->addEffort(edge, begTime, endTime, value);
588 } else {
589 WRITE_ERROR("Trying to set the effort for the unknown edge '" + id + "'.");
590 }
591 }
592
593
594 bool
loadEdgeData(const std::string & file)595 GUINet::loadEdgeData(const std::string& file) {
596 // discover edge attributes
597 DiscoverAttributes discoveryHandler(file);
598 XMLSubSys::runParser(discoveryHandler, file);
599 std::vector<std::string> attrs = discoveryHandler.getEdgeAttrs();
600 WRITE_MESSAGE("Loading edgedata from '" + file
601 + "' Found " + toString(attrs.size())
602 + " attributes: " + toString(attrs));
603 myEdgeDataEndTime = MAX2(myEdgeDataEndTime, discoveryHandler.lastIntervalEnd);
604 // create a retriever for each attribute
605 std::vector<EdgeFloatTimeLineRetriever_GUI> retrieverDefsInternal;
606 retrieverDefsInternal.reserve(attrs.size());
607 std::vector<SAXWeightsHandler::ToRetrieveDefinition*> retrieverDefs;
608 for (const std::string& attr : attrs) {
609 MSEdgeWeightsStorage* ws = new MSEdgeWeightsStorage();
610 myLoadedEdgeData[attr] = ws;
611 retrieverDefsInternal.push_back(EdgeFloatTimeLineRetriever_GUI(ws));
612 retrieverDefs.push_back(new SAXWeightsHandler::ToRetrieveDefinition(attr, true, retrieverDefsInternal.back()));
613 }
614 SAXWeightsHandler handler(retrieverDefs, "");
615 return XMLSubSys::runParser(handler, file);
616 }
617
618
619 std::vector<std::string>
getEdgeDataAttrs() const620 GUINet::getEdgeDataAttrs() const {
621 std::vector<std::string> result;
622 for (const auto& item : myLoadedEdgeData) {
623 result.push_back(item.first);
624 }
625 return result;
626 }
627
628 bool
isSelected(const MSTrafficLightLogic * tll) const629 GUINet::isSelected(const MSTrafficLightLogic* tll) const {
630 const auto it = myLogics2Wrapper.find(const_cast<MSTrafficLightLogic*>(tll));
631 return it != myLogics2Wrapper.end() && gSelected.isSelected(GLO_TLLOGIC, it->second->getGlID());
632 }
633
634 #ifdef HAVE_OSG
635 void
updateColor(const GUIVisualizationSettings & s)636 GUINet::updateColor(const GUIVisualizationSettings& s) {
637 for (std::vector<GUIEdge*>::const_iterator i = myEdgeWrapper.begin(); i != myEdgeWrapper.end(); ++i) {
638 if (!(*i)->isInternal()) {
639 const std::vector<MSLane*>& lanes = (*i)->getLanes();
640 for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
641 static_cast<GUILane*>(*j)->updateColor(s);
642 }
643 }
644 }
645 for (std::vector<GUIJunctionWrapper*>::iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
646 (*i)->updateColor(s);
647 }
648 }
649 #endif
650
651 /****************************************************************************/
652
653