SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GUILaneWrapper.cpp
Go to the documentation of this file.
1 /****************************************************************************/
9 // A MSLane extended for visualisation purposes.
10 /****************************************************************************/
11 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
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 <iostream>
35 #include <utility>
36 #ifdef HAVE_OSG
37 #include <osg/Geometry>
38 #endif
39 #include <microsim/MSLane.h>
40 #include <microsim/MSEdge.h>
41 #include <microsim/MSGlobals.h>
44 #include <microsim/MSNet.h>
45 #include <gui/GUIGlobals.h>
47 #include "GUILaneWrapper.h"
48 #include "GUIEdge.h"
49 #include <utils/common/ToString.h>
50 #include <utils/geom/GeomHelper.h>
51 #include <guisim/GUINet.h>
60 #include <utils/gui/div/GLHelper.h>
61 #include <gui/GUIViewTraffic.h>
63 #include <guisim/GUIVehicle.h>
68 
69 #ifdef CHECK_MEMORY_LEAKS
70 #include <foreign/nvwa/debug_new.h>
71 #endif // CHECK_MEMORY_LEAKS
72 
73 
74 // ===========================================================================
75 // method definitions
76 // ===========================================================================
77 GUILaneWrapper::GUILaneWrapper(MSLane& lane, const PositionVector& shape, unsigned int index) :
78  GUIGlObject(GLO_LANE, lane.getID()),
79  myLane(lane),
80  myShape(shape),
81  myIndex(index)
82 #ifdef HAVE_OSG
83  , myGeom(0)
84 #endif
85 {
86  myShapeRotations.reserve(myShape.size() - 1);
87  myShapeLengths.reserve(myShape.size() - 1);
88  int e = (int) myShape.size() - 1;
89  for (int i = 0; i < e; ++i) {
90  const Position& f = myShape[i];
91  const Position& s = myShape[i + 1];
92  myShapeLengths.push_back(f.distanceTo2D(s));
93  myShapeRotations.push_back(RAD2DEG(atan2(s.x() - f.x(), f.y() - s.y())));
94  }
95  //
98 }
99 
100 
102 
103 
104 bool
105 GUILaneWrapper::forLane(const MSLane& lane) const {
106  return (&myLane) == (&lane);
107 }
108 
109 
110 
111 void
113  unsigned int noLinks = getLinkNumber();
114  if (noLinks == 0) {
115  return;
116  }
117  // draw all links
118  SUMOReal w = myLane.getWidth() / (SUMOReal) noLinks;
119  SUMOReal x1 = myLane.getWidth() / (SUMOReal) 2.;
120  glPushMatrix();
121  const PositionVector& g = getShape();
122  const Position& end = g.back();
123  const Position& f = g[-2];
124  const Position& s = end;
125  SUMOReal rot = (SUMOReal) atan2((s.x() - f.x()), (f.y() - s.y())) * (SUMOReal) 180.0 / (SUMOReal) PI;
126  glTranslated(end.x(), end.y(), 0);
127  glRotated(rot, 0, 0, 1);
128  for (int i = noLinks; --i >= 0;) {
129  SUMOReal x2 = x1 - (SUMOReal)(w / 2.);
130  GLHelper::drawText(toString(getLane().getLinkCont()[i]->getRespondIndex()),
131  Position(x2, 0), 0, .6, RGBColor(128, 128, 255, 255), 180);
132  x1 -= w;
133  }
134  glPopMatrix();
135 }
136 
137 
138 void
140  unsigned int noLinks = getLinkNumber();
141  if (noLinks == 0) {
142  return;
143  }
144  // draw all links
145  SUMOReal w = myLane.getWidth() / (SUMOReal) noLinks;
146  SUMOReal x1 = (SUMOReal)(myLane.getWidth() / 2.);
147  glPushMatrix();
148  const PositionVector& g = getShape();
149  const Position& end = g.back();
150  const Position& f = g[-2];
151  const Position& s = end;
152  SUMOReal rot = (SUMOReal) atan2((s.x() - f.x()), (f.y() - s.y())) * (SUMOReal) 180.0 / (SUMOReal) PI;
153  glTranslated(end.x(), end.y(), 0);
154  glRotated(rot, 0, 0, 1);
155  for (int i = noLinks; --i >= 0;) {
156  SUMOReal x2 = x1 - (SUMOReal)(w / 2.);
157  int linkNo = net.getLinkTLIndex(getLane().getLinkCont()[i]);
158  if (linkNo < 0) {
159  continue;
160  }
162  Position(x2, 0), 0, .6, RGBColor(128, 128, 255, 255), 180);
163  x1 -= w;
164  }
165  glPopMatrix();
166 }
167 
168 
169 void
171  unsigned int noLinks = getLinkNumber();
172  const PositionVector& g = getShape();
173  const Position& end = g.back();
174  const Position& f = g[-2];
175  const Position& s = end;
176  SUMOReal rot = (SUMOReal) atan2((s.x() - f.x()), (f.y() - s.y())) * (SUMOReal) 180.0 / (SUMOReal) PI;
177  if (noLinks == 0) {
178  glPushName(getGlID());
179  // draw a grey bar if no links are on the street
180  glColor3d(0.5, 0.5, 0.5);
181  glPushMatrix();
182  glTranslated(end.x(), end.y(), 0);
183  glRotated(rot, 0, 0, 1);
184  glBegin(GL_QUADS);
185  glVertex2d(-myHalfLaneWidth, 0.0);
186  glVertex2d(-myHalfLaneWidth, 0.5);
187  glVertex2d(myHalfLaneWidth, 0.5);
188  glVertex2d(myHalfLaneWidth, 0.0);
189  glEnd();
190  glPopMatrix();
191  glPopName();
192  return;
193  }
194  // draw all links
195  SUMOReal w = myLane.getWidth() / (SUMOReal) noLinks;
196  SUMOReal x1 = 0;
197  glPushMatrix();
198  glTranslated(end.x(), end.y(), 0);
199  glRotated(rot, 0, 0, 1);
200  for (unsigned int i = 0; i < noLinks; ++i) {
201  SUMOReal x2 = x1 + w;
202  MSLink* link = getLane().getLinkCont()[i];
203  // select glID
204  switch (link->getState()) {
207  case LINKSTATE_TL_RED:
211  glPushName(net.getLinkTLID(link));
212  break;
213  case LINKSTATE_MAJOR:
214  case LINKSTATE_MINOR:
215  case LINKSTATE_EQUAL:
217  default:
218  glPushName(getGlID());
219  break;
220  }
221  // select color
222  switch (link->getState()) {
225  glColor3d(0, 1, 0);
226  break;
227  case LINKSTATE_TL_RED:
228  glColor3d(1, 0, 0);
229  break;
232  glColor3d(1, 1, 0);
233  break;
235  glColor3d(.7, .7, 0);
236  break;
238  glColor3d(0, 1, 1);
239  break;
240  case LINKSTATE_MAJOR:
241  glColor3d(1, 1, 1);
242  break;
243  case LINKSTATE_MINOR:
244  glColor3d(.2, .2, .2);
245  break;
246  case LINKSTATE_EQUAL:
247  glColor3d(.5, .5, .5);
248  break;
249  case LINKSTATE_DEADEND:
250  glColor3d(0, 0, 0);
251  break;
252  }
253  glBegin(GL_QUADS);
254  glVertex2d(x1 - myHalfLaneWidth, 0.0);
255  glVertex2d(x1 - myHalfLaneWidth, 0.5);
256  glVertex2d(x2 - myHalfLaneWidth, 0.5);
257  glVertex2d(x2 - myHalfLaneWidth, 0.0);
258  glEnd();
259  glPopName();
260  x1 = x2;
261  x2 += w;
262  }
263  glPopMatrix();
264 }
265 
266 
267 void
269  unsigned int noLinks = getLinkNumber();
270  if (noLinks == 0) {
271  return;
272  }
273  // draw all links
274  const Position& end = getShape().back();
275  const Position& f = getShape()[-2];
276  SUMOReal rot = (SUMOReal) atan2((end.x() - f.x()), (f.y() - end.y())) * (SUMOReal) 180.0 / (SUMOReal) PI;
277  glPushMatrix();
278  glPushName(0);
279  glColor3d(1, 1, 1);
280  glTranslated(end.x(), end.y(), 0);
281  glRotated(rot, 0, 0, 1);
282  for (unsigned int i = 0; i < noLinks; ++i) {
283  LinkDirection dir = getLane().getLinkCont()[i]->getDirection();
284  LinkState state = getLane().getLinkCont()[i]->getState();
285  if (state == LINKSTATE_TL_OFF_NOSIGNAL || dir == LINKDIR_NODIR) {
286  continue;
287  }
288  switch (dir) {
289  case LINKDIR_STRAIGHT:
290  GLHelper::drawBoxLine(Position(0, 4), 0, 2, .05);
292  break;
293  case LINKDIR_TURN:
294  GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
295  GLHelper::drawBoxLine(Position(0, 2.5), 90, .5, .05);
296  GLHelper::drawBoxLine(Position(0.5, 2.5), 180, 1, .05);
297  GLHelper::drawTriangleAtEnd(Line(Position(0.5, 2.5), Position(0.5, 4)), (SUMOReal) 1, (SUMOReal) .25);
298  break;
299  case LINKDIR_LEFT:
300  GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
301  GLHelper::drawBoxLine(Position(0, 2.5), 90, 1, .05);
302  GLHelper::drawTriangleAtEnd(Line(Position(0, 2.5), Position(1.5, 2.5)), (SUMOReal) 1, (SUMOReal) .25);
303  break;
304  case LINKDIR_RIGHT:
305  GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
306  GLHelper::drawBoxLine(Position(0, 2.5), -90, 1, .05);
307  GLHelper::drawTriangleAtEnd(Line(Position(0, 2.5), Position(-1.5, 2.5)), (SUMOReal) 1, (SUMOReal) .25);
308  break;
309  case LINKDIR_PARTLEFT:
310  GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
311  GLHelper::drawBoxLine(Position(0, 2.5), 45, .7, .05);
312  GLHelper::drawTriangleAtEnd(Line(Position(0, 2.5), Position(1.2, 1.3)), (SUMOReal) 1, (SUMOReal) .25);
313  break;
314  case LINKDIR_PARTRIGHT:
315  GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
316  GLHelper::drawBoxLine(Position(0, 2.5), -45, .7, .05);
317  GLHelper::drawTriangleAtEnd(Line(Position(0, 2.5), Position(-1.2, 1.3)), (SUMOReal) 1, (SUMOReal) .25);
318  break;
319  default:
320  break;
321  }
322  }
323  glPopMatrix();
324  glPopName();
325 }
326 
327 
328 void
330  unsigned int noLinks = getLinkNumber();
331  for (unsigned int i = 0; i < noLinks; ++i) {
332  LinkState state = getLane().getLinkCont()[i]->getState();
333  const MSLane* connected = getLane().getLinkCont()[i]->getLane();
334  if (connected == 0) {
335  continue;
336  }
337  switch (state) {
340  glColor3d(0, 1, 0);
341  break;
342  case LINKSTATE_TL_RED:
343  glColor3d(1, 0, 0);
344  break;
347  glColor3d(1, 1, 0);
348  break;
350  glColor3d(1, 1, 0);
351  break;
353  glColor3d(0, 1, 1);
354  break;
355  case LINKSTATE_MAJOR:
356  glColor3d(1, 1, 1);
357  break;
358  case LINKSTATE_MINOR:
359  glColor3d(.2, .2, .2);
360  break;
361  case LINKSTATE_EQUAL:
362  glColor3d(.5, .5, .5);
363  break;
364  case LINKSTATE_DEADEND:
365  glColor3d(0, 0, 0);
366  break;
367  }
368 
369  glBegin(GL_LINES);
370  const Position& p1 = getShape()[-1];
371  const Position& p2 = connected->getShape()[0];
372  glVertex2f(p1.x(), p1.y());
373  glVertex2f(p2.x(), p2.y());
374  glEnd();
375  GLHelper::drawTriangleAtEnd(Line(p1, p2), (SUMOReal) .4, (SUMOReal) .2);
376  }
377 }
378 
379 
380 void
382  glPushMatrix();
383  const bool isInternal = getLane().getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL;
384  bool mustDrawMarkings = false;
385  const bool drawDetails = s.scale * s.laneWidthExaggeration > 5;
386  if (isInternal) {
387  // draw internal lanes on top of junctions
388  glTranslated(0, 0, GLO_JUNCTION + 0.1);
389  } else {
390  glTranslated(0, 0, getType());
391  }
392  // set lane color
393  if (!MSGlobals::gUseMesoSim) {
394  setColor(s);
395  glPushName(getGlID()); // do not register for clicks in MESOSIM
396  }
397  // draw lane
398  // check whether it is not too small
399  if (s.scale * s.laneWidthExaggeration < 1.) {
401  if (!MSGlobals::gUseMesoSim) {
402  glPopName();
403  }
404  glPopMatrix();
405  } else if (isRailway(getLane().getPermissions())) {
406  // draw as railway
407  const SUMOReal halfRailWidth = 0.725;
409  glColor3d(1, 1, 1);
410  glTranslated(0, 0, .1);
412  drawCrossties(s);
413  if (!MSGlobals::gUseMesoSim) {
414  glPopName();
415  }
416  glPopMatrix();
417  } else {
418  const SUMOReal laneWidth = isInternal ? myQuarterLaneWidth : myHalfLaneWidth;
419  mustDrawMarkings = !isInternal;
421  if (!MSGlobals::gUseMesoSim) {
422  glPopName();
423  }
424  glPopMatrix();
425  // draw ROWs (not for inner lanes)
426  if (!isInternal && drawDetails) {
427  glPushMatrix();
428  glTranslated(0, 0, GLO_JUNCTION); // must draw on top of junction shape
429  GUINet* net = (GUINet*) MSNet::getInstance();
430  glTranslated(0, 0, .2);
431  drawLinkRules(*net);
432  if (s.showLinkDecals) {
433  drawArrows();
434  }
435  if (s.showLane2Lane) {
436  // this should be independent to the geometry:
437  // draw from end of first to the begin of second
439  }
440  glTranslated(0, 0, .1);
441  if (s.drawLinkJunctionIndex) {
442  drawLinkNo();
443  }
444  if (s.drawLinkTLIndex) {
445  drawTLSLinkNo(*net);
446  }
447  glPopMatrix();
448  }
449  }
450  if (mustDrawMarkings && drawDetails) { // needs matrix reset
451  drawMarkings(s);
452  }
453  // draw vehicles
454  if (s.scale > s.minVehicleSize) {
455  // retrieve vehicles from lane; disallow simulation
456  const MSLane::VehCont& vehicles = myLane.getVehiclesSecure();
457  for (MSLane::VehCont::const_iterator v = vehicles.begin(); v != vehicles.end(); ++v) {
458  static_cast<const GUIVehicle* const>(*v)->drawGL(s);
459  }
460  // allow lane simulation
462  }
463 }
464 
465 
466 void
468  glPushMatrix();
469  glPushName(0);
470  glTranslated(0, 0, GLO_EDGE);
471 #ifdef HAVE_INTERNAL
473 #endif
474  setColor(s);
475  // optionally draw inverse markings
476  if (myIndex > 0) {
478  int e = (int) getShape().size() - 1;
479  for (int i = 0; i < e; ++i) {
480  glPushMatrix();
481  glTranslated(getShape()[i].x(), getShape()[i].y(), 0.1);
482  glRotated(myShapeRotations[i], 0, 0, 1);
483  for (SUMOReal t = 0; t < myShapeLengths[i]; t += 6) {
484  glBegin(GL_QUADS);
485  glVertex2d(-mw, -t);
486  glVertex2d(-mw, -t - 3.);
487  glVertex2d(myQuarterLaneWidth, -t - 3.);
488  glVertex2d(myQuarterLaneWidth, -t);
489  glEnd();
490  }
491  glPopMatrix();
492  }
493  }
494  // draw white boundings and white markings
495  glColor3d(1, 1, 1);
497  getShape(),
499  getShapeLengths(),
501  glPopMatrix();
502  glPopName();
503 }
504 
505 
506 void
508  glPushMatrix();
509  glPushName(0);
510  if (!MSGlobals::gUseMesoSim) {
511  setColor(s);
512  }
513  // draw on top of of the white area between the rails
514  glTranslated(0, 0, 0.1);
515  int e = (int) getShape().size() - 1;
516  for (int i = 0; i < e; ++i) {
517  glPushMatrix();
518  glTranslated(getShape()[i].x(), getShape()[i].y(), 0.1);
519  glRotated(myShapeRotations[i], 0, 0, 1);
520  for (SUMOReal t = 0; t < myShapeLengths[i]; t += 1) {
521  glBegin(GL_QUADS);
522  glVertex2d(-1, -t);
523  glVertex2d(-1, -t - 0.3);
524  glVertex2d(1.0, -t - 0.3);
525  glVertex2d(1.0, -t);
526  glEnd();
527  }
528  glPopMatrix();
529  }
530  glPopMatrix();
531  glPopName();
532 }
533 
536  GUISUMOAbstractView& parent) {
537  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
538  buildPopupHeader(ret, app);
540  //
543  //
544  buildShowParamsPopupEntry(ret, false);
547  new FXMenuCommand(ret, ("pos: " + toString(pos)).c_str(), 0, 0, 0);
548  new FXMenuSeparator(ret);
549  buildPositionCopyEntry(ret, false);
550  return ret;
551 }
552 
553 
558  new GUIParameterTableWindow(app, *this, 4);
559  // add items
560  ret->mkItem("maxspeed [m/s]", false, myLane.getSpeedLimit());
561  ret->mkItem("length [m]", false, myLane.getLength());
562  ret->mkItem("permissions", false, getAllowedVehicleClassNames(myLane.getPermissions()));
563  ret->mkItem("street name", false, myLane.getEdge().getStreetName());
564  ret->mkItem("stored traveltime [s]", true, new FunctionBinding<GUILaneWrapper, SUMOReal>(this, &GUILaneWrapper::getStoredEdgeTravelTime));
565  // close building
566  ret->closeBuilding();
567  return ret;
568 }
569 
570 
571 Boundary
573  Boundary b;
574  b.add(myShape[0]);
575  b.add(myShape[-1]);
576  b.grow(20);
577  return b;
578 }
579 
580 
581 
582 
583 const PositionVector&
585  return myShape;
586 }
587 
588 
589 unsigned int
591  return (unsigned int) myLane.getLinkCont().size();
592 }
593 
594 
595 const std::vector<SUMOReal>&
597  return myShapeRotations;
598 }
599 
600 
601 const std::vector<SUMOReal>&
603  return myShapeLengths;
604 }
605 
606 
607 SUMOReal
609  return myLane.myVehicles.size() == 0
610  ? 0
611  : (*(myLane.myVehicles.end() - 1))->getWaitingSeconds();
612 }
613 
614 
615 SUMOReal
617  return (SUMOReal) myLane.getEdge().getLanes().size();
618 }
619 
620 
621 // ------------ Current state retrieval
622 SUMOReal
625 }
626 
627 
628 SUMOReal
631 }
632 
633 
634 SUMOReal
637 }
638 
639 
640 SUMOReal
643 }
644 
645 
646 SUMOReal
649 }
650 
651 
652 SUMOReal
655 }
656 
657 
658 void
661 }
662 
663 
664 SUMOReal
667  MSEdge& e = getLane().getEdge();
668  if (!ews.knowsTravelTime(&e)) {
669  return -1;
670  } else {
671  SUMOReal value(0);
672  ews.retrieveExistingTravelTime(&e, 0, STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()), value);
673  return value;
674  }
675 }
676 
677 SUMOReal
678 GUILaneWrapper::getColorValue(size_t activeScheme) const {
679  switch (activeScheme) {
680  case 1:
681  return (gSelected.isSelected(getType(), getGlID()) ||
682  gSelected.isSelected(GLO_EDGE, dynamic_cast<GUIEdge*>(&(getLane().getEdge()))->getGlID()));
683  case 2: {
685  return 0;
686  } else {
687  return 1;
688  }
689  }
690  case 3:
691  return getLane().getSpeedLimit();
692  case 4:
693  return getLane().getOccupancy();
694  case 5:
695  return firstWaitingTime();
696  case 6:
697  return getEdgeLaneNumber();
698  case 7:
700  case 8:
702  case 9:
704  case 10:
706  case 11:
708  case 12:
710  case 13:
712  case 14: {
713  return getStoredEdgeTravelTime();
714  }
715  case 15: {
717  MSEdge& e = getLane().getEdge();
718  if (!ews.knowsTravelTime(&e)) {
719  return -1;
720  } else {
721  SUMOReal value(0);
722  ews.retrieveExistingTravelTime(&e, 0, 0, value);
723  return 100 * getLane().getLength() / value / getLane().getSpeedLimit();
724  }
725  }
726  }
727  return 0;
728 }
729 
730 #ifdef HAVE_OSG
731 void
732 GUILaneWrapper::updateColor(const GUIVisualizationSettings& s) {
734  osg::Vec4ubArray* colors = dynamic_cast<osg::Vec4ubArray*>(myGeom->getColorArray());
735  (*colors)[0].set(col.red(), col.green(), col.blue(), col.alpha());
736  myGeom->setColorArray(colors);
737 }
738 #endif
739 
740 
741 /****************************************************************************/
742