SUMO - Simulation of Urban MObility
GUIOSGBuilder.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
16 // Builds OSG nodes from microsim objects
17 /****************************************************************************/
18 
19 
20 // ===========================================================================
21 // included modules
22 // ===========================================================================
23 #include <config.h>
24 
25 #ifdef HAVE_OSG
26 
27 #ifdef _MSC_VER
28 #pragma warning(push)
29 #pragma warning(disable: 4127) // do not warn about constant conditional expression
30 #endif
31 #include <osg/Version>
32 #include <osgViewer/ViewerEventHandlers>
33 #include <osgGA/TrackballManipulator>
34 #include <osgDB/ReadFile>
35 #include <osgDB/WriteFile>
36 #include <osg/ShapeDrawable>
37 #include <osg/Node>
38 #include <osg/Group>
39 #include <osg/Geode>
40 #include <osg/Geometry>
41 #include <osg/Sequence>
42 #include <osg/Texture2D>
43 #include <osgViewer/Viewer>
44 #include <osgUtil/Tessellator>
45 #include <osg/PositionAttitudeTransform>
46 #include <osg/ShadeModel>
47 #include <osg/Light>
48 #include <osg/LightSource>
49 #ifdef _MSC_VER
50 #pragma warning(pop)
51 #endif
52 
53 #include <microsim/MSNet.h>
54 #include <microsim/MSEdge.h>
55 #include <microsim/MSLane.h>
56 #include <microsim/MSEdgeControl.h>
58 #include <microsim/MSJunction.h>
59 #include <microsim/MSVehicleType.h>
63 #include <guisim/GUINet.h>
64 #include <guisim/GUIEdge.h>
65 #include <guisim/GUILane.h>
69 #include "GUIOSGView.h"
70 #include "GUIOSGBuilder.h"
71 
72 
73 // ===========================================================================
74 // static member variables
75 // ===========================================================================
76 std::map<std::string, osg::ref_ptr<osg::Node> > GUIOSGBuilder::myCars;
77 
78 
79 // ===========================================================================
80 // member method definitions
81 // ===========================================================================
82 osg::Group*
83 GUIOSGBuilder::buildOSGScene(osg::Node* const tlg, osg::Node* const tly, osg::Node* const tlr, osg::Node* const tlu) {
84  osgUtil::Tessellator tesselator;
85  osg::Group* root = new osg::Group();
86  GUINet* net = static_cast<GUINet*>(MSNet::getInstance());
87  // build edges
88  for (const MSEdge* e : net->getEdgeControl().getEdges()) {
89  if (!e->isInternal()) {
90  buildOSGEdgeGeometry(*e, *root, tesselator);
91  }
92  }
93  // build junctions
94  for (int index = 0; index < (int)net->myJunctionWrapper.size(); ++index) {
95  buildOSGJunctionGeometry(*net->myJunctionWrapper[index], *root, tesselator);
96  }
97  // build traffic lights
99  const std::vector<std::string> tlids = net->getTLSControl().getAllTLIds();
100  for (std::vector<std::string>::const_iterator i = tlids.begin(); i != tlids.end(); ++i) {
103  const MSLane* lastLane = 0;
104  int idx = 0;
105  for (MSTrafficLightLogic::LaneVectorVector::const_iterator j = lanes.begin(); j != lanes.end(); ++j, ++idx) {
106  if ((*j).size() == 0) {
107  continue;
108  }
109  const MSLane* const lane = (*j)[0];
110  const Position pos = lane->getShape().back();
111  const double 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::Vec4d(0.1, 0.5, 0.1, 1.0), .25), false);
122  switchNode->addChild(getTrafficLight(d, tly, osg::Vec4d(0.5, 0.5, 0.1, 1.0), .25), false);
123  switchNode->addChild(getTrafficLight(d, tlr, osg::Vec4d(0.5, 0.1, 0.1, 1.0), .25), false);
124  switchNode->addChild(getTrafficLight(d, tlu, osg::Vec4d(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::Vec3d(d.centerX, d.centerY, d.centerZ));
153  lightTransform->setScale(osg::Vec3d(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  const int shapeSize = (int)(edge.isWalkingArea() ? shape.size() : shape.size() * 2);
171  const float zOffset = edge.isWalkingArea() || edge.isCrossing() ? 0.01f : 0.f;
172  osg::Vec3Array* osg_coords = new osg::Vec3Array(shapeSize);
173  geom->setVertexArray(osg_coords);
174  if (edge.isWalkingArea()) {
175  int index = 0;
176  for (int k = 0; k < (int)shape.size(); ++k, ++index) {
177  (*osg_coords)[index].set((float)shape[k].x(), (float)shape[k].y(), (float)shape[k].z() + zOffset);
178  }
179  } else {
180  PositionVector rshape = shape;
181  rshape.move2side(l->getWidth() / 2);
182  int index = 0;
183  for (int k = 0; k < (int)rshape.size(); ++k, ++index) {
184  (*osg_coords)[index].set((float)rshape[k].x(), (float)rshape[k].y(), (float)rshape[k].z() + zOffset);
185  }
186  PositionVector lshape = shape;
187  lshape.move2side(-l->getWidth() / 2);
188  for (int k = (int) lshape.size() - 1; k >= 0; --k, ++index) {
189  (*osg_coords)[index].set((float)lshape[k].x(), (float)lshape[k].y(), (float)lshape[k].z() + zOffset);
190  }
191  }
192  osg::Vec3Array* osg_normals = new osg::Vec3Array(1);
193  (*osg_normals)[0] = osg::Vec3(0, 0, 1);
194 #if OSG_MIN_VERSION_REQUIRED(3,2,0)
195  geom->setNormalArray(osg_normals, osg::Array::BIND_PER_PRIMITIVE_SET);
196 #else
197  geom->setNormalArray(osg_normals);
198  geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
199 #endif
200  osg::Vec4ubArray* osg_colors = new osg::Vec4ubArray(1);
201  (*osg_colors)[0].set(128, 128, 128, 255);
202 #if OSG_MIN_VERSION_REQUIRED(3,2,0)
203  geom->setColorArray(osg_colors, osg::Array::BIND_OVERALL);
204 #else
205  geom->setColorArray(osg_colors);
206  geom->setColorBinding(osg::Geometry::BIND_OVERALL);
207 #endif
208  geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON, 0, shapeSize));
209 
210  osg::ref_ptr<osg::StateSet> ss = geode->getOrCreateStateSet();
211  ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
212  ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
213 
214  if (shape.size() > 2) {
215  tessellator.retessellatePolygons(*geom);
216  }
217  static_cast<GUILane*>(l)->setGeometry(geom);
218  }
219 }
220 
221 
222 void
223 GUIOSGBuilder::buildOSGJunctionGeometry(GUIJunctionWrapper& junction,
224  osg::Group& addTo,
225  osgUtil::Tessellator& tessellator) {
226  const PositionVector& shape = junction.getJunction().getShape();
227  osg::Geode* geode = new osg::Geode();
228  osg::Geometry* geom = new osg::Geometry();
229  geode->addDrawable(geom);
230  addTo.addChild(geode);
231  osg::Vec3Array* osg_coords = new osg::Vec3Array((int)shape.size());
232  geom->setVertexArray(osg_coords);
233  for (int k = 0; k < (int)shape.size(); ++k) {
234  (*osg_coords)[k].set((float)shape[k].x(), (float)shape[k].y(), (float)shape[k].z());
235  }
236  osg::Vec3Array* osg_normals = new osg::Vec3Array(1);
237  (*osg_normals)[0] = osg::Vec3(0, 0, 1);
238 #if OSG_MIN_VERSION_REQUIRED(3,2,0)
239  geom->setNormalArray(osg_normals, osg::Array::BIND_PER_PRIMITIVE_SET);
240 #else
241  geom->setNormalArray(osg_normals);
242  geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
243 #endif
244  osg::Vec4ubArray* osg_colors = new osg::Vec4ubArray(1);
245  (*osg_colors)[0].set(128, 128, 128, 255);
246 #if OSG_MIN_VERSION_REQUIRED(3,2,0)
247  geom->setColorArray(osg_colors, osg::Array::BIND_OVERALL);
248 #else
249  geom->setColorArray(osg_colors);
250  geom->setColorBinding(osg::Geometry::BIND_OVERALL);
251 #endif
252  geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON, 0, (int)shape.size()));
253 
254  osg::ref_ptr<osg::StateSet> ss = geode->getOrCreateStateSet();
255  ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
256  ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
257 
258  if (shape.size() > 4) {
259  tessellator.retessellatePolygons(*geom);
260  }
261  junction.setGeometry(geom);
262 }
263 
264 
265 void
266 GUIOSGBuilder::buildDecal(const GUISUMOAbstractView::Decal& d, osg::Group& addTo) {
267  osg::Node* pLoadedModel = osgDB::readNodeFile(d.filename);
268  if (pLoadedModel == 0) {
269  WRITE_ERROR("Could not load '" + d.filename + "'.");
270  return;
271  }
272  osg::ShadeModel* sm = new osg::ShadeModel();
273  sm->setMode(osg::ShadeModel::FLAT);
274  pLoadedModel->getOrCreateStateSet()->setAttribute(sm);
275  osg::PositionAttitudeTransform* base = new osg::PositionAttitudeTransform();
276  base->addChild(pLoadedModel);
277  GUIOSGBoundingBoxCalculator bboxCalc;
278  pLoadedModel->accept(bboxCalc);
279  const osg::BoundingBox& bbox = bboxCalc.getBoundingBox();
280  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())) + ".");
281  double xScale = d.width > 0 ? d.width / (bbox.xMax() - bbox.xMin()) : 1.;
282  double yScale = d.height > 0 ? d.height / (bbox.yMax() - bbox.yMin()) : 1.;
283  const double zScale = d.altitude > 0 ? d.altitude / (bbox.zMax() - bbox.zMin()) : 1.;
284  if (d.width < 0 && d.height < 0 && d.altitude > 0) {
285  xScale = yScale = zScale;
286  }
287  base->setScale(osg::Vec3d(xScale, yScale, zScale));
288  base->setPosition(osg::Vec3d(d.centerX, d.centerY, d.centerZ));
289  base->setAttitude(osg::Quat(osg::DegreesToRadians(d.roll), osg::Vec3d(1, 0, 0),
290  osg::DegreesToRadians(d.tilt), osg::Vec3d(0, 1, 0),
291  osg::DegreesToRadians(d.rot), osg::Vec3d(0, 0, 1)));
292  addTo.addChild(base);
293 }
294 
295 
296 osg::PositionAttitudeTransform*
297 GUIOSGBuilder::getTrafficLight(const GUISUMOAbstractView::Decal& d, osg::Node* tl, const osg::Vec4& color, const double size) {
298  osg::PositionAttitudeTransform* ret = new osg::PositionAttitudeTransform();
299  if (tl != 0) {
300  osg::PositionAttitudeTransform* base = new osg::PositionAttitudeTransform();
301  base->addChild(tl);
302  GUIOSGBoundingBoxCalculator bboxCalc;
303  tl->accept(bboxCalc);
304  const osg::BoundingBox& bbox = bboxCalc.getBoundingBox();
305  double xScale = d.width > 0 ? d.width / (bbox.xMax() - bbox.xMin()) : 1.;
306  double yScale = d.height > 0 ? d.height / (bbox.yMax() - bbox.yMin()) : 1.;
307  const double zScale = d.altitude > 0 ? d.altitude / (bbox.zMax() - bbox.zMin()) : 1.;
308  if (d.width < 0 && d.height < 0 && d.altitude > 0) {
309  xScale = yScale = zScale;
310  }
311  base->setScale(osg::Vec3d(xScale, yScale, zScale));
312  base->setPosition(osg::Vec3d(d.centerX, d.centerY, d.centerZ));
313  base->setAttitude(osg::Quat(osg::DegreesToRadians(d.roll), osg::Vec3(1, 0, 0),
314  osg::DegreesToRadians(d.tilt), osg::Vec3(0, 1, 0),
315  osg::DegreesToRadians(d.rot), osg::Vec3(0, 0, 1)));
316  ret->addChild(base);
317  }
318  osg::Geode* geode = new osg::Geode();
319  osg::Vec3d center(d.centerX, d.centerY, d.centerZ);
320  osg::ShapeDrawable* shape = new osg::ShapeDrawable(new osg::Sphere(center, (float)size));
321  geode->addDrawable(shape);
322  osg::ref_ptr<osg::StateSet> ss = shape->getOrCreateStateSet();
323  ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
324  ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
325  osg::PositionAttitudeTransform* ellipse = new osg::PositionAttitudeTransform();
326  ellipse->addChild(geode);
327  ellipse->setPivotPoint(center);
328  ellipse->setPosition(center);
329  ellipse->setScale(osg::Vec3d(4., 4., 2.5 * d.altitude + 1.1));
330  shape->setColor(color);
331  ret->addChild(ellipse);
332  return ret;
333 }
334 
335 
336 void
337 GUIOSGBuilder::setShapeState(osg::ref_ptr<osg::ShapeDrawable> shape) {
338  osg::ref_ptr<osg::StateSet> ss = shape->getOrCreateStateSet();
339  ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
340  ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
341 }
342 
343 
344 GUIOSGView::OSGMovable
345 GUIOSGBuilder::buildMovable(const MSVehicleType& type) {
346  GUIOSGView::OSGMovable m;
347  m.pos = new osg::PositionAttitudeTransform();
348  double enlarge = 0.;
349  const std::string& osgFile = type.getOSGFile();
350  if (myCars.find(osgFile) == myCars.end()) {
351  myCars[osgFile] = osgDB::readNodeFile(osgFile);
352  if (myCars[osgFile] == 0) {
353  WRITE_ERROR("Could not load '" + osgFile + "'.");
354  }
355  }
356  osg::Node* carNode = myCars[osgFile];
357  if (carNode != 0) {
358  GUIOSGBoundingBoxCalculator bboxCalc;
359  carNode->accept(bboxCalc);
360  const osg::BoundingBox& bbox = bboxCalc.getBoundingBox();
361  osg::PositionAttitudeTransform* base = new osg::PositionAttitudeTransform();
362  base->addChild(carNode);
363  base->setPivotPoint(osg::Vec3d((bbox.xMin() + bbox.xMax()) / 2., bbox.yMin(), bbox.zMin()));
364  base->setScale(osg::Vec3d(type.getWidth() / (bbox.xMax() - bbox.xMin()),
365  type.getLength() / (bbox.yMax() - bbox.yMin()),
366  type.getHeight() / (bbox.zMax() - bbox.zMin())));
367  m.pos->addChild(base);
368  enlarge = type.getMinGap() / 2.;
369  }
370  m.lights = new osg::Switch();
371  for (double offset = -0.3; offset < 0.5; offset += 0.6) {
372  osg::Geode* geode = new osg::Geode();
373  osg::ShapeDrawable* right = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3d(offset, (type.getLength() - .9) / 2., (type.getHeight() - .5) / 2.), .1f));
374  geode->addDrawable(right);
375  setShapeState(right);
376  right->setColor(osg::Vec4(1.f, .5f, 0.f, .8f));
377  osg::Sequence* seq = new osg::Sequence();
378  // Wikipedia says about 1.5Hz
379  seq->addChild(geode, .33);
380  seq->addChild(new osg::Geode(), .33);
381  // loop through all children
382  seq->setInterval(osg::Sequence::LOOP, 0, -1);
383  // real-time playback, repeat indefinitely
384  seq->setDuration(1.0f, -1);
385  // must be started explicitly
386  seq->setMode(osg::Sequence::START);
387  m.lights->addChild(seq);
388  }
389 
390  osg::Geode* geode = new osg::Geode();
391  osg::CompositeShape* comp = new osg::CompositeShape();
392  comp->addChild(new osg::Sphere(osg::Vec3d(-0.3, (type.getLength() + .8) / 2., (type.getHeight() - .5) / 2.), .1f));
393  comp->addChild(new osg::Sphere(osg::Vec3d(0.3, (type.getLength() + .8) / 2., (type.getHeight() - .5) / 2.), .1f));
394  osg::ShapeDrawable* brake = new osg::ShapeDrawable(comp);
395  brake->setColor(osg::Vec4(1.f, 0.f, 0.f, .8f));
396  geode->addDrawable(brake);
397  setShapeState(brake);
398  m.lights->addChild(geode);
399 
400  geode = new osg::Geode();
401  osg::Vec3d center(0, type.getLength() / 2., type.getHeight() / 2.);
402  m.geom = new osg::ShapeDrawable(new osg::Sphere(center, .5f));
403  geode->addDrawable(m.geom);
404  setShapeState(m.geom);
405  osg::PositionAttitudeTransform* ellipse = new osg::PositionAttitudeTransform();
406  ellipse->addChild(geode);
407  ellipse->addChild(m.lights);
408  ellipse->setPivotPoint(center);
409  ellipse->setPosition(center);
410  ellipse->setScale(osg::Vec3d(type.getWidth() + enlarge, type.getLength() + enlarge, type.getHeight() + enlarge));
411  m.pos->addChild(ellipse);
412  m.active = true;
413  return m;
414 }
415 
416 #endif
417 
418 
419 /****************************************************************************/
420 
A decal (an image) that can be shown.
double altitude
The altitude of the image (net coordinates in z-direction, in m)
double rotationDegreeAtOffset(double pos) const
Returns the rotation at the given length.
Storage for all programs of a single tls.
std::vector< GUIJunctionWrapper * > myJunctionWrapper
Wrapped MS-junctions.
Definition: GUINet.h:346
double z() const
Returns the z-position.
Definition: Position.h:67
double y() const
Returns the y-position.
Definition: Position.h:62
const LaneVectorVector & getLaneVectors() const
Returns the list of lists of all lanes controlled by this tls.
double x() const
Returns the x-position.
Definition: Position.h:57
double centerX
The center of the image in x-direction (net coordinates, in m)
const std::vector< MSLane * > & getLanes() const
Returns this edge&#39;s lanes.
Definition: MSEdge.h:162
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:165
const PositionVector & getShape() const
Returns this lane&#39;s shape.
Definition: MSLane.h:456
const LinkVector & getLinksAt(int i) const
Returns the list of links that are controlled by the signals at the given position.
double height
The height of the image (net coordinates in y-direction, in m)
double getWidth() const
Returns the lane&#39;s width.
Definition: MSLane.h:530
The car-following model and parameter.
Definition: MSVehicleType.h:66
Representation of a lane in the micro simulation (gui-version)
Definition: GUILane.h:63
double roll
The roll of the image to the ground plane (in degrees)
A road/street connecting two junctions.
Definition: MSEdge.h:75
void addSwitchCommand(OnSwitchAction *c)
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:39
MSTLLogicControl & getTLSControl()
Returns the tls logics control.
Definition: MSNet.h:389
A list of positions.
double rot
The rotation of the image in the ground plane (in degrees)
double centerY
The center of the image in y-direction (net coordinates, in m)
double getMinGap() const
Get the free space in front of vehicles of this class.
std::string filename
The path to the file the image is located at.
bool isCrossing() const
return whether this edge is a pedestrian crossing
Definition: MSEdge.h:230
void move2side(double amount)
move position vector to side using certain ammount
double width
The width of the image (net coordinates in x-direction, in m)
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:247
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
double getHeight() const
Get the height which vehicles of this class shall have when being drawn.
std::vector< LaneVector > LaneVectorVector
Definition of a list that holds lists of lanes that do have the same attribute.
A MSNet extended by some values for usage within the gui.
Definition: GUINet.h:82
const MSJunction & getJunction() const
Returns the represented junction.
double centerZ
The center of the image in z-direction (net coordinates, in m)
double getLength() const
Get vehicle&#39;s length [m].
const MSEdgeVector & getEdges() const
Returns loaded edges.
double tilt
The tilt of the image to the ground plane (in degrees)
bool isWalkingArea() const
return whether this edge is walking area
Definition: MSEdge.h:244
MSEdgeControl & getEdgeControl()
Returns the edge control.
Definition: MSNet.h:359
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.
MSTrafficLightLogic * getActive() const
std::vector< std::string > getAllTLIds() const
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:242
Representation of a lane in the micro simulation.
Definition: MSLane.h:78
const PositionVector & getShape() const
Returns this junction&#39;s shape.
Definition: MSJunction.h:90