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  break;
298  case LINKSTATE_MINOR:
299  glColor3d(.2, .2, .2);
300  break;
301  case LINKSTATE_STOP:
302  glColor3d(.4, .2, .2);
303  break;
304  case LINKSTATE_EQUAL:
305  glColor3d(.5, .5, .5);
306  break;
308  glColor3d(.2, .2, .4);
309  break;
310  case LINKSTATE_DEADEND:
311  glColor3d(0, 0, 0);
312  break;
313  }
314  if (!railway || link->getState() != LINKSTATE_MAJOR) {
315  // THE WHITE BAR SHOULD BE THE DEFAULT FOR MOST RAILWAY
316  // LINKS AND LOOKS UGLY SO WE DO NOT DRAW IT
317  glBegin(GL_QUADS);
318  glVertex2d(x1 - myHalfLaneWidth, 0.0);
319  glVertex2d(x1 - myHalfLaneWidth, 0.5);
320  glVertex2d(x2 - myHalfLaneWidth, 0.5);
321  glVertex2d(x2 - myHalfLaneWidth, 0.0);
322  glEnd();
323  }
324  glPopName();
325  x1 = x2;
326  x2 += w;
327  }
328  glPopMatrix();
329 }
330 
331 
332 void
334  if (myLinks.size() == 0) {
335  return;
336  }
337  // draw all links
338  const Position& end = getShape().back();
339  const Position& f = getShape()[-2];
340  const SUMOReal rot = RAD2DEG(atan2((end.x() - f.x()), (f.y() - end.y())));
341  glPushMatrix();
342  glPushName(0);
343  glColor3d(1, 1, 1);
344  glTranslated(end.x(), end.y(), 0);
345  glRotated(rot, 0, 0, 1);
346  for (std::vector<MSLink*>::const_iterator i = myLinks.begin(); i != myLinks.end(); ++i) {
347  LinkDirection dir = (*i)->getDirection();
348  LinkState state = (*i)->getState();
349  if (state == LINKSTATE_TL_OFF_NOSIGNAL || dir == LINKDIR_NODIR) {
350  continue;
351  }
352  switch (dir) {
353  case LINKDIR_STRAIGHT:
354  GLHelper::drawBoxLine(Position(0, 4), 0, 2, .05);
356  break;
357  case LINKDIR_TURN:
358  GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
359  GLHelper::drawBoxLine(Position(0, 2.5), 90, .5, .05);
360  GLHelper::drawBoxLine(Position(0.5, 2.5), 180, 1, .05);
361  GLHelper::drawTriangleAtEnd(Line(Position(0.5, 2.5), Position(0.5, 4)), (SUMOReal) 1, (SUMOReal) .25);
362  break;
363  case LINKDIR_LEFT:
364  GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
365  GLHelper::drawBoxLine(Position(0, 2.5), 90, 1, .05);
366  GLHelper::drawTriangleAtEnd(Line(Position(0, 2.5), Position(1.5, 2.5)), (SUMOReal) 1, (SUMOReal) .25);
367  break;
368  case LINKDIR_RIGHT:
369  GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
370  GLHelper::drawBoxLine(Position(0, 2.5), -90, 1, .05);
371  GLHelper::drawTriangleAtEnd(Line(Position(0, 2.5), Position(-1.5, 2.5)), (SUMOReal) 1, (SUMOReal) .25);
372  break;
373  case LINKDIR_PARTLEFT:
374  GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
375  GLHelper::drawBoxLine(Position(0, 2.5), 45, .7, .05);
376  GLHelper::drawTriangleAtEnd(Line(Position(0, 2.5), Position(1.2, 1.3)), (SUMOReal) 1, (SUMOReal) .25);
377  break;
378  case LINKDIR_PARTRIGHT:
379  GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
380  GLHelper::drawBoxLine(Position(0, 2.5), -45, .7, .05);
381  GLHelper::drawTriangleAtEnd(Line(Position(0, 2.5), Position(-1.2, 1.3)), (SUMOReal) 1, (SUMOReal) .25);
382  break;
383  default:
384  break;
385  }
386  }
387  glPopMatrix();
388  glPopName();
389 }
390 
391 
392 void
394  for (std::vector<MSLink*>::const_iterator i = myLinks.begin(); i != myLinks.end(); ++i) {
395  LinkState state = (*i)->getState();
396  const MSLane* connected = (*i)->getLane();
397  if (connected == 0) {
398  continue;
399  }
400  switch (state) {
403  glColor3d(0, 1, 0);
404  break;
405  case LINKSTATE_TL_RED:
406  glColor3d(1, 0, 0);
407  break;
410  glColor3d(1, 1, 0);
411  break;
413  glColor3d(1, 1, 0);
414  break;
416  glColor3d(0, 1, 1);
417  break;
418  case LINKSTATE_MAJOR:
419  glColor3d(1, 1, 1);
420  break;
421  case LINKSTATE_MINOR:
422  glColor3d(.2, .2, .2);
423  break;
424  case LINKSTATE_STOP:
425  glColor3d(.4, .2, .2);
426  break;
427  case LINKSTATE_EQUAL:
428  glColor3d(.5, .5, .5);
429  break;
431  glColor3d(.2, .2, .4);
432  break;
433  case LINKSTATE_DEADEND:
434  glColor3d(0, 0, 0);
435  break;
436  }
437 
438  glBegin(GL_LINES);
439  const Position& p1 = getShape()[-1];
440  const Position& p2 = connected->getShape()[0];
441  glVertex2f(p1.x(), p1.y());
442  glVertex2f(p2.x(), p2.y());
443  glEnd();
444  GLHelper::drawTriangleAtEnd(Line(p1, p2), (SUMOReal) .4, (SUMOReal) .2);
445  }
446 }
447 
448 
449 void
451  glPushMatrix();
452  const bool isInternal = myEdge->getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL;
453  bool mustDrawMarkings = false;
454  const bool drawDetails = s.scale * s.laneWidthExaggeration > 5;
455  if (isInternal) {
456  // draw internal lanes on top of junctions
457  glTranslated(0, 0, GLO_JUNCTION + 0.1);
458  } else {
459  glTranslated(0, 0, getType());
460  }
461  // set lane color
462  if (!MSGlobals::gUseMesoSim) {
463  setColor(s);
464  glPushName(getGlID()); // do not register for clicks in MESOSIM
465  }
466  // draw lane
467  // check whether it is not too small
468  if (s.scale * s.laneWidthExaggeration < 1.) {
470  if (!MSGlobals::gUseMesoSim) {
471  glPopName();
472  }
473  glPopMatrix();
474  } else {
475  if (isRailway(myPermissions)) {
476  // draw as railway
477  const SUMOReal halfRailWidth = 0.725;
479  glColor3d(1, 1, 1);
480  glTranslated(0, 0, .1);
482  drawCrossties(s);
483  } else {
484  const SUMOReal laneWidth = isInternal ? myQuarterLaneWidth : myHalfLaneWidth;
485  mustDrawMarkings = !isInternal;
487  }
488  if (!MSGlobals::gUseMesoSim) {
489  glPopName();
490  }
491  glPopMatrix();
492  // draw ROWs (not for inner lanes)
493  if (!isInternal && drawDetails) {
494  glPushMatrix();
495  glTranslated(0, 0, GLO_JUNCTION); // must draw on top of junction shape
496  GUINet* net = (GUINet*) MSNet::getInstance();
497  glTranslated(0, 0, .2);
498  drawLinkRules(*net);
500  drawArrows();
501  }
502  if (s.showLane2Lane) {
503  // this should be independent to the geometry:
504  // draw from end of first to the begin of second
506  }
507  glTranslated(0, 0, .1);
508  if (s.drawLinkJunctionIndex) {
509  drawLinkNo();
510  }
511  if (s.drawLinkTLIndex) {
512  drawTLSLinkNo(*net);
513  }
514  glPopMatrix();
515  }
516  }
517  if (mustDrawMarkings && drawDetails) { // needs matrix reset
518  drawMarkings(s);
519  }
520  // draw vehicles
521  if (s.scale > s.minVehicleSize) {
522  // retrieve vehicles from lane; disallow simulation
523  const MSLane::VehCont& vehicles = getVehiclesSecure();
524  for (MSLane::VehCont::const_iterator v = vehicles.begin(); v != vehicles.end(); ++v) {
525  if ((*v)->getLane() == this) {
526  static_cast<const GUIVehicle* const>(*v)->drawGL(s);
527  } // else: this is the shadow during a continuous lane change
528  }
529  // draw parking vehicles
530  const std::set<const MSVehicle*> parking = MSVehicleTransfer::getInstance()->getParkingVehicles(this);
531  for (std::set<const MSVehicle*>::const_iterator v = parking.begin(); v != parking.end(); ++v) {
532  static_cast<const GUIVehicle* const>(*v)->drawGL(s);
533  }
534  // allow lane simulation
535  releaseVehicles();
536  }
537 }
538 
539 
540 void
542  glPushMatrix();
543  glPushName(0);
544  glTranslated(0, 0, GLO_EDGE);
545 #ifdef HAVE_INTERNAL
547 #endif
548  setColor(s);
549  // optionally draw inverse markings
550  if (myIndex > 0) {
552  int e = (int) getShape().size() - 1;
553  for (int i = 0; i < e; ++i) {
554  glPushMatrix();
555  glTranslated(getShape()[i].x(), getShape()[i].y(), 0.1);
556  glRotated(myShapeRotations[i], 0, 0, 1);
557  for (SUMOReal t = 0; t < myShapeLengths[i]; t += 6) {
558  glBegin(GL_QUADS);
559  glVertex2d(-mw, -t);
560  glVertex2d(-mw, -t - 3.);
561  glVertex2d(myQuarterLaneWidth, -t - 3.);
562  glVertex2d(myQuarterLaneWidth, -t);
563  glEnd();
564  }
565  glPopMatrix();
566  }
567  }
568  // draw white boundings and white markings
569  glColor3d(1, 1, 1);
571  getShape(),
573  getShapeLengths(),
575  glPopMatrix();
576  glPopName();
577 }
578 
579 
580 void
582  glPushMatrix();
583  glPushName(0);
584  if (!MSGlobals::gUseMesoSim) {
585  setColor(s);
586  }
587  // draw on top of of the white area between the rails
588  glTranslated(0, 0, 0.1);
589  int e = (int) getShape().size() - 1;
590  for (int i = 0; i < e; ++i) {
591  glPushMatrix();
592  glTranslated(getShape()[i].x(), getShape()[i].y(), 0.1);
593  glRotated(myShapeRotations[i], 0, 0, 1);
594  for (SUMOReal t = 0; t < myShapeLengths[i]; t += 1) {
595  glBegin(GL_QUADS);
596  glVertex2d(-1, -t);
597  glVertex2d(-1, -t - 0.3);
598  glVertex2d(1.0, -t - 0.3);
599  glVertex2d(1.0, -t);
600  glEnd();
601  }
602  glPopMatrix();
603  }
604  glPopMatrix();
605  glPopName();
606 }
607 
608 // ------ inherited from GUIGlObject
611  GUISUMOAbstractView& parent) {
612  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
613  buildPopupHeader(ret, app);
615  //
618  //
619  buildShowParamsPopupEntry(ret, false);
621  new FXMenuCommand(ret, ("pos: " + toString(pos)).c_str(), 0, 0, 0);
622  new FXMenuSeparator(ret);
623  buildPositionCopyEntry(ret, false);
624  return ret;
625 }
626 
627 
632  new GUIParameterTableWindow(app, *this, 5);
633  // add items
634  ret->mkItem("maxspeed [m/s]", false, getSpeedLimit());
635  ret->mkItem("length [m]", false, myLength);
636  ret->mkItem("street name", false, myEdge->getStreetName());
637  ret->mkItem("stored traveltime [s]", true, new FunctionBinding<GUILane, SUMOReal>(this, &GUILane::getStoredEdgeTravelTime));
638  ret->mkItem("allowed vehicle class", false, getAllowedVehicleClassNames(myPermissions));
639  ret->mkItem("disallowed vehicle class", false, getAllowedVehicleClassNames(~myPermissions));
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 getBruttoOccupancy();
763  case 5:
764  return getNettoOccupancy();
765  case 6:
766  return firstWaitingTime();
767  case 7:
768  return getEdgeLaneNumber();
769  case 8:
771  case 9:
773  case 10:
775  case 11:
777  case 12:
779  case 13:
781  case 14:
783  case 15: {
784  return getStoredEdgeTravelTime();
785  }
786  case 16: {
788  if (!ews.knowsTravelTime(myEdge)) {
789  return -1;
790  } else {
791  SUMOReal value(0);
792  ews.retrieveExistingTravelTime(myEdge, 0, 0, value);
793  return 100 * myLength / value / getSpeedLimit();
794  }
795  }
796  case 17: {
797  return 1 / myLengthGeometryFactor;
798  }
799  }
800  return 0;
801 }
802 
803 #ifdef HAVE_OSG
804 void
805 GUILane::updateColor(const GUIVisualizationSettings& s) {
807  osg::Vec4ubArray* colors = dynamic_cast<osg::Vec4ubArray*>(myGeom->getColorArray());
808  (*colors)[0].set(col.red(), col.green(), col.blue(), col.alpha());
809  myGeom->setColorArray(colors);
810 }
811 #endif
812 
813 
814 
815 /****************************************************************************/
816