SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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
std::string getOSGFile() const
Get this vehicle type's 3D model file name.
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:192
const PositionVector & getShape() const
Returns this junction's shape.
Definition: MSJunction.h:93
SUMOReal getLength() const
Get vehicle's length [m].
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:159
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)
const LinkVector & getLinksAt(int i) const
Returns the list of links that are controlled by the signals at the given position.
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:380
A list of positions.
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:55
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's shape.
Definition: MSLane.h:427
void move2side(SUMOReal amount)
move position vector to side using certain ammount
#define SUMOReal
Definition: config.h:214
MSEdgeControl & getEdgeControl()
Returns the edge control.
Definition: MSNet.h:350
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:79
SUMOReal rot
The rotation of the image in the ground plane (in degrees)
const MSEdgeVector & getEdges() const
Returns loaded edges.