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")) {
71 const bool origNames = oc.
getBool(
"output.original-names");
79 device <<
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
82 std::string dstr(ctime(&now));
87 device.openTag(
"header");
88 device.writeAttr(
"revMajor",
"1");
89 device.writeAttr(
"revMinor",
"4");
90 device.writeAttr(
"name",
"");
91 device.writeAttr(
"version",
"1.00");
92 device.writeAttr(
"date", dstr.substr(0, dstr.length() - 1));
93 device.writeAttr(
"north", b.
ymax());
94 device.writeAttr(
"south", b.
ymin());
95 device.writeAttr(
"east", b.
xmax());
96 device.writeAttr(
"west", b.
xmin());
105 for (std::map<std::string, NBEdge*>::const_iterator i = ec.
begin(); i != ec.
end(); ++i) {
106 const NBEdge* e = (*i).second;
107 device.openTag(
"road");
109 device.writeAttr(
"length", e->
getLength());
110 device.writeAttr(
"id",
getID(e->
getID(), edgeMap, edgeID));
111 device.writeAttr(
"junction", -1);
112 device.openTag(
"link");
113 device.openTag(
"predecessor");
114 device.writeAttr(
"elementType",
"junction");
117 device.openTag(
"successor");
118 device.writeAttr(
"elementType",
"junction");
122 device.openTag(
"type").writeAttr(
"s", 0).writeAttr(
"type",
"town").closeTag();
123 device.openTag(
"planView");
124 device.setPrecision(8);
126 const std::vector<NBEdge::Lane>& lanes = e->
getLanes();
128 #ifdef DEBUG_SMOOTH_GEOM 130 std::cout <<
"write planview for edge " << e->
getID() <<
"\n";
148 assert(shape0.size() >= 2);
152 stopLine.push_back(to);
155 for (
int lane = 1; lane < e->
getNumLanes(); ++lane) {
167 device <<
" <lateralProfile/>\n";
168 device <<
" <lanes>\n";
169 device <<
" <laneSection s=\"0\">\n";
171 device <<
" <right>\n";
174 device <<
" <link/>\n";
182 device <<
" <width sOffset=\"0\" a=\"" << e->
getLaneWidth(j) <<
"\" b=\"0\" c=\"0\" d=\"0\"/>\n";
183 std::string markType =
"broken";
187 device <<
" <roadMark sOffset=\"0\" type=\"" << markType <<
"\" weight=\"standard\" color=\"standard\" width=\"0.13\"/>\n";
188 device <<
" <speed sOffset=\"0\" max=\"" << lanes[j].speed <<
"\"/>\n";
189 device <<
" </lane>\n";
191 device <<
" </right>\n";
192 device <<
" </laneSection>\n";
193 device <<
" </lanes>\n";
194 device <<
" <objects/>\n";
195 device <<
" <signals/>\n";
197 device <<
" <userData code=\"sumoId\" value=\"" << e->
getID() <<
"\"/>\n";
203 for (std::map<std::string, NBNode*>::const_iterator i = nc.
begin(); i != nc.
end(); ++i) {
206 for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) {
207 const NBEdge* inEdge = *j;
208 const std::vector<NBEdge::Connection>& elv = inEdge->
getConnections();
209 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
225 if (init.size() == 0) {
226 fallBackShape.push_back(begShape.back());
227 fallBackShape.push_back(endShape.front());
234 length =
bezier(init, 12).length2D();
237 device.openTag(
"road");
239 device.writeAttr(
"length", length);
241 device.writeAttr(
"junction",
getID(n->
getID(), nodeMap, nodeID));
242 device.openTag(
"link");
243 device.openTag(
"predecessor");
244 device.writeAttr(
"elementType",
"road");
245 device.writeAttr(
"elementId",
getID(inEdge->
getID(), edgeMap, edgeID));
246 device.writeAttr(
"contactPoint",
"end");
248 device.openTag(
"successor");
249 device.writeAttr(
"elementType",
"road");
250 device.writeAttr(
"elementId",
getID(outEdge->
getID(), edgeMap, edgeID));
251 device.writeAttr(
"contactPoint",
"start");
254 device.openTag(
"type").writeAttr(
"s", 0).writeAttr(
"type",
"town").closeTag();
255 device.openTag(
"planView");
256 device.setPrecision(8);
258 if (init.size() == 0) {
266 device <<
" <lateralProfile/>\n";
267 device <<
" <lanes>\n";
268 device <<
" <laneSection s=\"0\">\n";
270 device <<
" <right>\n";
272 device <<
" <link>\n";
275 device <<
" </link>\n";
276 device <<
" <width sOffset=\"0\" a=\"" << width <<
"\" b=\"0\" c=\"0\" d=\"0\"/>\n";
277 device <<
" <roadMark sOffset=\"0\" type=\"none\" weight=\"standard\" color=\"standard\" width=\"0.13\"/>\n";
278 device <<
" </lane>\n";
279 device <<
" </right>\n";
280 device <<
" </laneSection>\n";
281 device <<
" </lanes>\n";
282 device <<
" <objects/>\n";
283 device <<
" <signals/>\n";
290 for (std::map<std::string, NBNode*>::const_iterator i = nc.
begin(); i != nc.
end(); ++i) {
294 int numConnections = 0;
295 for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) {
296 numConnections += (int)((*j)->getConnections().size());
298 if (numConnections == 0) {
301 device <<
" <junction name=\"" << n->
getID() <<
"\" id=\"" <<
getID(n->
getID(), nodeMap, nodeID) <<
"\">\n";
303 for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) {
304 const NBEdge* inEdge = *j;
305 const std::vector<NBEdge::Connection>& elv = inEdge->
getConnections();
306 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
312 device <<
" <connection id=\"" 313 << index <<
"\" incomingRoad=\"" <<
getID(inEdge->
getID(), edgeMap, edgeID)
314 <<
"\" connectingRoad=\"" 316 <<
"\" contactPoint=\"start\">\n";
320 device <<
" </connection>\n";
324 device <<
" </junction>\n";
334 for (
int j = 0; j < (int)shape.size() - 1; ++j) {
347 elevationDevice <<
" <elevation s=\"" << offset <<
"\" a=\"" << p.
z() <<
"\" b=\"" << (p2.
z() - p.
z()) /
MAX2(
POSITION_EPS, length) <<
"\" c=\"0\" d=\"0\"/>\n";
356 device <<
" <center>\n";
357 device <<
" <lane id=\"0\" type=\"none\" level=\"true\">\n";
358 device <<
" <link/>\n";
359 device <<
" <roadMark sOffset=\"0\" type=\"" << mark <<
"\" weight=\"standard\" color=\"standard\" width=\"" << markWidth <<
"\"/>\n";
360 device <<
" </lane>\n";
361 device <<
" </center>\n";
368 return map.
get(origID);
370 map.
insert(origID, lastID++);
377 switch (permissions) {
396 if (permissions ==
SVCAll) {
412 if (laneIndex == -1) {
426 for (
int i = leftmost; i > laneIndex; i--) {
444 assert(init.size() == 3 || init.size() == 4);
452 init.
add(-p.
x(), -p.
y(), -p.
z());
461 if (init.size() == 3) {
464 bU = 2 * init[1].x() - 2 * init[0].x();
465 cU = init[0].x() - 2 * init[1].x() + init[2].x();
469 bV = 2 * init[1].y() - 2 * init[0].y();
470 cV = init[0].y() - 2 * init[1].y() + init[2].y();
475 bZ = (2 * init[1].z() - 2 * init[0].z()) / length;
476 cZ = (init[0].z() - 2 * init[1].z() + init[2].z()) / (length * length);
482 bU = 3 * init[1].x() - 3 * init[0].x();
483 cU = 3 * init[0].x() - 6 * init[1].x() + 3 * init[2].x();
484 dU = -init[0].x() + 3 * init[1].x() - 3 * init[2].x() + init[3].x();
487 bV = 3 * init[1].y() - 3 * init[0].y();
488 cV = 3 * init[0].y() - 6 * init[1].y() + 3 * init[2].y();
489 dV = -init[0].y() + 3 * init[1].y() - 3 * init[2].y() + init[3].y();
493 bZ = (3 * init[1].z() - 3 * init[0].z()) / length;
494 cZ = (3 * init[0].z() - 6 * init[1].z() + 3 * init[2].z()) / (length * length);
495 dZ = (-init[0].z() + 3 * init[1].z() - 3 * init[2].z() + init[3].z()) / (length * length * length);
518 elevationDevice.
openTag(
"elevation");
526 return offset + length;
532 #ifdef DEBUG_SMOOTH_GEOM 534 std::cout <<
"writeGeomSmooth\n n=" << shape.size() <<
" shape=" <<
toString(shape) <<
"\n";
540 const SUMOReal curveCutout = longThresh / 2;
542 assert(longThresh >= 2 * curveCutout);
543 assert(shape.size() > 2);
549 for (
int j = 1; j < (int)shape.size() - 1; ++j) {
557 maxAngleDiff =
MAX2(maxAngleDiff, dAngle);
558 #ifdef DEBUG_SMOOTH_GEOM 560 std::cout <<
" j=" << j <<
" dAngle=" <<
RAD2DEG(dAngle) <<
" length1=" << length1 <<
" length2=" << length2 <<
"\n";
563 if (dAngle > angleThresh
564 && (length1 > longThresh || j == 1)
565 && (length2 > longThresh || j == (
int)shape.size() - 2)) {
568 shape2.removeClosest(p1);
572 const int numPoints = (int)shape2.size();
573 #ifdef DEBUG_SMOOTH_GEOM 575 std::cout <<
" n=" << numPoints <<
" shape2=" <<
toString(shape2) <<
"\n";
579 if (maxAngleDiff < angleThresh) {
581 #ifdef DEBUG_SMOOTH_GEOM 583 std::cout <<
" special case: all lines. maxAngleDiff=" << maxAngleDiff <<
"\n";
591 for (
int j = 0; j < numPoints - 1; ++j) {
598 if (lineLength >= longThresh) {
600 #ifdef DEBUG_SMOOTH_GEOM 602 std::cout <<
" writeLine=" <<
toString(line) <<
"\n";
612 begShape.
add(p0 - begShape.back());
613 }
else if (j == 1 || p0.
distanceTo2D(shape2[j - 1]) > longThresh) {
615 begShape.push_back(shape2[j - 1]);
616 begShape.push_back(p0);
619 begShape.push_back(shape2[j - 1]);
620 begShape.push_back(p1);
621 begShape.
add(p0 - begShape.back());
623 if (j == numPoints - 2) {
626 endShape.
add(p1 - endShape.front());
627 }
else if (j == numPoints - 3 || p1.
distanceTo2D(shape2[j + 2]) > longThresh) {
629 endShape.push_back(p1);
630 endShape.push_back(shape2[j + 2]);
633 endShape.push_back(p0);
634 endShape.push_back(shape2[j + 2]);
635 endShape.
add(p1 - endShape.front());
638 if (init.size() == 0) {
641 #ifdef DEBUG_SMOOTH_GEOM 643 std::cout <<
" writeLine lineLength=" << lineLength <<
" begShape=" <<
toString(begShape) <<
" endShape=" <<
toString(endShape) <<
" init=" <<
toString(init) <<
"\n";
649 offset =
writeGeomPP3(device, elevationDevice, init, curveLength, offset);
650 #ifdef DEBUG_SMOOTH_GEOM 652 std::cout <<
" writeCurve lineLength=" << lineLength <<
" curveLength=" << curveLength <<
" begShape=" <<
toString(begShape) <<
" endShape=" <<
toString(endShape) <<
" init=" <<
toString(init) <<
"\n";
666 SUMOReal z = shape.size() == 0 ? 0 : shape[0].z();
667 for (
int i = 1; i < (int)shape.size(); ++i) {
673 device <<
" <elevationProfile>\n";
675 device <<
" <elevation s=\"0\" a=\"" << z <<
"\" b=\"0\" c=\"0\" d=\"0\"/>\n";
679 device <<
" </elevationProfile>\n";
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)
static bool writeGeomSmooth(const PositionVector &shape, SUMOReal speed, OutputDevice &device, OutputDevice &elevationDevice)
write geometry as sequence of lines and bezier curves
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
A structure which describes a connection between edges or lanes.
int toLane
The lane the connections yields in.
std::map< std::string, NBNode * >::const_iterator begin() const
Returns the pointer to the begin of the stored nodes.
SUMOReal angleTo2D(const Position &other) const
returns the angle in the plane of the vector pointing from here to the other position ...
NBEdge * toEdge
The edge the connections yields in.
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.
vehicle is a not electrified rail
std::string getString() const
Returns the current content as a string.
The representation of a single edge during network building.
static std::string escapeXML(const std::string &orig)
Replaces the standard escapes by their XML entities.
void setPrecision(int precision=OUTPUT_ACCURACY)
Sets the precison or resets it to default.
SUMOReal ymin() const
Returns minimum y-coordinate.
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
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)
SUMOReal ymax() const
Returns maximum y-coordinate.
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
static SUMOReal angleDiff(const SUMOReal angle1, const SUMOReal angle2)
Returns the difference of the second angle to the first angle in radiants.
A class that stores a 2D geometrical boundary.
SUMOReal xmin() const
Returns minimum x-coordinate.
vehicle is a (possibly fast moving) electric rail
#define WRITE_WARNING(msg)
SUMOReal distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
void rotate2D(SUMOReal angle)
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.
std::map< std::string, NBEdge * >::const_iterator begin() const
Returns the pointer to the begin of the stored edges.
SUMOReal angleAt2D(int pos) const
get angle in certain position of position vector
SUMOReal z() const
Returns the z-position.
std::string getLaneID(int lane) const
get Lane ID (Secure)
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()
Returns the edge container.
void add(SUMOReal xoff, SUMOReal yoff, SUMOReal zoff)
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)
static void writeEmptyCenterLane(OutputDevice &device, const std::string &mark, SUMOReal markWidth)
Storage for edges, including some functionality operating on multiple edges.
SUMOReal x() const
Returns the x-position.
void bezier(int npts, SUMOReal b[], int cpts, SUMOReal p[])
const std::string & getStreetName() const
Returns the street name of this edge.
SUMOReal length2D() const
Returns the length.
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) ...
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
static PositionVector bezierControlPoints(const PositionVector &begShape, const PositionVector &endShape, bool isTurnaround, SUMOReal extrapolateBeg, SUMOReal extrapolateEnd, bool &ok, NBNode *recordError=0)
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)
static std::string getLaneType(SVCPermissions permissions)
SUMOReal xmax() const
Returns maximum x-coordinate.
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges.
const std::vector< Connection > & getConnections() const
Returns the connections.
NBNodeCont & getNodeCont()
Returns the node container.
Instance responsible for building networks.
static OutputDevice & getDevice(const std::string &name)
Returns the described OutputDevice.
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...
SUMOReal getSpeed() const
Returns the speed allowed on this edge.
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.
Position positionAtOffset2D(SUMOReal pos, SUMOReal lateralOffset=0) const
Returns the position at the given length.
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.
NBNode * getFromNode() const
Returns the origin node of the edge.
Container for nodes during the netbuilding process.
std::string getInternalLaneID() const
get ID of internal lnae
bool hasString(const std::string &str) const
SUMOReal y() const
Returns the y-position.
static int getID(const std::string &origID, StringBijection< int > &map, int &lastID)
SUMOReal getLaneWidth() const
Returns the default width of lanes of this edge.
NBNode * getToNode() const
Returns the destination node of the edge.
static void writeElevationProfile(const PositionVector &shape, OutputDevice &device, const OutputDevice_String &elevationDevice)
SUMOReal getLength() const
Returns the computed length of the edge.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
An output device that encapsulates an ofstream.