SUMO - Simulation of Urban MObility
GUIOSGBuilder.cpp
Go to the documentation of this file.
1 /****************************************************************************/
8 // Builds OSG nodes from microsim objects
9 /****************************************************************************/
10 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
11 // Copyright (C) 2001-2016 DLR (http://www.dlr.de/) and contributors
12 /****************************************************************************/
13 //
14 // This file is part of SUMO.
15 // SUMO is free software: you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation, either version 3 of the License, or
18 // (at your option) any later version.
19 //
20 /****************************************************************************/
21 
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #ifdef _MSC_VER
27 #include <windows_config.h>
28 #else
29 #include <config.h>
30 #endif
31 
32 #ifdef HAVE_OSG
33 
34 #include <osg/Version>
35 #include <osgViewer/ViewerEventHandlers>
36 #include <osgGA/TrackballManipulator>
37 #include <osgDB/ReadFile>
38 #include <osgDB/WriteFile>
39 #include <osg/ShapeDrawable>
40 #include <osg/Node>
41 #include <osg/Group>
42 #include <osg/Geode>
43 #include <osg/Geometry>
44 #include <osg/Sequence>
45 #include <osg/Texture2D>
46 #include <osgViewer/Viewer>
47 #include <osgUtil/Tessellator>
48 #include <osg/PositionAttitudeTransform>
49 #include <osg/ShadeModel>
50 #include <osg/Light>
51 #include <osg/LightSource>
52 #include <microsim/MSNet.h>
53 #include <microsim/MSEdge.h>
54 #include <microsim/MSLane.h>
55 #include <microsim/MSEdgeControl.h>
57 #include <microsim/MSJunction.h>
58 #include <microsim/MSVehicleType.h>
62 #include <guisim/GUINet.h>
63 #include <guisim/GUIEdge.h>
64 #include <guisim/GUILane.h>
68 #include "GUIOSGView.h"
69 #include "GUIOSGBuilder.h"
70 
71 #ifdef CHECK_MEMORY_LEAKS
72 #include <foreign/nvwa/debug_new.h>
73 #endif // CHECK_MEMORY_LEAKS
74 
75 
76 // ===========================================================================
77 // static member variables
78 // ===========================================================================
79 std::map<std::string, osg::ref_ptr<osg::Node> > GUIOSGBuilder::myCars;
80 
81 
82 // ===========================================================================
83 // member method definitions
84 // ===========================================================================
85 osg::Group*
86 GUIOSGBuilder::buildOSGScene(osg::Node* const tlg, osg::Node* const tly, osg::Node* const tlr, osg::Node* const tlu) {
87  osgUtil::Tessellator tesselator;
88  osg::Group* root = new osg::Group();
89  GUINet* net = static_cast<GUINet*>(MSNet::getInstance());
90  // build edges
91  const MSEdgeVector& edges = net->getEdgeControl().getEdges();
92  for (MSEdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
93  if ((*i)->getPurpose() != MSEdge::EDGEFUNCTION_INTERNAL) {
94  buildOSGEdgeGeometry(**i, *root, tesselator);
95  }
96  }
97  // build junctions
98  for (int index = 0; index < (int)net->myJunctionWrapper.size(); ++index) {
99  buildOSGJunctionGeometry(*net->myJunctionWrapper[index], *root, tesselator);
100  }
101  // build traffic lights
103  const std::vector<std::string> tlids = net->getTLSControl().getAllTLIds();
104  for (std::vector<std::string>::const_iterator i = tlids.begin(); i != tlids.end(); ++i) {
107  const MSLane* lastLane = 0;
108  int idx = 0;
109  for (MSTrafficLightLogic::LaneVectorVector::const_iterator j = lanes.begin(); j != lanes.end(); ++j, ++idx) {
110  const MSLane* const lane = (*j)[0];
111  const Position pos = lane->getShape().back();
112  const SUMOReal angle = osg::DegreesToRadians(lane->getShape().rotationDegreeAtOffset(-1.) + 90.);
113  d.centerZ = pos.z() + 4.;
114  if (lane == lastLane) {
115  d.centerX += 1.2 * sin(angle);
116  d.centerY += 1.2 * cos(angle);
117  } else {
118  d.centerX = pos.x() - 1.5 * sin(angle);
119  d.centerY = pos.y() - 1.5 * cos(angle);
120  }
121  osg::Switch* switchNode = new osg::Switch();
122  switchNode->addChild(getTrafficLight(d, tlg, osg::Vec4(0.1, 0.5, 0.1, 1.0), .25), false);
123  switchNode->addChild(getTrafficLight(d, tly, osg::Vec4(0.5, 0.5, 0.1, 1.0), .25), false);
124  switchNode->addChild(getTrafficLight(d, tlr, osg::Vec4(0.5, 0.1, 0.1, 1.0), .25), false);
125  switchNode->addChild(getTrafficLight(d, tlu, osg::Vec4(0.8, 0.4, 0.0, 1.0), .25), false);
126  root->addChild(switchNode);
127  const MSLink* const l = vars.getActive()->getLinksAt(idx)[0];
128  vars.addSwitchCommand(new GUIOSGView::Command_TLSChange(l, switchNode));
129  lastLane = lane;
130  }
131  }
132  return root;
133 }
134 
135 
136 void
137 GUIOSGBuilder::buildLight(const GUISUMOAbstractView::Decal& d, osg::Group& addTo) {
138  // each light must have a unique number
139  osg::Light* light = new osg::Light(d.filename[5] - '0');
140  // we set the light's position via a PositionAttitudeTransform object
141  light->setPosition(osg::Vec4(0.0, 0.0, 0.0, 1.0));
142  light->setDiffuse(osg::Vec4(1.0, 1.0, 1.0, 1.0));
143  light->setSpecular(osg::Vec4(1.0, 1.0, 1.0, 1.0));
144  light->setAmbient(osg::Vec4(1.0, 1.0, 1.0, 1.0));
145 
146  osg::LightSource* lightSource = new osg::LightSource();
147  lightSource->setLight(light);
148  lightSource->setLocalStateSetModes(osg::StateAttribute::ON);
149  lightSource->setStateSetModes(*addTo.getOrCreateStateSet(), osg::StateAttribute::ON);
150 
151  osg::PositionAttitudeTransform* lightTransform = new osg::PositionAttitudeTransform();
152  lightTransform->addChild(lightSource);
153  lightTransform->setPosition(osg::Vec3(d.centerX, d.centerY, d.centerZ));
154  lightTransform->setScale(osg::Vec3(0.1, 0.1, 0.1));
155  addTo.addChild(lightTransform);
156 }
157 
158 
159 void
160 GUIOSGBuilder::buildOSGEdgeGeometry(const MSEdge& edge,
161  osg::Group& addTo,
162  osgUtil::Tessellator& tessellator) {
163  const std::vector<MSLane*>& lanes = edge.getLanes();
164  for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
165  MSLane* l = (*j);
166  const PositionVector& shape = l->getShape();
167  osg::Geode* geode = new osg::Geode();
168  osg::Geometry* geom = new osg::Geometry();
169  geode->addDrawable(geom);
170  addTo.addChild(geode);
171  osg::Vec3Array* osg_coords = new osg::Vec3Array(shape.size() * 2);
172  geom->setVertexArray(osg_coords);
173  PositionVector rshape = shape;
175  int index = 0;
176  for (int k = 0; k < (int)rshape.size(); ++k, ++index) {
177  (*osg_coords)[index].set(rshape[k].x(), rshape[k].y(), rshape[k].z());
178  }
179  PositionVector lshape = shape;
181  for (int k = (int) lshape.size() - 1; k >= 0; --k, ++index) {
182  (*osg_coords)[index].set(lshape[k].x(), lshape[k].y(), lshape[k].z());
183  }
184  osg::Vec3Array* osg_normals = new osg::Vec3Array(1);
185  (*osg_normals)[0] = osg::Vec3(0, 0, 1);
186 #if OSG_MIN_VERSION_REQUIRED(3,2,0)
187  geom->setNormalArray(osg_normals, osg::Array::BIND_PER_PRIMITIVE_SET);
188 #else
189  geom->setNormalArray(osg_normals);
190  geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
191 #endif
192  osg::Vec4ubArray* osg_colors = new osg::Vec4ubArray(1);
193  (*osg_colors)[0].set(128, 128, 128, 255);
194 #if OSG_MIN_VERSION_REQUIRED(3,2,0)
195  geom->setColorArray(osg_colors, osg::Array::BIND_OVERALL);
196 #else
197  geom->setColorArray(osg_colors);
198  geom->setColorBinding(osg::Geometry::BIND_OVERALL);
199 #endif
200  geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON, 0, shape.size() * 2));
201 
202  osg::ref_ptr<osg::StateSet> ss = geode->getOrCreateStateSet();
203  ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
204  ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
205 
206  if (shape.size() > 2) {
207  tessellator.retessellatePolygons(*geom);
208  }
209  static_cast<GUILane*>(l)->setGeometry(geom);
210  }
211 }
212 
213 
214 void
215 GUIOSGBuilder::buildOSGJunctionGeometry(GUIJunctionWrapper& junction,
216  osg::Group& addTo,
217  osgUtil::Tessellator& tessellator) {
218  const PositionVector& shape = junction.getJunction().getShape();
219  osg::Geode* geode = new osg::Geode();
220  osg::Geometry* geom = new osg::Geometry();
221  geode->addDrawable(geom);
222  addTo.addChild(geode);
223  osg::Vec3Array* osg_coords = new osg::Vec3Array(shape.size());
224  geom->setVertexArray(osg_coords);
225  for (int k = 0; k < (int)shape.size(); ++k) {
226  (*osg_coords)[k].set(shape[k].x(), shape[k].y(), shape[k].z());
227  }
228  osg::Vec3Array* osg_normals = new osg::Vec3Array(1);
229  (*osg_normals)[0] = osg::Vec3(0, 0, 1);
230 #if OSG_MIN_VERSION_REQUIRED(3,2,0)
231  geom->setNormalArray(osg_normals, osg::Array::BIND_PER_PRIMITIVE_SET);
232 #else
233  geom->setNormalArray(osg_normals);
234  geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
235 #endif
236  osg::Vec4ubArray* osg_colors = new osg::Vec4ubArray(1);
237  (*osg_colors)[0].set(128, 128, 128, 255);
238 #if OSG_MIN_VERSION_REQUIRED(3,2,0)
239  geom->setColorArray(osg_colors, osg::Array::BIND_OVERALL);
240 #else
241  geom->setColorArray(osg_colors);
242  geom->setColorBinding(osg::Geometry::BIND_OVERALL);
243 #endif
244  geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON, 0, shape.size()));
245 
246  osg::ref_ptr<osg::StateSet> ss = geode->getOrCreateStateSet();
247  ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
248  ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
249 
250  if (shape.size() > 4) {
251  tessellator.retessellatePolygons(*geom);
252  }
253  junction.setGeometry(geom);
254 }
255 
256 
257 void
258 GUIOSGBuilder::buildDecal(const GUISUMOAbstractView::Decal& d, osg::Group& addTo) {
259  osg::Node* pLoadedModel = osgDB::readNodeFile(d.filename);
260  if (pLoadedModel == 0) {
261  WRITE_ERROR("Could not load '" + d.filename + "'.");
262  return;
263  }
264  osg::ShadeModel* sm = new osg::ShadeModel();
265  sm->setMode(osg::ShadeModel::FLAT);
266  pLoadedModel->getOrCreateStateSet()->setAttribute(sm);
267  osg::PositionAttitudeTransform* base = new osg::PositionAttitudeTransform();
268  base->addChild(pLoadedModel);
269  GUIOSGBoundingBoxCalculator bboxCalc;
270  pLoadedModel->accept(bboxCalc);
271  const osg::BoundingBox& bbox = bboxCalc.getBoundingBox();
272  WRITE_MESSAGE("Loaded decal '" + d.filename + "' with bounding box " + toString(Position(bbox.xMin(), bbox.yMin(), bbox.zMin())) + " " + toString(Position(bbox.xMax(), bbox.yMax(), bbox.zMax())) + ".");
273  SUMOReal xScale = d.width > 0 ? d.width / (bbox.xMax() - bbox.xMin()) : 1.;
274  SUMOReal yScale = d.height > 0 ? d.height / (bbox.yMax() - bbox.yMin()) : 1.;
275  const SUMOReal zScale = d.altitude > 0 ? d.altitude / (bbox.zMax() - bbox.zMin()) : 1.;
276  if (d.width < 0 && d.height < 0 && d.altitude > 0) {
277  xScale = yScale = zScale;
278  }
279  base->setScale(osg::Vec3(xScale, yScale, zScale));
280  base->setPosition(osg::Vec3(d.centerX, d.centerY, d.centerZ));
281  base->setAttitude(osg::Quat(osg::DegreesToRadians(d.roll), osg::Vec3(1, 0, 0),
282  osg::DegreesToRadians(d.tilt), osg::Vec3(0, 1, 0),
283  osg::DegreesToRadians(d.rot), osg::Vec3(0, 0, 1)));
284  addTo.addChild(base);
285 }
286 
287 
288 osg::PositionAttitudeTransform*
289 GUIOSGBuilder::getTrafficLight(const GUISUMOAbstractView::Decal& d, osg::Node* tl, const osg::Vec4& color, const SUMOReal size) {
290  osg::PositionAttitudeTransform* ret = new osg::PositionAttitudeTransform();
291  if (tl != 0) {
292  osg::PositionAttitudeTransform* base = new osg::PositionAttitudeTransform();
293  base->addChild(tl);
294  GUIOSGBoundingBoxCalculator bboxCalc;
295  tl->accept(bboxCalc);
296  const osg::BoundingBox& bbox = bboxCalc.getBoundingBox();
297  SUMOReal xScale = d.width > 0 ? d.width / (bbox.xMax() - bbox.xMin()) : 1.;
298  SUMOReal yScale = d.height > 0 ? d.height / (bbox.yMax() - bbox.yMin()) : 1.;
299  const SUMOReal zScale = d.altitude > 0 ? d.altitude / (bbox.zMax() - bbox.zMin()) : 1.;
300  if (d.width < 0 && d.height < 0 && d.altitude > 0) {
301  xScale = yScale = zScale;
302  }
303  base->setScale(osg::Vec3(xScale, yScale, zScale));
304  base->setPosition(osg::Vec3(d.centerX, d.centerY, d.centerZ));
305  base->setAttitude(osg::Quat(osg::DegreesToRadians(d.roll), osg::Vec3(1, 0, 0),
306  osg::DegreesToRadians(d.tilt), osg::Vec3(0, 1, 0),
307  osg::DegreesToRadians(d.rot), osg::Vec3(0, 0, 1)));
308  ret->addChild(base);
309  }
310  osg::Geode* geode = new osg::Geode();
311  osg::Vec3 center(d.centerX, d.centerY, d.centerZ);
312  osg::ShapeDrawable* shape = new osg::ShapeDrawable(new osg::Sphere(center, size));
313  geode->addDrawable(shape);
314  osg::ref_ptr<osg::StateSet> ss = shape->getOrCreateStateSet();
315  ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
316  ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
317  osg::PositionAttitudeTransform* ellipse = new osg::PositionAttitudeTransform();
318  ellipse->addChild(geode);
319  ellipse->setPivotPoint(center);
320  ellipse->setPosition(center);
321  ellipse->setScale(osg::Vec3(4., 4., 2.5 * d.altitude + 1.1));
322  shape->setColor(color);
323  ret->addChild(ellipse);
324  return ret;
325 }
326 
327 
328 void
329 GUIOSGBuilder::setShapeState(osg::ref_ptr<osg::ShapeDrawable> shape) {
330  osg::ref_ptr<osg::StateSet> ss = shape->getOrCreateStateSet();
331  ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
332  ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
333 }
334 
335 
336 GUIOSGView::OSGMovable
337 GUIOSGBuilder::buildMovable(const MSVehicleType& type) {
338  GUIOSGView::OSGMovable m;
339  m.pos = new osg::PositionAttitudeTransform();
340  SUMOReal enlarge = 0.;
341  const std::string& osgFile = type.getOSGFile();
342  if (myCars.find(osgFile) == myCars.end()) {
343  myCars[osgFile] = osgDB::readNodeFile(osgFile);
344  if (myCars[osgFile] == 0) {
345  WRITE_ERROR("Could not load '" + osgFile + "'.");
346  }
347  }
348  osg::Node* carNode = myCars[osgFile];
349  if (carNode != 0) {
350  GUIOSGBoundingBoxCalculator bboxCalc;
351  carNode->accept(bboxCalc);
352  const osg::BoundingBox& bbox = bboxCalc.getBoundingBox();
353  osg::PositionAttitudeTransform* base = new osg::PositionAttitudeTransform();
354  base->addChild(carNode);
355  base->setPivotPoint(osg::Vec3((bbox.xMin() + bbox.xMax()) / 2., bbox.yMin(), bbox.zMin()));
356  base->setScale(osg::Vec3(type.getWidth() / (bbox.xMax() - bbox.xMin()),
357  type.getLength() / (bbox.yMax() - bbox.yMin()),
358  type.getHeight() / (bbox.zMax() - bbox.zMin())));
359  m.pos->addChild(base);
360  enlarge = type.getMinGap() / 2.;
361  }
362  m.lights = new osg::Switch();
363  for (SUMOReal offset = -0.3; offset < 0.5; offset += 0.6) {
364  osg::Geode* geode = new osg::Geode();
365  osg::ShapeDrawable* right = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(offset, (type.getLength() - .9) / 2., (type.getHeight() - .5) / 2.), .1f));
366  geode->addDrawable(right);
367  setShapeState(right);
368  right->setColor(osg::Vec4(1.f, .5f, 0.f, .8f));
369  osg::Sequence* seq = new osg::Sequence();
370  // Wikipedia says about 1.5Hz
371  seq->addChild(geode, .33);
372  seq->addChild(new osg::Geode(), .33);
373  // loop through all children
374  seq->setInterval(osg::Sequence::LOOP, 0, -1);
375  // real-time playback, repeat indefinitely
376  seq->setDuration(1.0f, -1);
377  // must be started explicitly
378  seq->setMode(osg::Sequence::START);
379  m.lights->addChild(seq);
380  }
381 
382  osg::Geode* geode = new osg::Geode();
383  osg::CompositeShape* comp = new osg::CompositeShape();
384  comp->addChild(new osg::Sphere(osg::Vec3(-0.3, (type.getLength() + .8) / 2., (type.getHeight() - .5) / 2.), .1f));
385  comp->addChild(new osg::Sphere(osg::Vec3(0.3, (type.getLength() + .8) / 2., (type.getHeight() - .5) / 2.), .1f));
386  osg::ShapeDrawable* brake = new osg::ShapeDrawable(comp);
387  brake->setColor(osg::Vec4(1.f, 0.f, 0.f, .8f));
388  geode->addDrawable(brake);
389  setShapeState(brake);
390  m.lights->addChild(geode);
391 
392  geode = new osg::Geode();
393  osg::Vec3 center(0, type.getLength() / 2., type.getHeight() / 2.);
394  m.geom = new osg::ShapeDrawable(new osg::Sphere(center, .5f));
395  geode->addDrawable(m.geom);
396  setShapeState(m.geom);
397  osg::PositionAttitudeTransform* ellipse = new osg::PositionAttitudeTransform();
398  ellipse->addChild(geode);
399  ellipse->addChild(m.lights);
400  ellipse->setPivotPoint(center);
401  ellipse->setPosition(center);
402  ellipse->setScale(osg::Vec3(type.getWidth() + enlarge, type.getLength() + enlarge, type.getHeight() + enlarge));
403  m.pos->addChild(ellipse);
404  return m;
405 }
406 
407 #endif
408 
409 
410 /****************************************************************************/
411 
A decal (an image) that can be shown.
SUMOReal roll
The roll of the image to the ground plane (in degrees)
Storage for all programs of a single tls.
std::vector< GUIJunctionWrapper * > myJunctionWrapper
Wrapped MS-junctions.
Definition: GUINet.h:340
const LaneVectorVector & getLaneVectors() const
Returns the list of lists of all lanes controlled by this tls.
SUMOReal getLength() const
Get vehicle&#39;s length [m].
SUMOReal getHeight() const
Get the height which vehicles of this class shall have when being drawn.
const std::vector< MSLane * > & getLanes() const
Returns this edge&#39;s lanes.
Definition: MSEdge.h:192
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:159
const PositionVector & getShape() const
Returns this lane&#39;s shape.
Definition: MSLane.h:427
SUMOReal centerZ
The center of the image in z-direction (net coordinates, in m)
SUMOReal width
The width of the image (net coordinates in x-direction, in m)
const LinkVector & getLinksAt(int i) const
Returns the list of links that are controlled by the signals at the given position.
The car-following model and parameter.
Definition: MSVehicleType.h:74
Representation of a lane in the micro simulation (gui-version)
Definition: GUILane.h:70
A road/street connecting two junctions.
Definition: MSEdge.h:80
SUMOReal getWidth() const
Get the width which vehicles of this class shall have when being drawn.
void addSwitchCommand(OnSwitchAction *c)
SUMOReal z() const
Returns the z-position.
Definition: Position.h:73
SUMOReal altitude
The altitude of the image (net coordinates in z-direction, in m)
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
SUMOReal centerY
The center of the image in y-direction (net coordinates, in m)
MSTLLogicControl & getTLSControl()
Returns the tls logics control.
Definition: MSNet.h:380
A list of positions.
SUMOReal rotationDegreeAtOffset(SUMOReal pos) const
Returns the rotation at the given length.
SUMOReal x() const
Returns the x-position.
Definition: Position.h:63
std::string filename
The path to the file the image is located at.
static int comp(const void *key, const void *target)
Definition: polyfonts.c:820
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:206
SUMOReal height
The height of the image (net coordinates in y-direction, in m)
SUMOReal centerX
The center of the image in x-direction (net coordinates, in m)
std::vector< LaneVector > LaneVectorVector
Definition of a list that holds lists of links that do have the same attribute.
A MSNet extended by some values for usage within the gui.
Definition: GUINet.h:89
const MSJunction & getJunction() const
Returns the represented junction.
const MSEdgeVector & getEdges() const
Returns loaded edges.
SUMOReal getMinGap() const
Get the free space in front of vehicles of this class.
void move2side(SUMOReal amount)
move position vector to side using certain ammount
#define SUMOReal
Definition: config.h:213
MSEdgeControl & getEdgeControl()
Returns the edge control.
Definition: MSNet.h:350
std::string getOSGFile() const
Get this vehicle type&#39;s 3D model file name.
TLSLogicVariants & get(const std::string &id) const
Returns the variants of a named tls.
SUMOReal tilt
The tilt of the image to the ground plane (in degrees)
std::vector< MSEdge * > MSEdgeVector
Definition: MSEdge.h:77
MSTrafficLightLogic * getActive() const
std::vector< std::string > getAllTLIds() const
const SUMOReal SUMO_const_halfLaneWidth
Definition: StdDefs.h:50
The edge is an internal edge.
Definition: MSEdge.h:97
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:201
SUMOReal y() const
Returns the y-position.
Definition: Position.h:68
Representation of a lane in the micro simulation.
Definition: MSLane.h:79
const PositionVector & getShape() const
Returns this junction&#39;s shape.
Definition: MSJunction.h:93
SUMOReal rot
The rotation of the image in the ground plane (in degrees)