Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-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 GUINet.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @author Laura Bieker
19 : /// @date Sept 2002
20 : ///
21 : // A MSNet extended by some values for usage within the gui
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/GUIDesigns.h>
34 : #include <utils/gui/div/GUIParameterTableWindow.h>
35 : #include <utils/gui/div/GUIGlobalSelection.h>
36 : #include <utils/gui/globjects/GUIShapeContainer.h>
37 : #include <utils/xml/XMLSubSys.h>
38 : #include <utils/common/MsgHandler.h>
39 : #include <utils/common/StringUtils.h>
40 : #include <utils/common/RGBColor.h>
41 : #include <utils/iodevices/OutputDevice.h>
42 : #include <utils/gui/div/GLObjectValuePassConnector.h>
43 : #include <microsim/MSNet.h>
44 : #include <microsim/MSEdgeWeightsStorage.h>
45 : #include <microsim/MSJunction.h>
46 : #include <microsim/output/MSDetectorControl.h>
47 : #include <microsim/MSEdge.h>
48 : #include <microsim/transportables/MSPModel.h>
49 : #include <microsim/MSInsertionControl.h>
50 : #include <microsim/traffic_lights/MSTrafficLightLogic.h>
51 : #include <microsim/traffic_lights/MSTLLogicControl.h>
52 : #include <microsim/MSJunctionControl.h>
53 : #include <guisim/Command_Hotkey_TrafficLight.h>
54 : #include <guisim/GUIEdge.h>
55 : #include <guisim/GUILane.h>
56 : #include <guisim/GUITransportableControl.h>
57 : #include <guisim/GUILaneSpeedTrigger.h>
58 : #include <guisim/GUIDetectorWrapper.h>
59 : #include <guisim/GUICalibrator.h>
60 : #include <guisim/GUITrafficLightLogicWrapper.h>
61 : #include <guisim/GUIJunctionWrapper.h>
62 : #include <guisim/GUIVehicleControl.h>
63 : #include <gui/GUIGlobals.h>
64 : #include <gui/GUIApplicationWindow.h>
65 : #include "GUINet.h"
66 :
67 : #include <mesogui/GUIMEVehicleControl.h>
68 :
69 :
70 : // ===========================================================================
71 : // definition of static variables used for visualisation of objects' values
72 : // ===========================================================================
73 : template std::vector< GLObjectValuePassConnector<double>* > GLObjectValuePassConnector<double>::myContainer;
74 : template FXMutex GLObjectValuePassConnector<double>::myLock;
75 :
76 : template std::vector< GLObjectValuePassConnector<std::pair<int, class MSPhaseDefinition> >* > GLObjectValuePassConnector<std::pair<int, class MSPhaseDefinition> >::myContainer;
77 : template FXMutex GLObjectValuePassConnector<std::pair<int, class MSPhaseDefinition> >::myLock;
78 :
79 :
80 : // ===========================================================================
81 : // member method definitions
82 : // ===========================================================================
83 7981 : GUINet::GUINet(MSVehicleControl* vc, MSEventControl* beginOfTimestepEvents,
84 : MSEventControl* endOfTimestepEvents,
85 7981 : MSEventControl* insertionEvents) :
86 7981 : MSNet(vc, beginOfTimestepEvents, endOfTimestepEvents, insertionEvents, new GUIShapeContainer(myGrid)),
87 : GUIGlObject(GLO_NETWORK, "", nullptr),
88 7981 : myLastSimDuration(0), /*myLastVisDuration(0),*/ myLastIdleDuration(0),
89 23943 : myLastVehicleMovementCount(0), myOverallVehicleCount(0), myOverallSimDuration(0) {
90 : GUIGlObjectStorage::gIDStorage.setNetObject(this);
91 7981 : }
92 :
93 :
94 15916 : GUINet::~GUINet() {
95 7958 : if (myLock.locked()) {
96 0 : myLock.unlock();
97 : }
98 : // delete allocated wrappers
99 : // of junctions
100 100870 : for (std::vector<GUIJunctionWrapper*>::iterator i1 = myJunctionWrapper.begin(); i1 != myJunctionWrapper.end(); i1++) {
101 92912 : delete (*i1);
102 : }
103 : // of additional structures
104 7958 : GUIGlObject_AbstractAdd::clearDictionary();
105 : // of tl-logics
106 27400 : for (Logics2WrapperMap::iterator i3 = myLogics2Wrapper.begin(); i3 != myLogics2Wrapper.end(); i3++) {
107 19442 : delete (*i3).second;
108 : }
109 : // of detectors
110 9057 : for (std::vector<GUIDetectorWrapper*>::iterator i = myDetectorWrapper.begin(); i != myDetectorWrapper.end(); ++i) {
111 1099 : delete *i;
112 : }
113 : // of calibrators
114 8042 : for (GUICalibrator* cw : myCalibratorWrapper) {
115 84 : delete cw;
116 : }
117 7958 : for (auto& item : myLoadedEdgeData) {
118 0 : delete item.second;
119 : }
120 23874 : }
121 :
122 :
123 : const Boundary&
124 0 : GUINet::getBoundary() const {
125 0 : return myBoundary;
126 : }
127 :
128 :
129 : MSTransportableControl&
130 4012938 : GUINet::getPersonControl() {
131 4012938 : if (myPersonControl == nullptr) {
132 1532 : myPersonControl = new GUITransportableControl(true);
133 : }
134 4012938 : return *myPersonControl;
135 : }
136 :
137 :
138 : MSTransportableControl&
139 148161 : GUINet::getContainerControl() {
140 148161 : if (myContainerControl == nullptr) {
141 173 : myContainerControl = new GUITransportableControl(false);
142 : }
143 148161 : return *myContainerControl;
144 : }
145 :
146 :
147 : void
148 7726 : GUINet::initTLMap() {
149 : // go through the loaded tl-logics
150 27179 : for (MSTrafficLightLogic* const tll : getTLSControl().getAllLogics()) {
151 19453 : createTLWrapper(tll);
152 7726 : }
153 7726 : }
154 :
155 :
156 : void
157 19465 : GUINet::createTLWrapper(MSTrafficLightLogic* tll) {
158 : if (myLogics2Wrapper.count(tll) > 0) {
159 : return;
160 : }
161 : // get the links
162 19465 : const MSTrafficLightLogic::LinkVectorVector& links = tll->getLinks();
163 19465 : if (links.size() == 0) { // @legacy this should never happen in 0.13.0+ networks
164 : return;
165 : }
166 : // build the wrapper
167 19464 : GUITrafficLightLogicWrapper* tllw = new GUITrafficLightLogicWrapper(*myLogics, *tll);
168 38928 : if (tll->hasParameter("hotkeyAbort")) {
169 0 : Command_Hotkey_TrafficLight::registerHotkey(tll->getParameter("hotkeyAbort"), *tll);
170 : }
171 : // build the association link->wrapper
172 : MSTrafficLightLogic::LinkVectorVector::const_iterator j;
173 222859 : for (j = links.begin(); j != links.end(); ++j) {
174 : MSTrafficLightLogic::LinkVector::const_iterator j2;
175 406467 : for (j2 = (*j).begin(); j2 != (*j).end(); ++j2) {
176 203072 : myLinks2Logic[*j2] = tll->getID();
177 : }
178 : }
179 19464 : myGrid.addAdditionalGLObject(tllw);
180 19464 : myLogics2Wrapper[tll] = tllw;
181 : }
182 :
183 :
184 : Position
185 0 : GUINet::getJunctionPosition(const std::string& name) const {
186 : // !!! no check for existance!
187 0 : return myJunctions->get(name)->getPosition();
188 : }
189 :
190 :
191 : bool
192 0 : GUINet::vehicleExists(const std::string& name) const {
193 0 : return myVehicleControl->getVehicle(name) != nullptr;
194 : }
195 :
196 :
197 : int
198 60602 : GUINet::getLinkTLID(const MSLink* const link) const {
199 : if (myLinks2Logic.count(link) == 0) {
200 : //assert(false);
201 : return 0;
202 : }
203 121168 : MSTrafficLightLogic* tll = myLogics->getActive(myLinks2Logic.find(link)->second);
204 : if (myLogics2Wrapper.count(tll) == 0) {
205 : // tll may have been added via traci. @see ticket #459
206 : return 0;
207 : }
208 60584 : return myLogics2Wrapper.find(tll)->second->getGlID();
209 : }
210 :
211 :
212 : int
213 0 : GUINet::getLinkTLIndex(const MSLink* const link) const {
214 : Links2LogicMap::const_iterator i = myLinks2Logic.find(link);
215 0 : if (i == myLinks2Logic.end()) {
216 : return -1;
217 : }
218 0 : if (myLogics2Wrapper.find(myLogics->getActive((*i).second)) == myLogics2Wrapper.end()) {
219 : return -1;
220 : }
221 0 : return myLogics2Wrapper.find(myLogics->getActive((*i).second))->second->getLinkIndex(link);
222 : }
223 :
224 :
225 : GUITrafficLightLogicWrapper*
226 0 : GUINet::getTLLWrapper(MSTrafficLightLogic* tll) {
227 0 : if (myLogics2Wrapper.find(tll) == myLogics2Wrapper.end()) {
228 : return nullptr;
229 : }
230 0 : return myLogics2Wrapper.find(tll)->second;
231 : }
232 :
233 :
234 : void
235 6481294 : GUINet::guiSimulationStep() {
236 6481294 : GLObjectValuePassConnector<double>::updateAll();
237 6481294 : GLObjectValuePassConnector<std::pair<SUMOTime, MSPhaseDefinition> >::updateAll();
238 6481294 : }
239 :
240 :
241 : void
242 6481416 : GUINet::simulationStep() {
243 6481416 : FXMutexLock locker(myLock);
244 6481416 : MSNet::simulationStep();
245 6481294 : }
246 :
247 :
248 : std::vector<GUIGlID>
249 0 : GUINet::getJunctionIDs(bool includeInternal) const {
250 : std::vector<GUIGlID> ret;
251 0 : for (std::vector<GUIJunctionWrapper*>::const_iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
252 0 : if (!(*i)->isInternal() || includeInternal) {
253 0 : ret.push_back((*i)->getGlID());
254 : }
255 : }
256 0 : return ret;
257 0 : }
258 :
259 :
260 : std::vector<GUIGlID>
261 0 : GUINet::getTLSIDs() const {
262 : std::vector<GUIGlID> ret;
263 : std::vector<std::string> ids;
264 0 : for (std::map<MSTrafficLightLogic*, GUITrafficLightLogicWrapper*>::const_iterator i = myLogics2Wrapper.begin(); i != myLogics2Wrapper.end(); ++i) {
265 0 : std::string sid = (*i).second->getMicrosimID();
266 0 : if (find(ids.begin(), ids.end(), sid) == ids.end()) {
267 0 : ret.push_back((*i).second->getGlID());
268 0 : ids.push_back(sid);
269 : }
270 : }
271 0 : return ret;
272 0 : }
273 :
274 :
275 : void
276 7726 : GUINet::initGUIStructures() {
277 : // initialise detector storage for gui
278 7726 : const std::vector<SumoXMLTag> types = myDetectorControl->getAvailableTypes();
279 8215 : for (std::vector<SumoXMLTag>::const_iterator i = types.begin(); i != types.end(); ++i) {
280 1625 : for (const auto& j : myDetectorControl->getTypedDetectors(*i)) {
281 1136 : GUIDetectorWrapper* wrapper = j.second->buildDetectorGUIRepresentation();
282 1136 : if (wrapper != nullptr) {
283 1105 : myDetectorWrapper.push_back(wrapper);
284 1105 : myGrid.addAdditionalGLObject(wrapper);
285 : }
286 : }
287 : }
288 : // let's always track emission parameters for the GUI
289 7726 : MSGlobals::gHaveEmissions = true;
290 : // initialise calibrators
291 7810 : for (auto& item : MSCalibrator::getInstances()) {
292 84 : GUICalibrator* wrapper = new GUICalibrator(item.second);
293 84 : myCalibratorWrapper.push_back(wrapper);
294 84 : myGrid.addAdditionalGLObject(wrapper);
295 : }
296 : // initialise the tl-map
297 7726 : initTLMap();
298 : // initialise edge storage for gui
299 7726 : const MSEdgeVector& edges = MSEdge::getAllEdges();
300 7726 : myEdgeWrapper.reserve(edges.size());
301 335302 : for (MSEdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
302 : // VISIM connector edges shall be drawn (they have lanes)
303 327576 : if (!(*i)->isTazConnector() || (*i)->getLanes().size() > 0) {
304 324188 : myEdgeWrapper.push_back(static_cast<GUIEdge*>(*i));
305 : }
306 : }
307 : // initialise junction storage for gui
308 7726 : int size = myJunctions->size();
309 7726 : myJunctionWrapper.reserve(size);
310 : std::map<MSJunction*, std::string> junction2TLL;
311 27179 : for (const auto tls : getTLSControl().getAllLogics()) {
312 222641 : for (const auto& links : tls->getLinks()) {
313 406057 : for (const MSLink* l : links) {
314 405738 : junction2TLL[l->getJunction()] = l->getTLLogic()->getID();
315 : }
316 : }
317 7726 : }
318 100846 : for (const auto& i : *myJunctions) {
319 93120 : myJunctionWrapper.push_back(new GUIJunctionWrapper(*i.second, junction2TLL[i.second]));
320 : }
321 : // build the visualization tree
322 331914 : for (std::vector<GUIEdge*>::iterator i = myEdgeWrapper.begin(); i != myEdgeWrapper.end(); ++i) {
323 324188 : GUIEdge* edge = *i;
324 324188 : Boundary b;
325 : const std::vector<MSLane*>& lanes = edge->getLanes();
326 705380 : for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
327 381192 : b.add((*j)->getShape().getBoxBoundary());
328 : }
329 : // make sure persons are always drawn and selectable since they depend on their edge being drawn
330 324188 : b.grow(MSPModel::SIDEWALK_OFFSET + 1 + lanes.front()->getWidth() / 2);
331 324188 : const float cmin[2] = { (float)b.xmin(), (float)b.ymin() };
332 324188 : const float cmax[2] = { (float)b.xmax(), (float)b.ymax() };
333 324188 : myGrid.Insert(cmin, cmax, edge);
334 324188 : myBoundary.add(b);
335 324188 : if (myBoundary.getWidth() > 10e16 || myBoundary.getHeight() > 10e16) {
336 0 : throw ProcessError(TL("Network size exceeds 1 Lightyear. Please reconsider your inputs.\n"));
337 : }
338 : }
339 100846 : for (std::vector<GUIJunctionWrapper*>::iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
340 93120 : GUIJunctionWrapper* junction = *i;
341 : Boundary b = junction->getBoundary();
342 93120 : b.grow(2.);
343 93120 : const float cmin[2] = { (float)b.xmin(), (float)b.ymin() };
344 93120 : const float cmax[2] = { (float)b.xmax(), (float)b.ymax() };
345 93120 : myGrid.Insert(cmin, cmax, junction);
346 93120 : myBoundary.add(b);
347 : }
348 7726 : myGrid.add(myBoundary);
349 :
350 15452 : if (OptionsCont::getOptions().isSet("alternative-net-file")) {
351 : // build secondary visualization tree
352 0 : for (GUIEdge* edge : myEdgeWrapper) {
353 0 : Boundary b;
354 0 : for (MSLane* lane : edge->getLanes()) {
355 0 : b.add(static_cast<GUILane*>(lane)->getShape(true).getBoxBoundary());
356 : }
357 : // make sure persons are always drawn and selectable since they depend on their edge being drawn
358 0 : b.grow(MSPModel::SIDEWALK_OFFSET + 1);
359 0 : const float cmin[2] = { (float)b.xmin(), (float)b.ymin() };
360 0 : const float cmax[2] = { (float)b.xmax(), (float)b.ymax() };
361 0 : myGrid2.Insert(cmin, cmax, edge);
362 : }
363 0 : for (std::vector<GUIJunctionWrapper*>::iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
364 0 : GUIJunctionWrapper* junction = *i;
365 0 : Position pos = junction->getJunction().getPosition(true);
366 0 : Boundary b = Boundary(pos.x() - 3., pos.y() - 3., pos.x() + 3., pos.y() + 3.);
367 0 : const float cmin[2] = { (float)b.xmin(), (float)b.ymin() };
368 0 : const float cmax[2] = { (float)b.xmax(), (float)b.ymax() };
369 0 : myGrid2.Insert(cmin, cmax, junction);
370 : }
371 : }
372 7726 : }
373 :
374 :
375 : void
376 3373 : GUINet::registerRenderedObject(GUIGlObject* o) {
377 3373 : getVisualisationSpeedUp().addAdditionalGLObject(o);
378 6746 : if (OptionsCont::getOptions().isSet("alternative-net-file")) {
379 0 : GUIGlobals::gSecondaryShape = true;
380 0 : myGrid2.addAdditionalGLObject(o);
381 0 : GUIGlobals::gSecondaryShape = false;
382 : }
383 3373 : }
384 :
385 :
386 : int
387 0 : GUINet::getWholeDuration() const {
388 0 : return myLastSimDuration +/*myLastVisDuration+*/myLastIdleDuration;
389 : }
390 :
391 :
392 : int
393 0 : GUINet::getSimDuration() const {
394 0 : return myLastSimDuration;
395 : }
396 :
397 : /*
398 : int
399 : GUINet::getVisDuration() const
400 : {
401 : return myLastVisDuration;
402 : }
403 : */
404 :
405 :
406 : double
407 0 : GUINet::getRTFactor() const {
408 0 : if (myLastSimDuration == 0) {
409 : return -1;
410 : }
411 0 : return (double)DELTA_T / (double)myLastSimDuration;
412 : }
413 :
414 :
415 : double
416 0 : GUINet::getUPS() const {
417 0 : if (myLastSimDuration == 0) {
418 : return -1;
419 : }
420 0 : return (double) myLastVehicleMovementCount / (double) myLastSimDuration * (double) 1000.;
421 : }
422 :
423 :
424 : double
425 0 : GUINet::getMeanRTFactor(int duration) const {
426 0 : if (myOverallSimDuration == 0) {
427 : return -1;
428 : }
429 0 : return ((double)(duration) * (double) 1000. / (double)myOverallSimDuration);
430 : }
431 :
432 :
433 : double
434 0 : GUINet::getMeanUPS() const {
435 0 : if (myOverallSimDuration == 0) {
436 : return -1;
437 : }
438 0 : return ((double)myVehiclesMoved / (double)myOverallSimDuration * (double) 1000.);
439 : }
440 :
441 :
442 : int
443 0 : GUINet::getIdleDuration() const {
444 0 : return myLastIdleDuration;
445 : }
446 :
447 :
448 : void
449 6481416 : GUINet::setSimDuration(int val) {
450 6481416 : myLastSimDuration = val;
451 6481416 : myOverallSimDuration += val;
452 6481416 : myLastVehicleMovementCount = getVehicleControl().getRunningVehicleNo();
453 6481416 : myOverallVehicleCount += myLastVehicleMovementCount;
454 6481416 : }
455 :
456 : /*
457 : void
458 : GUINet::setVisDuration(int val)
459 : {
460 : myLastVisDuration = val;
461 : }
462 : */
463 :
464 : void
465 6473925 : GUINet::setIdleDuration(int val) {
466 6473925 : myLastIdleDuration = val;
467 6473925 : }
468 :
469 :
470 : GUIGLObjectPopupMenu*
471 0 : GUINet::getPopUpMenu(GUIMainWindow& app,
472 : GUISUMOAbstractView& parent) {
473 0 : GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, this);
474 0 : buildPopupHeader(ret, app);
475 0 : buildCenterPopupEntry(ret);
476 0 : buildShowParamsPopupEntry(ret);
477 0 : buildPositionCopyEntry(ret, app);
478 0 : if (GeoConvHelper::getFinal().usingGeoProjection()) {
479 0 : GUIDesigns::buildFXMenuCommand(ret, TL("Copy view geo-boundary to clipboard"), nullptr, ret, MID_COPY_VIEW_GEOBOUNDARY);
480 : }
481 0 : return ret;
482 : }
483 :
484 :
485 : GUIParameterTableWindow*
486 0 : GUINet::getParameterWindow(GUIMainWindow& app,
487 : GUISUMOAbstractView& parent) {
488 0 : GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
489 : // add items
490 0 : ret->mkItem(TL("loaded vehicles [#]"), true,
491 0 : new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getLoadedVehicleNo));
492 0 : ret->mkItem(TL("insertion-backlogged vehicles [#]"), true,
493 0 : new FunctionBinding<MSInsertionControl, int>(&getInsertionControl(), &MSInsertionControl::getWaitingVehicleNo));
494 0 : ret->mkItem(TL("departed vehicles [#]"), true,
495 0 : new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getDepartedVehicleNo));
496 0 : ret->mkItem(TL("running vehicles [#]"), true,
497 0 : new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getRunningVehicleNo));
498 0 : ret->mkItem(TL("arrived vehicles [#]"), true,
499 0 : new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getArrivedVehicleNo));
500 0 : ret->mkItem(TL("discarded vehicles [#]"), true,
501 0 : new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getDiscardedVehicleNo));
502 0 : ret->mkItem(TL("collisions [#]"), true,
503 0 : new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getCollisionCount));
504 0 : ret->mkItem(TL("teleports [#]"), true,
505 0 : new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getTeleportCount));
506 0 : ret->mkItem(TL("halting [#]"), true,
507 0 : new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getHaltingVehicleNo));
508 0 : ret->mkItem(TL("stopped [#]"), true,
509 0 : new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getStoppedVehiclesCount));
510 0 : ret->mkItem(TL("avg. speed [m/s]"), true,
511 0 : new FunctionBinding<MSVehicleControl, double>(&getVehicleControl(), &MSVehicleControl::getVehicleMeanSpeed));
512 0 : ret->mkItem(TL("avg. relative speed"), true,
513 0 : new FunctionBinding<MSVehicleControl, double>(&getVehicleControl(), &MSVehicleControl::getVehicleMeanSpeedRelative));
514 0 : if (myPersonControl != nullptr) {
515 0 : ret->mkItem(TL("loaded persons [#]"), true,
516 0 : new FunctionBinding<MSTransportableControl, int>(&getPersonControl(), &MSTransportableControl::getLoadedNumber));
517 0 : ret->mkItem(TL("running persons [#]"), true,
518 0 : new FunctionBinding<MSTransportableControl, int>(&getPersonControl(), &MSTransportableControl::getRunningNumber));
519 0 : ret->mkItem(TL("jammed persons [#]"), true,
520 0 : new FunctionBinding<MSTransportableControl, int>(&getPersonControl(), &MSTransportableControl::getJammedNumber));
521 : }
522 0 : ret->mkItem(TL("end time [s]"), false, OptionsCont::getOptions().getString("end"));
523 0 : ret->mkItem(TL("begin time [s]"), false, OptionsCont::getOptions().getString("begin"));
524 : // ret->mkItem(TL("time step [s]"), true, new FunctionBinding<GUINet, SUMOTime>(this, &GUINet::getCurrentTimeStep));
525 0 : if (logSimulationDuration()) {
526 0 : ret->mkItem(TL("step duration [ms]"), true, new FunctionBinding<GUINet, int>(this, &GUINet::getWholeDuration));
527 0 : ret->mkItem(TL("FPS"), true, new FunctionBinding<GUISUMOAbstractView, double>(&parent, &GUISUMOAbstractView::getFPS));
528 0 : ret->mkItem(TL("simulation duration [ms]"), true, new FunctionBinding<GUINet, int>(this, &GUINet::getSimDuration));
529 : /*
530 : ret->mkItem(TL("visualisation duration [ms]"), true,
531 : new CastingFunctionBinding<GUINet, double, int>(
532 : &(getNet()), &GUINet::getVisDuration));
533 : */
534 0 : ret->mkItem(TL("idle duration [ms]"), true, new FunctionBinding<GUINet, int>(this, &GUINet::getIdleDuration));
535 0 : ret->mkItem(TL("duration factor"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getRTFactor));
536 : /*
537 : ret->mkItem(TL("mean duration factor []"), true,
538 : new FuncBinding_IntParam<GUINet, double>(
539 : &(getNet()), &GUINet::getMeanRTFactor), 1);
540 : */
541 0 : ret->mkItem(TL("updates per second"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getUPS));
542 0 : ret->mkItem(TL("avg. updates per second"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getMeanUPS));
543 : }
544 0 : if (OptionsCont::getOptions().isSet("tripinfo-output") || OptionsCont::getOptions().getBool("duration-log.statistics")) {
545 0 : ret->mkItem(TL("avg. trip length [m]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgRouteLength));
546 0 : ret->mkItem(TL("avg. trip duration [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgDuration));
547 0 : ret->mkItem(TL("avg. trip waiting time [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgWaitingTime));
548 0 : ret->mkItem(TL("avg. trip time loss [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgTimeLoss));
549 0 : ret->mkItem(TL("avg. trip depart delay [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgDepartDelay));
550 0 : ret->mkItem(TL("avg. trip speed [m/s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgTripSpeed));
551 0 : if (myPersonControl != nullptr) {
552 0 : ret->mkItem(TL("avg. walk length [m]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgWalkRouteLength));
553 0 : ret->mkItem(TL("avg. walk duration [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgWalkDuration));
554 0 : ret->mkItem(TL("avg. walk time loss [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgWalkTimeLoss));
555 : }
556 : }
557 0 : ret->mkItem(TL("nodes [#]"), false, (int)getJunctionIDs(false).size());
558 0 : ret->mkItem(TL("edges [#]"), false, (int)GUIEdge::getIDs(false).size());
559 0 : ret->mkItem(TL("total edge length [km]"), false, GUIEdge::getTotalLength(false, false) / 1000);
560 0 : ret->mkItem(TL("total lane length [km]"), false, GUIEdge::getTotalLength(false, true) / 1000);
561 0 : ret->mkItem(TL("network version "), false, toString(myVersion));
562 :
563 : // close building
564 0 : ret->closeBuilding();
565 0 : return ret;
566 : }
567 :
568 :
569 : void
570 0 : GUINet::drawGL(const GUIVisualizationSettings& /*s*/) const {
571 0 : }
572 :
573 :
574 : Boundary
575 0 : GUINet::getCenteringBoundary() const {
576 0 : return getBoundary();
577 : }
578 :
579 :
580 : GUINet*
581 1078283 : GUINet::getGUIInstance() {
582 1078283 : GUINet* net = dynamic_cast<GUINet*>(MSNet::getInstance());
583 1078283 : if (net != nullptr) {
584 1078283 : return net;
585 : }
586 0 : throw ProcessError("A gui-network was not yet constructed.");
587 : }
588 :
589 :
590 : GUIVehicleControl*
591 0 : GUINet::getGUIVehicleControl() {
592 0 : return dynamic_cast<GUIVehicleControl*>(myVehicleControl);
593 : }
594 :
595 :
596 : void
597 5 : GUINet::lock() {
598 5 : myLock.lock();
599 5 : }
600 :
601 :
602 : void
603 5 : GUINet::unlock() {
604 5 : myLock.unlock();
605 5 : }
606 :
607 : GUIMEVehicleControl*
608 419090 : GUINet::getGUIMEVehicleControl() {
609 419090 : return dynamic_cast<GUIMEVehicleControl*>(myVehicleControl);
610 : }
611 :
612 :
613 : double
614 0 : GUINet::getEdgeData(const MSEdge* edge, const std::string& attr) {
615 : auto it = myLoadedEdgeData.find(attr);
616 0 : if (it != myLoadedEdgeData.end()) {
617 : double value;
618 0 : bool found = it->second->retrieveExistingEffort(edge, STEPS2TIME(getCurrentTimeStep()), value);
619 0 : if (found) {
620 0 : return value;
621 : } else {
622 0 : return GUIVisualizationSettings::MISSING_DATA;
623 : }
624 : } else {
625 0 : return GUIVisualizationSettings::MISSING_DATA;
626 : }
627 : }
628 :
629 :
630 : double
631 0 : GUINet::getMeanData(const MSLane* lane, const std::string& id, const std::string& attr) {
632 0 : auto item = myDetectorControl->getMeanData().find(id);
633 0 : if (item != myDetectorControl->getMeanData().end() && !item->second.empty()) {
634 0 : SumoXMLAttr a = (SumoXMLAttr)SUMOXMLDefinitions::Attrs.get(attr);
635 0 : return item->second.front()->getAttributeValue(lane, a, GUIVisualizationSettings::MISSING_DATA);
636 : } else {
637 0 : return GUIVisualizationSettings::MISSING_DATA;
638 : }
639 : }
640 :
641 :
642 : void
643 0 : GUINet::DiscoverAttributes::myStartElement(int element, const SUMOSAXAttributes& attrs) {
644 0 : if (element == SUMO_TAG_EDGE || element == SUMO_TAG_LANE) {
645 0 : std::vector<std::string> tmp = attrs.getAttributeNames();
646 : edgeAttrs.insert(tmp.begin(), tmp.end());
647 0 : } else if (element == SUMO_TAG_EDGEREL) {
648 0 : for (const std::string& a : attrs.getAttributeNames()) {
649 0 : if (a != "from" && a != "to") {
650 : edgeAttrs.insert(a);
651 : }
652 0 : }
653 0 : } else if (element == SUMO_TAG_INTERVAL) {
654 : bool ok;
655 0 : numIntervals++;
656 0 : firstIntervalBegin = MIN2(firstIntervalBegin, attrs.getSUMOTimeReporting(SUMO_ATTR_BEGIN, nullptr, ok));
657 0 : lastIntervalEnd = MAX2(lastIntervalEnd, attrs.getSUMOTimeReporting(SUMO_ATTR_END, nullptr, ok));
658 : }
659 0 : }
660 :
661 :
662 : std::vector<std::string>
663 0 : GUINet::DiscoverAttributes::getEdgeAttrs() {
664 0 : edgeAttrs.erase(toString(SUMO_ATTR_ID));
665 0 : return std::vector<std::string>(edgeAttrs.begin(), edgeAttrs.end());
666 : }
667 :
668 :
669 : void
670 0 : GUINet::EdgeFloatTimeLineRetriever_GUI::addEdgeWeight(const std::string& id,
671 : double value, double begTime, double endTime) const {
672 0 : MSEdge* const edge = MSEdge::dictionary(id);
673 0 : if (edge != nullptr) {
674 0 : myWeightStorage->addEffort(edge, begTime, endTime, value);
675 : } else {
676 0 : WRITE_WARNINGF(TL("Trying to set data value for the unknown edge '%'."), id);
677 : }
678 0 : }
679 :
680 :
681 : void
682 0 : GUINet::EdgeFloatTimeLineRetriever_GUI::addEdgeRelWeight(const std::string& from, const std::string& to,
683 : double val, double beg, double end) const {
684 0 : MSEdge* const fromEdge = MSEdge::dictionary(from);
685 0 : MSEdge* const toEdge = MSEdge::dictionary(to);
686 : bool haveRel = false;
687 0 : if (fromEdge != nullptr && toEdge != nullptr) {
688 0 : for (auto item : fromEdge->getViaSuccessors()) {
689 0 : if (item.first == toEdge) {
690 : const MSEdge* edge = item.second;
691 0 : while (edge != nullptr && edge->isInternal()) {
692 0 : myWeightStorage->addEffort(edge, beg, end, val);
693 0 : edge = edge->getViaSuccessors().front().second;
694 : haveRel = true;
695 : }
696 : }
697 : }
698 : }
699 0 : if (!haveRel) {
700 0 : WRITE_WARNINGF(TL("Trying to set data value for the unknown relation from edge '%' to edge '%'."), from, to);
701 : }
702 0 : }
703 :
704 :
705 : bool
706 0 : GUINet::loadEdgeData(const std::string& file) {
707 : // discover edge attributes
708 0 : DiscoverAttributes discoveryHandler(file);
709 0 : XMLSubSys::runParser(discoveryHandler, file);
710 0 : std::vector<std::string> attrs = discoveryHandler.getEdgeAttrs();
711 0 : WRITE_MESSAGE("Loading edgedata from '" + file + "':"
712 : + "\n " + toString(discoveryHandler.numIntervals) + " intervals between"
713 : + " " + time2string(discoveryHandler.firstIntervalBegin) + " and"
714 : + " " + time2string(discoveryHandler.lastIntervalEnd)
715 : + ".\n Found " + toString(attrs.size())
716 : + " attributes: " + toString(attrs));
717 0 : if (discoveryHandler.lastIntervalEnd < string2time(OptionsCont::getOptions().getString("begin"))) {
718 0 : WRITE_WARNING(TL("No data defined after simulation begin time."));
719 : }
720 0 : myEdgeDataEndTime = MAX2(myEdgeDataEndTime, discoveryHandler.lastIntervalEnd);
721 : // create a retriever for each attribute
722 : std::vector<EdgeFloatTimeLineRetriever_GUI> retrieverDefsInternal;
723 0 : retrieverDefsInternal.reserve(attrs.size());
724 : std::vector<SAXWeightsHandler::ToRetrieveDefinition*> retrieverDefs;
725 0 : for (const std::string& attr : attrs) {
726 0 : MSEdgeWeightsStorage* ws = new MSEdgeWeightsStorage();
727 0 : myLoadedEdgeData[attr] = ws;
728 0 : retrieverDefsInternal.push_back(EdgeFloatTimeLineRetriever_GUI(ws));
729 0 : retrieverDefs.push_back(new SAXWeightsHandler::ToRetrieveDefinition(attr, true, retrieverDefsInternal.back()));
730 : }
731 0 : SAXWeightsHandler handler(retrieverDefs, "");
732 : // temporarily modify warning threshold to avoid swamping the UI
733 0 : const int threshold = MsgHandler::getWarningInstance()->getAggregationThreshold();
734 0 : MsgHandler::getWarningInstance()->setAggregationThreshold(10);
735 0 : bool ok = XMLSubSys::runParser(handler, file);
736 0 : MsgHandler::getWarningInstance()->clear(false);
737 0 : MsgHandler::getWarningInstance()->setAggregationThreshold(threshold);
738 0 : return ok;
739 0 : }
740 :
741 :
742 : std::vector<std::string>
743 0 : GUINet::getEdgeDataAttrs() const {
744 : std::vector<std::string> result;
745 0 : for (const auto& item : myLoadedEdgeData) {
746 0 : result.push_back(item.first);
747 : }
748 0 : return result;
749 0 : }
750 :
751 :
752 : std::vector<std::string>
753 0 : GUINet::getMeanDataIDs() const {
754 : std::vector<std::string> result;
755 :
756 0 : for (auto item : myDetectorControl->getMeanData()) {
757 0 : result.push_back(item.first);
758 : }
759 0 : std::sort(result.begin(), result.end());
760 0 : return result;
761 0 : }
762 :
763 : std::vector<std::string>
764 0 : GUINet::getMeanDataAttrs(const std::string& meanDataID) const {
765 0 : auto item = myDetectorControl->getMeanData().find(meanDataID);
766 0 : if (item != myDetectorControl->getMeanData().end() && !item->second.empty()) {
767 0 : return item->second.front()->getAttributeNames();
768 : } else {
769 0 : return std::vector<std::string>();
770 : }
771 : }
772 :
773 :
774 : bool
775 0 : GUINet::isSelected(const MSTrafficLightLogic* tll) const {
776 : const auto it = myLogics2Wrapper.find(const_cast<MSTrafficLightLogic*>(tll));
777 0 : return it != myLogics2Wrapper.end() && gSelected.isSelected(GLO_TLLOGIC, it->second->getGlID());
778 : }
779 :
780 : void
781 34 : GUINet::updateGUI() const {
782 : try {
783 : // gui only
784 34 : GUIApplicationWindow* aw = static_cast<GUIApplicationWindow*>(GUIMainWindow::getInstance());
785 : // update the view
786 34 : aw->handleEvent_SimulationStep(nullptr);
787 0 : } catch (ProcessError&) { }
788 34 : }
789 :
790 : void
791 0 : GUINet::addHotkey(int key, Command* press, Command* release) {
792 : try {
793 : // gui only
794 0 : GUIApplicationWindow* aw = static_cast<GUIApplicationWindow*>(GUIMainWindow::getInstance());
795 : // update the view
796 0 : aw->addHotkey(key, press, release);
797 0 : } catch (ProcessError&) { }
798 0 : }
799 :
800 : void
801 0 : GUINet::flushOutputsAtEnd() {
802 0 : mySkipFinalReset = true;
803 0 : myDetectorControl->close(SIMSTEP);
804 0 : OutputDevice::flushAll();
805 : // update tracker windows
806 0 : guiSimulationStep();
807 0 : }
808 :
809 : #ifdef HAVE_OSG
810 : void
811 16024 : GUINet::updateColor(const GUIVisualizationSettings& s) {
812 280210 : for (std::vector<GUIEdge*>::const_iterator i = myEdgeWrapper.begin(); i != myEdgeWrapper.end(); ++i) {
813 264186 : if (!(*i)->isInternal()) {
814 : const std::vector<MSLane*>& lanes = (*i)->getLanes();
815 294881 : for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
816 188099 : static_cast<GUILane*>(*j)->updateColor(s);
817 : }
818 : }
819 : }
820 139192 : for (std::vector<GUIJunctionWrapper*>::iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
821 123168 : (*i)->updateColor(s);
822 : }
823 16024 : }
824 : #endif
825 :
826 :
827 : /****************************************************************************/
|