49 #ifdef CHECK_MEMORY_LEAKS 51 #endif // CHECK_MEMORY_LEAKS 54 #define DEBUGCOND true 56 #define MIN_TURN_DIAMETER 2.0 68 if (!oc.
isSet(
"opendrive-output")) {
73 const bool origNames = oc.
getBool(
"output.original-names");
77 int edgeID = nc.
size() * 10;
82 device <<
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
85 std::string dstr(ctime(&now));
88 device.openTag(
"header");
89 device.writeAttr(
"revMajor",
"1");
90 device.writeAttr(
"revMinor",
"4");
91 device.writeAttr(
"name",
"");
92 device.writeAttr(
"version",
"1.00");
93 device.writeAttr(
"date", dstr.substr(0, dstr.length() - 1));
94 device.writeAttr(
"north", b.
ymax());
95 device.writeAttr(
"south", b.
ymin());
96 device.writeAttr(
"east", b.
xmax());
97 device.writeAttr(
"west", b.
xmin());
106 for (std::map<std::string, NBEdge*>::const_iterator i = ec.
begin(); i != ec.
end(); ++i) {
107 const NBEdge* e = (*i).second;
116 planViewOSS.
openTag(
"planView");
119 const std::vector<NBEdge::Lane>& lanes = e->
getLanes();
121 #ifdef DEBUG_SMOOTH_GEOM 123 std::cout <<
"write planview for edge " << e->
getID() <<
"\n";
138 device.openTag(
"road");
140 device.setPrecision(8);
143 device.writeAttr(
"id",
getID(e->
getID(), edgeMap, edgeID));
144 device.writeAttr(
"junction", -1);
147 if (hasPred || hasSucc) {
148 device.openTag(
"link");
150 device.openTag(
"predecessor");
151 device.writeAttr(
"elementType",
"junction");
156 device.openTag(
"successor");
157 device.writeAttr(
"elementType",
"junction");
163 device.openTag(
"type").writeAttr(
"s", 0).writeAttr(
"type",
"town").closeTag();
166 device <<
" <lateralProfile/>\n";
167 device <<
" <lanes>\n";
168 device <<
" <laneSection s=\"0\">\n";
170 device <<
" <right>\n";
173 device <<
" <link/>\n";
181 device <<
" <width sOffset=\"0\" a=\"" << e->
getLaneWidth(j) <<
"\" b=\"0\" c=\"0\" d=\"0\"/>\n";
182 std::string markType =
"broken";
186 device <<
" <roadMark sOffset=\"0\" type=\"" << markType <<
"\" weight=\"standard\" color=\"standard\" width=\"0.13\"/>\n";
187 device <<
" <speed sOffset=\"0\" max=\"" << lanes[j].speed <<
"\"/>\n";
188 device <<
" </lane>\n";
190 device <<
" </right>\n";
191 device <<
" </laneSection>\n";
192 device <<
" </lanes>\n";
193 device <<
" <objects/>\n";
194 device <<
" <signals/>\n";
196 device <<
" <userData code=\"sumoId\" value=\"" << e->
getID() <<
"\"/>\n";
204 for (std::map<std::string, NBNode*>::const_iterator i = nc.
begin(); i != nc.
end(); ++i) {
207 for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) {
208 const NBEdge* inEdge = *j;
209 const std::vector<NBEdge::Connection>& elv = inEdge->
getConnections();
210 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
223 fallBackShape.push_back(begShape.back());
224 fallBackShape.push_back(endShape.front());
228 if (init.size() == 0) {
235 length =
bezier(init, 12).length2D();
238 device.openTag(
"road");
240 device.setPrecision(8);
244 device.writeAttr(
"junction",
getID(n->
getID(), nodeMap, nodeID));
245 device.openTag(
"link");
246 device.openTag(
"predecessor");
247 device.writeAttr(
"elementType",
"road");
248 device.writeAttr(
"elementId",
getID(inEdge->
getID(), edgeMap, edgeID));
249 device.writeAttr(
"contactPoint",
"end");
251 device.openTag(
"successor");
252 device.writeAttr(
"elementType",
"road");
253 device.writeAttr(
"elementId",
getID(outEdge->
getID(), edgeMap, edgeID));
254 device.writeAttr(
"contactPoint",
"start");
257 device.openTag(
"type").writeAttr(
"s", 0).writeAttr(
"type",
"town").closeTag();
258 device.openTag(
"planView");
259 device.setPrecision(8);
261 #ifdef DEBUG_SMOOTH_GEOM 263 std::cout <<
"write planview for internal edge " << c.
getInternalLaneID() <<
" init=" << init <<
" fallback=" << fallBackShape <<
"\n";
266 if (init.size() == 0) {
274 device <<
" <lateralProfile/>\n";
275 device <<
" <lanes>\n";
276 device <<
" <laneSection s=\"0\">\n";
278 device <<
" <right>\n";
280 device <<
" <link>\n";
283 device <<
" </link>\n";
284 device <<
" <width sOffset=\"0\" a=\"" << width <<
"\" b=\"0\" c=\"0\" d=\"0\"/>\n";
285 device <<
" <roadMark sOffset=\"0\" type=\"none\" weight=\"standard\" color=\"standard\" width=\"0.13\"/>\n";
286 device <<
" </lane>\n";
287 device <<
" </right>\n";
288 device <<
" </laneSection>\n";
289 device <<
" </lanes>\n";
290 device <<
" <objects/>\n";
291 device <<
" <signals/>\n";
298 for (std::map<std::string, NBNode*>::const_iterator i = nc.
begin(); i != nc.
end(); ++i) {
302 int numConnections = 0;
303 for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) {
304 numConnections += (int)((*j)->getConnections().size());
306 if (numConnections == 0) {
309 device <<
" <junction name=\"" << n->
getID() <<
"\" id=\"" <<
getID(n->
getID(), nodeMap, nodeID) <<
"\">\n";
311 for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) {
312 const NBEdge* inEdge = *j;
313 const std::vector<NBEdge::Connection>& elv = inEdge->
getConnections();
314 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
320 device <<
" <connection id=\"" 321 << index <<
"\" incomingRoad=\"" <<
getID(inEdge->
getID(), edgeMap, edgeID)
322 <<
"\" connectingRoad=\"" 324 <<
"\" contactPoint=\"start\">\n";
328 device <<
" </connection>\n";
332 device <<
" </junction>\n";
342 for (
int j = 0; j < (int)shape.size() - 1; ++j) {
355 elevationDevice <<
" <elevation s=\"" << offset <<
"\" a=\"" << p.
z() <<
"\" b=\"" << (p2.
z() - p.
z()) /
MAX2(
POSITION_EPS, length) <<
"\" c=\"0\" d=\"0\"/>\n";
364 device <<
" <center>\n";
365 device <<
" <lane id=\"0\" type=\"none\" level=\"true\">\n";
366 device <<
" <link/>\n";
367 device <<
" <roadMark sOffset=\"0\" type=\"" << mark <<
"\" weight=\"standard\" color=\"standard\" width=\"" << markWidth <<
"\"/>\n";
368 device <<
" </lane>\n";
369 device <<
" </center>\n";
376 return map.
get(origID);
378 map.
insert(origID, lastID++);
385 switch (permissions) {
404 if (permissions ==
SVCAll) {
420 if (laneIndex == -1) {
434 for (
int i = leftmost; i > laneIndex; i--) {
452 assert(init.size() == 3 || init.size() == 4);
463 init.
add(-p.
x(), -p.
y(), -p.
z());
472 if (init.size() == 3) {
475 bU = 2 * init[1].x() - 2 * init[0].x();
476 cU = init[0].x() - 2 * init[1].x() + init[2].x();
480 bV = 2 * init[1].y() - 2 * init[0].y();
481 cV = init[0].y() - 2 * init[1].y() + init[2].y();
486 bZ = (2 * initZ[1].z() - 2 * initZ[0].z()) / length;
487 cZ = (initZ[0].z() - 2 * initZ[1].z() + initZ[2].z()) / (length * length);
493 bU = 3 * init[1].x() - 3 * init[0].x();
494 cU = 3 * init[0].x() - 6 * init[1].x() + 3 * init[2].x();
495 dU = -init[0].x() + 3 * init[1].x() - 3 * init[2].x() + init[3].x();
498 bV = 3 * init[1].y() - 3 * init[0].y();
499 cV = 3 * init[0].y() - 6 * init[1].y() + 3 * init[2].y();
500 dV = -init[0].y() + 3 * init[1].y() - 3 * init[2].y() + init[3].y();
504 bZ = (3 * initZ[1].z() - 3 * initZ[0].z()) / length;
505 cZ = (3 * initZ[0].z() - 6 * initZ[1].z() + 3 * initZ[2].z()) / (length * length);
506 dZ = (-initZ[0].z() + 3 * initZ[1].z() - 3 * initZ[2].z() + initZ[3].z()) / (length * length * length);
529 elevationDevice.
openTag(
"elevation");
537 return offset + length;
543 #ifdef DEBUG_SMOOTH_GEOM 545 std::cout <<
"writeGeomSmooth\n n=" << shape.size() <<
" shape=" <<
toString(shape) <<
"\n";
550 const SUMOReal curveCutout = longThresh / 2;
552 assert(longThresh >= 2 * curveCutout);
553 assert(shape.size() > 2);
559 for (
int j = 1; j < (int)shape.size() - 1; ++j) {
567 maxAngleDiff =
MAX2(maxAngleDiff, dAngle);
568 #ifdef DEBUG_SMOOTH_GEOM 570 std::cout <<
" j=" << j <<
" dAngle=" <<
RAD2DEG(dAngle) <<
" length1=" << length1 <<
" length2=" << length2 <<
"\n";
573 if (dAngle > straightThresh
574 && (length1 > longThresh || j == 1)
575 && (length2 > longThresh || j == (
int)shape.size() - 2)) {
578 shape2.removeClosest(p1);
582 const int numPoints = (int)shape2.size();
583 #ifdef DEBUG_SMOOTH_GEOM 585 std::cout <<
" n=" << numPoints <<
" shape2=" <<
toString(shape2) <<
"\n";
589 if (maxAngleDiff < straightThresh) {
591 #ifdef DEBUG_SMOOTH_GEOM 593 std::cout <<
" special case: all lines. maxAngleDiff=" << maxAngleDiff <<
"\n";
601 for (
int j = 0; j < numPoints - 1; ++j) {
608 if (lineLength >= longThresh) {
610 #ifdef DEBUG_SMOOTH_GEOM 612 std::cout <<
" writeLine=" <<
toString(line) <<
"\n";
619 if (j == 0 || j == numPoints - 2) {
622 begShape.
add(p0 - begShape.back());
623 }
else if (j == 1 || p0.
distanceTo2D(shape2[j - 1]) > longThresh) {
625 begShape.push_back(shape2[j - 1]);
626 begShape.push_back(p0);
629 begShape.push_back(shape2[j - 1]);
630 begShape.push_back(p1);
631 begShape.
add(p0 - begShape.back());
634 if (j == 0 || j == numPoints - 2) {
637 endShape.
add(p1 - endShape.front());
638 }
else if (j == numPoints - 3 || p1.
distanceTo2D(shape2[j + 2]) > longThresh) {
640 endShape.push_back(p1);
641 endShape.push_back(shape2[j + 2]);
644 endShape.push_back(p0);
645 endShape.push_back(shape2[j + 2]);
646 endShape.
add(p1 - endShape.front());
650 if (init.size() == 0) {
653 #ifdef DEBUG_SMOOTH_GEOM 655 std::cout <<
" writeLine lineLength=" << lineLength <<
" begShape" << j <<
"=" <<
toString(begShape) <<
" endShape" << j <<
"=" <<
toString(endShape) <<
" init" << j <<
"=" <<
toString(init) <<
"\n";
661 offset =
writeGeomPP3(device, elevationDevice, init, curveLength, offset);
662 #ifdef DEBUG_SMOOTH_GEOM 664 std::cout <<
" writeCurve lineLength=" << lineLength <<
" curveLength=" << curveLength <<
" begShape" << j <<
"=" <<
toString(begShape) <<
" endShape" << j <<
"=" <<
toString(endShape) <<
" init" << j <<
"=" <<
toString(init) <<
"\n";
679 SUMOReal z = shape.size() == 0 ? 0 : shape[0].z();
680 for (
int i = 1; i < (int)shape.size(); ++i) {
686 device <<
" <elevationProfile>\n";
688 device <<
" <elevation s=\"0\" a=\"" << z <<
"\" b=\"0\" c=\"0\" d=\"0\"/>\n";
692 device <<
" </elevationProfile>\n";
702 assert(shape0.size() >= 2);
706 stopLine.push_back(to);
709 for (
int lane = 1; lane < e->
getNumLanes(); ++lane) {
static SUMOReal writeGeomLines(const PositionVector &shape, OutputDevice &device, OutputDevice &elevationDevice, SUMOReal offset=0)
write geometry as sequence of lines (sumo style)
static SUMOReal writeGeomPP3(OutputDevice &device, OutputDevice &elevationDevice, PositionVector init, SUMOReal length, SUMOReal offset=0)
write geometry as a single bezier curve (paramPoly3)
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
static Position sideOffset(const Position &beg, const Position &end, const SUMOReal amount)
get a side position of position vector using a offset
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
A structure which describes a connection between edges or lanes.
int toLane
The lane the connections yields in.
std::string getString() const
Returns the current content as a string.
NBEdge * toEdge
The edge the connections yields in.
bool hasString(const std::string &str) const
vehicle is a not electrified rail
int gPrecision
the precision for floating point outputs
static PositionVector bezierControlPoints(const PositionVector &begShape, const PositionVector &endShape, bool isTurnaround, SUMOReal extrapolateBeg, SUMOReal extrapolateEnd, bool &ok, NBNode *recordError=0, SUMOReal straightThresh=DEG2RAD(5))
get bezier control points
SUMOReal ymin() const
Returns minimum y-coordinate.
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
The representation of a single edge during network building.
SUMOReal xmin() const
Returns minimum x-coordinate.
EdgeVector getIncomingEdges() const
Returns the list of incoming edges unsorted.
void setPrecision(int precision=gPrecision)
Sets the precison or resets it to default.
SUMOReal getLaneWidth() const
Returns the default width of lanes of this edge.
SUMOReal getFloat(const std::string &name) const
Returns the SUMOReal-value of the named option (only for Option_Float)
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
const SVCPermissions SVCAll
static SUMOReal angleDiff(const SUMOReal angle1, const SUMOReal angle2)
Returns the difference of the second angle to the first angle in radiants.
SUMOReal x() const
Returns the x-position.
Position positionAtOffset2D(SUMOReal pos, SUMOReal lateralOffset=0) const
Returns the position at the given length.
SUMOReal xmax() const
Returns maximum x-coordinate.
A class that stores a 2D geometrical boundary.
vehicle is a (possibly fast moving) electric rail
#define WRITE_WARNING(msg)
SUMOReal 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) ...
void rotate2D(SUMOReal angle)
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
Returns the id.
SUMOReal length2D() const
Returns the length.
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.
std::map< std::string, NBEdge * >::const_iterator end() const
Returns the pointer to the end of the stored edges.
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
std::string getInternalLaneID() const
get ID of internal lane
int fromLane
The lane the connections starts at.
A point in 2D or 3D with translation and scaling methods.
NBEdgeCont & getEdgeCont()
void add(SUMOReal xoff, SUMOReal yoff, SUMOReal zoff)
SUMOReal z() const
Returns the z-position.
int getNumLanes() const
Returns the number of lanes.
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
static void writeEmptyCenterLane(OutputDevice &device, const std::string &mark, SUMOReal markWidth)
Storage for edges, including some functionality operating on multiple edges.
void bezier(int npts, SUMOReal b[], int cpts, SUMOReal p[])
std::map< std::string, NBNode * >::const_iterator end() const
Returns the pointer to the end of the stored nodes.
const Boundary & getConvBoundary() const
Returns the converted boundary.
static std::string escapeXML(const std::string &orig, const bool maskDoubleHyphen=false)
Replaces the standard escapes by their XML entities.
vehicle is a passenger car (a "normal" car)
std::map< std::string, NBEdge * >::const_iterator begin() const
Returns the pointer to the begin of the stored edges.
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
static std::string getLaneType(SVCPermissions permissions)
NBNode * getToNode() const
Returns the destination node of the edge.
SUMOReal angleAt2D(int pos) const
get angle in certain position of position vector
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.
SUMOReal y() const
Returns the y-position.
A storage for options typed value containers)
static PositionVector getLeftLaneBorder(const NBEdge *edge, int laneIndex=-1)
get the left border of the given lane (the leftmost one by default)
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
Represents a single node (junction) during network building.
T get(const std::string &str) const
SUMOReal distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
void move2side(SUMOReal amount)
move position vector to side using certain ammount
Static storage of an output device and its base (abstract) implementation.
bool closeTag()
Closes the most recently opened tag.
SUMOReal ymax() const
Returns maximum y-coordinate.
int size() const
Returns the number of nodes stored in this container.
std::string getLaneID(int lane) const
get Lane ID (Secure)
SUMOReal getSpeed() const
Returns the speed allowed on this edge.
Container for nodes during the netbuilding process.
static void checkLaneGeometries(const NBEdge *e)
check if the lane geometries are compatible with OpenDRIVE assumptions (colinear stop line) ...
static bool writeGeomSmooth(const PositionVector &shape, SUMOReal speed, OutputDevice &device, OutputDevice &elevationDevice, SUMOReal straightThresh, SUMOReal &length)
static int getID(const std::string &origID, StringBijection< int > &map, int &lastID)
const std::string & getStreetName() const
Returns the street name of this edge.
const std::vector< Connection > & getConnections() const
Returns the connections.
std::map< std::string, NBNode * >::const_iterator begin() const
Returns the pointer to the begin of the stored nodes.
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
static void writeElevationProfile(const PositionVector &shape, OutputDevice &device, const OutputDevice_String &elevationDevice)
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
SUMOReal angleTo2D(const Position &other) const
returns the angle in the plane of the vector pointing from here to the other position ...
An output device that encapsulates an ofstream.
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
NBNode * getFromNode() const
Returns the origin node of the edge.