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