SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GUIEdge.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // A road/street connecting two junctions (gui-version)
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
13 // Copyright (C) 2001-2013 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
34 #include <vector>
35 #include <cmath>
36 #include <string>
37 #include <algorithm>
42 #include <utils/geom/GeomHelper.h>
45 #include <utils/gui/div/GLHelper.h>
48 #include <microsim/MSBaseVehicle.h>
49 #include <microsim/MSEdge.h>
50 #include <microsim/MSJunction.h>
51 #include <microsim/MSLaneChanger.h>
52 #include <microsim/MSGlobals.h>
55 #include "GUIEdge.h"
56 #include "GUINet.h"
57 #include "GUILane.h"
58 #include "GUIPerson.h"
59 
60 #ifdef HAVE_INTERNAL
61 #include <mesogui/GUIMEVehicleControl.h>
62 #include <mesosim/MESegment.h>
63 #include <mesosim/MELoop.h>
64 #include <mesosim/MEVehicle.h>
65 #endif
66 
67 #ifdef CHECK_MEMORY_LEAKS
68 #include <foreign/nvwa/debug_new.h>
69 #endif // CHECK_MEMORY_LEAKS
70 
71 
72 // ===========================================================================
73 // included modules
74 // ===========================================================================
75 GUIEdge::GUIEdge(const std::string& id, int numericalID,
76  const EdgeBasicFunction function, const std::string& streetName)
77  : MSEdge(id, numericalID, function, streetName),
78  GUIGlObject(GLO_EDGE, id) {}
79 
80 
82  // just to quit cleanly on a failure
83  if (myLock.locked()) {
84  myLock.unlock();
85  }
86 }
87 
88 
89 MSLane&
90 GUIEdge::getLane(size_t laneNo) {
91  assert(laneNo < myLanes->size());
92  return *((*myLanes)[laneNo]);
93 }
94 
95 
96 std::vector<GUIGlID>
97 GUIEdge::getIDs(bool includeInternal) {
98  std::vector<GUIGlID> ret;
99  ret.reserve(MSEdge::myDict.size());
100  for (MSEdge::DictType::iterator i = MSEdge::myDict.begin(); i != MSEdge::myDict.end(); ++i) {
101  GUIEdge* edge = dynamic_cast<GUIEdge*>(i->second);
102  assert(edge);
103  if (edge->getPurpose() != EDGEFUNCTION_INTERNAL || includeInternal) {
104  ret.push_back(edge->getGlID());
105  }
106  }
107  return ret;
108 }
109 
110 
111 Boundary
113  Boundary ret;
114  for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
115  ret.add((*i)->getShape().getBoxBoundary());
116  }
117  ret.grow(10);
118  return ret;
119 }
120 
121 
122 void
123 GUIEdge::fill(std::vector<GUIEdge*>& netsWrappers) {
124  size_t size = MSEdge::dictSize();
125  netsWrappers.reserve(size);
126  for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
127  if (i->second->getPurpose() != MSEdge::EDGEFUNCTION_DISTRICT) {
128  netsWrappers.push_back(static_cast<GUIEdge*>((*i).second));
129  }
130  }
131 }
132 
133 
134 
137  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
138  buildPopupHeader(ret, app);
144  }
145  const SUMOReal pos = getLanes()[0]->getShape().nearest_offset_to_point2D(parent.getPositionInformation());
146  new FXMenuCommand(ret, ("pos: " + toString(pos)).c_str(), 0, 0, 0);
147  buildPositionCopyEntry(ret, false);
148  return ret;
149 }
150 
151 
154  GUISUMOAbstractView& parent) {
155  GUIParameterTableWindow* ret = 0;
156 #ifdef HAVE_INTERNAL
157  ret = new GUIParameterTableWindow(app, *this, 16);
158  // add edge items
159  ret->mkItem("length [m]", false, (*myLanes)[0]->getLength());
160  ret->mkItem("allowed speed [m/s]", false, getAllowedSpeed());
161  ret->mkItem("occupancy [%]", true, new FunctionBinding<GUIEdge, SUMOReal>(this, &GUIEdge::getBruttoOccupancy));
162  ret->mkItem("mean vehicle speed [m/s]", true, new FunctionBinding<GUIEdge, SUMOReal>(this, &GUIEdge::getMeanSpeed));
163  ret->mkItem("flow [veh/h/lane]", true, new FunctionBinding<GUIEdge, SUMOReal>(this, &GUIEdge::getFlow));
164  ret->mkItem("#vehicles", true, new CastingFunctionBinding<GUIEdge, SUMOReal, unsigned int>(this, &GUIEdge::getVehicleNo));
165  ret->mkItem("vehicle ids", false, getVehicleIDs());
166  // add segment items
167  MESegment* segment = getSegmentAtPosition(parent.getPositionInformation());
168  ret->mkItem("segment index", false, segment->getIndex());
169  ret->mkItem("segment length [m]", false, segment->getLength());
170  ret->mkItem("segment allowed speed [m/s]", false, segment->getMaxSpeed());
171  ret->mkItem("segment jam threshold [%]", false, segment->getRelativeJamThreshold());
172  ret->mkItem("segment occupancy [%]", true, new FunctionBinding<MESegment, SUMOReal>(segment, &MESegment::getRelativeOccupancy));
173  ret->mkItem("segment mean vehicle speed [m/s]", true, new FunctionBinding<MESegment, SUMOReal>(segment, &MESegment::getMeanSpeed));
174  ret->mkItem("segment flow [veh/h/lane]", true, new FunctionBinding<MESegment, SUMOReal>(segment, &MESegment::getFlow));
175  ret->mkItem("segment #vehicles", true, new CastingFunctionBinding<MESegment, SUMOReal, size_t>(segment, &MESegment::getCarNumber));
176  ret->mkItem("segment leader leave time", true, new FunctionBinding<MESegment, SUMOReal>(segment, &MESegment::getEventTimeSeconds));
177 
178  // close building
179  ret->closeBuilding();
180 #else
181  UNUSED_PARAMETER(app);
182  UNUSED_PARAMETER(parent);
183 #endif
184  return ret;
185 }
186 
187 
188 Boundary
190  Boundary b = getBoundary();
191  b.grow(20);
192  return b;
193 }
194 
195 
196 void
199  return;
200  }
202  glPushName(getGlID());
203  }
204  // draw the lanes
205  for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
206 #ifdef HAVE_INTERNAL
208  setColor(s);
209  }
210 #endif
211  GUILane* l = dynamic_cast<GUILane*>(*i);
212  if (l != 0) {
213  l->drawGL(s);
214  }
215  }
216 #ifdef HAVE_INTERNAL
218  const GUIVisualizationTextSettings& nameSettings = s.vehicleName;
219  GUIMEVehicleControl* vehicleControl = GUINet::getGUIInstance()->getGUIMEVehicleControl();
220  if (vehicleControl != 0) {
221  // draw the meso vehicles
222  vehicleControl->secureVehicles();
223  size_t laneIndex = 0;
224  MESegment::Queue queue;
225  for (std::vector<MSLane*>::const_iterator msl = myLanes->begin(); msl != myLanes->end(); ++msl, ++laneIndex) {
226  GUILane* l = static_cast<GUILane*>(*msl);
227  const PositionVector& shape = l->getShape();
228  const std::vector<SUMOReal>& shapeRotations = l->getShapeRotations();
229  const std::vector<SUMOReal>& shapeLengths = l->getShapeLengths();
230  const Position& laneBeg = shape[0];
231  glPushMatrix();
232  glTranslated(laneBeg.x(), laneBeg.y(), 0);
233  glRotated(shapeRotations[0], 0, 0, 1);
234  // go through the vehicles
235  int shapeIndex = 0;
236  SUMOReal shapeOffset = 0; // ofset at start of current shape
237  SUMOReal segmentOffset = 0; // offset at start of current segment
238  for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this);
239  segment != 0; segment = segment->getNextSegment()) {
240  const SUMOReal length = segment->getLength();
241  if (laneIndex < segment->numQueues()) {
242  // make a copy so we don't have to worry about synchronization
243  queue = segment->getQueue(laneIndex);
244  const SUMOReal avgCarSize = segment->getBruttoOccupancy() / segment->getCarNumber();
245  const size_t queueSize = queue.size();
246  for (size_t i = 0; i < queueSize; ++i) {
247  MSBaseVehicle* veh = queue[queueSize - i - 1];
248  setVehicleColor(s, veh);
249  SUMOReal vehiclePosition = segmentOffset + length - i * avgCarSize;
250  SUMOReal xOff = 0.f;
251  while (vehiclePosition < segmentOffset) {
252  // if there is only a single queue for a
253  // multi-lane edge shift vehicles and start
254  // drawing again from the end of the segment
255  vehiclePosition += length;
256  xOff += 0.5f;
257  }
258  while (shapeIndex < (int)shapeRotations.size() - 1 && vehiclePosition > shapeOffset + shapeLengths[shapeIndex]) {
259  glPopMatrix();
260  shapeOffset += shapeLengths[shapeIndex];
261  shapeIndex++;
262  glPushMatrix();
263  glTranslated(shape[shapeIndex].x(), shape[shapeIndex].y(), 0);
264  glRotated(shapeRotations[shapeIndex], 0, 0, 1);
265  }
266  glPushMatrix();
267  glTranslated(xOff, -(vehiclePosition - shapeOffset), GLO_VEHICLE);
268  glPushMatrix();
269  glScaled(1, avgCarSize, 1);
270  glBegin(GL_TRIANGLES);
271  glVertex2d(0, 0);
272  glVertex2d(0 - 1.25, 1);
273  glVertex2d(0 + 1.25, 1);
274  glEnd();
275  glPopMatrix();
276  glPopMatrix();
277  if (nameSettings.show) {
278  GLHelper::drawText(veh->getID(),
279  Position(xOff, -(vehiclePosition - shapeOffset)),
280  GLO_MAX, nameSettings.size / s.scale, nameSettings.color, 0);
281  }
282  }
283  }
284  segmentOffset += length;
285  }
286  glPopMatrix();
287  }
288  vehicleControl->releaseVehicles();
289  }
290  glPopName();
291  }
292 #endif
293  // (optionally) draw the name and/or the street name
294  const bool drawEdgeName = s.edgeName.show && myFunction == EDGEFUNCTION_NORMAL;
295  const bool drawInternalEdgeName = s.internalEdgeName.show && myFunction != EDGEFUNCTION_NORMAL;
296  const bool drawStreetName = s.streetName.show && myStreetName != "";
297  if (drawEdgeName || drawInternalEdgeName || drawStreetName) {
298  GUILane* lane1 = dynamic_cast<GUILane*>((*myLanes)[0]);
299  GUILane* lane2 = dynamic_cast<GUILane*>((*myLanes).back());
300  if (lane1 != 0 && lane2 != 0) {
301  Position p = lane1->getShape().positionAtOffset(lane1->getShape().length() / (SUMOReal) 2.);
302  p.add(lane2->getShape().positionAtOffset(lane2->getShape().length() / (SUMOReal) 2.));
303  p.mul(.5);
304  SUMOReal angle = lane1->getShape().rotationDegreeAtOffset(lane1->getShape().length() / (SUMOReal) 2.);
305  angle += 90;
306  if (angle > 90 && angle < 270) {
307  angle -= 180;
308  }
309  if (drawEdgeName) {
310  drawName(p, s.scale, s.edgeName, angle);
311  } else if (drawInternalEdgeName) {
312  drawName(p, s.scale, s.internalEdgeName, angle);
313  }
314  if (drawStreetName) {
316  s.streetName.size / s.scale, s.streetName.color, angle);
317  }
318  }
319  }
320  myLock.lock();
321  for (std::set<MSPerson*>::const_iterator i = myPersons.begin(); i != myPersons.end(); ++i) {
322  GUIPerson* person = dynamic_cast<GUIPerson*>(*i);
323  assert(person != 0);
324  person->drawGL(s);
325  }
326  myLock.unlock();
327 }
328 
329 #ifdef HAVE_INTERNAL
330 unsigned int
331 GUIEdge::getVehicleNo() const {
332  size_t vehNo = 0;
333  for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != 0; segment = segment->getNextSegment()) {
334  vehNo += segment->getCarNumber();
335  }
336  return (unsigned int)vehNo;
337 }
338 
339 
340 std::string
341 GUIEdge::getVehicleIDs() const {
342  std::string result = " ";
343  std::vector<const MEVehicle*> vehs;
344  for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != 0; segment = segment->getNextSegment()) {
345  std::vector<const MEVehicle*> segmentVehs = segment->getVehicles();
346  vehs.insert(vehs.end(), segmentVehs.begin(), segmentVehs.end());
347  }
348  for (std::vector<const MEVehicle*>::const_iterator it = vehs.begin(); it != vehs.end(); it++) {
349  result += (*it)->getID() + " ";
350  }
351  return result;
352 }
353 
354 
355 SUMOReal
356 GUIEdge::getFlow() const {
357  SUMOReal flow = 0;
358  for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != 0; segment = segment->getNextSegment()) {
359  flow += (SUMOReal) segment->getCarNumber() * segment->getMeanSpeed();
360  }
361  return 3600 * flow / (*myLanes)[0]->getLength();
362 }
363 
364 
365 SUMOReal
366 GUIEdge::getBruttoOccupancy() const {
367  SUMOReal occ = 0;
368  for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != 0; segment = segment->getNextSegment()) {
369  occ += segment->getBruttoOccupancy();
370  }
371  return occ / (*myLanes)[0]->getLength() / (SUMOReal)(myLanes->size());
372 }
373 
374 
375 SUMOReal
376 GUIEdge::getMeanSpeed() const {
377  SUMOReal v = 0;
378  SUMOReal no = 0;
379  for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != 0; segment = segment->getNextSegment()) {
380  SUMOReal vehNo = (SUMOReal) segment->getCarNumber();
381  v += vehNo * segment->getMeanSpeed();
382  no += vehNo;
383  }
384  if (no == 0) {
385  return getSpeedLimit();
386  }
387  return v / no;
388 }
389 
390 
391 SUMOReal
392 GUIEdge::getAllowedSpeed() const {
393  return (*myLanes)[0]->getSpeedLimit();
394 }
395 
396 
397 SUMOReal
398 GUIEdge::getRelativeSpeed() const {
399  return getMeanSpeed() / getAllowedSpeed();
400 }
401 
402 
403 void
404 GUIEdge::setColor(const GUIVisualizationSettings& s) const {
405  GLHelper::setColor(s.edgeColorer.getScheme().getColor(getColorValue(s.edgeColorer.getActive())));
406 }
407 
408 
409 SUMOReal
410 GUIEdge::getColorValue(size_t activeScheme) const {
411  switch (activeScheme) {
412  case 1:
413  return gSelected.isSelected(getType(), getGlID());
414  case 2:
415  return getPurpose();
416  case 3:
417  return getAllowedSpeed();
418  case 4:
419  return getBruttoOccupancy();
420  case 5:
421  return getMeanSpeed();
422  case 6:
423  return getFlow();
424  case 7:
425  return getRelativeSpeed();
426  }
427  return 0;
428 }
429 
430 
431 MESegment*
432 GUIEdge::getSegmentAtPosition(const Position& pos) {
433  const PositionVector& shape = getLanes()[0]->getShape();
434  const SUMOReal lanePos = shape.nearest_offset_to_point2D(pos);
435  return MSGlobals::gMesoNet->getSegmentForEdge(*this, lanePos);
436 }
437 
438 
439 void
440 GUIEdge::setVehicleColor(const GUIVisualizationSettings& s, MSBaseVehicle* veh) const {
441  const GUIColorer& c = s.vehicleColorer;
442  switch (c.getActive()) {
443  case 0:
444  if (veh->getParameter().wasSet(VEHPARS_COLOR_SET)) {
446  }
449  }
450  if (veh->getRoute().getColor() != RGBColor::DEFAULT_COLOR) {
452  }
453  break;
454  case 2:
456  break;
457  case 4:
459  break;
460  case 5:
462  break;
463  default:
465  }
466 }
467 
468 #endif
469 
470 /****************************************************************************/
471