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.sourceforge.net/
13 // Copyright (C) 2001-2012 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  for (LaneWrapperVector::iterator i = myLaneGeoms.begin(); i != myLaneGeoms.end(); ++i) {
83  delete(*i);
84  }
85  // just to quit cleanly on a failure
86  if (myLock.locked()) {
87  myLock.unlock();
88  }
89 }
90 
91 
92 void
94  // don't do this twice
95  if (myLaneGeoms.size() > 0) {
96  return;
97  }
98  // build the lane wrapper
99  myLaneGeoms.reserve(myLanes->size());
100  for (unsigned int i = 0; i < myLanes->size(); i++) {
101  myLaneGeoms.push_back(myLanes->at(i)->buildLaneWrapper(i));
102  }
103 }
104 
105 
106 MSLane&
107 GUIEdge::getLane(size_t laneNo) {
108  assert(laneNo < myLanes->size());
109  return *((*myLanes)[laneNo]);
110 }
111 
112 
114 GUIEdge::getLaneGeometry(size_t laneNo) const {
115  assert(laneNo < myLanes->size());
116  return *(myLaneGeoms[laneNo]);
117 }
118 
119 
121 GUIEdge::getLaneGeometry(const MSLane* lane) const {
122  LaneWrapperVector::const_iterator i =
123  find_if(myLaneGeoms.begin(), myLaneGeoms.end(), lane_wrapper_finder(*lane));
124  assert(i != myLaneGeoms.end());
125  return *(*i);
126 }
127 
128 
129 std::vector<GUIGlID>
130 GUIEdge::getIDs(bool includeInternal) {
131  std::vector<GUIGlID> ret;
132  ret.reserve(MSEdge::myDict.size());
133  for (MSEdge::DictType::iterator i = MSEdge::myDict.begin(); i != MSEdge::myDict.end(); ++i) {
134  GUIEdge* edge = dynamic_cast<GUIEdge*>(i->second);
135  assert(edge);
136  if (edge->getPurpose() != EDGEFUNCTION_INTERNAL || includeInternal) {
137  ret.push_back(edge->getGlID());
138  }
139  }
140  return ret;
141 }
142 
143 
144 Boundary
146  Boundary ret;
147  for (LaneWrapperVector::const_iterator i = myLaneGeoms.begin(); i != myLaneGeoms.end(); ++i) {
148  const PositionVector& g = (*i)->getShape();
149  for (unsigned int j = 0; j < g.size(); j++) {
150  ret.add(g[j]);
151  }
152  }
153  ret.grow(10);
154  return ret;
155 }
156 
157 
158 void
159 GUIEdge::fill(std::vector<GUIEdge*>& netsWrappers) {
160  size_t size = MSEdge::dictSize();
161  netsWrappers.reserve(size);
162  for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
163  if (i->second->getPurpose() != MSEdge::EDGEFUNCTION_DISTRICT) {
164  netsWrappers.push_back(static_cast<GUIEdge*>((*i).second));
165  }
166  }
167 }
168 
169 
170 
173  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
174  buildPopupHeader(ret, app);
180  }
181  const SUMOReal pos = getLanes()[0]->getShape().nearest_position_on_line_to_point2D(parent.getPositionInformation());
182  new FXMenuCommand(ret, ("pos: " + toString(pos)).c_str(), 0, 0, 0);
183  buildPositionCopyEntry(ret, false);
184  return ret;
185 }
186 
187 
190  GUISUMOAbstractView& parent) {
191  GUIParameterTableWindow* ret = 0;
192 #ifdef HAVE_INTERNAL
193  ret = new GUIParameterTableWindow(app, *this, 16);
194  // add edge items
195  ret->mkItem("length [m]", false, (*myLanes)[0]->getLength());
196  ret->mkItem("allowed speed [m/s]", false, getAllowedSpeed());
197  ret->mkItem("occupancy [%]", true,
198  new FunctionBinding<GUIEdge, SUMOReal>(this, &GUIEdge::getOccupancy));
199  ret->mkItem("mean vehicle speed [m/s]", true,
200  new FunctionBinding<GUIEdge, SUMOReal>(this, &GUIEdge::getMeanSpeed));
201  ret->mkItem("flow [veh/h/lane]", true,
202  new FunctionBinding<GUIEdge, SUMOReal>(this, &GUIEdge::getFlow));
203  ret->mkItem("#vehicles", true,
204  new CastingFunctionBinding<GUIEdge, SUMOReal, unsigned int>(this, &GUIEdge::getVehicleNo));
205  ret->mkItem("vehicle ids", false, getVehicleIDs());
206  // add segment items
207  MESegment* segment = getSegmentAtPosition(parent.getPositionInformation());
208  ret->mkItem("segment index", false, segment->getIndex());
209  ret->mkItem("segment length [m]", false, segment->getLength());
210  ret->mkItem("segment allowed speed [m/s]", false, segment->getMaxSpeed());
211  ret->mkItem("segment jam threshold [%]", false, segment->getRelativeJamThreshold());
212  ret->mkItem("segment occupancy [%]", true, new FunctionBinding<MESegment, SUMOReal>(segment, &MESegment::getRelativeOccupancy));
213  ret->mkItem("segment mean vehicle speed [m/s]", true, new FunctionBinding<MESegment, SUMOReal>(segment, &MESegment::getMeanSpeed));
214  ret->mkItem("segment flow [veh/h/lane]", true, new FunctionBinding<MESegment, SUMOReal>(segment, &MESegment::getFlow));
215  ret->mkItem("segment #vehicles", true, new CastingFunctionBinding<MESegment, SUMOReal, size_t>(segment, &MESegment::getCarNumber));
216  ret->mkItem("segment leader leave time", true, new FunctionBinding<MESegment, SUMOReal>(segment, &MESegment::getEventTimeSeconds));
217 
218  // close building
219  ret->closeBuilding();
220 #else
221  UNUSED_PARAMETER(app);
222  UNUSED_PARAMETER(parent);
223 #endif
224  return ret;
225 }
226 
227 
228 Boundary
230  Boundary b = getBoundary();
231  b.grow(20);
232  return b;
233 }
234 
235 
236 void
239  return;
240  }
242  glPushName(getGlID());
243  }
244  // draw the lanes
245  for (LaneWrapperVector::const_iterator i = myLaneGeoms.begin(); i != myLaneGeoms.end(); ++i) {
246 #ifdef HAVE_INTERNAL
248  setColor(s);
249  }
250 #endif
251  (*i)->drawGL(s);
252  }
253 #ifdef HAVE_INTERNAL
255  const GUIVisualizationTextSettings& nameSettings = s.vehicleName;
256  GUIMEVehicleControl* vehicleControl = GUINet::getGUIInstance()->getGUIMEVehicleControl();
257  if (vehicleControl != 0) {
258  // draw the meso vehicles
259  vehicleControl->secureVehicles();
260  size_t laneIndex = 0;
261  MESegment::Queue queue;
262  for (LaneWrapperVector::const_iterator l = myLaneGeoms.begin(); l != myLaneGeoms.end(); ++l, ++laneIndex) {
263  const PositionVector& shape = (*l)->getShape();
264  const std::vector<SUMOReal>& shapeRotations = (*l)->getShapeRotations();
265  const std::vector<SUMOReal>& shapeLengths = (*l)->getShapeLengths();
266  const Position& laneBeg = shape[0];
267  glPushMatrix();
268  glTranslated(laneBeg.x(), laneBeg.y(), 0);
269  glRotated(shapeRotations[0], 0, 0, 1);
270  // go through the vehicles
271  int shapeIndex = 0;
272  SUMOReal shapeOffset = 0; // ofset at start of current shape
273  SUMOReal segmentOffset = 0; // offset at start of current segment
274  for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this);
275  segment != 0; segment = segment->getNextSegment()) {
276  const SUMOReal length = segment->getLength();
277  if (laneIndex < segment->numQueues()) {
278  // make a copy so we don't have to worry about synchronization
279  queue = segment->getQueue(laneIndex);
280  const SUMOReal avgCarSize = segment->getOccupancy() / segment->getCarNumber();
281  const size_t queueSize = queue.size();
282  for (size_t i = 0; i < queueSize; i++) {
283  MSBaseVehicle* veh = queue[queueSize - i - 1];
284  setVehicleColor(s, veh);
285  SUMOReal vehiclePosition = segmentOffset + length - i * avgCarSize;
286  SUMOReal xOff = 0.f;
287  while (vehiclePosition < segmentOffset) {
288  // if there is only a single queue for a
289  // multi-lane edge shift vehicles and start
290  // drawing again from the end of the segment
291  vehiclePosition += length;
292  xOff += 0.5f;
293  }
294  while (shapeIndex < (int)shapeRotations.size() - 1 && vehiclePosition > shapeOffset + shapeLengths[shapeIndex]) {
295  glPopMatrix();
296  shapeOffset += shapeLengths[shapeIndex];
297  shapeIndex++;
298  glPushMatrix();
299  glTranslated(shape[shapeIndex].x(), shape[shapeIndex].y(), 0);
300  glRotated(shapeRotations[shapeIndex], 0, 0, 1);
301  }
302  glPushMatrix();
303  glTranslated(xOff, -(vehiclePosition - shapeOffset), GLO_VEHICLE);
304  glPushMatrix();
305  glScaled(1, avgCarSize, 1);
306  glBegin(GL_TRIANGLES);
307  glVertex2d(0, 0);
308  glVertex2d(0 - 1.25, 1);
309  glVertex2d(0 + 1.25, 1);
310  glEnd();
311  glPopMatrix();
312  glPopMatrix();
313  if (nameSettings.show) {
314  GLHelper::drawText(veh->getID(),
315  Position(xOff, -(vehiclePosition - shapeOffset)),
316  GLO_MAX, nameSettings.size / s.scale, nameSettings.color, 0);
317  }
318  }
319  }
320  segmentOffset += length;
321  }
322  glPopMatrix();
323  }
324  vehicleControl->releaseVehicles();
325  }
326  glPopName();
327  }
328 #endif
329  // (optionally) draw the name and/or the street name
330  const bool drawEdgeName = s.edgeName.show && myFunction == EDGEFUNCTION_NORMAL;
331  const bool drawInternalEdgeName = s.internalEdgeName.show && myFunction != EDGEFUNCTION_NORMAL;
332  const bool drawStreetName = s.streetName.show && myStreetName != "";
333  if (drawEdgeName || drawInternalEdgeName || drawStreetName) {
334  GUILaneWrapper* lane1 = myLaneGeoms[0];
335  GUILaneWrapper* lane2 = myLaneGeoms[myLaneGeoms.size() - 1];
336  Position p = lane1->getShape().positionAtLengthPosition(lane1->getShape().length() / (SUMOReal) 2.);
337  p.add(lane2->getShape().positionAtLengthPosition(lane2->getShape().length() / (SUMOReal) 2.));
338  p.mul(.5);
339  SUMOReal angle = lane1->getShape().rotationDegreeAtLengthPosition(lane1->getShape().length() / (SUMOReal) 2.);
340  angle += 90;
341  if (angle > 90 && angle < 270) {
342  angle -= 180;
343  }
344  if (drawEdgeName) {
345  drawName(p, s.scale, s.edgeName, angle);
346  } else if (drawInternalEdgeName) {
347  drawName(p, s.scale, s.internalEdgeName, angle);
348  }
349  if (drawStreetName) {
351  s.streetName.size / s.scale, s.streetName.color, angle);
352  }
353  }
354  myLock.lock();
355  for (std::set<MSPerson*>::const_iterator i = myPersons.begin(); i != myPersons.end(); ++i) {
356  GUIPerson* person = dynamic_cast<GUIPerson*>(*i);
357  assert(person != 0);
358  person->drawGL(s);
359  }
360  myLock.unlock();
361 }
362 
363 #ifdef HAVE_INTERNAL
364 unsigned int
365 GUIEdge::getVehicleNo() const {
366  size_t vehNo = 0;
367  for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != 0; segment = segment->getNextSegment()) {
368  vehNo += segment->getCarNumber();
369  }
370  return (unsigned int)vehNo;
371 }
372 
373 
374 std::string
375 GUIEdge::getVehicleIDs() const {
376  std::string result = " ";
377  std::vector<const MEVehicle*> vehs;
378  for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != 0; segment = segment->getNextSegment()) {
379  std::vector<const MEVehicle*> segmentVehs = segment->getVehicles();
380  vehs.insert(vehs.end(), segmentVehs.begin(), segmentVehs.end());
381  }
382  for (std::vector<const MEVehicle*>::const_iterator it = vehs.begin(); it != vehs.end(); it++) {
383  result += (*it)->getID() + " ";
384  }
385  return result;
386 }
387 
388 
389 SUMOReal
390 GUIEdge::getFlow() const {
391  SUMOReal flow = 0;
392  for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != 0; segment = segment->getNextSegment()) {
393  flow += (SUMOReal) segment->getCarNumber() * segment->getMeanSpeed();
394  }
395  return 3600 * flow / (*myLanes)[0]->getLength();
396 }
397 
398 
399 SUMOReal
400 GUIEdge::getOccupancy() const {
401  SUMOReal occ = 0;
402  for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != 0; segment = segment->getNextSegment()) {
403  occ += segment->getOccupancy();
404  }
405  return occ / (*myLanes)[0]->getLength() / (SUMOReal)(myLanes->size());
406 }
407 
408 
409 SUMOReal
410 GUIEdge::getMeanSpeed() const {
411  SUMOReal v = 0;
412  SUMOReal no = 0;
413  for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != 0; segment = segment->getNextSegment()) {
414  SUMOReal vehNo = (SUMOReal) segment->getCarNumber();
415  v += vehNo * segment->getMeanSpeed();
416  no += vehNo;
417  }
418  if (no == 0) {
419  return getSpeedLimit();
420  }
421  return v / no;
422 }
423 
424 
425 SUMOReal
426 GUIEdge::getAllowedSpeed() const {
427  return (*myLanes)[0]->getSpeedLimit();
428 }
429 
430 
431 SUMOReal
432 GUIEdge::getRelativeSpeed() const {
433  return getMeanSpeed() / getAllowedSpeed();
434 }
435 
436 
437 void
438 GUIEdge::setColor(const GUIVisualizationSettings& s) const {
439  GLHelper::setColor(s.edgeColorer.getScheme().getColor(getColorValue(s.edgeColorer.getActive())));
440 }
441 
442 
443 SUMOReal
444 GUIEdge::getColorValue(size_t activeScheme) const {
445  switch (activeScheme) {
446  case 1:
447  return gSelected.isSelected(getType(), getGlID());
448  case 2:
449  return getPurpose();
450  case 3:
451  return getAllowedSpeed();
452  case 4:
453  return getOccupancy();
454  case 5:
455  return getMeanSpeed();
456  case 6:
457  return getFlow();
458  case 7:
459  return getRelativeSpeed();
460  }
461  return 0;
462 }
463 
464 
465 MESegment*
466 GUIEdge::getSegmentAtPosition(const Position& pos) {
467  const PositionVector& shape = getLanes()[0]->getShape();
468  const SUMOReal lanePos = shape.nearest_position_on_line_to_point2D(pos);
469  return MSGlobals::gMesoNet->getSegmentForEdge(*this, lanePos);
470 }
471 
472 
473 void
474 GUIEdge::setVehicleColor(const GUIVisualizationSettings& s, MSBaseVehicle* veh) const {
475  const GUIColorer& c = s.vehicleColorer;
476  switch (c.getActive()) {
477  case 1:
479  break;
480  case 2:
482  break;
483  case 3:
485  break;
486  default:
488  }
489 }
490 
491 #endif
492 
493 /****************************************************************************/
494