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-2012 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 #include <microsim/MSLane.h>
37 #include <microsim/MSEdge.h>
38 #include <microsim/MSGlobals.h>
41 #include <microsim/MSNet.h>
42 #include <gui/GUIGlobals.h>
44 #include "GUILaneWrapper.h"
45 #include "GUIEdge.h"
46 #include <utils/common/ToString.h>
47 #include <utils/geom/GeomHelper.h>
48 #include <guisim/GUINet.h>
57 #include <utils/gui/div/GLHelper.h>
58 #include <gui/GUIViewTraffic.h>
60 #include <guisim/GUIVehicle.h>
65 
66 #ifdef CHECK_MEMORY_LEAKS
67 #include <foreign/nvwa/debug_new.h>
68 #endif // CHECK_MEMORY_LEAKS
69 
70 
71 // ===========================================================================
72 // static member definitions
73 // ===========================================================================
75 
76 
77 // ===========================================================================
78 // method definitions
79 // ===========================================================================
80 GUILaneWrapper::GUILaneWrapper(MSLane& lane, const PositionVector& shape, unsigned int index) :
81  GUIGlObject(GLO_LANE, lane.getID()),
82  myLane(lane),
83  myShape(shape),
84  myIndex(index) {
85  myShapeRotations.reserve(myShape.size() - 1);
86  myShapeLengths.reserve(myShape.size() - 1);
87  int e = (int) myShape.size() - 1;
88  for (int i = 0; i < e; ++i) {
89  const Position& f = myShape[i];
90  const Position& s = myShape[i + 1];
91  myShapeLengths.push_back(f.distanceTo2D(s));
92  myShapeRotations.push_back((SUMOReal) atan2((s.x() - f.x()), (f.y() - s.y())) * (SUMOReal) 180.0 / (SUMOReal) PI);
93  }
94  //
97 }
98 
99 
101 
102 
103 bool
104 GUILaneWrapper::forLane(const MSLane& lane) const {
105  return (&myLane) == (&lane);
106 }
107 
108 
109 
110 void
112  unsigned int noLinks = getLinkNumber();
113  if (noLinks == 0) {
114  return;
115  }
116  // draw all links
117  SUMOReal w = myLane.getWidth() / (SUMOReal) noLinks;
118  SUMOReal x1 = myLane.getWidth() / (SUMOReal) 2.;
119  glPushMatrix();
120  const PositionVector& g = getShape();
121  const Position& end = g.getEnd();
122  const Position& f = g[-2];
123  const Position& s = end;
124  SUMOReal rot = (SUMOReal) atan2((s.x() - f.x()), (f.y() - s.y())) * (SUMOReal) 180.0 / (SUMOReal) PI;
125  glTranslated(end.x(), end.y(), 0);
126  glRotated(rot, 0, 0, 1);
127  for (int i = noLinks; --i >= 0;) {
128  SUMOReal x2 = x1 - (SUMOReal)(w / 2.);
129  GLHelper::drawText(toString(getLane().getLinkCont()[i]->getRespondIndex()),
130  Position(x2, 0), 0, .6, RGBColor(.5, .5, 1), 180);
131  x1 -= w;
132  }
133  glPopMatrix();
134 }
135 
136 
137 void
139  unsigned int noLinks = getLinkNumber();
140  if (noLinks == 0) {
141  return;
142  }
143  // draw all links
144  SUMOReal w = myLane.getWidth() / (SUMOReal) noLinks;
145  SUMOReal x1 = (SUMOReal)(myLane.getWidth() / 2.);
146  glPushMatrix();
147  const PositionVector& g = getShape();
148  const Position& end = g.getEnd();
149  const Position& f = g[-2];
150  const Position& s = end;
151  SUMOReal rot = (SUMOReal) atan2((s.x() - f.x()), (f.y() - s.y())) * (SUMOReal) 180.0 / (SUMOReal) PI;
152  glTranslated(end.x(), end.y(), 0);
153  glRotated(rot, 0, 0, 1);
154  for (int i = noLinks; --i >= 0;) {
155  SUMOReal x2 = x1 - (SUMOReal)(w / 2.);
156  int linkNo = net.getLinkTLIndex(getLane().getLinkCont()[i]);
157  if (linkNo < 0) {
158  continue;
159  }
161  Position(x2, 0), 0, .6, RGBColor(.5, .5, 1), 180);
162  x1 -= w;
163  }
164  glPopMatrix();
165 }
166 
167 
168 void
170  unsigned int noLinks = getLinkNumber();
171  const PositionVector& g = getShape();
172  const Position& end = g.getEnd();
173  const Position& f = g[-2];
174  const Position& s = end;
175  SUMOReal rot = (SUMOReal) atan2((s.x() - f.x()), (f.y() - s.y())) * (SUMOReal) 180.0 / (SUMOReal) PI;
176  if (noLinks == 0) {
177  glPushName(getGlID());
178  // draw a grey bar if no links are on the street
179  glColor3d(0.5, 0.5, 0.5);
180  glPushMatrix();
181  glTranslated(end.x(), end.y(), 0);
182  glRotated(rot, 0, 0, 1);
183  glBegin(GL_QUADS);
184  glVertex2d(-myHalfLaneWidth, 0.0);
185  glVertex2d(-myHalfLaneWidth, 0.5);
186  glVertex2d(myHalfLaneWidth, 0.5);
187  glVertex2d(myHalfLaneWidth, 0.0);
188  glEnd();
189  glPopMatrix();
190  glPopName();
191  return;
192  }
193  // draw all links
194  SUMOReal w = myLane.getWidth() / (SUMOReal) noLinks;
195  SUMOReal x1 = 0;
196  glPushMatrix();
197  glTranslated(end.x(), end.y(), 0);
198  glRotated(rot, 0, 0, 1);
199  for (unsigned int i = 0; i < noLinks; ++i) {
200  SUMOReal x2 = x1 + w;
201  MSLink* link = getLane().getLinkCont()[i];
202  // select glID
203  switch (link->getState()) {
206  case LINKSTATE_TL_RED:
210  glPushName(net.getLinkTLID(link));
211  break;
212  case LINKSTATE_MAJOR:
213  case LINKSTATE_MINOR:
214  case LINKSTATE_EQUAL:
216  default:
217  glPushName(getGlID());
218  break;
219  }
220  // select color
221  switch (link->getState()) {
224  glColor3d(0, 1, 0);
225  break;
226  case LINKSTATE_TL_RED:
227  glColor3d(1, 0, 0);
228  break;
231  glColor3d(1, 1, 0);
232  break;
234  glColor3d(.7, .7, 0);
235  break;
237  glColor3d(0, 1, 1);
238  break;
239  case LINKSTATE_MAJOR:
240  glColor3d(1, 1, 1);
241  break;
242  case LINKSTATE_MINOR:
243  glColor3d(.2, .2, .2);
244  break;
245  case LINKSTATE_EQUAL:
246  glColor3d(.5, .5, .5);
247  break;
248  case LINKSTATE_DEADEND:
249  glColor3d(0, 0, 0);
250  break;
251  }
252  glBegin(GL_QUADS);
253  glVertex2d(x1 - myHalfLaneWidth, 0.0);
254  glVertex2d(x1 - myHalfLaneWidth, 0.5);
255  glVertex2d(x2 - myHalfLaneWidth, 0.5);
256  glVertex2d(x2 - myHalfLaneWidth, 0.0);
257  glEnd();
258  glPopName();
259  x1 = x2;
260  x2 += w;
261  }
262  glPopMatrix();
263 }
264 
265 
266 void
268  unsigned int noLinks = getLinkNumber();
269  if (noLinks == 0) {
270  return;
271  }
272  // draw all links
273  const Position& end = getShape().getEnd();
274  const Position& f = getShape()[-2];
275  SUMOReal rot = (SUMOReal) atan2((end.x() - f.x()), (f.y() - end.y())) * (SUMOReal) 180.0 / (SUMOReal) PI;
276  glPushMatrix();
277  glPushName(0);
278  glColor3d(1, 1, 1);
279  glTranslated(end.x(), end.y(), 0);
280  glRotated(rot, 0, 0, 1);
281  for (unsigned int i = 0; i < noLinks; ++i) {
282  LinkDirection dir = getLane().getLinkCont()[i]->getDirection();
283  LinkState state = getLane().getLinkCont()[i]->getState();
284  if (state == LINKSTATE_TL_OFF_NOSIGNAL || dir == LINKDIR_NODIR) {
285  continue;
286  }
287  switch (dir) {
288  case LINKDIR_STRAIGHT:
289  GLHelper::drawBoxLine(Position(0, 4), 0, 2, .05);
291  break;
292  case LINKDIR_TURN:
293  GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
294  GLHelper::drawBoxLine(Position(0, 2.5), 90, .5, .05);
295  GLHelper::drawBoxLine(Position(0.5, 2.5), 180, 1, .05);
296  GLHelper::drawTriangleAtEnd(Line(Position(0.5, 2.5), Position(0.5, 4)), (SUMOReal) 1, (SUMOReal) .25);
297  break;
298  case LINKDIR_LEFT:
299  GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
300  GLHelper::drawBoxLine(Position(0, 2.5), 90, 1, .05);
301  GLHelper::drawTriangleAtEnd(Line(Position(0, 2.5), Position(1.5, 2.5)), (SUMOReal) 1, (SUMOReal) .25);
302  break;
303  case LINKDIR_RIGHT:
304  GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
305  GLHelper::drawBoxLine(Position(0, 2.5), -90, 1, .05);
306  GLHelper::drawTriangleAtEnd(Line(Position(0, 2.5), Position(-1.5, 2.5)), (SUMOReal) 1, (SUMOReal) .25);
307  break;
308  case LINKDIR_PARTLEFT:
309  GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
310  GLHelper::drawBoxLine(Position(0, 2.5), 45, .7, .05);
311  GLHelper::drawTriangleAtEnd(Line(Position(0, 2.5), Position(1.2, 1.3)), (SUMOReal) 1, (SUMOReal) .25);
312  break;
313  case LINKDIR_PARTRIGHT:
314  GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
315  GLHelper::drawBoxLine(Position(0, 2.5), -45, .7, .05);
316  GLHelper::drawTriangleAtEnd(Line(Position(0, 2.5), Position(-1.2, 1.3)), (SUMOReal) 1, (SUMOReal) .25);
317  break;
318  default:
319  break;
320  }
321  }
322  glPopMatrix();
323  glPopName();
324 }
325 
326 
327 void
329  unsigned int noLinks = getLinkNumber();
330  for (unsigned int i = 0; i < noLinks; ++i) {
331  LinkState state = getLane().getLinkCont()[i]->getState();
332  const MSLane* connected = getLane().getLinkCont()[i]->getLane();
333  if (connected == 0) {
334  continue;
335  }
336  switch (state) {
339  glColor3d(0, 1, 0);
340  break;
341  case LINKSTATE_TL_RED:
342  glColor3d(1, 0, 0);
343  break;
346  glColor3d(1, 1, 0);
347  break;
349  glColor3d(1, 1, 0);
350  break;
352  glColor3d(0, 1, 1);
353  break;
354  case LINKSTATE_MAJOR:
355  glColor3d(1, 1, 1);
356  break;
357  case LINKSTATE_MINOR:
358  glColor3d(.2, .2, .2);
359  break;
360  case LINKSTATE_EQUAL:
361  glColor3d(.5, .5, .5);
362  break;
363  case LINKSTATE_DEADEND:
364  glColor3d(0, 0, 0);
365  break;
366  }
367 
368  glBegin(GL_LINES);
369  const Position& p1 = getShape()[-1];
370  const Position& p2 = connected->getShape()[0];
371  glVertex2f(p1.x(), p1.y());
372  glVertex2f(p2.x(), p2.y());
373  glEnd();
374  GLHelper::drawTriangleAtEnd(Line(p1, p2), (SUMOReal) .4, (SUMOReal) .2);
375  }
376 }
377 
378 
379 void
381  glPushMatrix();
382  const bool isInternal = getLane().getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL;
383  bool mustDrawMarkings = false;
384  const bool drawDetails = s.scale * s.laneWidthExaggeration > 5;
385  if (isInternal) {
386  // draw internal lanes on top of junctions
387  glTranslated(0, 0, GLO_JUNCTION + 0.1);
388  } else {
389  glTranslated(0, 0, getType());
390  }
391  // set lane color
392  if (!MSGlobals::gUseMesoSim) {
393  setColor(s);
394  glPushName(getGlID()); // do not register for clicks in MESOSIM
395  }
396  // draw lane
397  // check whether it is not too small
398  if (s.scale * s.laneWidthExaggeration < 1.) {
400  if (!MSGlobals::gUseMesoSim) {
401  glPopName();
402  }
403  glPopMatrix();
404  } else if (isRailway(getLane().getPermissions())) {
405  // draw as railway
406  const SUMOReal halfRailWidth = 0.725;
408  glColor3d(1, 1, 1);
409  glTranslated(0, 0, .1);
411  drawCrossties(s);
412  if (!MSGlobals::gUseMesoSim) {
413  glPopName();
414  }
415  glPopMatrix();
416  } else {
417  const SUMOReal laneWidth = isInternal ? myQuarterLaneWidth : myHalfLaneWidth;
418  mustDrawMarkings = !isInternal;
420  if (!MSGlobals::gUseMesoSim) {
421  glPopName();
422  }
423  glPopMatrix();
424  // draw ROWs (not for inner lanes)
425  if (!isInternal && drawDetails) {
426  glPushMatrix();
427  glTranslated(0, 0, GLO_JUNCTION); // must draw on top of junction shape
428  GUINet* net = (GUINet*) MSNet::getInstance();
429  glTranslated(0, 0, .2);
431  if (s.showLinkDecals) {
433  }
434  if (s.showLane2Lane) {
435  // this should be independent to the geometry:
436  // draw from end of first to the begin of second
438  }
439  glTranslated(0, 0, .1);
440  if (s.drawLinkJunctionIndex) {
442  }
443  if (s.drawLinkTLIndex) {
445  }
446  glPopMatrix();
447  }
448  }
449  if (mustDrawMarkings && drawDetails) { // needs matrix reset
450  drawMarkings(s);
451  }
452  // draw vehicles
453  if (s.scale > s.minVehicleSize) {
454  // retrieve vehicles from lane; disallow simulation
455  const MSLane::VehCont& vehicles = myLane.getVehiclesSecure();
456  for (MSLane::VehCont::const_iterator v = vehicles.begin(); v != vehicles.end(); ++v) {
457  static_cast<const GUIVehicle* const>(*v)->drawGL(s);
458  }
459  // allow lane simulation
461  }
462 }
463 
464 
465 void
467  glPushMatrix();
468  glPushName(0);
469  glTranslated(0, 0, GLO_EDGE);
470 #ifdef HAVE_INTERNAL
472 #endif
473  setColor(s);
474  // optionally draw inverse markings
475  if (myIndex > 0) {
476  int e = (int) getShape().size() - 1;
477  for (int i = 0; i < e; i++) {
478  glPushMatrix();
479  glTranslated(getShape()[i].x(), getShape()[i].y(), 0.1);
480  glRotated(myShapeRotations[i], 0, 0, 1);
481  for (SUMOReal t = 0; t < myShapeLengths[i]; t += 6) {
482  glBegin(GL_QUADS);
483  glVertex2d(-1.8, -t);
484  glVertex2d(-1.8, -t - 3.);
485  glVertex2d(1.0, -t - 3.);
486  glVertex2d(1.0, -t);
487  glEnd();
488  }
489  glPopMatrix();
490  }
491  }
492  // draw white boundings and white markings
493  glColor3d(1, 1, 1);
495  getShape(),
497  getShapeLengths(),
499  glPopMatrix();
500  glPopName();
501 }
502 
503 
504 void
506  glPushMatrix();
507  glPushName(0);
508  if (!MSGlobals::gUseMesoSim) {
509  setColor(s);
510  }
511  // draw on top of of the white area between the rails
512  glTranslated(0, 0, 0.1);
513  int e = (int) getShape().size() - 1;
514  for (int i = 0; i < e; i++) {
515  glPushMatrix();
516  glTranslated(getShape()[i].x(), getShape()[i].y(), 0.1);
517  glRotated(myShapeRotations[i], 0, 0, 1);
518  for (SUMOReal t = 0; t < myShapeLengths[i]; t += 1) {
519  glBegin(GL_QUADS);
520  glVertex2d(-1, -t);
521  glVertex2d(-1, -t - 0.3);
522  glVertex2d(1.0, -t - 0.3);
523  glVertex2d(1.0, -t);
524  glEnd();
525  }
526  glPopMatrix();
527  }
528  glPopMatrix();
529  glPopName();
530 }
531 
534  GUISUMOAbstractView& parent) {
535  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
536  buildPopupHeader(ret, app);
538  //
541  //
542  buildShowParamsPopupEntry(ret, false);
545  new FXMenuCommand(ret, ("pos: " + toString(pos)).c_str(), 0, 0, 0);
546  new FXMenuSeparator(ret);
547  buildPositionCopyEntry(ret, false);
548  return ret;
549 }
550 
551 
556  new GUIParameterTableWindow(app, *this, 4);
557  // add items
558  ret->mkItem("maxspeed [m/s]", false, myLane.getSpeedLimit());
559  ret->mkItem("length [m]", false, myLane.getLength());
560  ret->mkItem("permissions", false, getAllowedVehicleClassNames(myLane.getPermissions()));
561  ret->mkItem("street name", false, myLane.getEdge().getStreetName());
562  ret->mkItem("stored traveltime [s]", true, new FunctionBinding<GUILaneWrapper, SUMOReal>(this, &GUILaneWrapper::getStoredEdgeTravelTime));
563  // close building
564  ret->closeBuilding();
565  return ret;
566 }
567 
568 
569 Boundary
571  Boundary b;
572  b.add(myShape[0]);
573  b.add(myShape[-1]);
574  b.grow(20);
575  return b;
576 }
577 
578 
579 
580 
581 const PositionVector&
583  return myShape;
584 }
585 
586 
587 unsigned int
589  return (unsigned int) myLane.getLinkCont().size();
590 }
591 
592 
593 const std::vector<SUMOReal>&
595  return myShapeRotations;
596 }
597 
598 
599 const std::vector<SUMOReal>&
601  return myShapeLengths;
602 }
603 
604 
605 SUMOReal
607  return myLane.myVehicles.size() == 0
608  ? 0
609  : (*(myLane.myVehicles.end() - 1))->getWaitingSeconds();
610 }
611 
612 
613 SUMOReal
615  return (SUMOReal) myLane.getEdge().getLanes().size();
616 }
617 
618 
619 // ------------ Current state retrieval
620 SUMOReal
623 }
624 
625 
626 SUMOReal
629 }
630 
631 
632 SUMOReal
635 }
636 
637 
638 SUMOReal
641 }
642 
643 
644 SUMOReal
647 }
648 
649 
650 SUMOReal
653 }
654 
655 
656 void
659 }
660 
661 
662 SUMOReal
665  MSEdge& e = getLane().getEdge();
666  if (!ews.knowsTravelTime(&e)) {
667  return -1;
668  } else {
669  SUMOReal value(0);
670  ews.retrieveExistingTravelTime(&e, 0, STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()), value);
671  return value;
672  }
673 }
674 
675 SUMOReal
676 GUILaneWrapper::getColorValue(size_t activeScheme) const {
677  switch (activeScheme) {
678  case 1:
679  return (gSelected.isSelected(getType(), getGlID()) ||
680  gSelected.isSelected(GLO_EDGE, dynamic_cast<GUIEdge*>(&(getLane().getEdge()))->getGlID()));
681  case 2: {
683  return 0;
684  } else {
685  return 1;
686  }
687  }
688  case 3:
689  return getLane().getSpeedLimit();
690  case 4:
691  return getLane().getOccupancy();
692  case 5:
693  return firstWaitingTime();
694  case 6:
695  return getEdgeLaneNumber();
696  case 7:
698  case 8:
700  case 9:
702  case 10:
704  case 11:
706  case 12:
708  case 13:
710  case 14: {
711  return getStoredEdgeTravelTime();
712  }
713  case 15: {
715  MSEdge& e = getLane().getEdge();
716  if (!ews.knowsTravelTime(&e)) {
717  return -1;
718  } else {
719  SUMOReal value(0);
720  ews.retrieveExistingTravelTime(&e, 0, 0, value);
721  return 100 * getLane().getLength() / value / getLane().getSpeedLimit();
722  }
723  }
724  }
725  return 0;
726 }
727 
728 /****************************************************************************/
729