SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GUILane.cpp
Go to the documentation of this file.
1 /****************************************************************************/
9 // Representation of a lane in the micro simulation (gui-version)
10 /****************************************************************************/
11 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
12 // Copyright (C) 2001-2013 DLR (http://www.dlr.de/) and contributors
13 /****************************************************************************/
14 //
15 // This file is part of SUMO.
16 // SUMO is free software: you can redistribute it and/or modify
17 // it under the terms of the GNU General Public License as published by
18 // the Free Software Foundation, either version 3 of the License, or
19 // (at your option) any later version.
20 //
21 /****************************************************************************/
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #include <string>
34 #include <utility>
36 #include <utils/geom/GeomHelper.h>
37 #include <utils/geom/Position.h>
40 #include <utils/geom/GeomHelper.h>
41 #include <utils/gui/div/GLHelper.h>
46 #include <microsim/MSLane.h>
49 #include <microsim/MSNet.h>
51 #include "GUILane.h"
52 #include "GUIEdge.h"
53 #include "GUIVehicle.h"
54 #include "GUINet.h"
55 
56 #ifdef HAVE_OSG
57 #include <osg/Geometry>
58 #endif
59 
60 #ifdef CHECK_MEMORY_LEAKS
61 #include <foreign/nvwa/debug_new.h>
62 #endif // CHECK_MEMORY_LEAKS
63 
64 
65 // ===========================================================================
66 // method definitions
67 // ===========================================================================
68 GUILane::GUILane(const std::string& id, SUMOReal maxSpeed, SUMOReal length,
69  MSEdge* const edge, unsigned int numericalID,
70  const PositionVector& shape, SUMOReal width,
71  SVCPermissions permissions, unsigned int index)
72  : MSLane(id, maxSpeed, length, edge, numericalID, shape, width, permissions),
73  GUIGlObject(GLO_LANE, id) {
74  myShapeRotations.reserve(myShape.size() - 1);
75  myShapeLengths.reserve(myShape.size() - 1);
76  int e = (int) myShape.size() - 1;
77  for (int i = 0; i < e; ++i) {
78  const Position& f = myShape[i];
79  const Position& s = myShape[i + 1];
80  myShapeLengths.push_back(f.distanceTo2D(s));
81  myShapeRotations.push_back(RAD2DEG(atan2(s.x() - f.x(), f.y() - s.y())));
82  }
83  //
86  myIndex = index;
87 }
88 
89 
91  // just to quit cleanly on a failure
92  if (myLock.locked()) {
93  myLock.unlock();
94  }
95 }
96 
97 
98 // ------ Vehicle insertion ------
99 void
101  const MSLane::VehCont::iterator& at,
102  MSMoveReminder::Notification notification) {
104  MSLane::incorporateVehicle(veh, pos, speed, at, notification);
105 }
106 
107 
108 // ------ Access to vehicles ------
109 const MSLane::VehCont&
111  myLock.lock();
112  return myVehicles;
113 }
114 
115 
116 void
118  myLock.unlock();
119 }
120 
121 
122 void
126 }
127 
128 
129 bool
130 GUILane::executeMovements(SUMOTime t, std::vector<MSLane*>& into) {
132  return MSLane::executeMovements(t, into);
133 }
134 
135 
136 MSVehicle*
139  return MSLane::removeVehicle(remVehicle, notification);
140 }
141 
142 
143 void
147 }
148 
149 
150 bool
153  return MSLane::integrateNewVehicle(t);
154 }
155 
156 
157 void
158 GUILane::detectCollisions(SUMOTime timestep, int stage) {
160  MSLane::detectCollisions(timestep, stage);
161 }
162 
163 
164 // ------ Drawing methods ------
165 void
167  unsigned int noLinks = (unsigned int)myLinks.size();
168  if (noLinks == 0) {
169  return;
170  }
171  // draw all links
172  SUMOReal w = myWidth / (SUMOReal) noLinks;
174  glPushMatrix();
175  const PositionVector& g = getShape();
176  const Position& end = g.back();
177  const Position& f = g[-2];
178  const Position& s = end;
179  const SUMOReal rot = RAD2DEG(atan2((s.x() - f.x()), (f.y() - s.y())));
180  glTranslated(end.x(), end.y(), 0);
181  glRotated(rot, 0, 0, 1);
182  for (int i = noLinks; --i >= 0;) {
183  SUMOReal x2 = x1 - (SUMOReal)(w / 2.);
184  GLHelper::drawText(toString(myLinks[i]->getRespondIndex()),
185  Position(x2, 0), 0, .6, RGBColor(128, 128, 255, 255), 180);
186  x1 -= w;
187  }
188  glPopMatrix();
189 }
190 
191 
192 void
193 GUILane::drawTLSLinkNo(const GUINet& net) const {
194  unsigned int noLinks = (unsigned int)myLinks.size();
195  if (noLinks == 0) {
196  return;
197  }
198  // draw all links
199  SUMOReal w = myWidth / (SUMOReal) noLinks;
201  glPushMatrix();
202  const PositionVector& g = getShape();
203  const Position& end = g.back();
204  const Position& f = g[-2];
205  const Position& s = end;
206  const SUMOReal rot = RAD2DEG(atan2((s.x() - f.x()), (f.y() - s.y())));
207  glTranslated(end.x(), end.y(), 0);
208  glRotated(rot, 0, 0, 1);
209  for (int i = noLinks; --i >= 0;) {
210  SUMOReal x2 = x1 - (SUMOReal)(w / 2.);
211  int linkNo = net.getLinkTLIndex(myLinks[i]);
212  if (linkNo < 0) {
213  continue;
214  }
216  Position(x2, 0), 0, .6, RGBColor(128, 128, 255, 255), 180);
217  x1 -= w;
218  }
219  glPopMatrix();
220 }
221 
222 
223 void
224 GUILane::drawLinkRules(const GUINet& net) const {
225  unsigned int noLinks = (unsigned int)myLinks.size();
226  const PositionVector& g = getShape();
227  const Position& end = g.back();
228  const Position& f = g[-2];
229  const Position& s = end;
230  const SUMOReal rot = RAD2DEG(atan2((s.x() - f.x()), (f.y() - s.y())));
231  if (noLinks == 0) {
232  glPushName(getGlID());
233  // draw a grey bar if no links are on the street
234  glColor3d(0.5, 0.5, 0.5);
235  glPushMatrix();
236  glTranslated(end.x(), end.y(), 0);
237  glRotated(rot, 0, 0, 1);
238  glBegin(GL_QUADS);
239  glVertex2d(-myHalfLaneWidth, 0.0);
240  glVertex2d(-myHalfLaneWidth, 0.5);
241  glVertex2d(myHalfLaneWidth, 0.5);
242  glVertex2d(myHalfLaneWidth, 0.0);
243  glEnd();
244  glPopMatrix();
245  glPopName();
246  return;
247  }
248  // draw all links
249  const bool railway = isRailway(myPermissions);
250  SUMOReal w = myWidth / (SUMOReal) noLinks;
251  SUMOReal x1 = 0;
252  glPushMatrix();
253  glTranslated(end.x(), end.y(), 0);
254  glRotated(rot, 0, 0, 1);
255  for (unsigned int i = 0; i < noLinks; ++i) {
256  SUMOReal x2 = x1 + w;
257  MSLink* link = myLinks[i];
258  // select glID
259  switch (link->getState()) {
262  case LINKSTATE_TL_RED:
266  glPushName(net.getLinkTLID(link));
267  break;
268  case LINKSTATE_MAJOR:
269  case LINKSTATE_MINOR:
270  case LINKSTATE_EQUAL:
272  default:
273  glPushName(getGlID());
274  break;
275  }
276  // select color
277  switch (link->getState()) {
280  glColor3d(0, 1, 0);
281  break;
282  case LINKSTATE_TL_RED:
283  glColor3d(1, 0, 0);
284  break;
287  glColor3d(1, 1, 0);
288  break;
290  glColor3d(.7, .7, 0);
291  break;
293  glColor3d(0, 1, 1);
294  break;
295  case LINKSTATE_MAJOR:
296  glColor3d(1, 1, 1);
297  if (railway) {
298  // the white bar should be the default for most railway
299  // links and looks ugly so we do not draw it
300  continue;
301  }
302  break;
303  case LINKSTATE_MINOR:
304  glColor3d(.2, .2, .2);
305  break;
306  case LINKSTATE_STOP:
307  glColor3d(.4, .2, .2);
308  break;
309  case LINKSTATE_EQUAL:
310  glColor3d(.5, .5, .5);
311  break;
313  glColor3d(.2, .2, .4);
314  break;
315  case LINKSTATE_DEADEND:
316  glColor3d(0, 0, 0);
317  break;
318  }
319  glBegin(GL_QUADS);
320  glVertex2d(x1 - myHalfLaneWidth, 0.0);
321  glVertex2d(x1 - myHalfLaneWidth, 0.5);
322  glVertex2d(x2 - myHalfLaneWidth, 0.5);
323  glVertex2d(x2 - myHalfLaneWidth, 0.0);
324  glEnd();
325  glPopName();
326  x1 = x2;
327  x2 += w;
328  }
329  glPopMatrix();
330 }
331 
332 
333 void
335  if (myLinks.size() == 0) {
336  return;
337  }
338  // draw all links
339  const Position& end = getShape().back();
340  const Position& f = getShape()[-2];
341  const SUMOReal rot = RAD2DEG(atan2((end.x() - f.x()), (f.y() - end.y())));
342  glPushMatrix();
343  glPushName(0);
344  glColor3d(1, 1, 1);
345  glTranslated(end.x(), end.y(), 0);
346  glRotated(rot, 0, 0, 1);
347  for (std::vector<MSLink*>::const_iterator i = myLinks.begin(); i != myLinks.end(); ++i) {
348  LinkDirection dir = (*i)->getDirection();
349  LinkState state = (*i)->getState();
350  if (state == LINKSTATE_TL_OFF_NOSIGNAL || dir == LINKDIR_NODIR) {
351  continue;
352  }
353  switch (dir) {
354  case LINKDIR_STRAIGHT:
355  GLHelper::drawBoxLine(Position(0, 4), 0, 2, .05);
357  break;
358  case LINKDIR_TURN:
359  GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
360  GLHelper::drawBoxLine(Position(0, 2.5), 90, .5, .05);
361  GLHelper::drawBoxLine(Position(0.5, 2.5), 180, 1, .05);
362  GLHelper::drawTriangleAtEnd(Line(Position(0.5, 2.5), Position(0.5, 4)), (SUMOReal) 1, (SUMOReal) .25);
363  break;
364  case LINKDIR_LEFT:
365  GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
366  GLHelper::drawBoxLine(Position(0, 2.5), 90, 1, .05);
367  GLHelper::drawTriangleAtEnd(Line(Position(0, 2.5), Position(1.5, 2.5)), (SUMOReal) 1, (SUMOReal) .25);
368  break;
369  case LINKDIR_RIGHT:
370  GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
371  GLHelper::drawBoxLine(Position(0, 2.5), -90, 1, .05);
372  GLHelper::drawTriangleAtEnd(Line(Position(0, 2.5), Position(-1.5, 2.5)), (SUMOReal) 1, (SUMOReal) .25);
373  break;
374  case LINKDIR_PARTLEFT:
375  GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
376  GLHelper::drawBoxLine(Position(0, 2.5), 45, .7, .05);
377  GLHelper::drawTriangleAtEnd(Line(Position(0, 2.5), Position(1.2, 1.3)), (SUMOReal) 1, (SUMOReal) .25);
378  break;
379  case LINKDIR_PARTRIGHT:
380  GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
381  GLHelper::drawBoxLine(Position(0, 2.5), -45, .7, .05);
382  GLHelper::drawTriangleAtEnd(Line(Position(0, 2.5), Position(-1.2, 1.3)), (SUMOReal) 1, (SUMOReal) .25);
383  break;
384  default:
385  break;
386  }
387  }
388  glPopMatrix();
389  glPopName();
390 }
391 
392 
393 void
395  for (std::vector<MSLink*>::const_iterator i = myLinks.begin(); i != myLinks.end(); ++i) {
396  LinkState state = (*i)->getState();
397  const MSLane* connected = (*i)->getLane();
398  if (connected == 0) {
399  continue;
400  }
401  switch (state) {
404  glColor3d(0, 1, 0);
405  break;
406  case LINKSTATE_TL_RED:
407  glColor3d(1, 0, 0);
408  break;
411  glColor3d(1, 1, 0);
412  break;
414  glColor3d(1, 1, 0);
415  break;
417  glColor3d(0, 1, 1);
418  break;
419  case LINKSTATE_MAJOR:
420  glColor3d(1, 1, 1);
421  break;
422  case LINKSTATE_MINOR:
423  glColor3d(.2, .2, .2);
424  break;
425  case LINKSTATE_STOP:
426  glColor3d(.4, .2, .2);
427  break;
428  case LINKSTATE_EQUAL:
429  glColor3d(.5, .5, .5);
430  break;
432  glColor3d(.2, .2, .4);
433  break;
434  case LINKSTATE_DEADEND:
435  glColor3d(0, 0, 0);
436  break;
437  }
438 
439  glBegin(GL_LINES);
440  const Position& p1 = getShape()[-1];
441  const Position& p2 = connected->getShape()[0];
442  glVertex2f(p1.x(), p1.y());
443  glVertex2f(p2.x(), p2.y());
444  glEnd();
445  GLHelper::drawTriangleAtEnd(Line(p1, p2), (SUMOReal) .4, (SUMOReal) .2);
446  }
447 }
448 
449 
450 void
452  glPushMatrix();
453  const bool isInternal = myEdge->getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL;
454  bool mustDrawMarkings = false;
455  const bool drawDetails = s.scale * s.laneWidthExaggeration > 5;
456  if (isInternal) {
457  // draw internal lanes on top of junctions
458  glTranslated(0, 0, GLO_JUNCTION + 0.1);
459  } else {
460  glTranslated(0, 0, getType());
461  }
462  // set lane color
463  if (!MSGlobals::gUseMesoSim) {
464  setColor(s);
465  glPushName(getGlID()); // do not register for clicks in MESOSIM
466  }
467  // draw lane
468  // check whether it is not too small
469  if (s.scale * s.laneWidthExaggeration < 1.) {
471  if (!MSGlobals::gUseMesoSim) {
472  glPopName();
473  }
474  glPopMatrix();
475  } else {
476  if (isRailway(myPermissions)) {
477  // draw as railway
478  const SUMOReal halfRailWidth = 0.725;
480  glColor3d(1, 1, 1);
481  glTranslated(0, 0, .1);
483  drawCrossties(s);
484  } else {
485  const SUMOReal laneWidth = isInternal ? myQuarterLaneWidth : myHalfLaneWidth;
486  mustDrawMarkings = !isInternal;
488  }
489  if (!MSGlobals::gUseMesoSim) {
490  glPopName();
491  }
492  glPopMatrix();
493  // draw ROWs (not for inner lanes)
494  if (!isInternal && drawDetails) {
495  glPushMatrix();
496  glTranslated(0, 0, GLO_JUNCTION); // must draw on top of junction shape
497  GUINet* net = (GUINet*) MSNet::getInstance();
498  glTranslated(0, 0, .2);
499  drawLinkRules(*net);
501  drawArrows();
502  }
503  if (s.showLane2Lane) {
504  // this should be independent to the geometry:
505  // draw from end of first to the begin of second
507  }
508  glTranslated(0, 0, .1);
509  if (s.drawLinkJunctionIndex) {
510  drawLinkNo();
511  }
512  if (s.drawLinkTLIndex) {
513  drawTLSLinkNo(*net);
514  }
515  glPopMatrix();
516  }
517  }
518  if (mustDrawMarkings && drawDetails) { // needs matrix reset
519  drawMarkings(s);
520  }
521  // draw vehicles
522  if (s.scale > s.minVehicleSize) {
523  // retrieve vehicles from lane; disallow simulation
524  const MSLane::VehCont& vehicles = getVehiclesSecure();
525  for (MSLane::VehCont::const_iterator v = vehicles.begin(); v != vehicles.end(); ++v) {
526  if ((*v)->getLane() == this) {
527  static_cast<const GUIVehicle* const>(*v)->drawGL(s);
528  } // else: this is the shadow during a continuous lane change
529  }
530  // draw parking vehicles
531  const std::set<const MSVehicle*> parking = MSVehicleTransfer::getInstance()->getParkingVehicles(this);
532  for (std::set<const MSVehicle*>::const_iterator v = parking.begin(); v != parking.end(); ++v) {
533  static_cast<const GUIVehicle* const>(*v)->drawGL(s);
534  }
535  // allow lane simulation
536  releaseVehicles();
537  }
538 }
539 
540 
541 void
543  glPushMatrix();
544  glPushName(0);
545  glTranslated(0, 0, GLO_EDGE);
546 #ifdef HAVE_INTERNAL
548 #endif
549  setColor(s);
550  // optionally draw inverse markings
551  if (myIndex > 0) {
553  int e = (int) getShape().size() - 1;
554  for (int i = 0; i < e; ++i) {
555  glPushMatrix();
556  glTranslated(getShape()[i].x(), getShape()[i].y(), 0.1);
557  glRotated(myShapeRotations[i], 0, 0, 1);
558  for (SUMOReal t = 0; t < myShapeLengths[i]; t += 6) {
559  glBegin(GL_QUADS);
560  glVertex2d(-mw, -t);
561  glVertex2d(-mw, -t - 3.);
562  glVertex2d(myQuarterLaneWidth, -t - 3.);
563  glVertex2d(myQuarterLaneWidth, -t);
564  glEnd();
565  }
566  glPopMatrix();
567  }
568  }
569  // draw white boundings and white markings
570  glColor3d(1, 1, 1);
572  getShape(),
574  getShapeLengths(),
576  glPopMatrix();
577  glPopName();
578 }
579 
580 
581 void
583  glPushMatrix();
584  glPushName(0);
585  if (!MSGlobals::gUseMesoSim) {
586  setColor(s);
587  }
588  // draw on top of of the white area between the rails
589  glTranslated(0, 0, 0.1);
590  int e = (int) getShape().size() - 1;
591  for (int i = 0; i < e; ++i) {
592  glPushMatrix();
593  glTranslated(getShape()[i].x(), getShape()[i].y(), 0.1);
594  glRotated(myShapeRotations[i], 0, 0, 1);
595  for (SUMOReal t = 0; t < myShapeLengths[i]; t += 1) {
596  glBegin(GL_QUADS);
597  glVertex2d(-1, -t);
598  glVertex2d(-1, -t - 0.3);
599  glVertex2d(1.0, -t - 0.3);
600  glVertex2d(1.0, -t);
601  glEnd();
602  }
603  glPopMatrix();
604  }
605  glPopMatrix();
606  glPopName();
607 }
608 
609 // ------ inherited from GUIGlObject
612  GUISUMOAbstractView& parent) {
613  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
614  buildPopupHeader(ret, app);
616  //
619  //
620  buildShowParamsPopupEntry(ret, false);
622  new FXMenuCommand(ret, ("pos: " + toString(pos)).c_str(), 0, 0, 0);
623  new FXMenuSeparator(ret);
624  buildPositionCopyEntry(ret, false);
625  return ret;
626 }
627 
628 
633  new GUIParameterTableWindow(app, *this, 4);
634  // add items
635  ret->mkItem("maxspeed [m/s]", false, getSpeedLimit());
636  ret->mkItem("length [m]", false, myLength);
637  ret->mkItem("permissions", false, getAllowedVehicleClassNames(myPermissions));
638  ret->mkItem("street name", false, myEdge->getStreetName());
639  ret->mkItem("stored traveltime [s]", true, new FunctionBinding<GUILane, SUMOReal>(this, &GUILane::getStoredEdgeTravelTime));
640  // close building
641  ret->closeBuilding();
642  return ret;
643 }
644 
645 
646 Boundary
648  Boundary b;
649  b.add(myShape[0]);
650  b.add(myShape[-1]);
651  b.grow(20);
652  return b;
653 }
654 
655 
656 
657 
658 
659 
660 
661 const PositionVector&
663  return myShape;
664 }
665 
666 
667 const std::vector<SUMOReal>&
669  return myShapeRotations;
670 }
671 
672 
673 const std::vector<SUMOReal>&
675  return myShapeLengths;
676 }
677 
678 
679 SUMOReal
681  return myVehicles.size() == 0 ? 0 : myVehicles.back()->getWaitingSeconds();
682 }
683 
684 
685 SUMOReal
687  return (SUMOReal) myEdge->getLanes().size();
688 }
689 
690 
691 // ------------ Current state retrieval
692 SUMOReal
694  return getHBEFA_CO2Emissions() / getLength();
695 }
696 
697 
698 SUMOReal
700  return getHBEFA_COEmissions() / getLength();
701 }
702 
703 
704 SUMOReal
706  return getHBEFA_PMxEmissions() / getLength();
707 }
708 
709 
710 SUMOReal
712  return getHBEFA_NOxEmissions() / getLength();
713 }
714 
715 
716 SUMOReal
718  return getHBEFA_HCEmissions() / getLength();
719 }
720 
721 
722 SUMOReal
724  return getHBEFA_FuelConsumption() / getLength();
725 }
726 
727 
728 void
731 }
732 
733 
734 SUMOReal
737  if (!ews.knowsTravelTime(myEdge)) {
738  return -1;
739  } else {
740  SUMOReal value(0);
741  ews.retrieveExistingTravelTime(myEdge, 0, STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()), value);
742  return value;
743  }
744 }
745 
746 SUMOReal
747 GUILane::getColorValue(size_t activeScheme) const {
748  switch (activeScheme) {
749  case 1:
750  return gSelected.isSelected(getType(), getGlID()) ||
751  gSelected.isSelected(GLO_EDGE, dynamic_cast<GUIEdge*>(myEdge)->getGlID());
752  case 2: {
754  return 0;
755  } else {
756  return 1;
757  }
758  }
759  case 3:
760  return getSpeedLimit();
761  case 4:
762  return getOccupancy();
763  case 5:
764  return firstWaitingTime();
765  case 6:
766  return getEdgeLaneNumber();
767  case 7:
769  case 8:
771  case 9:
773  case 10:
775  case 11:
777  case 12:
779  case 13:
781  case 14: {
782  return getStoredEdgeTravelTime();
783  }
784  case 15: {
786  if (!ews.knowsTravelTime(myEdge)) {
787  return -1;
788  } else {
789  SUMOReal value(0);
790  ews.retrieveExistingTravelTime(myEdge, 0, 0, value);
791  return 100 * myLength / value / getSpeedLimit();
792  }
793  }
794  case 16: {
795  return 1 / myLengthGeometryFactor;
796  }
797  }
798  return 0;
799 }
800 
801 #ifdef HAVE_OSG
802 void
803 GUILane::updateColor(const GUIVisualizationSettings& s) {
805  osg::Vec4ubArray* colors = dynamic_cast<osg::Vec4ubArray*>(myGeom->getColorArray());
806  (*colors)[0].set(col.red(), col.green(), col.blue(), col.alpha());
807  myGeom->setColorArray(colors);
808 }
809 #endif
810 
811 
812 
813 /****************************************************************************/
814