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