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-2017 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 #ifdef _MSC_VER
35 #pragma warning(push)
36 #pragma warning(disable: 4127) // do not warn about constant conditional expression
37 #endif
38 #include <osg/Version>
39 #include <osgViewer/ViewerEventHandlers>
40 #include <osgGA/TrackballManipulator>
41 #include <osgDB/ReadFile>
42 #include <osgDB/WriteFile>
43 #include <osg/ShapeDrawable>
44 #include <osg/Node>
45 #include <osg/Group>
46 #include <osg/Geode>
47 #include <osg/Geometry>
48 #include <osg/Sequence>
49 #include <osg/Texture2D>
50 #include <osgViewer/Viewer>
51 #include <osgUtil/Tessellator>
52 #include <osg/PositionAttitudeTransform>
53 #include <osg/ShadeModel>
54 #include <osg/Light>
55 #include <osg/LightSource>
56 #ifdef _MSC_VER
57 #pragma warning(pop)
58 #endif
59 
60 #include <microsim/MSNet.h>
61 #include <microsim/MSEdge.h>
62 #include <microsim/MSLane.h>
63 #include <microsim/MSEdgeControl.h>
65 #include <microsim/MSJunction.h>
66 #include <microsim/MSVehicleType.h>
70 #include <guisim/GUINet.h>
71 #include <guisim/GUIEdge.h>
72 #include <guisim/GUILane.h>
76 #include "GUIOSGView.h"
77 #include "GUIOSGBuilder.h"
78 
79 
80 // ===========================================================================
81 // static member variables
82 // ===========================================================================
83 std::map<std::string, osg::ref_ptr<osg::Node> > GUIOSGBuilder::myCars;
84 
85 
86 // ===========================================================================
87 // member method definitions
88 // ===========================================================================
89 osg::Group*
90 GUIOSGBuilder::buildOSGScene(osg::Node* const tlg, osg::Node* const tly, osg::Node* const tlr, osg::Node* const tlu) {
91  osgUtil::Tessellator tesselator;
92  osg::Group* root = new osg::Group();
93  GUINet* net = static_cast<GUINet*>(MSNet::getInstance());
94  // build edges
95  const MSEdgeVector& edges = net->getEdgeControl().getEdges();
96  for (MSEdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
97  if ((*i)->getPurpose() != MSEdge::EDGEFUNCTION_INTERNAL) {
98  buildOSGEdgeGeometry(**i, *root, tesselator);
99  }
100  }
101  // build junctions
102  for (int index = 0; index < (int)net->myJunctionWrapper.size(); ++index) {
103  buildOSGJunctionGeometry(*net->myJunctionWrapper[index], *root, tesselator);
104  }
105  // build traffic lights
107  const std::vector<std::string> tlids = net->getTLSControl().getAllTLIds();
108  for (std::vector<std::string>::const_iterator i = tlids.begin(); i != tlids.end(); ++i) {
111  const MSLane* lastLane = 0;
112  int idx = 0;
113  for (MSTrafficLightLogic::LaneVectorVector::const_iterator j = lanes.begin(); j != lanes.end(); ++j, ++idx) {
114  const MSLane* const lane = (*j)[0];
115  const Position pos = lane->getShape().back();
116  const double angle = osg::DegreesToRadians(lane->getShape().rotationDegreeAtOffset(-1.) + 90.);
117  d.centerZ = pos.z() + 4.;
118  if (lane == lastLane) {
119  d.centerX += 1.2 * sin(angle);
120  d.centerY += 1.2 * cos(angle);
121  } else {
122  d.centerX = pos.x() - 1.5 * sin(angle);
123  d.centerY = pos.y() - 1.5 * cos(angle);
124  }
125  osg::Switch* switchNode = new osg::Switch();
126  switchNode->addChild(getTrafficLight(d, tlg, osg::Vec4d(0.1, 0.5, 0.1, 1.0), .25), false);
127  switchNode->addChild(getTrafficLight(d, tly, osg::Vec4d(0.5, 0.5, 0.1, 1.0), .25), false);
128  switchNode->addChild(getTrafficLight(d, tlr, osg::Vec4d(0.5, 0.1, 0.1, 1.0), .25), false);
129  switchNode->addChild(getTrafficLight(d, tlu, osg::Vec4d(0.8, 0.4, 0.0, 1.0), .25), false);
130  root->addChild(switchNode);
131  const MSLink* const l = vars.getActive()->getLinksAt(idx)[0];
132  vars.addSwitchCommand(new GUIOSGView::Command_TLSChange(l, switchNode));
133  lastLane = lane;
134  }
135  }
136  return root;
137 }
138 
139 
140 void
141 GUIOSGBuilder::buildLight(const GUISUMOAbstractView::Decal& d, osg::Group& addTo) {
142  // each light must have a unique number
143  osg::Light* light = new osg::Light(d.filename[5] - '0');
144  // we set the light's position via a PositionAttitudeTransform object
145  light->setPosition(osg::Vec4(0.0, 0.0, 0.0, 1.0));
146  light->setDiffuse(osg::Vec4(1.0, 1.0, 1.0, 1.0));
147  light->setSpecular(osg::Vec4(1.0, 1.0, 1.0, 1.0));
148  light->setAmbient(osg::Vec4(1.0, 1.0, 1.0, 1.0));
149 
150  osg::LightSource* lightSource = new osg::LightSource();
151  lightSource->setLight(light);
152  lightSource->setLocalStateSetModes(osg::StateAttribute::ON);
153  lightSource->setStateSetModes(*addTo.getOrCreateStateSet(), osg::StateAttribute::ON);
154 
155  osg::PositionAttitudeTransform* lightTransform = new osg::PositionAttitudeTransform();
156  lightTransform->addChild(lightSource);
157  lightTransform->setPosition(osg::Vec3d(d.centerX, d.centerY, d.centerZ));
158  lightTransform->setScale(osg::Vec3d(0.1, 0.1, 0.1));
159  addTo.addChild(lightTransform);
160 }
161 
162 
163 void
164 GUIOSGBuilder::buildOSGEdgeGeometry(const MSEdge& edge,
165  osg::Group& addTo,
166  osgUtil::Tessellator& tessellator) {
167  const std::vector<MSLane*>& lanes = edge.getLanes();
168  for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
169  MSLane* l = (*j);
170  const PositionVector& shape = l->getShape();
171  osg::Geode* geode = new osg::Geode();
172  osg::Geometry* geom = new osg::Geometry();
173  geode->addDrawable(geom);
174  addTo.addChild(geode);
175  osg::Vec3dArray* osg_coords = new osg::Vec3dArray((int)shape.size() * 2);
176  geom->setVertexArray(osg_coords);
177  PositionVector rshape = shape;
179  int index = 0;
180  for (int k = 0; k < (int)rshape.size(); ++k, ++index) {
181  (*osg_coords)[index].set(rshape[k].x(), rshape[k].y(), rshape[k].z());
182  }
183  PositionVector lshape = shape;
185  for (int k = (int) lshape.size() - 1; k >= 0; --k, ++index) {
186  (*osg_coords)[index].set(lshape[k].x(), lshape[k].y(), lshape[k].z());
187  }
188  osg::Vec3Array* osg_normals = new osg::Vec3Array(1);
189  (*osg_normals)[0] = osg::Vec3(0, 0, 1);
190 #if OSG_MIN_VERSION_REQUIRED(3,2,0)
191  geom->setNormalArray(osg_normals, osg::Array::BIND_PER_PRIMITIVE_SET);
192 #else
193  geom->setNormalArray(osg_normals);
194  geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
195 #endif
196  osg::Vec4ubArray* osg_colors = new osg::Vec4ubArray(1);
197  (*osg_colors)[0].set(128, 128, 128, 255);
198 #if OSG_MIN_VERSION_REQUIRED(3,2,0)
199  geom->setColorArray(osg_colors, osg::Array::BIND_OVERALL);
200 #else
201  geom->setColorArray(osg_colors);
202  geom->setColorBinding(osg::Geometry::BIND_OVERALL);
203 #endif
204  geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON, 0, (int)shape.size() * 2));
205 
206  osg::ref_ptr<osg::StateSet> ss = geode->getOrCreateStateSet();
207  ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
208  ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
209 
210  if (shape.size() > 2) {
211  tessellator.retessellatePolygons(*geom);
212  }
213  static_cast<GUILane*>(l)->setGeometry(geom);
214  }
215 }
216 
217 
218 void
219 GUIOSGBuilder::buildOSGJunctionGeometry(GUIJunctionWrapper& junction,
220  osg::Group& addTo,
221  osgUtil::Tessellator& tessellator) {
222  const PositionVector& shape = junction.getJunction().getShape();
223  osg::Geode* geode = new osg::Geode();
224  osg::Geometry* geom = new osg::Geometry();
225  geode->addDrawable(geom);
226  addTo.addChild(geode);
227  osg::Vec3dArray* osg_coords = new osg::Vec3dArray((int)shape.size());
228  geom->setVertexArray(osg_coords);
229  for (int k = 0; k < (int)shape.size(); ++k) {
230  (*osg_coords)[k].set(shape[k].x(), shape[k].y(), shape[k].z());
231  }
232  osg::Vec3dArray* osg_normals = new osg::Vec3dArray(1);
233  (*osg_normals)[0] = osg::Vec3(0, 0, 1);
234 #if OSG_MIN_VERSION_REQUIRED(3,2,0)
235  geom->setNormalArray(osg_normals, osg::Array::BIND_PER_PRIMITIVE_SET);
236 #else
237  geom->setNormalArray(osg_normals);
238  geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
239 #endif
240  osg::Vec4ubArray* osg_colors = new osg::Vec4ubArray(1);
241  (*osg_colors)[0].set(128, 128, 128, 255);
242 #if OSG_MIN_VERSION_REQUIRED(3,2,0)
243  geom->setColorArray(osg_colors, osg::Array::BIND_OVERALL);
244 #else
245  geom->setColorArray(osg_colors);
246  geom->setColorBinding(osg::Geometry::BIND_OVERALL);
247 #endif
248  geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON, 0, (int)shape.size()));
249 
250  osg::ref_ptr<osg::StateSet> ss = geode->getOrCreateStateSet();
251  ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
252  ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
253 
254  if (shape.size() > 4) {
255  tessellator.retessellatePolygons(*geom);
256  }
257  junction.setGeometry(geom);
258 }
259 
260 
261 void
262 GUIOSGBuilder::buildDecal(const GUISUMOAbstractView::Decal& d, osg::Group& addTo) {
263  osg::Node* pLoadedModel = osgDB::readNodeFile(d.filename);
264  if (pLoadedModel == 0) {
265  WRITE_ERROR("Could not load '" + d.filename + "'.");
266  return;
267  }
268  osg::ShadeModel* sm = new osg::ShadeModel();
269  sm->setMode(osg::ShadeModel::FLAT);
270  pLoadedModel->getOrCreateStateSet()->setAttribute(sm);
271  osg::PositionAttitudeTransform* base = new osg::PositionAttitudeTransform();
272  base->addChild(pLoadedModel);
273  GUIOSGBoundingBoxCalculator bboxCalc;
274  pLoadedModel->accept(bboxCalc);
275  const osg::BoundingBox& bbox = bboxCalc.getBoundingBox();
276  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())) + ".");
277  double xScale = d.width > 0 ? d.width / (bbox.xMax() - bbox.xMin()) : 1.;
278  double yScale = d.height > 0 ? d.height / (bbox.yMax() - bbox.yMin()) : 1.;
279  const double zScale = d.altitude > 0 ? d.altitude / (bbox.zMax() - bbox.zMin()) : 1.;
280  if (d.width < 0 && d.height < 0 && d.altitude > 0) {
281  xScale = yScale = zScale;
282  }
283  base->setScale(osg::Vec3d(xScale, yScale, zScale));
284  base->setPosition(osg::Vec3d(d.centerX, d.centerY, d.centerZ));
285  base->setAttitude(osg::Quat(osg::DegreesToRadians(d.roll), osg::Vec3d(1, 0, 0),
286  osg::DegreesToRadians(d.tilt), osg::Vec3d(0, 1, 0),
287  osg::DegreesToRadians(d.rot), osg::Vec3d(0, 0, 1)));
288  addTo.addChild(base);
289 }
290 
291 
292 osg::PositionAttitudeTransform*
293 GUIOSGBuilder::getTrafficLight(const GUISUMOAbstractView::Decal& d, osg::Node* tl, const osg::Vec4& color, const double size) {
294  osg::PositionAttitudeTransform* ret = new osg::PositionAttitudeTransform();
295  if (tl != 0) {
296  osg::PositionAttitudeTransform* base = new osg::PositionAttitudeTransform();
297  base->addChild(tl);
298  GUIOSGBoundingBoxCalculator bboxCalc;
299  tl->accept(bboxCalc);
300  const osg::BoundingBox& bbox = bboxCalc.getBoundingBox();
301  double xScale = d.width > 0 ? d.width / (bbox.xMax() - bbox.xMin()) : 1.;
302  double yScale = d.height > 0 ? d.height / (bbox.yMax() - bbox.yMin()) : 1.;
303  const double zScale = d.altitude > 0 ? d.altitude / (bbox.zMax() - bbox.zMin()) : 1.;
304  if (d.width < 0 && d.height < 0 && d.altitude > 0) {
305  xScale = yScale = zScale;
306  }
307  base->setScale(osg::Vec3d(xScale, yScale, zScale));
308  base->setPosition(osg::Vec3d(d.centerX, d.centerY, d.centerZ));
309  base->setAttitude(osg::Quat(osg::DegreesToRadians(d.roll), osg::Vec3(1, 0, 0),
310  osg::DegreesToRadians(d.tilt), osg::Vec3(0, 1, 0),
311  osg::DegreesToRadians(d.rot), osg::Vec3(0, 0, 1)));
312  ret->addChild(base);
313  }
314  osg::Geode* geode = new osg::Geode();
315  osg::Vec3d center(d.centerX, d.centerY, d.centerZ);
316  osg::ShapeDrawable* shape = new osg::ShapeDrawable(new osg::Sphere(center, (float)size));
317  geode->addDrawable(shape);
318  osg::ref_ptr<osg::StateSet> ss = shape->getOrCreateStateSet();
319  ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
320  ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
321  osg::PositionAttitudeTransform* ellipse = new osg::PositionAttitudeTransform();
322  ellipse->addChild(geode);
323  ellipse->setPivotPoint(center);
324  ellipse->setPosition(center);
325  ellipse->setScale(osg::Vec3d(4., 4., 2.5 * d.altitude + 1.1));
326  shape->setColor(color);
327  ret->addChild(ellipse);
328  return ret;
329 }
330 
331 
332 void
333 GUIOSGBuilder::setShapeState(osg::ref_ptr<osg::ShapeDrawable> shape) {
334  osg::ref_ptr<osg::StateSet> ss = shape->getOrCreateStateSet();
335  ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
336  ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
337 }
338 
339 
340 GUIOSGView::OSGMovable
341 GUIOSGBuilder::buildMovable(const MSVehicleType& type) {
342  GUIOSGView::OSGMovable m;
343  m.pos = new osg::PositionAttitudeTransform();
344  double enlarge = 0.;
345  const std::string& osgFile = type.getOSGFile();
346  if (myCars.find(osgFile) == myCars.end()) {
347  myCars[osgFile] = osgDB::readNodeFile(osgFile);
348  if (myCars[osgFile] == 0) {
349  WRITE_ERROR("Could not load '" + osgFile + "'.");
350  }
351  }
352  osg::Node* carNode = myCars[osgFile];
353  if (carNode != 0) {
354  GUIOSGBoundingBoxCalculator bboxCalc;
355  carNode->accept(bboxCalc);
356  const osg::BoundingBox& bbox = bboxCalc.getBoundingBox();
357  osg::PositionAttitudeTransform* base = new osg::PositionAttitudeTransform();
358  base->addChild(carNode);
359  base->setPivotPoint(osg::Vec3d((bbox.xMin() + bbox.xMax()) / 2., bbox.yMin(), bbox.zMin()));
360  base->setScale(osg::Vec3d(type.getWidth() / (bbox.xMax() - bbox.xMin()),
361  type.getLength() / (bbox.yMax() - bbox.yMin()),
362  type.getHeight() / (bbox.zMax() - bbox.zMin())));
363  m.pos->addChild(base);
364  enlarge = type.getMinGap() / 2.;
365  }
366  m.lights = new osg::Switch();
367  for (double offset = -0.3; offset < 0.5; offset += 0.6) {
368  osg::Geode* geode = new osg::Geode();
369  osg::ShapeDrawable* right = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3d(offset, (type.getLength() - .9) / 2., (type.getHeight() - .5) / 2.), .1f));
370  geode->addDrawable(right);
371  setShapeState(right);
372  right->setColor(osg::Vec4(1.f, .5f, 0.f, .8f));
373  osg::Sequence* seq = new osg::Sequence();
374  // Wikipedia says about 1.5Hz
375  seq->addChild(geode, .33);
376  seq->addChild(new osg::Geode(), .33);
377  // loop through all children
378  seq->setInterval(osg::Sequence::LOOP, 0, -1);
379  // real-time playback, repeat indefinitely
380  seq->setDuration(1.0f, -1);
381  // must be started explicitly
382  seq->setMode(osg::Sequence::START);
383  m.lights->addChild(seq);
384  }
385 
386  osg::Geode* geode = new osg::Geode();
387  osg::CompositeShape* comp = new osg::CompositeShape();
388  comp->addChild(new osg::Sphere(osg::Vec3d(-0.3, (type.getLength() + .8) / 2., (type.getHeight() - .5) / 2.), .1f));
389  comp->addChild(new osg::Sphere(osg::Vec3d(0.3, (type.getLength() + .8) / 2., (type.getHeight() - .5) / 2.), .1f));
390  osg::ShapeDrawable* brake = new osg::ShapeDrawable(comp);
391  brake->setColor(osg::Vec4(1.f, 0.f, 0.f, .8f));
392  geode->addDrawable(brake);
393  setShapeState(brake);
394  m.lights->addChild(geode);
395 
396  geode = new osg::Geode();
397  osg::Vec3d center(0, type.getLength() / 2., type.getHeight() / 2.);
398  m.geom = new osg::ShapeDrawable(new osg::Sphere(center, .5f));
399  geode->addDrawable(m.geom);
400  setShapeState(m.geom);
401  osg::PositionAttitudeTransform* ellipse = new osg::PositionAttitudeTransform();
402  ellipse->addChild(geode);
403  ellipse->addChild(m.lights);
404  ellipse->setPivotPoint(center);
405  ellipse->setPosition(center);
406  ellipse->setScale(osg::Vec3d(type.getWidth() + enlarge, type.getLength() + enlarge, type.getHeight() + enlarge));
407  m.pos->addChild(ellipse);
408  return m;
409 }
410 
411 #endif
412 
413 
414 /****************************************************************************/
415 
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:343
double z() const
Returns the z-position.
Definition: Position.h:73
double y() const
Returns the y-position.
Definition: Position.h:68
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:63
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:192
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:158
const PositionVector & getShape() const
Returns this lane&#39;s shape.
Definition: MSLane.h:426
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)
The car-following model and parameter.
Definition: MSVehicleType.h:74
Representation of a lane in the micro simulation (gui-version)
Definition: GUILane.h:70
double roll
The roll of the image to the ground plane (in degrees)
A road/street connecting two junctions.
Definition: MSEdge.h:80
void addSwitchCommand(OnSwitchAction *c)
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:56
const double SUMO_const_halfLaneWidth
Definition: StdDefs.h:49
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
MSTLLogicControl & getTLSControl()
Returns the tls logics control.
Definition: MSNet.h:383
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.
static int comp(const void *key, const void *target)
Definition: polyfonts.c:820
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:206
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:89
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)
MSEdgeControl & getEdgeControl()
Returns the edge control.
Definition: MSNet.h:353
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.
std::vector< MSEdge * > MSEdgeVector
Definition: MSEdge.h:77
MSTrafficLightLogic * getActive() const
std::vector< std::string > getAllTLIds() const
The edge is an internal edge.
Definition: MSEdge.h:97
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:201
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