Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2024 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 7525 : GUINet::GUINet(MSVehicleControl* vc, MSEventControl* beginOfTimestepEvents,
84 : MSEventControl* endOfTimestepEvents,
85 7525 : MSEventControl* insertionEvents) :
86 7525 : MSNet(vc, beginOfTimestepEvents, endOfTimestepEvents, insertionEvents, new GUIShapeContainer(myGrid)),
87 : GUIGlObject(GLO_NETWORK, "", nullptr),
88 7525 : myLastSimDuration(0), /*myLastVisDuration(0),*/ myLastIdleDuration(0),
89 22575 : myLastVehicleMovementCount(0), myOverallVehicleCount(0), myOverallSimDuration(0) {
90 : GUIGlObjectStorage::gIDStorage.setNetObject(this);
91 7525 : }
92 :
93 :
94 15024 : GUINet::~GUINet() {
95 7512 : if (myLock.locked()) {
96 0 : myLock.unlock();
97 : }
98 : // delete allocated wrappers
99 : // of junctions
100 93849 : for (std::vector<GUIJunctionWrapper*>::iterator i1 = myJunctionWrapper.begin(); i1 != myJunctionWrapper.end(); i1++) {
101 86337 : delete (*i1);
102 : }
103 : // of additional structures
104 7512 : GUIGlObject_AbstractAdd::clearDictionary();
105 : // of tl-logics
106 27774 : for (Logics2WrapperMap::iterator i3 = myLogics2Wrapper.begin(); i3 != myLogics2Wrapper.end(); i3++) {
107 20262 : delete (*i3).second;
108 : }
109 : // of detectors
110 8616 : for (std::vector<GUIDetectorWrapper*>::iterator i = myDetectorWrapper.begin(); i != myDetectorWrapper.end(); ++i) {
111 1104 : delete *i;
112 : }
113 : // of calibrators
114 7594 : for (GUICalibrator* cw : myCalibratorWrapper) {
115 82 : delete cw;
116 : }
117 7512 : for (auto& item : myLoadedEdgeData) {
118 0 : delete item.second;
119 : }
120 22536 : }
121 :
122 :
123 : const Boundary&
124 0 : GUINet::getBoundary() const {
125 0 : return myBoundary;
126 : }
127 :
128 :
129 : MSTransportableControl&
130 3434550 : GUINet::getPersonControl() {
131 3434550 : if (myPersonControl == nullptr) {
132 1407 : myPersonControl = new GUITransportableControl(true);
133 : }
134 3434550 : return *myPersonControl;
135 : }
136 :
137 :
138 : MSTransportableControl&
139 146839 : GUINet::getContainerControl() {
140 146839 : if (myContainerControl == nullptr) {
141 167 : myContainerControl = new GUITransportableControl(false);
142 : }
143 146839 : return *myContainerControl;
144 : }
145 :
146 :
147 : void
148 7274 : GUINet::initTLMap() {
149 : // go through the loaded tl-logics
150 27538 : for (MSTrafficLightLogic* const tll : getTLSControl().getAllLogics()) {
151 20264 : createTLWrapper(tll);
152 7274 : }
153 7274 : }
154 :
155 :
156 : void
157 20275 : GUINet::createTLWrapper(MSTrafficLightLogic* tll) {
158 : if (myLogics2Wrapper.count(tll) > 0) {
159 : return;
160 : }
161 : // get the links
162 20275 : const MSTrafficLightLogic::LinkVectorVector& links = tll->getLinks();
163 20275 : if (links.size() == 0) { // @legacy this should never happen in 0.13.0+ networks
164 : return;
165 : }
166 : // build the wrapper
167 20275 : GUITrafficLightLogicWrapper* tllw = new GUITrafficLightLogicWrapper(*myLogics, *tll);
168 40550 : 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 228930 : for (j = links.begin(); j != links.end(); ++j) {
174 : MSTrafficLightLogic::LinkVector::const_iterator j2;
175 416998 : for (j2 = (*j).begin(); j2 != (*j).end(); ++j2) {
176 208343 : myLinks2Logic[*j2] = tll->getID();
177 : }
178 : }
179 20275 : myGrid.addAdditionalGLObject(tllw);
180 20275 : 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 49173 : GUINet::getLinkTLID(const MSLink* const link) const {
199 : if (myLinks2Logic.count(link) == 0) {
200 : //assert(false);
201 : return 0;
202 : }
203 98318 : 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 49159 : 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 : void
226 5836382 : GUINet::guiSimulationStep() {
227 5836382 : GLObjectValuePassConnector<double>::updateAll();
228 5836382 : GLObjectValuePassConnector<std::pair<SUMOTime, MSPhaseDefinition> >::updateAll();
229 5836382 : }
230 :
231 :
232 : void
233 5836494 : GUINet::simulationStep() {
234 5836494 : FXMutexLock locker(myLock);
235 5836494 : MSNet::simulationStep();
236 5836382 : }
237 :
238 :
239 : std::vector<GUIGlID>
240 0 : GUINet::getJunctionIDs(bool includeInternal) const {
241 : std::vector<GUIGlID> ret;
242 0 : for (std::vector<GUIJunctionWrapper*>::const_iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
243 0 : if (!(*i)->isInternal() || includeInternal) {
244 0 : ret.push_back((*i)->getGlID());
245 : }
246 : }
247 0 : return ret;
248 0 : }
249 :
250 :
251 : std::vector<GUIGlID>
252 0 : GUINet::getTLSIDs() const {
253 : std::vector<GUIGlID> ret;
254 : std::vector<std::string> ids;
255 0 : for (std::map<MSTrafficLightLogic*, GUITrafficLightLogicWrapper*>::const_iterator i = myLogics2Wrapper.begin(); i != myLogics2Wrapper.end(); ++i) {
256 0 : std::string sid = (*i).second->getMicrosimID();
257 0 : if (find(ids.begin(), ids.end(), sid) == ids.end()) {
258 0 : ret.push_back((*i).second->getGlID());
259 0 : ids.push_back(sid);
260 : }
261 : }
262 0 : return ret;
263 0 : }
264 :
265 :
266 : void
267 7274 : GUINet::initGUIStructures() {
268 : // initialise detector storage for gui
269 7274 : const std::vector<SumoXMLTag> types = myDetectorControl->getAvailableTypes();
270 7763 : for (std::vector<SumoXMLTag>::const_iterator i = types.begin(); i != types.end(); ++i) {
271 1626 : for (const auto& j : myDetectorControl->getTypedDetectors(*i)) {
272 1137 : GUIDetectorWrapper* wrapper = j.second->buildDetectorGUIRepresentation();
273 1137 : if (wrapper != nullptr) {
274 1106 : myDetectorWrapper.push_back(wrapper);
275 1106 : myGrid.addAdditionalGLObject(wrapper);
276 : }
277 : }
278 : }
279 : // let's always track emission parameters for the GUI
280 7274 : MSGlobals::gHaveEmissions = true;
281 : // initialise calibrators
282 7356 : for (auto& item : MSCalibrator::getInstances()) {
283 82 : GUICalibrator* wrapper = new GUICalibrator(item.second);
284 82 : myCalibratorWrapper.push_back(wrapper);
285 82 : myGrid.addAdditionalGLObject(wrapper);
286 : }
287 : // initialise the tl-map
288 7274 : initTLMap();
289 : // initialise edge storage for gui
290 7274 : const MSEdgeVector& edges = MSEdge::getAllEdges();
291 7274 : myEdgeWrapper.reserve(edges.size());
292 304441 : for (MSEdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
293 : // VISIM connector edges shall be drawn (they have lanes)
294 297167 : if (!(*i)->isTazConnector() || (*i)->getLanes().size() > 0) {
295 294027 : myEdgeWrapper.push_back(static_cast<GUIEdge*>(*i));
296 : }
297 : }
298 : // initialise junction storage for gui
299 7274 : int size = myJunctions->size();
300 7274 : myJunctionWrapper.reserve(size);
301 : std::map<MSJunction*, std::string> junction2TLL;
302 27538 : for (const auto tls : getTLSControl().getAllLogics()) {
303 228713 : for (const auto& links : tls->getLinks()) {
304 416590 : for (const MSLink* l : links) {
305 416282 : junction2TLL[l->getJunction()] = l->getTLLogic()->getID();
306 : }
307 : }
308 7274 : }
309 93760 : for (const auto& i : *myJunctions) {
310 86486 : myJunctionWrapper.push_back(new GUIJunctionWrapper(*i.second, junction2TLL[i.second]));
311 : }
312 : // build the visualization tree
313 301301 : for (std::vector<GUIEdge*>::iterator i = myEdgeWrapper.begin(); i != myEdgeWrapper.end(); ++i) {
314 294027 : GUIEdge* edge = *i;
315 294027 : Boundary b;
316 : const std::vector<MSLane*>& lanes = edge->getLanes();
317 639541 : for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
318 345514 : b.add((*j)->getShape().getBoxBoundary());
319 : }
320 : // make sure persons are always drawn and selectable since they depend on their edge being drawn
321 294027 : b.grow(MSPModel::SIDEWALK_OFFSET + 1 + lanes.front()->getWidth() / 2);
322 294027 : const float cmin[2] = { (float)b.xmin(), (float)b.ymin() };
323 294027 : const float cmax[2] = { (float)b.xmax(), (float)b.ymax() };
324 294027 : myGrid.Insert(cmin, cmax, edge);
325 294027 : myBoundary.add(b);
326 294027 : if (myBoundary.getWidth() > 10e16 || myBoundary.getHeight() > 10e16) {
327 0 : throw ProcessError(TL("Network size exceeds 1 Lightyear. Please reconsider your inputs.\n"));
328 : }
329 294027 : }
330 93760 : for (std::vector<GUIJunctionWrapper*>::iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
331 86486 : GUIJunctionWrapper* junction = *i;
332 : Boundary b = junction->getBoundary();
333 86486 : b.grow(2.);
334 86486 : const float cmin[2] = { (float)b.xmin(), (float)b.ymin() };
335 86486 : const float cmax[2] = { (float)b.xmax(), (float)b.ymax() };
336 86486 : myGrid.Insert(cmin, cmax, junction);
337 86486 : myBoundary.add(b);
338 86486 : }
339 7274 : myGrid.add(myBoundary);
340 :
341 14548 : if (OptionsCont::getOptions().isSet("alternative-net-file")) {
342 : // build secondary visualization tree
343 0 : for (GUIEdge* edge : myEdgeWrapper) {
344 0 : Boundary b;
345 0 : for (MSLane* lane : edge->getLanes()) {
346 0 : b.add(static_cast<GUILane*>(lane)->getShape(true).getBoxBoundary());
347 : }
348 : // make sure persons are always drawn and selectable since they depend on their edge being drawn
349 0 : b.grow(MSPModel::SIDEWALK_OFFSET + 1);
350 0 : const float cmin[2] = { (float)b.xmin(), (float)b.ymin() };
351 0 : const float cmax[2] = { (float)b.xmax(), (float)b.ymax() };
352 0 : myGrid2.Insert(cmin, cmax, edge);
353 0 : }
354 0 : for (std::vector<GUIJunctionWrapper*>::iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
355 0 : GUIJunctionWrapper* junction = *i;
356 0 : Position pos = junction->getJunction().getPosition(true);
357 0 : Boundary b = Boundary(pos.x() - 3., pos.y() - 3., pos.x() + 3., pos.y() + 3.);
358 0 : const float cmin[2] = { (float)b.xmin(), (float)b.ymin() };
359 0 : const float cmax[2] = { (float)b.xmax(), (float)b.ymax() };
360 0 : myGrid2.Insert(cmin, cmax, junction);
361 0 : }
362 : }
363 7274 : }
364 :
365 :
366 : void
367 3006 : GUINet::registerRenderedObject(GUIGlObject* o) {
368 3006 : getVisualisationSpeedUp().addAdditionalGLObject(o);
369 6012 : if (OptionsCont::getOptions().isSet("alternative-net-file")) {
370 0 : GUIGlobals::gSecondaryShape = true;
371 0 : myGrid2.addAdditionalGLObject(o);
372 0 : GUIGlobals::gSecondaryShape = false;
373 : }
374 3006 : }
375 :
376 :
377 : int
378 0 : GUINet::getWholeDuration() const {
379 0 : return myLastSimDuration +/*myLastVisDuration+*/myLastIdleDuration;
380 : }
381 :
382 :
383 : int
384 0 : GUINet::getSimDuration() const {
385 0 : return myLastSimDuration;
386 : }
387 :
388 : /*
389 : int
390 : GUINet::getVisDuration() const
391 : {
392 : return myLastVisDuration;
393 : }
394 : */
395 :
396 :
397 : double
398 0 : GUINet::getRTFactor() const {
399 0 : if (myLastSimDuration == 0) {
400 : return -1;
401 : }
402 0 : return (double)DELTA_T / (double)myLastSimDuration;
403 : }
404 :
405 :
406 : double
407 0 : GUINet::getUPS() const {
408 0 : if (myLastSimDuration == 0) {
409 : return -1;
410 : }
411 0 : return (double) myLastVehicleMovementCount / (double) myLastSimDuration * (double) 1000.;
412 : }
413 :
414 :
415 : double
416 0 : GUINet::getMeanRTFactor(int duration) const {
417 0 : if (myOverallSimDuration == 0) {
418 : return -1;
419 : }
420 0 : return ((double)(duration) * (double) 1000. / (double)myOverallSimDuration);
421 : }
422 :
423 :
424 : double
425 0 : GUINet::getMeanUPS() const {
426 0 : if (myOverallSimDuration == 0) {
427 : return -1;
428 : }
429 0 : return ((double)myVehiclesMoved / (double)myOverallSimDuration * (double) 1000.);
430 : }
431 :
432 :
433 : int
434 0 : GUINet::getIdleDuration() const {
435 0 : return myLastIdleDuration;
436 : }
437 :
438 :
439 : void
440 5836494 : GUINet::setSimDuration(int val) {
441 5836494 : myLastSimDuration = val;
442 5836494 : myOverallSimDuration += val;
443 5836494 : myLastVehicleMovementCount = getVehicleControl().getRunningVehicleNo();
444 5836494 : myOverallVehicleCount += myLastVehicleMovementCount;
445 5836494 : }
446 :
447 : /*
448 : void
449 : GUINet::setVisDuration(int val)
450 : {
451 : myLastVisDuration = val;
452 : }
453 : */
454 :
455 : void
456 5829447 : GUINet::setIdleDuration(int val) {
457 5829447 : myLastIdleDuration = val;
458 5829447 : }
459 :
460 :
461 : GUIGLObjectPopupMenu*
462 0 : GUINet::getPopUpMenu(GUIMainWindow& app,
463 : GUISUMOAbstractView& parent) {
464 0 : GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
465 0 : buildPopupHeader(ret, app);
466 0 : buildCenterPopupEntry(ret);
467 0 : buildShowParamsPopupEntry(ret);
468 0 : buildPositionCopyEntry(ret, app);
469 0 : if (GeoConvHelper::getFinal().usingGeoProjection()) {
470 0 : GUIDesigns::buildFXMenuCommand(ret, TL("Copy view geo-boundary to clipboard"), nullptr, ret, MID_COPY_VIEW_GEOBOUNDARY);
471 : }
472 0 : return ret;
473 : }
474 :
475 :
476 : GUIParameterTableWindow*
477 0 : GUINet::getParameterWindow(GUIMainWindow& app,
478 : GUISUMOAbstractView& parent) {
479 0 : GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
480 : // add items
481 0 : ret->mkItem(TL("loaded vehicles [#]"), true,
482 0 : new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getLoadedVehicleNo));
483 0 : ret->mkItem(TL("insertion-backlogged vehicles [#]"), true,
484 0 : new FunctionBinding<MSInsertionControl, int>(&getInsertionControl(), &MSInsertionControl::getWaitingVehicleNo));
485 0 : ret->mkItem(TL("departed vehicles [#]"), true,
486 0 : new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getDepartedVehicleNo));
487 0 : ret->mkItem(TL("running vehicles [#]"), true,
488 0 : new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getRunningVehicleNo));
489 0 : ret->mkItem(TL("arrived vehicles [#]"), true,
490 0 : new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getArrivedVehicleNo));
491 0 : ret->mkItem(TL("discarded vehicles [#]"), true,
492 0 : new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getDiscardedVehicleNo));
493 0 : ret->mkItem(TL("collisions [#]"), true,
494 0 : new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getCollisionCount));
495 0 : ret->mkItem(TL("teleports [#]"), true,
496 0 : new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getTeleportCount));
497 0 : ret->mkItem(TL("halting [#]"), true,
498 0 : new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getHaltingVehicleNo));
499 0 : ret->mkItem(TL("stopped [#]"), true,
500 0 : new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getStoppedVehiclesCount));
501 0 : ret->mkItem(TL("avg. speed [m/s]"), true,
502 0 : new FunctionBinding<MSVehicleControl, double>(&getVehicleControl(), &MSVehicleControl::getVehicleMeanSpeed));
503 0 : ret->mkItem(TL("avg. relative speed"), true,
504 0 : new FunctionBinding<MSVehicleControl, double>(&getVehicleControl(), &MSVehicleControl::getVehicleMeanSpeedRelative));
505 0 : if (myPersonControl != nullptr) {
506 0 : ret->mkItem(TL("loaded persons [#]"), true,
507 0 : new FunctionBinding<MSTransportableControl, int>(&getPersonControl(), &MSTransportableControl::getLoadedNumber));
508 0 : ret->mkItem(TL("running persons [#]"), true,
509 0 : new FunctionBinding<MSTransportableControl, int>(&getPersonControl(), &MSTransportableControl::getRunningNumber));
510 0 : ret->mkItem(TL("jammed persons [#]"), true,
511 0 : new FunctionBinding<MSTransportableControl, int>(&getPersonControl(), &MSTransportableControl::getJammedNumber));
512 : }
513 0 : ret->mkItem(TL("end time [s]"), false, OptionsCont::getOptions().getString("end"));
514 0 : ret->mkItem(TL("begin time [s]"), false, OptionsCont::getOptions().getString("begin"));
515 : // ret->mkItem(TL("time step [s]"), true, new FunctionBinding<GUINet, SUMOTime>(this, &GUINet::getCurrentTimeStep));
516 0 : if (logSimulationDuration()) {
517 0 : ret->mkItem(TL("step duration [ms]"), true, new FunctionBinding<GUINet, int>(this, &GUINet::getWholeDuration));
518 0 : ret->mkItem(TL("FPS"), true, new FunctionBinding<GUISUMOAbstractView, double>(&parent, &GUISUMOAbstractView::getFPS));
519 0 : ret->mkItem(TL("simulation duration [ms]"), true, new FunctionBinding<GUINet, int>(this, &GUINet::getSimDuration));
520 : /*
521 : ret->mkItem(TL("visualisation duration [ms]"), true,
522 : new CastingFunctionBinding<GUINet, double, int>(
523 : &(getNet()), &GUINet::getVisDuration));
524 : */
525 0 : ret->mkItem(TL("idle duration [ms]"), true, new FunctionBinding<GUINet, int>(this, &GUINet::getIdleDuration));
526 0 : ret->mkItem(TL("duration factor"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getRTFactor));
527 : /*
528 : ret->mkItem(TL("mean duration factor []"), true,
529 : new FuncBinding_IntParam<GUINet, double>(
530 : &(getNet()), &GUINet::getMeanRTFactor), 1);
531 : */
532 0 : ret->mkItem(TL("updates per second"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getUPS));
533 0 : ret->mkItem(TL("avg. updates per second"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getMeanUPS));
534 : }
535 0 : if (OptionsCont::getOptions().isSet("tripinfo-output") || OptionsCont::getOptions().getBool("duration-log.statistics")) {
536 0 : ret->mkItem(TL("avg. trip length [m]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgRouteLength));
537 0 : ret->mkItem(TL("avg. trip duration [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgDuration));
538 0 : ret->mkItem(TL("avg. trip waiting time [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgWaitingTime));
539 0 : ret->mkItem(TL("avg. trip time loss [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgTimeLoss));
540 0 : ret->mkItem(TL("avg. trip depart delay [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgDepartDelay));
541 0 : ret->mkItem(TL("avg. trip speed [m/s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgTripSpeed));
542 0 : if (myPersonControl != nullptr) {
543 0 : ret->mkItem(TL("avg. walk length [m]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgWalkRouteLength));
544 0 : ret->mkItem(TL("avg. walk duration [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgWalkDuration));
545 0 : ret->mkItem(TL("avg. walk time loss [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgWalkTimeLoss));
546 : }
547 : }
548 0 : ret->mkItem(TL("nodes [#]"), false, (int)getJunctionIDs(false).size());
549 0 : ret->mkItem(TL("edges [#]"), false, (int)GUIEdge::getIDs(false).size());
550 0 : ret->mkItem(TL("total edge length [km]"), false, GUIEdge::getTotalLength(false, false) / 1000);
551 0 : ret->mkItem(TL("total lane length [km]"), false, GUIEdge::getTotalLength(false, true) / 1000);
552 0 : ret->mkItem(TL("network version "), false, toString(myVersion));
553 :
554 : // close building
555 0 : ret->closeBuilding();
556 0 : return ret;
557 : }
558 :
559 :
560 : void
561 0 : GUINet::drawGL(const GUIVisualizationSettings& /*s*/) const {
562 0 : }
563 :
564 :
565 : Boundary
566 0 : GUINet::getCenteringBoundary() const {
567 0 : return getBoundary();
568 : }
569 :
570 :
571 : GUINet*
572 873429 : GUINet::getGUIInstance() {
573 873429 : GUINet* net = dynamic_cast<GUINet*>(MSNet::getInstance());
574 873429 : if (net != nullptr) {
575 873429 : return net;
576 : }
577 0 : throw ProcessError("A gui-network was not yet constructed.");
578 : }
579 :
580 :
581 : GUIVehicleControl*
582 0 : GUINet::getGUIVehicleControl() {
583 0 : return dynamic_cast<GUIVehicleControl*>(myVehicleControl);
584 : }
585 :
586 :
587 : void
588 3 : GUINet::lock() {
589 3 : myLock.lock();
590 3 : }
591 :
592 :
593 : void
594 3 : GUINet::unlock() {
595 3 : myLock.unlock();
596 3 : }
597 :
598 : GUIMEVehicleControl*
599 323253 : GUINet::getGUIMEVehicleControl() {
600 323253 : return dynamic_cast<GUIMEVehicleControl*>(myVehicleControl);
601 : }
602 :
603 :
604 : double
605 0 : GUINet::getEdgeData(const MSEdge* edge, const std::string& attr) {
606 : auto it = myLoadedEdgeData.find(attr);
607 0 : if (it != myLoadedEdgeData.end()) {
608 : double value;
609 0 : bool found = it->second->retrieveExistingEffort(edge, STEPS2TIME(getCurrentTimeStep()), value);
610 0 : if (found) {
611 0 : return value;
612 : } else {
613 0 : return GUIVisualizationSettings::MISSING_DATA;
614 : }
615 : } else {
616 0 : return GUIVisualizationSettings::MISSING_DATA;
617 : }
618 : }
619 :
620 :
621 : double
622 0 : GUINet::getMeanData(const MSLane* lane, const std::string& id, const std::string& attr) {
623 0 : auto item = myDetectorControl->getMeanData().find(id);
624 0 : if (item != myDetectorControl->getMeanData().end() && !item->second.empty()) {
625 0 : SumoXMLAttr a = (SumoXMLAttr)SUMOXMLDefinitions::Attrs.get(attr);
626 0 : return item->second.front()->getAttributeValue(lane, a, GUIVisualizationSettings::MISSING_DATA);
627 : } else {
628 0 : return GUIVisualizationSettings::MISSING_DATA;
629 : }
630 : }
631 :
632 :
633 : void
634 0 : GUINet::DiscoverAttributes::myStartElement(int element, const SUMOSAXAttributes& attrs) {
635 0 : if (element == SUMO_TAG_EDGE || element == SUMO_TAG_LANE) {
636 0 : std::vector<std::string> tmp = attrs.getAttributeNames();
637 : edgeAttrs.insert(tmp.begin(), tmp.end());
638 0 : } else if (element == SUMO_TAG_EDGEREL) {
639 0 : for (const std::string& a : attrs.getAttributeNames()) {
640 0 : if (a != "from" && a != "to") {
641 : edgeAttrs.insert(a);
642 : }
643 0 : }
644 0 : } else if (element == SUMO_TAG_INTERVAL) {
645 : bool ok;
646 0 : numIntervals++;
647 0 : firstIntervalBegin = MIN2(firstIntervalBegin, attrs.getSUMOTimeReporting(SUMO_ATTR_BEGIN, nullptr, ok));
648 0 : lastIntervalEnd = MAX2(lastIntervalEnd, attrs.getSUMOTimeReporting(SUMO_ATTR_END, nullptr, ok));
649 : }
650 0 : }
651 :
652 :
653 : std::vector<std::string>
654 0 : GUINet::DiscoverAttributes::getEdgeAttrs() {
655 0 : edgeAttrs.erase(toString(SUMO_ATTR_ID));
656 0 : return std::vector<std::string>(edgeAttrs.begin(), edgeAttrs.end());
657 : }
658 :
659 :
660 : void
661 0 : GUINet::EdgeFloatTimeLineRetriever_GUI::addEdgeWeight(const std::string& id,
662 : double value, double begTime, double endTime) const {
663 0 : MSEdge* const edge = MSEdge::dictionary(id);
664 0 : if (edge != nullptr) {
665 0 : myWeightStorage->addEffort(edge, begTime, endTime, value);
666 : } else {
667 0 : WRITE_WARNINGF(TL("Trying to set data value for the unknown edge '%'."), id);
668 : }
669 0 : }
670 :
671 :
672 : void
673 0 : GUINet::EdgeFloatTimeLineRetriever_GUI::addEdgeRelWeight(const std::string& from, const std::string& to,
674 : double val, double beg, double end) const {
675 0 : MSEdge* const fromEdge = MSEdge::dictionary(from);
676 0 : MSEdge* const toEdge = MSEdge::dictionary(to);
677 : bool haveRel = false;
678 0 : if (fromEdge != nullptr && toEdge != nullptr) {
679 0 : for (auto item : fromEdge->getViaSuccessors()) {
680 0 : if (item.first == toEdge) {
681 : const MSEdge* edge = item.second;
682 0 : while (edge != nullptr && edge->isInternal()) {
683 0 : myWeightStorage->addEffort(edge, beg, end, val);
684 0 : edge = edge->getViaSuccessors().front().second;
685 : haveRel = true;
686 : }
687 : }
688 : }
689 : }
690 0 : if (!haveRel) {
691 0 : WRITE_WARNINGF(TL("Trying to set data value for the unknown relation from edge '%' to edge '%'."), from, to);
692 : }
693 0 : }
694 :
695 :
696 : bool
697 0 : GUINet::loadEdgeData(const std::string& file) {
698 : // discover edge attributes
699 0 : DiscoverAttributes discoveryHandler(file);
700 0 : XMLSubSys::runParser(discoveryHandler, file);
701 0 : std::vector<std::string> attrs = discoveryHandler.getEdgeAttrs();
702 0 : WRITE_MESSAGE("Loading edgedata from '" + file + "':"
703 : + "\n " + toString(discoveryHandler.numIntervals) + " intervals between"
704 : + " " + time2string(discoveryHandler.firstIntervalBegin) + " and"
705 : + " " + time2string(discoveryHandler.lastIntervalEnd)
706 : + ".\n Found " + toString(attrs.size())
707 : + " attributes: " + toString(attrs));
708 0 : if (discoveryHandler.lastIntervalEnd < string2time(OptionsCont::getOptions().getString("begin"))) {
709 0 : WRITE_WARNING(TL("No data defined after simulation begin time."));
710 : }
711 0 : myEdgeDataEndTime = MAX2(myEdgeDataEndTime, discoveryHandler.lastIntervalEnd);
712 : // create a retriever for each attribute
713 : std::vector<EdgeFloatTimeLineRetriever_GUI> retrieverDefsInternal;
714 0 : retrieverDefsInternal.reserve(attrs.size());
715 : std::vector<SAXWeightsHandler::ToRetrieveDefinition*> retrieverDefs;
716 0 : for (const std::string& attr : attrs) {
717 0 : MSEdgeWeightsStorage* ws = new MSEdgeWeightsStorage();
718 0 : myLoadedEdgeData[attr] = ws;
719 0 : retrieverDefsInternal.push_back(EdgeFloatTimeLineRetriever_GUI(ws));
720 0 : retrieverDefs.push_back(new SAXWeightsHandler::ToRetrieveDefinition(attr, true, retrieverDefsInternal.back()));
721 : }
722 0 : SAXWeightsHandler handler(retrieverDefs, "");
723 0 : return XMLSubSys::runParser(handler, file);
724 0 : }
725 :
726 :
727 : std::vector<std::string>
728 0 : GUINet::getEdgeDataAttrs() const {
729 : std::vector<std::string> result;
730 0 : for (const auto& item : myLoadedEdgeData) {
731 0 : result.push_back(item.first);
732 : }
733 0 : return result;
734 0 : }
735 :
736 :
737 : std::vector<std::string>
738 0 : GUINet::getMeanDataIDs() const {
739 : std::vector<std::string> result;
740 :
741 0 : for (auto item : myDetectorControl->getMeanData()) {
742 0 : result.push_back(item.first);
743 : }
744 0 : std::sort(result.begin(), result.end());
745 0 : return result;
746 0 : }
747 :
748 : std::vector<std::string>
749 0 : GUINet::getMeanDataAttrs(const std::string& meanDataID) const {
750 0 : auto item = myDetectorControl->getMeanData().find(meanDataID);
751 0 : if (item != myDetectorControl->getMeanData().end() && !item->second.empty()) {
752 0 : return item->second.front()->getAttributeNames();
753 : } else {
754 0 : return std::vector<std::string>();
755 : }
756 : }
757 :
758 :
759 : bool
760 0 : GUINet::isSelected(const MSTrafficLightLogic* tll) const {
761 : const auto it = myLogics2Wrapper.find(const_cast<MSTrafficLightLogic*>(tll));
762 0 : return it != myLogics2Wrapper.end() && gSelected.isSelected(GLO_TLLOGIC, it->second->getGlID());
763 : }
764 :
765 : void
766 34 : GUINet::updateGUI() const {
767 : try {
768 : // gui only
769 34 : GUIApplicationWindow* aw = static_cast<GUIApplicationWindow*>(GUIMainWindow::getInstance());
770 : // update the view
771 34 : aw->handleEvent_SimulationStep(nullptr);
772 0 : } catch (ProcessError&) { }
773 34 : }
774 :
775 : void
776 0 : GUINet::addHotkey(int key, Command* press, Command* release) {
777 : try {
778 : // gui only
779 0 : GUIApplicationWindow* aw = static_cast<GUIApplicationWindow*>(GUIMainWindow::getInstance());
780 : // update the view
781 0 : aw->addHotkey(key, press, release);
782 0 : } catch (ProcessError&) { }
783 0 : }
784 :
785 : void
786 0 : GUINet::flushOutputsAtEnd() {
787 0 : mySkipFinalReset = true;
788 0 : myDetectorControl->close(SIMSTEP);
789 0 : OutputDevice::flushAll();
790 : // update tracker windows
791 0 : guiSimulationStep();
792 0 : }
793 :
794 : #ifdef HAVE_OSG
795 : void
796 11672 : GUINet::updateColor(const GUIVisualizationSettings& s) {
797 191421 : for (std::vector<GUIEdge*>::const_iterator i = myEdgeWrapper.begin(); i != myEdgeWrapper.end(); ++i) {
798 179749 : if (!(*i)->isInternal()) {
799 : const std::vector<MSLane*>& lanes = (*i)->getLanes();
800 209698 : for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
801 134097 : static_cast<GUILane*>(*j)->updateColor(s);
802 : }
803 : }
804 : }
805 97554 : for (std::vector<GUIJunctionWrapper*>::iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
806 85882 : (*i)->updateColor(s);
807 : }
808 11672 : }
809 : #endif
810 :
811 :
812 : /****************************************************************************/
|