Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2026 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 8919 : GUINet::GUINet(MSVehicleControl* vc, MSEventControl* beginOfTimestepEvents,
84 : MSEventControl* endOfTimestepEvents,
85 8919 : MSEventControl* insertionEvents) :
86 8919 : MSNet(vc, beginOfTimestepEvents, endOfTimestepEvents, insertionEvents, new GUIShapeContainer(myGrid)),
87 : GUIGlObject(GLO_NETWORK, "", nullptr),
88 8919 : myLastSimDuration(0), /*myLastVisDuration(0),*/ myLastIdleDuration(0),
89 26757 : myLastVehicleMovementCount(0), myOverallVehicleCount(0), myOverallSimDuration(0) {
90 : GUIGlObjectStorage::gIDStorage.setNetObject(this);
91 8919 : }
92 :
93 :
94 17782 : GUINet::~GUINet() {
95 8891 : if (myLock.locked()) {
96 0 : myLock.unlock();
97 : }
98 : // delete allocated wrappers
99 : // of junctions
100 132110 : for (std::vector<GUIJunctionWrapper*>::iterator i1 = myJunctionWrapper.begin(); i1 != myJunctionWrapper.end(); i1++) {
101 123219 : delete (*i1);
102 : }
103 : // of additional structures
104 8891 : GUIGlObject_AbstractAdd::clearDictionary();
105 : // of tl-logics
106 31494 : for (Logics2WrapperMap::iterator i3 = myLogics2Wrapper.begin(); i3 != myLogics2Wrapper.end(); i3++) {
107 22603 : delete (*i3).second;
108 : }
109 : // of detectors
110 12219 : for (std::vector<GUIDetectorWrapper*>::iterator i = myDetectorWrapper.begin(); i != myDetectorWrapper.end(); ++i) {
111 3328 : delete *i;
112 : }
113 : // of calibrators
114 8977 : for (GUICalibrator* cw : myCalibratorWrapper) {
115 86 : delete cw;
116 : }
117 8891 : for (auto& item : myLoadedEdgeData) {
118 0 : delete item.second;
119 : }
120 26673 : }
121 :
122 :
123 : const Boundary&
124 0 : GUINet::getBoundary() const {
125 0 : return myBoundary;
126 : }
127 :
128 :
129 : MSTransportableControl&
130 4817071 : GUINet::getPersonControl() {
131 4817071 : if (myPersonControl == nullptr) {
132 1589 : myPersonControl = new GUITransportableControl(true);
133 : }
134 4817071 : return *myPersonControl;
135 : }
136 :
137 :
138 : MSTransportableControl&
139 148488 : GUINet::getContainerControl() {
140 148488 : if (myContainerControl == nullptr) {
141 173 : myContainerControl = new GUITransportableControl(false);
142 : }
143 148488 : return *myContainerControl;
144 : }
145 :
146 :
147 : void
148 8628 : GUINet::initTLMap() {
149 : // go through the loaded tl-logics
150 31245 : for (MSTrafficLightLogic* const tll : getTLSControl().getAllLogics()) {
151 22617 : createTLWrapper(tll);
152 8628 : }
153 8628 : }
154 :
155 :
156 : void
157 22627 : GUINet::createTLWrapper(MSTrafficLightLogic* tll) {
158 : if (myLogics2Wrapper.count(tll) > 0) {
159 : return;
160 : }
161 : // get the links
162 22627 : const MSTrafficLightLogic::LinkVectorVector& links = tll->getLinks();
163 22627 : if (links.size() == 0) { // @legacy this should never happen in 0.13.0+ networks
164 : return;
165 : }
166 : // build the wrapper
167 22627 : GUITrafficLightLogicWrapper* tllw = new GUITrafficLightLogicWrapper(*myLogics, *tll);
168 45254 : if (tll->hasParameter("hotkeyAbort")) {
169 4 : Command_Hotkey_TrafficLight::registerHotkey(tll->getParameter("hotkeyAbort"), *tll);
170 : }
171 : // build the association link->wrapper
172 : MSTrafficLightLogic::LinkVectorVector::const_iterator j;
173 258714 : for (j = links.begin(); j != links.end(); ++j) {
174 : MSTrafficLightLogic::LinkVector::const_iterator j2;
175 472219 : for (j2 = (*j).begin(); j2 != (*j).end(); ++j2) {
176 236132 : myLinks2Logic[*j2] = tll->getID();
177 : }
178 : }
179 22627 : myGrid.addAdditionalGLObject(tllw);
180 22627 : 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 78033 : GUINet::getLinkTLID(const MSLink* const link) const {
199 : if (myLinks2Logic.count(link) == 0) {
200 : //assert(false);
201 : return 0;
202 : }
203 156026 : 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 78013 : 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 13133365 : GUINet::guiSimulationStep() {
236 13133365 : GLObjectValuePassConnector<double>::updateAll();
237 13133365 : GLObjectValuePassConnector<std::pair<SUMOTime, MSPhaseDefinition> >::updateAll();
238 13133365 : }
239 :
240 :
241 : void
242 13133490 : GUINet::simulationStep() {
243 13133490 : FXMutexLock locker(myLock);
244 13133490 : MSNet::simulationStep();
245 13133365 : }
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 8628 : GUINet::initGUIStructures() {
277 : // initialise detector storage for gui
278 8628 : const std::vector<SumoXMLTag> types = myDetectorControl->getAvailableTypes();
279 9397 : for (std::vector<SumoXMLTag>::const_iterator i = types.begin(); i != types.end(); ++i) {
280 4132 : for (const auto& j : myDetectorControl->getTypedDetectors(*i)) {
281 3363 : GUIDetectorWrapper* wrapper = j.second->buildDetectorGUIRepresentation();
282 3363 : if (wrapper != nullptr) {
283 3332 : myDetectorWrapper.push_back(wrapper);
284 3332 : myGrid.addAdditionalGLObject(wrapper);
285 : }
286 : }
287 : }
288 : // let's always track emission parameters for the GUI
289 8628 : MSGlobals::gHaveEmissions = true;
290 : // initialise calibrators
291 8714 : for (auto& item : MSCalibrator::getInstances()) {
292 86 : GUICalibrator* wrapper = new GUICalibrator(item.second);
293 86 : myCalibratorWrapper.push_back(wrapper);
294 86 : myGrid.addAdditionalGLObject(wrapper);
295 : }
296 : // initialise the tl-map
297 8628 : initTLMap();
298 : // initialise edge storage for gui
299 8628 : const MSEdgeVector& edges = MSEdge::getAllEdges();
300 8628 : myEdgeWrapper.reserve(edges.size());
301 389360 : for (MSEdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
302 : // VISIM connector edges shall be drawn (they have lanes)
303 380732 : if (!(*i)->isTazConnector() || (*i)->getLanes().size() > 0) {
304 374928 : myEdgeWrapper.push_back(static_cast<GUIEdge*>(*i));
305 : }
306 : }
307 : // initialise junction storage for gui
308 8628 : int size = myJunctions->size();
309 8628 : myJunctionWrapper.reserve(size);
310 : std::map<MSJunction*, std::string> junction2TLL;
311 31245 : for (const auto tls : getTLSControl().getAllLogics()) {
312 258518 : for (const auto& links : tls->getLinks()) {
313 471851 : for (const MSLink* l : links) {
314 471900 : junction2TLL[l->getJunction()] = l->getTLLogic()->getID();
315 : }
316 : }
317 8628 : }
318 132129 : for (const auto& i : *myJunctions) {
319 123501 : myJunctionWrapper.push_back(new GUIJunctionWrapper(*i.second, junction2TLL[i.second]));
320 : }
321 : // build the visualization tree
322 383556 : for (std::vector<GUIEdge*>::iterator i = myEdgeWrapper.begin(); i != myEdgeWrapper.end(); ++i) {
323 374928 : GUIEdge* edge = *i;
324 374928 : Boundary b;
325 : const std::vector<MSLane*>& lanes = edge->getLanes();
326 813747 : for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
327 438819 : b.add((*j)->getShape().getBoxBoundary());
328 : }
329 : // make sure persons are always drawn and selectable since they depend on their edge being drawn
330 374928 : b.grow(MSPModel::SIDEWALK_OFFSET + 1 + lanes.front()->getWidth() / 2);
331 374928 : const float cmin[2] = { (float)b.xmin(), (float)b.ymin() };
332 374928 : const float cmax[2] = { (float)b.xmax(), (float)b.ymax() };
333 374928 : myGrid.Insert(cmin, cmax, edge);
334 374928 : myBoundary.add(b);
335 374928 : 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 132129 : for (std::vector<GUIJunctionWrapper*>::iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
340 123501 : GUIJunctionWrapper* junction = *i;
341 : Boundary b = junction->getBoundary();
342 123501 : b.grow(2.);
343 123501 : const float cmin[2] = { (float)b.xmin(), (float)b.ymin() };
344 123501 : const float cmax[2] = { (float)b.xmax(), (float)b.ymax() };
345 123501 : myGrid.Insert(cmin, cmax, junction);
346 123501 : myBoundary.add(b);
347 : }
348 8628 : myGrid.add(myBoundary);
349 :
350 17256 : 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 8628 : }
373 :
374 :
375 : void
376 3879 : GUINet::registerRenderedObject(GUIGlObject* o) {
377 3879 : getVisualisationSpeedUp().addAdditionalGLObject(o);
378 7758 : if (OptionsCont::getOptions().isSet("alternative-net-file")) {
379 0 : GUIGlobals::gSecondaryShape = true;
380 0 : myGrid2.addAdditionalGLObject(o);
381 0 : GUIGlobals::gSecondaryShape = false;
382 : }
383 3879 : }
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 13133490 : GUINet::setSimDuration(int val) {
450 13133490 : myLastSimDuration = val;
451 13133490 : myOverallSimDuration += val;
452 13133490 : myLastVehicleMovementCount = getVehicleControl().getRunningVehicleNo();
453 13133490 : myOverallVehicleCount += myLastVehicleMovementCount;
454 13133490 : }
455 :
456 : /*
457 : void
458 : GUINet::setVisDuration(int val)
459 : {
460 : myLastVisDuration = val;
461 : }
462 : */
463 :
464 : void
465 13125105 : GUINet::setIdleDuration(int val) {
466 13125105 : myLastIdleDuration = val;
467 13125105 : }
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 2587616 : GUINet::getGUIInstance() {
582 2587616 : GUINet* net = dynamic_cast<GUINet*>(MSNet::getInstance());
583 2587616 : if (net != nullptr) {
584 2587616 : 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 3 : GUINet::lock() {
598 3 : myLock.lock();
599 3 : }
600 :
601 :
602 : void
603 3 : GUINet::unlock() {
604 3 : myLock.unlock();
605 3 : }
606 :
607 :
608 : void
609 1798267 : GUINet::lockPendingEmits() const {
610 1798267 : myPendingEmitsLock.lock();
611 1798267 : }
612 :
613 :
614 : void
615 1798226 : GUINet::unlockPendingEmits() const {
616 1798226 : myPendingEmitsLock.unlock();
617 1798226 : }
618 :
619 :
620 : GUIMEVehicleControl*
621 1655625 : GUINet::getGUIMEVehicleControl() {
622 1655625 : return dynamic_cast<GUIMEVehicleControl*>(myVehicleControl);
623 : }
624 :
625 :
626 : double
627 0 : GUINet::getEdgeData(const MSEdge* edge, const std::string& attr) {
628 : auto it = myLoadedEdgeData.find(attr);
629 0 : if (it != myLoadedEdgeData.end()) {
630 : double value;
631 0 : bool found = it->second->retrieveExistingEffort(edge, STEPS2TIME(getCurrentTimeStep()), value);
632 0 : if (found) {
633 0 : return value;
634 : } else {
635 0 : return GUIVisualizationSettings::MISSING_DATA;
636 : }
637 : } else {
638 0 : return GUIVisualizationSettings::MISSING_DATA;
639 : }
640 : }
641 :
642 :
643 : double
644 0 : GUINet::getMeanData(const MSLane* lane, const std::string& id, const std::string& attr) {
645 0 : auto item = myDetectorControl->getMeanData().find(id);
646 0 : if (item != myDetectorControl->getMeanData().end() && !item->second.empty()) {
647 0 : SumoXMLAttr a = (SumoXMLAttr)SUMOXMLDefinitions::Attrs.get(attr);
648 0 : return item->second.front()->getAttributeValue(lane, a, GUIVisualizationSettings::MISSING_DATA);
649 : } else {
650 0 : return GUIVisualizationSettings::MISSING_DATA;
651 : }
652 : }
653 :
654 :
655 : void
656 0 : GUINet::DiscoverAttributes::myStartElement(int element, const SUMOSAXAttributes& attrs) {
657 0 : if (element == SUMO_TAG_EDGE || element == SUMO_TAG_LANE) {
658 0 : std::vector<std::string> tmp = attrs.getAttributeNames();
659 : edgeAttrs.insert(tmp.begin(), tmp.end());
660 0 : } else if (element == SUMO_TAG_EDGEREL) {
661 0 : for (const std::string& a : attrs.getAttributeNames()) {
662 0 : if (a != "from" && a != "to") {
663 : edgeAttrs.insert(a);
664 : }
665 0 : }
666 0 : } else if (element == SUMO_TAG_INTERVAL) {
667 : bool ok;
668 0 : numIntervals++;
669 0 : firstIntervalBegin = MIN2(firstIntervalBegin, attrs.getSUMOTimeReporting(SUMO_ATTR_BEGIN, nullptr, ok));
670 0 : lastIntervalEnd = MAX2(lastIntervalEnd, attrs.getSUMOTimeReporting(SUMO_ATTR_END, nullptr, ok));
671 : }
672 0 : }
673 :
674 :
675 : std::vector<std::string>
676 0 : GUINet::DiscoverAttributes::getEdgeAttrs() {
677 0 : edgeAttrs.erase(toString(SUMO_ATTR_ID));
678 0 : return std::vector<std::string>(edgeAttrs.begin(), edgeAttrs.end());
679 : }
680 :
681 :
682 : void
683 0 : GUINet::EdgeFloatTimeLineRetriever_GUI::addEdgeWeight(const std::string& id,
684 : double value, double begTime, double endTime) const {
685 0 : MSEdge* const edge = MSEdge::dictionary(id);
686 0 : if (edge != nullptr) {
687 0 : myWeightStorage->addEffort(edge, begTime, endTime, value);
688 : } else {
689 0 : WRITE_WARNINGF(TL("Trying to set data value for the unknown edge '%'."), id);
690 : }
691 0 : }
692 :
693 :
694 : void
695 0 : GUINet::EdgeFloatTimeLineRetriever_GUI::addEdgeRelWeight(const std::string& from, const std::string& to,
696 : double val, double beg, double end) const {
697 0 : MSEdge* const fromEdge = MSEdge::dictionary(from);
698 0 : MSEdge* const toEdge = MSEdge::dictionary(to);
699 : bool haveRel = false;
700 0 : if (fromEdge != nullptr && toEdge != nullptr) {
701 0 : for (auto item : fromEdge->getViaSuccessors()) {
702 0 : if (item.first == toEdge) {
703 : const MSEdge* edge = item.second;
704 0 : while (edge != nullptr && edge->isInternal()) {
705 0 : myWeightStorage->addEffort(edge, beg, end, val);
706 0 : edge = edge->getViaSuccessors().front().second;
707 : haveRel = true;
708 : }
709 : }
710 : }
711 : }
712 0 : if (!haveRel) {
713 0 : WRITE_WARNINGF(TL("Trying to set data value for the unknown relation from edge '%' to edge '%'."), from, to);
714 : }
715 0 : }
716 :
717 :
718 : bool
719 0 : GUINet::loadEdgeData(const std::string& file) {
720 : // discover edge attributes
721 0 : DiscoverAttributes discoveryHandler(file);
722 0 : XMLSubSys::runParser(discoveryHandler, file);
723 0 : std::vector<std::string> attrs = discoveryHandler.getEdgeAttrs();
724 0 : WRITE_MESSAGE("Loading edgedata from '" + file + "':"
725 : + "\n " + toString(discoveryHandler.numIntervals) + " intervals between"
726 : + " " + time2string(discoveryHandler.firstIntervalBegin) + " and"
727 : + " " + time2string(discoveryHandler.lastIntervalEnd)
728 : + ".\n Found " + toString(attrs.size())
729 : + " attributes: " + toString(attrs));
730 0 : if (discoveryHandler.lastIntervalEnd < string2time(OptionsCont::getOptions().getString("begin"))) {
731 0 : WRITE_WARNING(TL("No data defined after simulation begin time."));
732 : }
733 0 : myEdgeDataEndTime = MAX2(myEdgeDataEndTime, discoveryHandler.lastIntervalEnd);
734 : // create a retriever for each attribute
735 : std::vector<EdgeFloatTimeLineRetriever_GUI> retrieverDefsInternal;
736 0 : retrieverDefsInternal.reserve(attrs.size());
737 : std::vector<SAXWeightsHandler::ToRetrieveDefinition*> retrieverDefs;
738 0 : for (const std::string& attr : attrs) {
739 0 : MSEdgeWeightsStorage* ws = new MSEdgeWeightsStorage();
740 0 : myLoadedEdgeData[attr] = ws;
741 0 : retrieverDefsInternal.push_back(EdgeFloatTimeLineRetriever_GUI(ws));
742 0 : retrieverDefs.push_back(new SAXWeightsHandler::ToRetrieveDefinition(attr, true, retrieverDefsInternal.back()));
743 : }
744 0 : SAXWeightsHandler handler(retrieverDefs, "");
745 : // temporarily modify warning threshold to avoid swamping the UI
746 0 : const int threshold = MsgHandler::getWarningInstance()->getAggregationThreshold();
747 0 : MsgHandler::getWarningInstance()->setAggregationThreshold(10);
748 0 : bool ok = XMLSubSys::runParser(handler, file);
749 0 : MsgHandler::getWarningInstance()->clear(false);
750 0 : MsgHandler::getWarningInstance()->setAggregationThreshold(threshold);
751 0 : return ok;
752 0 : }
753 :
754 :
755 : std::vector<std::string>
756 0 : GUINet::getEdgeDataAttrs() const {
757 : std::vector<std::string> result;
758 0 : for (const auto& item : myLoadedEdgeData) {
759 0 : result.push_back(item.first);
760 : }
761 0 : return result;
762 0 : }
763 :
764 :
765 : std::vector<std::string>
766 0 : GUINet::getMeanDataIDs() const {
767 : std::vector<std::string> result;
768 :
769 0 : for (auto item : myDetectorControl->getMeanData()) {
770 0 : result.push_back(item.first);
771 : }
772 0 : std::sort(result.begin(), result.end());
773 0 : return result;
774 0 : }
775 :
776 : std::vector<std::string>
777 0 : GUINet::getMeanDataAttrs(const std::string& meanDataID) const {
778 0 : auto item = myDetectorControl->getMeanData().find(meanDataID);
779 0 : if (item != myDetectorControl->getMeanData().end() && !item->second.empty()) {
780 0 : return item->second.front()->getAttributeNames();
781 : } else {
782 0 : return std::vector<std::string>();
783 : }
784 : }
785 :
786 :
787 : bool
788 0 : GUINet::isSelected(const MSTrafficLightLogic* tll) const {
789 : const auto it = myLogics2Wrapper.find(const_cast<MSTrafficLightLogic*>(tll));
790 0 : return it != myLogics2Wrapper.end() && gSelected.isSelected(GLO_TLLOGIC, it->second->getGlID());
791 : }
792 :
793 : void
794 44 : GUINet::updateGUI() const {
795 : try {
796 : // gui only
797 44 : GUIApplicationWindow* aw = static_cast<GUIApplicationWindow*>(GUIMainWindow::getInstance());
798 : // update the view
799 44 : aw->handleEvent_SimulationStep(nullptr);
800 0 : } catch (ProcessError&) { }
801 44 : }
802 :
803 : void
804 98 : GUINet::addHotkey(int key, Command* press, Command* release) {
805 : try {
806 : // gui only
807 98 : GUIApplicationWindow* aw = static_cast<GUIApplicationWindow*>(GUIMainWindow::getInstance());
808 : // update the view
809 98 : aw->addHotkey(key, press, release);
810 0 : } catch (ProcessError&) { }
811 98 : }
812 :
813 : void
814 0 : GUINet::flushOutputsAtEnd() {
815 0 : mySkipFinalReset = true;
816 0 : myDetectorControl->close(SIMSTEP);
817 0 : OutputDevice::flushAll();
818 : // update tracker windows
819 0 : guiSimulationStep();
820 0 : }
821 :
822 : #ifdef HAVE_OSG
823 : void
824 20426 : GUINet::updateColor(const GUIVisualizationSettings& s) {
825 368767 : for (std::vector<GUIEdge*>::const_iterator i = myEdgeWrapper.begin(); i != myEdgeWrapper.end(); ++i) {
826 348341 : if (!(*i)->isInternal()) {
827 : const std::vector<MSLane*>& lanes = (*i)->getLanes();
828 378589 : for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
829 241056 : static_cast<GUILane*>(*j)->updateColor(s);
830 : }
831 : }
832 : }
833 179557 : for (std::vector<GUIJunctionWrapper*>::iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
834 159131 : (*i)->updateColor(s);
835 : }
836 20426 : }
837 : #endif
838 :
839 :
840 : /****************************************************************************/
|