44 #define DEBUGCOND true 46 #define MIN_TURN_DIAMETER 2.0 58 if (!oc.
isSet(
"opendrive-output")) {
63 const bool origNames = oc.
getBool(
"output.original-names");
64 const bool lefthand = oc.
getBool(
"lefthand");
65 const double straightThresh =
DEG2RAD(oc.
getFloat(
"opendrive-output.straight-threshold"));
68 int edgeID = nc.
size() * 10;
73 device <<
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
75 time_t now = time(
nullptr);
76 std::string dstr(ctime(&now));
79 device.openTag(
"header");
80 device.writeAttr(
"revMajor",
"1");
81 device.writeAttr(
"revMinor",
"4");
82 device.writeAttr(
"name",
"");
83 device.writeAttr(
"version",
"1.00");
84 device.writeAttr(
"date", dstr.substr(0, dstr.length() - 1));
85 device.writeAttr(
"north", b.
ymax());
86 device.writeAttr(
"south", b.
ymin());
87 device.writeAttr(
"east", b.
xmax());
88 device.writeAttr(
"west", b.
xmin());
99 device.openTag(
"geoReference");
100 device.writePreformattedTag(
" <![CDATA[\n " 110 for (std::map<std::string, NBEdge*>::const_iterator i = ec.
begin(); i != ec.
end(); ++i) {
111 const NBEdge* e = (*i).second;
116 fromNodeID, toNodeID,
117 origNames, straightThresh,
124 for (std::map<std::string, NBNode*>::const_iterator i = nc.
begin(); i != nc.
end(); ++i) {
126 int connectionID = 0;
127 const int nID =
getID(n->
getID(), nodeMap, nodeID);
129 junctionOSS <<
" <junction name=\"" << n->
getID() <<
"\" id=\"" << nID <<
"\">\n";
131 std::vector<NBEdge*> incoming = (*i).second->getIncomingEdges();
133 std::reverse(incoming.begin(), incoming.end());
135 for (
NBEdge* inEdge : incoming) {
136 std::string centerMark =
"none";
137 const int inEdgeID =
getID(inEdge->getID(), edgeMap, edgeID);
139 const NBEdge* outEdge =
nullptr;
140 bool isOuterEdge =
true;
141 int lastFromLane = -1;
142 std::vector<NBEdge::Connection> parallel;
143 std::vector<NBEdge::Connection> connections = inEdge->
getConnections();
145 std::reverse(connections.begin(), connections.end());
148 assert(c.toEdge != 0);
149 if (outEdge != c.toEdge || c.fromLane == lastFromLane) {
150 if (outEdge !=
nullptr) {
155 getID(parallel.back().getInternalLaneID(), edgeMap, edgeID),
157 getID(outEdge->getID(), edgeMap, edgeID),
159 parallel, isOuterEdge, straightThresh, centerMark);
165 lastFromLane = c.fromLane;
166 parallel.push_back(c);
171 if (!parallel.empty()) {
172 if (!lefthand && (n->
geometryLike() || inEdge->isTurningDirectionAt(outEdge))) {
173 centerMark =
"solid";
176 getID(parallel.back().getInternalLaneID(), edgeMap, edgeID),
178 getID(outEdge->getID(), edgeMap, edgeID),
180 parallel, isOuterEdge, straightThresh, centerMark);
185 junctionOSS <<
" </junction>\n";
192 for (std::map<std::string, NBNode*>::const_iterator i = nc.
begin(); i != nc.
end(); ++i) {
196 int numConnections = 0;
197 for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) {
198 numConnections += (int)((*j)->getConnections().size());
200 if (numConnections == 0) {
203 for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) {
204 const NBEdge* inEdge = *j;
205 const std::vector<NBEdge::Connection>& elv = inEdge->
getConnections();
206 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
209 if (outEdge ==
nullptr) {
223 int edgeID,
int fromNodeID,
int toNodeID,
224 const bool origNames,
225 const double straightThresh,
234 planViewOSS.
openTag(
"planView");
236 const std::vector<NBEdge::Lane>& lanes = e->
getLanes();
238 #ifdef DEBUG_SMOOTH_GEOM 240 std::cout <<
"write planview for edge " << e->
getID() <<
"\n";
266 device.
writeAttr(
"elementType",
"junction");
267 device.
writeAttr(
"elementId", fromNodeID);
272 device.
writeAttr(
"elementType",
"junction");
281 device <<
" <lateralProfile/>\n";
282 device <<
" <lanes>\n";
283 device <<
" <laneSection s=\"0\">\n";
286 device <<
" <right>\n";
289 device <<
" <link/>\n";
297 device <<
" <width sOffset=\"0\" a=\"" << e->
getLaneWidth(j) <<
"\" b=\"0\" c=\"0\" d=\"0\"/>\n";
298 std::string markType =
"broken";
309 device <<
" <roadMark sOffset=\"0\" type=\"" << markType <<
"\" weight=\"standard\" color=\"standard\" width=\"0.13\"/>\n";
310 device <<
" <speed sOffset=\"0\" max=\"" << lanes[j].speed <<
"\"/>\n";
311 device <<
" </lane>\n";
313 device <<
" </right>\n";
314 device <<
" </laneSection>\n";
315 device <<
" </lanes>\n";
317 device <<
" <signals/>\n";
319 device <<
" <userData code=\"sumoId\" value=\"" << e->
getID() <<
"\"/>\n";
329 if (outEdge !=
nullptr 333 || parallel.front().fromLane != 0
334 || parallel.front().toLane != 0)) {
335 parallel.insert(parallel.begin(),
NBEdge::Connection(0, const_cast<NBEdge*>(outEdge), 0,
false));
336 parallel.front().vmax = (inEdge->
getLanes()[0].speed + outEdge->
getLanes()[0].speed) / (
double) 2.0;
343 int edgeID,
int inEdgeID,
int outEdgeID,
345 const std::vector<NBEdge::Connection>& parallel,
346 const bool isOuterEdge,
347 const double straightThresh,
348 const std::string& centerMark) {
349 assert(parallel.size() != 0);
351 const NBEdge* outEdge = cLeft.toEdge;
357 double laneOffset = 0;
359 fallBackShape.push_back(begShape.back());
360 fallBackShape.push_back(endShape.front());
364 if (init.size() == 0) {
368 WRITE_WARNING(
"Could not compute smooth shape from lane '" + inEdge->
getLaneID(cLeft.fromLane) +
"' to lane '" + outEdge->
getLaneID(cLeft.toLane) +
"'. Use option 'junctions.scurve-stretch' or increase radius of junction '" + inEdge->
getToNode()->
getID() +
"' to fix this.");
375 if (init.size() != 0) {
385 junctionDevice <<
" <connection id=\"" << connectionID <<
"\" incomingRoad=\"" << inEdgeID <<
"\" connectingRoad=\"" << edgeID <<
"\" contactPoint=\"start\">\n";
401 device.
writeAttr(
"elementId", outEdgeID);
402 device.
writeAttr(
"contactPoint",
"start");
410 #ifdef DEBUG_SMOOTH_GEOM 412 std::cout <<
"write planview for internal edge " << cLeft.id <<
" init=" << init <<
" fallback=" << fallBackShape
413 <<
" begShape=" << begShape <<
" endShape=" << endShape
417 if (init.size() == 0) {
425 device <<
" <lateralProfile/>\n";
426 device <<
" <lanes>\n";
427 if (laneOffset != 0) {
428 device <<
" <laneOffset s=\"0\" a=\"" << laneOffset <<
"\" b=\"0\" c=\"0\" d=\"0\"/>\n";
430 device <<
" <laneSection s=\"0\">\n";
432 device <<
" <right>\n";
433 for (
int j = (
int)parallel.size(); --j >= 0;) {
438 device <<
" <link>\n";
439 device <<
" <predecessor id=\"" << fromIndex <<
"\"/>\n";
440 device <<
" <successor id=\"" << toIndex <<
"\"/>\n";
441 device <<
" </link>\n";
442 device <<
" <width sOffset=\"0\" a=\"" << outEdge->
getLaneWidth(c.
toLane) <<
"\" b=\"0\" c=\"0\" d=\"0\"/>\n";
443 std::string markType =
"broken";
449 }
else if (isOuterEdge && j > 0
464 device <<
" <roadMark sOffset=\"0\" type=\"" << markType <<
"\" weight=\"standard\" color=\"standard\" width=\"0.13\"/>\n";
465 device <<
" <speed sOffset=\"0\" max=\"" << c.
vmax <<
"\"/>\n";
466 device <<
" </lane>\n";
468 junctionDevice <<
" <laneLink from=\"" << fromIndex <<
"\" to=\"" << toIndex <<
"\"/>\n";
471 device <<
" </right>\n";
472 device <<
" </laneSection>\n";
473 device <<
" </lanes>\n";
474 device <<
" <objects/>\n";
475 device <<
" <signals/>\n";
477 junctionDevice <<
" </connection>\n";
485 for (
int j = 0; j < (int)shape.size() - 1; ++j) {
498 elevationDevice <<
" <elevation s=\"" << offset <<
"\" a=\"" << p.
z() <<
"\" b=\"" << (p2.
z() - p.
z()) /
MAX2(
POSITION_EPS, length) <<
"\" c=\"0\" d=\"0\"/>\n";
507 device <<
" <center>\n";
508 device <<
" <lane id=\"0\" type=\"none\" level=\"true\">\n";
509 device <<
" <link/>\n";
510 device <<
" <roadMark sOffset=\"0\" type=\"" << mark <<
"\" weight=\"standard\" color=\"standard\" width=\"" << markWidth <<
"\"/>\n";
511 device <<
" </lane>\n";
512 device <<
" </center>\n";
519 return map.
get(origID);
521 map.
insert(origID, lastID++);
528 switch (permissions) {
548 if (permissions ==
SVCAll) {
565 if (laneIndex == -1) {
567 laneIndex = lefthand ? 0 : (int)edge->
getNumLanes() - 1;
576 const int leftmost = lefthand ? 0 : (int)edge->
getNumLanes() - 1;
580 for (
int i = leftmost; i < laneIndex; i++) {
584 for (
int i = leftmost; i > laneIndex; i--) {
608 assert(init.size() == 3 || init.size() == 4);
619 init.
add(-p.
x(), -p.
y(), -p.
z());
623 double aU, bU, cU, dU;
624 double aV, bV, cV, dV;
625 double aZ, bZ, cZ, dZ;
628 if (init.size() == 3) {
631 bU = 2 * init[1].x() - 2 * init[0].x();
632 cU = init[0].x() - 2 * init[1].x() + init[2].x();
636 bV = 2 * init[1].y() - 2 * init[0].y();
637 cV = init[0].y() - 2 * init[1].y() + init[2].y();
642 bZ = (2 * initZ[1].z() - 2 * initZ[0].z()) / length;
643 cZ = (initZ[0].z() - 2 * initZ[1].z() + initZ[2].z()) / (length * length);
649 bU = 3 * init[1].x() - 3 * init[0].x();
650 cU = 3 * init[0].x() - 6 * init[1].x() + 3 * init[2].x();
651 dU = -init[0].x() + 3 * init[1].x() - 3 * init[2].x() + init[3].x();
654 bV = 3 * init[1].y() - 3 * init[0].y();
655 cV = 3 * init[0].y() - 6 * init[1].y() + 3 * init[2].y();
656 dV = -init[0].y() + 3 * init[1].y() - 3 * init[2].y() + init[3].y();
660 bZ = (3 * initZ[1].z() - 3 * initZ[0].z()) / length;
661 cZ = (3 * initZ[0].z() - 6 * initZ[1].z() + 3 * initZ[2].z()) / (length * length);
662 dZ = (-initZ[0].z() + 3 * initZ[1].z() - 3 * initZ[2].z() + initZ[3].z()) / (length * length * length);
685 elevationDevice.
openTag(
"elevation");
693 return offset + length;
699 #ifdef DEBUG_SMOOTH_GEOM 701 std::cout <<
"writeGeomSmooth\n n=" << shape.size() <<
" shape=" <<
toString(shape) <<
"\n";
705 const double longThresh = speed;
706 const double curveCutout = longThresh / 2;
708 assert(longThresh >= 2 * curveCutout);
709 assert(shape.size() > 2);
713 double maxAngleDiff = 0;
715 for (
int j = 1; j < (int)shape.size() - 1; ++j) {
723 maxAngleDiff =
MAX2(maxAngleDiff, dAngle);
724 #ifdef DEBUG_SMOOTH_GEOM 726 std::cout <<
" j=" << j <<
" dAngle=" <<
RAD2DEG(dAngle) <<
" length1=" << length1 <<
" length2=" << length2 <<
"\n";
729 if (dAngle > straightThresh
730 && (length1 > longThresh || j == 1)
731 && (length2 > longThresh || j == (
int)shape.size() - 2)) {
734 shape2.removeClosest(p1);
738 const int numPoints = (int)shape2.size();
739 #ifdef DEBUG_SMOOTH_GEOM 741 std::cout <<
" n=" << numPoints <<
" shape2=" <<
toString(shape2) <<
"\n";
745 if (maxAngleDiff < straightThresh) {
747 #ifdef DEBUG_SMOOTH_GEOM 749 std::cout <<
" special case: all lines. maxAngleDiff=" << maxAngleDiff <<
"\n";
757 for (
int j = 0; j < numPoints - 1; ++j) {
763 const double lineLength = line.
length2D();
764 if (lineLength >= longThresh) {
766 #ifdef DEBUG_SMOOTH_GEOM 768 std::cout <<
" writeLine=" <<
toString(line) <<
"\n";
775 if (j == 0 || j == numPoints - 2) {
778 begShape.
add(p0 - begShape.back());
779 }
else if (j == 1 || p0.
distanceTo2D(shape2[j - 1]) > longThresh) {
781 begShape.push_back(shape2[j - 1]);
782 begShape.push_back(p0);
785 begShape.push_back(shape2[j - 1]);
786 begShape.push_back(p1);
787 begShape.
add(p0 - begShape.back());
790 if (j == 0 || j == numPoints - 2) {
793 endShape.
add(p1 - endShape.front());
794 }
else if (j == numPoints - 3 || p1.
distanceTo2D(shape2[j + 2]) > longThresh) {
796 endShape.push_back(p1);
797 endShape.push_back(shape2[j + 2]);
800 endShape.push_back(p0);
801 endShape.push_back(shape2[j + 2]);
802 endShape.
add(p1 - endShape.front());
804 const double extrapolateLength =
MIN2((
double)25, lineLength / 4);
806 if (init.size() == 0) {
809 #ifdef DEBUG_SMOOTH_GEOM 811 std::cout <<
" writeLine lineLength=" << lineLength <<
" begShape" << j <<
"=" <<
toString(begShape) <<
" endShape" << j <<
"=" <<
toString(endShape) <<
" init" << j <<
"=" <<
toString(init) <<
"\n";
817 offset =
writeGeomPP3(device, elevationDevice, init, curveLength, offset);
818 #ifdef DEBUG_SMOOTH_GEOM 820 std::cout <<
" writeCurve lineLength=" << lineLength <<
" curveLength=" << curveLength <<
" begShape" << j <<
"=" <<
toString(begShape) <<
" endShape" << j <<
"=" <<
toString(endShape) <<
" init" << j <<
"=" <<
toString(init) <<
"\n";
835 double z = shape.size() == 0 ? 0 : shape[0].z();
836 for (
int i = 1; i < (int)shape.size(); ++i) {
842 device <<
" <elevationProfile>\n";
844 device <<
" <elevation s=\"0\" a=\"" << z <<
"\" b=\"0\" c=\"0\" d=\"0\"/>\n";
848 device <<
" </elevationProfile>\n";
858 assert(shape0.size() >= 2);
862 stopLine.push_back(to);
865 for (
int lane = 1; lane < e->
getNumLanes(); ++lane) {
883 WRITE_WARNING(
"Road object polygon '" +
id +
"' not found for edge '" + e->
getID() +
"'");
884 }
else if (p->
getShape().size() != 4) {
892 const double absAngle = sideline.
angleAt2D(0);
893 const double length = sideline.
length2D();
894 const double width = ortholine.
length2D();
897 WRITE_WARNING(
"Cannot map road object polygon '" +
id +
"' with center " +
toString(center) +
" onto edge '" + e->
getID() +
"'");
902 const double relAngle = absAngle - edgeAngle;
929 device <<
" <objects/>\n";
The link is a partial left direction.
double vmax
maximum velocity
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
double ymin() const
Returns minimum y-coordinate.
ShapeContainer & getShapeCont()
double length2D() const
Returns the length.
double xmax() const
Returns maximum x-coordinate.
A structure which describes a connection between edges or lanes.
int toLane
The lane the connections yields in.
int numNormalConnections() const
return the number of lane-to-lane connections at this junction (excluding crossings) ...
static void writeEmptyCenterLane(OutputDevice &device, const std::string &mark, double markWidth)
std::map< std::string, NBNode * >::const_iterator begin() const
Returns the pointer to the begin of the stored nodes.
double z() const
Returns the z-position.
double distance2D(const Position &p, bool perpendicular=false) const
closest 2D-distance to point p (or -1 if perpendicular is true and the point is beyond this vector) ...
NBEdge * toEdge
The edge the connections yields in.
EdgeVector getIncomingEdges() const
Returns the list of incoming edges unsorted.
const Boundary & getConvBoundary() const
Returns the converted boundary.
std::map< std::string, NBNode * >::const_iterator end() const
Returns the pointer to the end of the stored nodes.
const Polygons & getPolygons() const
Returns all polygons.
vehicle is a not electrified rail
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
int gPrecision
the precision for floating point outputs
Position positionAtOffset2D(double pos, double lateralOffset=0) const
Returns the position at the given length.
std::string getString() const
Returns the current content as a string.
double y() const
Returns the y-position.
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
T get(const std::string &id) const
Retrieves an item.
bool usingGeoProjection() const
Returns whether a transformation from geo to metric coordinates will be performed.
The representation of a single edge during network building.
double x() const
Returns the x-position.
void setPrecision(int precision=gPrecision)
Sets the precison or resets it to default.
double angleTo2D(const Position &other) const
returns the angle in the plane of the vector pointing from here to the other position ...
const PositionVector & getShape() const
Returns whether the shape of the polygon.
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
double rotationAtOffset(double pos) const
Returns the rotation at the given length.
Storage for geometrical objects.
std::map< std::string, NBEdge * >::const_iterator end() const
Returns the pointer to the end of the stored edges.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const std::string & getProjString() const
Returns the original projection definition.
const std::string & getID() const
Returns the id.
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
const SVCPermissions SVCAll
all VClasses are allowed
A class that stores a 2D geometrical boundary.
The link is a (hard) left direction.
rail vehicle that requires electrified tracks
#define WRITE_WARNING(msg)
static OptionsCont & getOptions()
Retrieves the options.
const std::string & getShapeType() const
Returns the (abstract) type of the Shape.
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)...
PositionVector bezier(int numPoints)
return a bezier interpolation
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
void insert(const std::string str, const T key, bool checkDuplicates=true)
static void writeNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Writes the network into a openDRIVE-file.
static double writeGeomPP3(OutputDevice &device, OutputDevice &elevationDevice, PositionVector init, double length, double offset=0)
write geometry as a single bezier curve (paramPoly3)
std::map< std::string, NBEdge * >::const_iterator begin() const
Returns the pointer to the begin of the stored edges.
bool knowsParameter(const std::string &key) const
Returns whether the parameter is known.
static methods for processing the coordinates conversion for the current net
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
static bool writeGeomSmooth(const PositionVector &shape, double speed, OutputDevice &device, OutputDevice &elevationDevice, double straightThresh, double &length)
static void writeRoadObjects(OutputDevice &device, const NBEdge *e, const ShapeContainer &shc)
write road objects referenced as edge parameters
int size() const
Returns the number of nodes stored in this container.
std::string getLaneID(int lane) const
get lane ID
int getNumLanes() const
Returns the number of lanes.
int fromLane
The lane the connections starts at.
A point in 2D or 3D with translation and scaling methods.
NBEdgeCont & getEdgeCont()
static PositionVector getRightLaneBorder(const NBEdge *edge, int laneIndex=-1)
Position getPolygonCenter() const
Returns the arithmetic of all corner points.
void move2side(double amount, double maxExtension=100)
move position vector to side using certain ammount
T get(const std::string &str) const
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
const std::string & getID() const
bool geometryLike() const
whether this is structurally similar to a geometry node
Storage for edges, including some functionality operating on multiple edges.
double xmin() const
Returns minimum x-coordinate.
The link is a (hard) right direction.
const std::string & getStreetName() const
Returns the street name of this edge.
static void writeNormalEdge(OutputDevice &device, const NBEdge *e, int edgeID, int fromNodeID, int toNodeID, const bool origNames, const double straightThresh, const ShapeContainer &shc)
write normal edge to device
static PositionVector getLeftLaneBorder(const NBEdge *edge, int laneIndex=-1, double widthOffset=0)
get the left border of the given lane (the leftmost one by default)
static PositionVector bezierControlPoints(const PositionVector &begShape, const PositionVector &endShape, bool isTurnaround, double extrapolateBeg, double extrapolateEnd, bool &ok, NBNode *recordError=0, double straightThresh=DEG2RAD(5), int shapeFlag=0)
get bezier control points
static const double INVALID_OFFSET
a value to signify offsets outside the range of [0, Line.length()]
PositionVector getSubpartByIndex(int beginIndex, int count) const
get subpart of a position vector using index and a cout
static std::string escapeXML(const std::string &orig, const bool maskDoubleHyphen=false)
Replaces the standard escapes by their XML entities.
The link is a partial right direction.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
vehicle is a passenger car (a "normal" car)
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing, bool leftHand=false) const
Returns the representation of the described stream's direction.
double getSpeed() const
Returns the speed allowed on this edge.
PositionVector getSubpart2D(double beginOffset, double endOffset) const
get subpart of a position vector in two dimensions (Z is ignored)
double getLaneWidth() const
Returns the default width of lanes of this edge.
void rotate2D(double angle)
static std::string getLaneType(SVCPermissions permissions)
static double writeGeomLines(const PositionVector &shape, OutputDevice &device, OutputDevice &elevationDevice, double offset=0)
write geometry as sequence of lines (sumo style)
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
const std::vector< Connection > & getConnections() const
Returns the connections.
NBNodeCont & getNodeCont()
Returns a reference to the node container.
Instance responsible for building networks.
static OutputDevice & getDevice(const std::string &name)
Returns the described OutputDevice.
static Position sideOffset(const Position &beg, const Position &end, const double amount)
get a side position of position vector using a offset
A storage for options typed value containers)
const std::string getParameter(const std::string &key, const std::string &defaultValue="") const
Returns the value for a given key.
double angleAt2D(int pos) const
get angle in certain position of position vector
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
const Position getOffsetBase() const
Returns the network base.
static void addPedestrianConnection(const NBEdge *inEdge, const NBEdge *outEdge, std::vector< NBEdge::Connection > ¶llel)
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Represents a single node (junction) during network building.
Static storage of an output device and its base (abstract) implementation.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
NBNode * getFromNode() const
Returns the origin node of the edge.
Container for nodes during the netbuilding process.
bool hasString(const std::string &str) const
static double angleDiff(const double angle1, const double angle2)
Returns the difference of the second angle to the first angle in radiants.
static void checkLaneGeometries(const NBEdge *e)
check if the lane geometries are compatible with OpenDRIVE assumptions (colinear stop line) ...
void add(double xoff, double yoff, double zoff)
double ymax() const
Returns maximum y-coordinate.
static int writeInternalEdge(OutputDevice &device, OutputDevice &junctionDevice, const NBEdge *inEdge, int nodeID, int edgeID, int inEdgeID, int outEdgeID, int connectionID, const std::vector< NBEdge::Connection > ¶llel, const bool isOuterEdge, const double straightThresh, const std::string ¢erMark)
write internal edge to device, return next connectionID
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
static int getID(const std::string &origID, StringBijection< int > &map, int &lastID)
NBNode * getToNode() const
Returns the destination node of the edge.
vehicle that is allowed to drive on high-speed rail tracks
static void writeElevationProfile(const PositionVector &shape, OutputDevice &device, const OutputDevice_String &elevationDevice)
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
void lf()
writes a line feed if applicable
An output device that encapsulates an ofstream.