SUMO - Simulation of Urban MObility

NIImporter_OpenDrive.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00010 // Importer for networks stored in openDrive format
00011 /****************************************************************************/
00012 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00013 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
00014 /****************************************************************************/
00015 //
00016 //   This file is part of SUMO.
00017 //   SUMO is free software: you can redistribute it and/or modify
00018 //   it under the terms of the GNU General Public License as published by
00019 //   the Free Software Foundation, either version 3 of the License, or
00020 //   (at your option) any later version.
00021 //
00022 /****************************************************************************/
00023 
00024 
00025 // ===========================================================================
00026 // included modules
00027 // ===========================================================================
00028 #ifdef _MSC_VER
00029 #include <windows_config.h>
00030 #else
00031 #include <config.h>
00032 #endif
00033 #include <string>
00034 #include <cmath>
00035 #include <utils/xml/SUMOSAXHandler.h>
00036 #include <utils/common/UtilExceptions.h>
00037 #include <utils/common/TplConvert.h>
00038 #include <utils/common/ToString.h>
00039 #include <utils/common/MsgHandler.h>
00040 #include <netbuild/NBEdge.h>
00041 #include <netbuild/NBEdgeCont.h>
00042 #include <netbuild/NBNode.h>
00043 #include <netbuild/NBNodeCont.h>
00044 #include <netbuild/NBNetBuilder.h>
00045 #include <utils/xml/SUMOXMLDefinitions.h>
00046 #include <utils/geom/GeoConvHelper.h>
00047 #include <utils/geom/GeomConvHelper.h>
00048 #include <foreign/eulerspiral/euler.h>
00049 #include <utils/options/OptionsCont.h>
00050 #include <utils/common/FileHelpers.h>
00051 #include <utils/xml/XMLSubSys.h>
00052 #include <utils/geom/Boundary.h>
00053 #include "NILoader.h"
00054 #include "NIImporter_OpenDrive.h"
00055 
00056 #ifdef CHECK_MEMORY_LEAKS
00057 #include <foreign/nvwa/debug_new.h>
00058 #endif // CHECK_MEMORY_LEAKS
00059 
00060 
00061 // ===========================================================================
00062 // definitions
00063 // ===========================================================================
00064 #define C_LENGTH 10.
00065 
00066 
00067 // ===========================================================================
00068 // static variables
00069 // ===========================================================================
00070 StringBijection<int>::Entry NIImporter_OpenDrive::openDriveTags[] = {
00071     { "header",           NIImporter_OpenDrive::OPENDRIVE_TAG_HEADER },
00072     { "road",             NIImporter_OpenDrive::OPENDRIVE_TAG_ROAD },
00073     { "predecessor",      NIImporter_OpenDrive::OPENDRIVE_TAG_PREDECESSOR },
00074     { "successor",        NIImporter_OpenDrive::OPENDRIVE_TAG_SUCCESSOR },
00075     { "geometry",         NIImporter_OpenDrive::OPENDRIVE_TAG_GEOMETRY },
00076     { "line",             NIImporter_OpenDrive::OPENDRIVE_TAG_LINE },
00077     { "spiral",           NIImporter_OpenDrive::OPENDRIVE_TAG_SPIRAL },
00078     { "arc",              NIImporter_OpenDrive::OPENDRIVE_TAG_ARC },
00079     { "poly3",            NIImporter_OpenDrive::OPENDRIVE_TAG_POLY3 },
00080     { "laneSection",      NIImporter_OpenDrive::OPENDRIVE_TAG_LANESECTION },
00081     { "left",             NIImporter_OpenDrive::OPENDRIVE_TAG_LEFT },
00082     { "center",           NIImporter_OpenDrive::OPENDRIVE_TAG_CENTER },
00083     { "right",            NIImporter_OpenDrive::OPENDRIVE_TAG_RIGHT },
00084     { "lane",             NIImporter_OpenDrive::OPENDRIVE_TAG_LANE },
00085 
00086     { "",                 NIImporter_OpenDrive::OPENDRIVE_TAG_NOTHING }
00087 };
00088 
00089 
00090 StringBijection<int>::Entry NIImporter_OpenDrive::openDriveAttrs[] = {
00091     { "revMajor",       NIImporter_OpenDrive::OPENDRIVE_ATTR_REVMAJOR },
00092     { "revMinor",       NIImporter_OpenDrive::OPENDRIVE_ATTR_REVMINOR },
00093     { "id",             NIImporter_OpenDrive::OPENDRIVE_ATTR_ID },
00094     { "length",         NIImporter_OpenDrive::OPENDRIVE_ATTR_LENGTH },
00095     { "junction",       NIImporter_OpenDrive::OPENDRIVE_ATTR_JUNCTION },
00096     { "elementType",    NIImporter_OpenDrive::OPENDRIVE_ATTR_ELEMENTTYPE },
00097     { "elementId",      NIImporter_OpenDrive::OPENDRIVE_ATTR_ELEMENTID },
00098     { "contactPoint",   NIImporter_OpenDrive::OPENDRIVE_ATTR_CONTACTPOINT },
00099     { "s",              NIImporter_OpenDrive::OPENDRIVE_ATTR_S },
00100     { "x",              NIImporter_OpenDrive::OPENDRIVE_ATTR_X },
00101     { "y",              NIImporter_OpenDrive::OPENDRIVE_ATTR_Y },
00102     { "hdg",            NIImporter_OpenDrive::OPENDRIVE_ATTR_HDG },
00103     { "curvStart",      NIImporter_OpenDrive::OPENDRIVE_ATTR_CURVSTART },
00104     { "curvEnd",        NIImporter_OpenDrive::OPENDRIVE_ATTR_CURVEND },
00105     { "curvature",      NIImporter_OpenDrive::OPENDRIVE_ATTR_CURVATURE },
00106     { "a",              NIImporter_OpenDrive::OPENDRIVE_ATTR_A },
00107     { "b",              NIImporter_OpenDrive::OPENDRIVE_ATTR_B },
00108     { "c",              NIImporter_OpenDrive::OPENDRIVE_ATTR_C },
00109     { "d",              NIImporter_OpenDrive::OPENDRIVE_ATTR_D },
00110     { "type",           NIImporter_OpenDrive::OPENDRIVE_ATTR_TYPE },
00111     { "level",          NIImporter_OpenDrive::OPENDRIVE_ATTR_LEVEL },
00112 
00113     { "",               NIImporter_OpenDrive::OPENDRIVE_ATTR_NOTHING }
00114 };
00115 
00116 
00117 // ===========================================================================
00118 // method definitions
00119 // ===========================================================================
00120 // ---------------------------------------------------------------------------
00121 // static methods (interface in this case)
00122 // ---------------------------------------------------------------------------
00123 void
00124 NIImporter_OpenDrive::loadNetwork(const OptionsCont& oc, NBNetBuilder& nb) {
00125     // check whether the option is set (properly)
00126     if (!oc.isUsableFileList("opendrive-files")) {
00127         return;
00128     }
00129     // build the handler
00130     std::vector<OpenDriveEdge> innerEdges, outerEdges;
00131     NIImporter_OpenDrive handler(innerEdges, outerEdges);
00132     // parse file(s)
00133     std::vector<std::string> files = oc.getStringVector("opendrive-files");
00134     for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
00135         if (!FileHelpers::exists(*file)) {
00136             WRITE_ERROR("Could not open opendrive file '" + *file + "'.");
00137             return;
00138         }
00139         handler.setFileName(*file);
00140         PROGRESS_BEGIN_MESSAGE("Parsing opendrive from '" + *file + "'");
00141         XMLSubSys::runParser(handler, *file);
00142         PROGRESS_DONE_MESSAGE();
00143     }
00144     // convert geometries into a discretised representation
00145     computeShapes(innerEdges);
00146     computeShapes(outerEdges);
00147 
00148     // -------------------------
00149     // node building
00150     // -------------------------
00151     // build nodes#1
00152     //  look at all links which belong to a node, collect their bounding boxes
00153     //  and place the node in the middle of this bounding box
00154     std::map<std::string, Boundary> posMap;
00155     std::map<std::string, std::string> edge2junction;
00156     //   compute node positions
00157     for (std::vector<OpenDriveEdge>::iterator i = innerEdges.begin(); i != innerEdges.end(); ++i) {
00158         OpenDriveEdge& e = *i;
00159         assert(e.junction != "-1" && e.junction != "");
00160         edge2junction[e.id] = e.junction;
00161         if (posMap.find(e.junction) == posMap.end()) {
00162             posMap[e.junction] = Boundary();
00163         }
00164         posMap[e.junction].add(e.geom.getBoxBoundary());
00165     }
00166     //   build nodes
00167     for (std::map<std::string, Boundary>::iterator i = posMap.begin(); i != posMap.end(); ++i) {
00168         if (!nb.getNodeCont().insert((*i).first, (*i).second.getCenter())) {
00169             throw ProcessError("Could not add node '" + (*i).first + "'.");
00170         }
00171     }
00172     //  assign built nodes
00173     for (std::vector<OpenDriveEdge>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
00174         OpenDriveEdge& e = *i;
00175         for (std::vector<OpenDriveLink>::iterator j = e.links.begin(); j != e.links.end(); ++j) {
00176             OpenDriveLink& l = *j;
00177             if (l.elementType != OPENDRIVE_ET_ROAD) {
00178                 // set node information
00179                 setNodeSecure(nb.getNodeCont(), e, l.elementID, l.linkType);
00180                 continue;
00181             }
00182             if (edge2junction.find(l.elementID) != edge2junction.end()) {
00183                 // set node information of an internal road
00184                 setNodeSecure(nb.getNodeCont(), e, edge2junction[l.elementID], l.linkType);
00185                 continue;
00186             }
00187         }
00188     }
00189     //  we should now have all nodes set for links which are not outer edge-to-outer edge links
00190 
00191 
00192     // build nodes#2
00193     //  build nodes for all outer edge-to-outer edge connections
00194     for (std::vector<OpenDriveEdge>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
00195         OpenDriveEdge& e = *i;
00196         for (std::vector<OpenDriveLink>::iterator j = e.links.begin(); j != e.links.end(); ++j) {
00197             OpenDriveLink& l = *j;
00198             if (l.elementType != OPENDRIVE_ET_ROAD || edge2junction.find(l.elementID) != edge2junction.end()) {
00199                 // is a connection to an internal edge, or a node, skip
00200                 continue;
00201             }
00202             // we have a direct connection between to external edges
00203             std::string id1 = e.id;
00204             std::string id2 = l.elementID;
00205             if (id1 < id2) {
00206                 std::swap(id1, id2);
00207             }
00208             std::string nid = id1 + "." + id2;
00209             if (nb.getNodeCont().retrieve(nid) == 0) {
00210                 // not yet seen, build
00211                 Position pos = l.linkType == OPENDRIVE_LT_SUCCESSOR ? e.geom[(int)e.geom.size() - 1] : e.geom[0];
00212                 if (!nb.getNodeCont().insert(nid, pos)) {
00213                     throw ProcessError("Could not build node '" + nid + "'.");
00214                 }
00215             }
00216             /* debug-stuff
00217             else {
00218                 Position pos = l.linkType==OPENDRIVE_LT_SUCCESSOR ? e.geom[e.geom.size()-1] : e.geom[0];
00219                 cout << nid << " " << pos << " " << nb.getNodeCont().retrieve(nid)->getPosition() << endl;
00220             }
00221             */
00222             setNodeSecure(nb.getNodeCont(), e, nid, l.linkType);
00223         }
00224     }
00225     // we should now have start/end nodes for all outer edge-to-outer edge connections
00226 
00227 
00228     // build nodes#3
00229     //  assign further nodes generated from inner-edges
00230     //  these nodes have not been assigned earlier, because the connectiosn are referenced in inner-edges
00231     for (std::vector<OpenDriveEdge>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
00232         OpenDriveEdge& e = *i;
00233         if (e.to != 0 && e.from != 0) {
00234             continue;
00235         }
00236         for (std::vector<OpenDriveEdge>::iterator j = innerEdges.begin(); j != innerEdges.end(); ++j) {
00237             OpenDriveEdge& ie = *j;
00238             for (std::vector<OpenDriveLink>::iterator k = ie.links.begin(); k != ie.links.end(); ++k) {
00239                 OpenDriveLink& il = *k;
00240                 if (il.elementType != OPENDRIVE_ET_ROAD || il.elementID != e.id) {
00241                     // not conneted to the currently investigated outer edge
00242                     continue;
00243                 }
00244                 std::string nid = edge2junction[ie.id];
00245                 if (il.contactPoint == OPENDRIVE_CP_START) {
00246                     setNodeSecure(nb.getNodeCont(), e, nid, OPENDRIVE_LT_PREDECESSOR);
00247                 } else {
00248                     setNodeSecure(nb.getNodeCont(), e, nid, OPENDRIVE_LT_SUCCESSOR);
00249                 }
00250             }
00251         }
00252 
00253     }
00254     //
00255 
00256 
00257     // build start/end nodes which were not defined previously
00258     for (std::vector<OpenDriveEdge>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
00259         OpenDriveEdge& e = *i;
00260         if (e.from == 0) {
00261             std::string nid = e.id + ".begin";
00262             Position pos(e.geometries[0].x, e.geometries[0].y);
00263             e.from = getOrBuildNode(nid, e.geom[0], nb.getNodeCont());
00264         }
00265         if (e.to == 0) {
00266             std::string nid = e.id + ".end";
00267             Position pos(e.geometries[e.geometries.size() - 1].x, e.geometries[e.geometries.size() - 1].y);
00268             e.to = getOrBuildNode(nid, e.geom[(int)e.geom.size() - 1], nb.getNodeCont());
00269         }
00270     }
00271 
00272 
00273     // -------------------------
00274     // edge building
00275     // -------------------------
00276     std::map<NBEdge*, std::map<int, int> > fromLaneMap;
00277     std::map<NBEdge*, std::map<int, int> > toLaneMap;
00278     // build edges
00279     for (std::vector<OpenDriveEdge>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
00280         OpenDriveEdge& e = *i;
00281         SUMOReal speed = nb.getTypeCont().getSpeed("");
00282         int priority = nb.getTypeCont().getPriority("");
00283         LaneSpreadFunction lsf = LANESPREAD_CENTER;
00284         unsigned int noLanesRight = e.getMaxLaneNumber(OPENDRIVE_TAG_RIGHT);
00285         unsigned int noLanesLeft = e.getMaxLaneNumber(OPENDRIVE_TAG_LEFT);
00286         if (noLanesRight != 0 || noLanesLeft != 0) {
00287             lsf = LANESPREAD_RIGHT;
00288         } else {
00289             WRITE_WARNING("Edge '" + e.id + "' has no lanes.");
00290         }
00291         if (noLanesRight > 0) {
00292             NBEdge* nbe = new NBEdge("-" + e.id, e.from, e.to, "", speed, noLanesRight, priority, -1, -1, e.geom, "", lsf, true);
00293             if (!nb.getEdgeCont().insert(nbe)) {
00294                 throw ProcessError("Could not add edge '" + std::string("-") + e.id + "'.");
00295             }
00296             fromLaneMap[nbe] = e.laneSections.back().buildLaneMapping(OPENDRIVE_TAG_RIGHT);
00297             toLaneMap[nbe] = e.laneSections[0].buildLaneMapping(OPENDRIVE_TAG_RIGHT);
00298         }
00299         if (noLanesLeft > 0) {
00300             NBEdge* nbe = new NBEdge(e.id, e.to, e.from, "", speed, noLanesLeft, priority, -1, -1, e.geom.reverse(), "", lsf, true);
00301             if (!nb.getEdgeCont().insert(nbe)) {
00302                 throw ProcessError("Could not add edge '" + e.id + "'.");
00303             }
00304             fromLaneMap[nbe] = e.laneSections[0].buildLaneMapping(OPENDRIVE_TAG_LEFT);
00305             toLaneMap[nbe] = e.laneSections.back().buildLaneMapping(OPENDRIVE_TAG_LEFT);
00306         }
00307     }
00308 
00309 
00310     // -------------------------
00311     // connections building
00312     // -------------------------
00313     std::vector<Connection> connections;
00314     // connections#1
00315     //  build connections between outer-edges
00316     for (std::vector<OpenDriveEdge>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
00317         OpenDriveEdge& e = *i;
00318         for (std::vector<OpenDriveLink>::iterator j = e.links.begin(); j != e.links.end(); ++j) {
00319             OpenDriveLink& l = *j;
00320             if (l.elementType != OPENDRIVE_ET_ROAD) {
00321                 // we are not interested in connections to nodes
00322                 continue;
00323             }
00324             if (edge2junction.find(l.elementID) != edge2junction.end()) {
00325                 // connection via an inner-road
00326                 addViaConnectionSecure(nb.getEdgeCont(),
00327                                        nb.getNodeCont().retrieve(edge2junction[l.elementID]),
00328                                        e, l.linkType, l.elementID, connections);
00329             } else {
00330                 // connection between two outer-edges; can be used directly
00331                 std::vector<OpenDriveEdge>::iterator p = std::find_if(outerEdges.begin(), outerEdges.end(), edge_by_id_finder(l.elementID));
00332                 if (p == outerEdges.end()) {
00333                     throw ProcessError("Could not find connection edge.");
00334                 }
00335                 std::string id1 = e.id;
00336                 std::string id2 = (*p).id;
00337                 if (id1 < id2) {
00338                     std::swap(id1, id2);
00339                 }
00340                 std::string nid = id1 + "." + id2;
00341                 if (l.linkType == OPENDRIVE_LT_PREDECESSOR) {
00342                     addE2EConnectionsSecure(nb.getEdgeCont(), nb.getNodeCont().retrieve(nid), *p, e, connections);
00343                 } else {
00344                     addE2EConnectionsSecure(nb.getEdgeCont(), nb.getNodeCont().retrieve(nid), e, *p, connections);
00345                 }
00346             }
00347         }
00348     }
00349 
00350     // build inner-edge connections
00351     for (std::vector<OpenDriveEdge>::iterator i = innerEdges.begin(); i != innerEdges.end(); ++i) {
00352         OpenDriveEdge& e = *i;
00353         std::string pred, succ;
00354         ContactPoint predC, succC;
00355         for (std::vector<OpenDriveLink>::iterator j = e.links.begin(); j != e.links.end(); ++j) {
00356             OpenDriveLink& l = *j;
00357             if (l.elementType != OPENDRIVE_ET_ROAD) {
00358                 // we are not interested in connections to nodes
00359                 std::cout << "unsupported" << std::endl;
00360                 continue;
00361             }
00362             if (edge2junction.find(l.elementID) != edge2junction.end()) {
00363                 // not supported
00364                 std::cout << "unsupported" << std::endl;
00365                 continue;
00366             }
00367             if (l.linkType == OPENDRIVE_LT_SUCCESSOR) {
00368                 if (succ != "") {
00369                     std::cout << "double succ" << std::endl;
00370                 }
00371                 succ = l.elementID;
00372                 succC = l.contactPoint;
00373             } else {
00374                 if (pred != "") {
00375                     std::cout << "double pred" << std::endl;
00376                 }
00377                 pred = l.elementID;
00378                 predC = l.contactPoint;
00379             }
00380         }
00381 
00382         if (e.getMaxLaneNumber(OPENDRIVE_TAG_LEFT) != 0 && e.getMaxLaneNumber(OPENDRIVE_TAG_RIGHT) != 0) {
00383             std::cout << "Both dirs given!" << std::endl;
00384         }
00385 
00386         bool isReversed = false;
00387         if (e.getMaxLaneNumber(OPENDRIVE_TAG_LEFT) != 0) {
00388             //            std::swap(pred, succ);
00389             //std::swap(predC, succC);
00390             isReversed = true;
00391         }
00392 
00393         if (succ == "" || pred == "") {
00394             std::cout << "Missing edge." << std::endl;
00395             continue; // yes, occurs
00396         }
00397         // !!!why edge2junction; e already has the junction...
00398         NBNode* n = nb.getNodeCont().retrieve(edge2junction[e.id]);
00399         std::vector<OpenDriveEdge>::iterator predEdge = std::find_if(outerEdges.begin(), outerEdges.end(), edge_by_id_finder(pred));
00400         if (predEdge == outerEdges.end()) {
00401             throw ProcessError("Could not find connection edge.");
00402         }
00403         std::vector<OpenDriveEdge>::iterator succEdge = std::find_if(outerEdges.begin(), outerEdges.end(), edge_by_id_finder(succ));
00404         if (succEdge == outerEdges.end()) {
00405             throw ProcessError("Could not find connection edge.");
00406         }
00407         NBEdge* fromEdge, *toEdge;
00408         if (!isReversed) {
00409             fromEdge = predC == OPENDRIVE_CP_END ? nb.getEdgeCont().retrieve("-" + pred) : nb.getEdgeCont().retrieve(pred);
00410             toEdge = succC == OPENDRIVE_CP_START ? nb.getEdgeCont().retrieve("-" + succ) : nb.getEdgeCont().retrieve(succ);
00411         } else {
00412             fromEdge = predC != OPENDRIVE_CP_END ? nb.getEdgeCont().retrieve("-" + pred) : nb.getEdgeCont().retrieve(pred);
00413             toEdge = succC != OPENDRIVE_CP_START ? nb.getEdgeCont().retrieve("-" + succ) : nb.getEdgeCont().retrieve(succ);
00414         }
00415         /*
00416         Connection c(
00417             n->hasIncoming(nb.getEdgeCont().retrieve("-" + pred)) ? nb.getEdgeCont().retrieve("-" + pred) : nb.getEdgeCont().retrieve(pred),
00418             e.id,
00419             n->hasOutgoing(nb.getEdgeCont().retrieve("-" + succ)) ? nb.getEdgeCont().retrieve("-" + succ) : nb.getEdgeCont().retrieve(succ));
00420             */
00421         Connection c(fromEdge, e.id, toEdge);
00422         if (c.from == 0 || c.to == 0 || c.from == c.to) {
00423             throw ProcessError("Something's false");
00424         }
00425         setLaneConnections(c,
00426                            *predEdge, c.from->getID()[0] != '-', c.from->getID()[0] == '-' ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT,
00427                            e, isReversed, !isReversed ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT,
00428                            *succEdge, c.to->getID()[0] != '-', c.to->getID()[0] == '-' ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT);
00429         connections.push_back(c);
00430     }
00431     for (std::vector<Connection>::const_iterator i = connections.begin(); i != connections.end(); ++i) {
00432         if ((*i).from == 0 || (*i).to == 0) {
00433             std::cout << "Nope." << std::endl;
00434             continue;
00435         }
00436         (*i).from->addEdge2EdgeConnection((*i).to);
00437         std::map<int, int> fromMap = fromLaneMap[(*i).from];
00438         std::map<int, int> toMap = fromLaneMap[(*i).to];
00439         for (std::vector<std::pair<int, int> >::const_iterator j = (*i).lanes.begin(); j != (*i).lanes.end(); ++j) {
00440             int fromLane = fromMap[(*j).first];
00441             int toLane = toMap[(*j).second];
00442             if (static_cast<unsigned int>(fromLane) >= (*i).from->getNumLanes() || fromLane < 0) {
00443                 std::cout << "False " << std::endl;
00444             }
00445             if (static_cast<unsigned int>(toLane) >= (*i).to->getNumLanes() || toLane < 0) {
00446                 std::cout << "False " << std::endl;
00447             }
00448 
00449             (*i).from->addLane2LaneConnection(fromLane, (*i).to, toLane, NBEdge::L2L_VALIDATED, true);
00450         }
00451     }
00452 }
00453 
00454 
00455 void
00456 NIImporter_OpenDrive::addViaConnectionSecure(const NBEdgeCont& ec,
00457         const NBNode* const node, const OpenDriveEdge& e,
00458         LinkType lt, const std::string& via,
00459         std::vector<NIImporter_OpenDrive::Connection> &connections) {
00460     NBEdge* from = 0;
00461     NBEdge* to = 0;
00462     if (node == e.to) {
00463         // the connection is at the end of the "positive" direction
00464         if (lt == OPENDRIVE_LT_PREDECESSOR) {
00465             // via -> edge
00466             to = ec.retrieve(e.id);
00467         } else {
00468             // -edge -> via
00469             //  "ambigous?"
00470             from = ec.retrieve("-" + e.id);
00471         }
00472     } else {
00473         // the connection is at the begin of the "positive" direction
00474         if (lt == OPENDRIVE_LT_PREDECESSOR) {
00475             // via -> -edge
00476             to = ec.retrieve("-" + e.id);
00477         } else {
00478             // edge -> via
00479             //  "ambigous?"
00480             from = ec.retrieve(e.id);
00481         }
00482     }
00483     if (from == 0 && to == 0) {
00484         throw ProcessError("Missing edge");
00485     }
00486     Connection c(from, via, to);
00487     connections.push_back(c);
00488 }
00489 
00490 
00491 void
00492 NIImporter_OpenDrive::addE2EConnectionsSecure(const NBEdgeCont& ec, const NBNode* const node,
00493         const NIImporter_OpenDrive::OpenDriveEdge& from, const NIImporter_OpenDrive::OpenDriveEdge& to,
00494         std::vector<NIImporter_OpenDrive::Connection> &connections) {
00495     // positive direction (from is incoming, to is outgoing)
00496     NBEdge* fromEdge = ec.retrieve("-" + from.id);
00497     if (fromEdge == 0 || !node->hasIncoming(fromEdge)) {
00498         fromEdge = ec.retrieve(from.id);
00499     }
00500     NBEdge* toEdge = ec.retrieve("-" + to.id);
00501     if (toEdge == 0 || !node->hasOutgoing(toEdge)) {
00502         toEdge = ec.retrieve(to.id);
00503     }
00504     if (fromEdge != 0 && toEdge != 0) {
00505         Connection c(fromEdge, "", toEdge);
00506         setLaneConnections(c,
00507                            from, c.from->getID()[0] != '-', c.from->getID()[0] == '-' ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT,
00508                            to, c.to->getID()[0] != '-', c.to->getID()[0] == '-' ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT);
00509         connections.push_back(c);
00510     }
00511     // negative direction (to is incoming, from is outgoing)
00512     fromEdge = ec.retrieve("-" + from.id);
00513     if (fromEdge == 0 || !node->hasOutgoing(fromEdge)) {
00514         fromEdge = ec.retrieve(from.id);
00515     }
00516     toEdge = ec.retrieve("-" + to.id);
00517     if (toEdge == 0 || !node->hasIncoming(toEdge)) {
00518         toEdge = ec.retrieve(to.id);
00519     }
00520     if (fromEdge != 0 && toEdge != 0) {
00521         Connection c(toEdge, "", fromEdge);
00522         setLaneConnections(c,
00523                            to, c.to->getID()[0] != '-', c.to->getID()[0] == '-' ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT,
00524                            from, c.from->getID()[0] != '-', c.from->getID()[0] == '-' ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT);
00525         connections.push_back(c);
00526     }
00527 }
00528 
00529 
00530 void
00531 NIImporter_OpenDrive::setLaneConnections(NIImporter_OpenDrive::Connection& c,
00532         const OpenDriveEdge& from, bool fromAtBegin, OpenDriveXMLTag fromLaneDir,
00533         const OpenDriveEdge& to, bool toAtEnd, OpenDriveXMLTag toLaneDir) {
00534     const OpenDriveLaneSection& fromLS = fromAtBegin ? from.laneSections[0] : from.laneSections.back();
00535     const std::vector<OpenDriveLane> &fromLanes = fromLS.lanesByDir.find(fromLaneDir)->second;
00536     const OpenDriveLaneSection& toLS = toAtEnd ? to.laneSections.back() : to.laneSections[0];
00537     const std::vector<OpenDriveLane> &toLanes = toLS.lanesByDir.find(toLaneDir)->second;
00538     // in the following, we are probably using the same information twice, stored once
00539     //  in the from-edge's successor field and in the to-edge's precessor field.
00540     // though, we have no proof or information that this is always redundant
00541     for (std::vector<OpenDriveLane>::const_iterator i = fromLanes.begin(); i != fromLanes.end(); ++i) {
00542         if ((*i).type != "driving") {
00543             continue;
00544         }
00545         if (!fromAtBegin && (*i).successor != UNSET_CONNECTION) {
00546             c.lanes.push_back(std::make_pair((*i).id, (*i).successor));
00547         }
00548         if (fromAtBegin && (*i).predecessor != UNSET_CONNECTION) {
00549             c.lanes.push_back(std::make_pair((*i).id, (*i).predecessor));
00550         }
00551     }
00552     for (std::vector<OpenDriveLane>::const_iterator i = toLanes.begin(); i != toLanes.end(); ++i) {
00553         if ((*i).type != "driving") {
00554             continue;
00555         }
00556         if (!toAtEnd && (*i).predecessor != UNSET_CONNECTION) {
00557             c.lanes.push_back(std::make_pair((*i).predecessor, (*i).id));
00558         }
00559         if (toAtEnd && (*i).successor != UNSET_CONNECTION) {
00560             c.lanes.push_back(std::make_pair((*i).successor, (*i).id));
00561         }
00562     }
00563 }
00564 
00565 
00566 void
00567 NIImporter_OpenDrive::setLaneConnections(NIImporter_OpenDrive::Connection& c,
00568         const OpenDriveEdge& from, bool fromAtBegin, OpenDriveXMLTag fromLaneDir,
00569         const OpenDriveEdge& via, bool viaIsReversed, OpenDriveXMLTag viaLaneDir,
00570         const OpenDriveEdge& to, bool toAtEnd, OpenDriveXMLTag toLaneDir) {
00571     Connection from2via(0, "", 0);
00572     setLaneConnections(from2via, from, fromAtBegin, fromLaneDir, via, viaIsReversed, viaLaneDir);
00573     Connection via2to(0, "", 0);
00574     setLaneConnections(via2to, via, viaIsReversed, viaLaneDir, to, toAtEnd, toLaneDir);
00575     for (std::vector<std::pair<int, int> >::const_iterator i = from2via.lanes.begin(); i != from2via.lanes.end(); ++i) {
00576         int fromLane = (*i).first;
00577         int viaLane = (*i).second;
00578         for (std::vector<std::pair<int, int> >::const_iterator j = via2to.lanes.begin(); j != via2to.lanes.end(); ++j) {
00579             if ((*j).first == viaLane) {
00580                 c.lanes.push_back(std::make_pair(fromLane, (*j).second));
00581                 break;
00582             }
00583         }
00584     }
00585 }
00586 
00587 
00588 NBNode*
00589 NIImporter_OpenDrive::getOrBuildNode(const std::string& id, Position& pos,
00590                                      NBNodeCont& nc) {
00591     if (nc.retrieve(id) == 0) {
00592         // not yet built; build now
00593         if (!nc.insert(id, pos)) {
00594             // !!! clean up
00595             throw ProcessError("Could not add node '" + id + "'.");
00596         }
00597     }
00598     return nc.retrieve(id);
00599 }
00600 
00601 
00602 void
00603 NIImporter_OpenDrive::setNodeSecure(NBNodeCont& nc, OpenDriveEdge& e,
00604                                     const std::string& nodeID, NIImporter_OpenDrive::LinkType lt) {
00605     NBNode* n = nc.retrieve(nodeID);
00606     if (n == 0) {
00607         throw ProcessError("Could not find node '" + nodeID + "'.");
00608     }
00609     if (lt == OPENDRIVE_LT_SUCCESSOR) {
00610         if (e.to != 0 && e.to != n) {
00611             throw ProcessError("Edge '" + e.id + "' has two end nodes.");
00612         }
00613         e.to = n;
00614     } else {
00615         if (e.from != 0 && e.from != n) {
00616             throw ProcessError("Edge '" + e.id + "' has two start nodes.");
00617         }
00618         e.from = n;
00619     }
00620 }
00621 
00622 
00623 
00624 
00625 
00626 NBEdge*
00627 NIImporter_OpenDrive::getOutgoingDirectionalEdge(const NBEdgeCont& ec,
00628         const NBNodeCont& nc,
00629         const std::string& edgeID,
00630         const std::string& nodeID) {
00631     NBNode* node = nc.retrieve(nodeID);
00632     NBEdge* e = ec.retrieve(edgeID);
00633     if (e != 0 && node->hasOutgoing(e)) {
00634         return e;
00635     }
00636     e = ec.retrieve("-" + edgeID);
00637     if (e != 0 && node->hasOutgoing(e)) {
00638         return e;
00639     }
00640     return 0;
00641 }
00642 
00643 
00644 NBEdge*
00645 NIImporter_OpenDrive::getIncomingDirectionalEdge(const NBEdgeCont& ec,
00646         const NBNodeCont& nc,
00647         const std::string& edgeID,
00648         const std::string& nodeID) {
00649     NBNode* node = nc.retrieve(nodeID);
00650     NBEdge* e = ec.retrieve(edgeID);
00651     if (e != 0 && node->hasIncoming(e)) {
00652         return e;
00653     }
00654     e = ec.retrieve("-" + edgeID);
00655     if (e != 0 && node->hasIncoming(e)) {
00656         return e;
00657     }
00658     return 0;
00659 }
00660 
00661 
00662 void
00663 NIImporter_OpenDrive::computeShapes(std::vector<OpenDriveEdge> &edges) {
00664     for (std::vector<OpenDriveEdge>::iterator i = edges.begin(); i != edges.end(); ++i) {
00665         OpenDriveEdge& e = *i;
00666         for (std::vector<OpenDriveGeometry>::iterator j = e.geometries.begin(); j != e.geometries.end(); ++j) {
00667             OpenDriveGeometry& g = *j;
00668             std::vector<Position> geom;
00669             switch (g.type) {
00670                 case OPENDRIVE_GT_UNKNOWN:
00671                     break;
00672                 case OPENDRIVE_GT_LINE:
00673                     geom = geomFromLine(e, g);
00674                     break;
00675                 case OPENDRIVE_GT_SPIRAL:
00676                     geom = geomFromSpiral(e, g);
00677                     break;
00678                 case OPENDRIVE_GT_ARC:
00679                     geom = geomFromArc(e, g);
00680                     break;
00681                 case OPENDRIVE_GT_POLY3:
00682                     geom = geomFromPoly(e, g);
00683                     break;
00684                 default:
00685                     break;
00686             }
00687             for (std::vector<Position>::iterator k = geom.begin(); k != geom.end(); ++k) {
00688                 e.geom.push_back_noDoublePos(*k);
00689             }
00690         }
00691         for (unsigned int j = 0; j < e.geom.size(); ++j) {
00692             if (!NILoader::transformCoordinates(e.geom[j])) {
00693                 WRITE_ERROR("Unable to project coordinates for.");
00694             }
00695         }
00696     }
00697 }
00698 
00699 std::vector<Position>
00700 NIImporter_OpenDrive::geomFromLine(const OpenDriveEdge& e, const OpenDriveGeometry& g) {
00701     UNUSED_PARAMETER(e);
00702     std::vector<Position> ret;
00703     ret.push_back(Position(g.x, g.y));
00704     ret.push_back(calculateStraightEndPoint(g.hdg, g.length, Position(g.x, g.y)));
00705     return ret;
00706 }
00707 
00708 
00709 std::vector<Position>
00710 NIImporter_OpenDrive::geomFromSpiral(const OpenDriveEdge& e, const OpenDriveGeometry& g) {
00711     UNUSED_PARAMETER(e);
00712     std::vector<Position> ret;
00713     SUMOReal curveStart = g.params[0];
00714     SUMOReal curveEnd = g.params[1];
00715     Point2D<double> end;
00716     EulerSpiral s(Point2D<double>(g.x, g.y), g.hdg, curveStart, (curveEnd - curveStart) / g.length, g.length);
00717     std::vector<Point2D<double> > into;
00718     s.computeSpiral(into, 1.);
00719     for (std::vector<Point2D<double> >::iterator i = into.begin(); i != into.end(); ++i) {
00720         ret.push_back(Position((*i).getX(), (*i).getY()));
00721     }
00722     return ret;
00723 }
00724 
00725 
00726 std::vector<Position>
00727 NIImporter_OpenDrive::geomFromArc(const OpenDriveEdge& e, const OpenDriveGeometry& g) {
00728     UNUSED_PARAMETER(e);
00729     std::vector<Position> ret;
00730     SUMOReal dist = 0.0;
00731     SUMOReal centerX = g.x;
00732     SUMOReal centerY = g.y;
00733     // left: positive value
00734     SUMOReal curvature = g.params[0];
00735     SUMOReal radius = 1. / curvature;
00736     // center point
00737     calculateCurveCenter(&centerX, &centerY, radius, g.hdg);
00738     SUMOReal endX = g.x;
00739     SUMOReal endY = g.y;
00740     SUMOReal startX = g.x;
00741     SUMOReal startY = g.y;
00742     SUMOReal hdgS = g.hdg;
00743     SUMOReal hdgE;
00744     SUMOReal geo_posS = g.s;
00745     SUMOReal geo_posE = g.s;
00746     bool end = false;
00747     do {
00748         geo_posE += C_LENGTH;
00749         if (geo_posE - g.s > g.length) {
00750             geo_posE = g.s + g.length;
00751         }
00752         if (geo_posE - g.s > g.length) {
00753             geo_posE = g.s + g.length;
00754         }
00755         calcPointOnCurve(&endX, &endY, centerX, centerY, radius, geo_posE - geo_posS);
00756 
00757         dist += (geo_posE - geo_posS);
00758         if (curvature > 0.0) {
00759             hdgE = g.hdg + dist / fabs(radius);
00760         } else {
00761             hdgE = g.hdg - dist / fabs(radius);
00762         }
00763         //
00764         ret.push_back(Position(startX, startY));
00765         //
00766         startX = endX;
00767         startY = endY;
00768         geo_posS = geo_posE;
00769         hdgS = hdgE;
00770 
00771         if (geo_posE  - (g.s + g.length) < 0.001 && geo_posE  - (g.s + g.length) > -0.001) {
00772             end = true;
00773         }
00774     } while (!end);
00775     return ret;
00776 }
00777 
00778 
00779 std::vector<Position>
00780 NIImporter_OpenDrive::geomFromPoly(const OpenDriveEdge& e, const OpenDriveGeometry& g) {
00781     UNUSED_PARAMETER(g);
00782     UNUSED_PARAMETER(e);
00783     std::vector<Position> ret;
00784     return ret;
00785 }
00786 
00787 
00788 Position
00789 NIImporter_OpenDrive::calculateStraightEndPoint(double hdg, double length, const Position& start) {
00790     double normx = 1.0f;
00791     double normy = 0.0f;
00792     double x2 = normx * cos(hdg) - normy * sin(hdg);
00793     double y2 = normx * sin(hdg) + normy * cos(hdg);
00794     normx = x2 * length;
00795     normy = y2 * length;
00796     return Position(start.x() + normx, start.y() + normy);
00797 }
00798 
00799 
00800 void
00801 NIImporter_OpenDrive::calculateCurveCenter(SUMOReal* ad_x, SUMOReal* ad_y, SUMOReal ad_radius, SUMOReal ad_hdg) {
00802     SUMOReal normX = 1.0;
00803     SUMOReal normY = 0.0;
00804     SUMOReal tmpX;
00805     SUMOReal turn;
00806     if (ad_radius > 0) {
00807         turn = -1.0;
00808     } else {
00809         turn = 1.0;
00810     }
00811 
00812     tmpX = normX;
00813     normX = normX * cos(ad_hdg) + normY * sin(ad_hdg);
00814     normY = tmpX * sin(ad_hdg) + normY * cos(ad_hdg);
00815 
00816     tmpX = normX;
00817     normX = normX * cos(90 * PI / 180) + turn * normY * sin(90 * PI / 180);
00818     normY = -1 * turn * tmpX * sin(90 * PI / 180) + normY * cos(90 * PI / 180);
00819 
00820     normX = fabs(ad_radius) * normX;
00821     normY = fabs(ad_radius) * normY;
00822 
00823     *ad_x += normX;
00824     *ad_y += normY;
00825 }
00826 
00827 
00828 void
00829 NIImporter_OpenDrive::calcPointOnCurve(SUMOReal* ad_x, SUMOReal* ad_y, SUMOReal ad_centerX, SUMOReal ad_centerY,
00830                                        SUMOReal ad_r, SUMOReal ad_length) {
00831     double rotAngle = ad_length / fabs(ad_r);
00832     double vx = *ad_x - ad_centerX;
00833     double vy = *ad_y - ad_centerY;
00834     double tmpx;
00835 
00836     double turn;
00837     if (ad_r > 0) {
00838         turn = -1;    //left
00839     } else {
00840         turn = 1;    //right
00841     }
00842     tmpx = vx;
00843     vx = vx * cos(rotAngle) + turn * vy * sin(rotAngle);
00844     vy = -1 * turn * tmpx * sin(rotAngle) + vy * cos(rotAngle);
00845     *ad_x = vx + ad_centerX;
00846     *ad_y = vy + ad_centerY;
00847 }
00848 
00849 // ---------------------------------------------------------------------------
00850 // loader methods
00851 // ---------------------------------------------------------------------------
00852 NIImporter_OpenDrive::NIImporter_OpenDrive(
00853     std::vector<OpenDriveEdge> &innerEdges,
00854     std::vector<OpenDriveEdge> &outerEdges)
00855     : GenericSAXHandler(openDriveTags, OPENDRIVE_TAG_NOTHING, openDriveAttrs, OPENDRIVE_ATTR_NOTHING, "opendrive"),
00856       myCurrentEdge("", "", -1), myInnerEdges(innerEdges), myOuterEdges(outerEdges) {
00857 }
00858 
00859 
00860 NIImporter_OpenDrive::~NIImporter_OpenDrive() {
00861 }
00862 
00863 
00864 void
00865 NIImporter_OpenDrive::myStartElement(int element,
00866                                      const SUMOSAXAttributes& attrs) {
00867     bool ok = true;
00868     switch (element) {
00869         case OPENDRIVE_TAG_HEADER: {
00870             int majorVersion = attrs.getIntReporting(OPENDRIVE_ATTR_REVMAJOR, 0, ok);
00871             int minorVersion = attrs.getIntReporting(OPENDRIVE_ATTR_REVMINOR, 0, ok);
00872             if (majorVersion != 1 || minorVersion != 2) {
00873                 WRITE_WARNING("Given openDrive file '" + getFileName() + "' uses version " + toString(majorVersion) + "." + toString(minorVersion) + ";\n Version 1.2 is supported.");
00874             }
00875         }
00876         break;
00877         case OPENDRIVE_TAG_ROAD: {
00878             std::string id = attrs.getStringReporting(OPENDRIVE_ATTR_ID, 0, ok);
00879             std::string junction = attrs.getStringReporting(OPENDRIVE_ATTR_JUNCTION, id.c_str(), ok);
00880             SUMOReal length = attrs.getSUMORealReporting(OPENDRIVE_ATTR_LENGTH, id.c_str(), ok);
00881             myCurrentEdge = OpenDriveEdge(id, junction, length);
00882         }
00883         break;
00884         case OPENDRIVE_TAG_PREDECESSOR: {
00885             if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_ROAD) {
00886                 std::string elementType = attrs.getStringReporting(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok);
00887                 std::string elementID = attrs.getStringReporting(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok);
00888                 std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT)
00889                                            ? attrs.getStringReporting(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentEdge.id.c_str(), ok)
00890                                            : "end";
00891                 addLink(OPENDRIVE_LT_PREDECESSOR, elementType, elementID, contactPoint);
00892             }
00893             if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_LANE) {
00894                 int no = attrs.getIntReporting(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
00895                 OpenDriveLane& l = myCurrentEdge.laneSections[myCurrentEdge.laneSections.size() - 1].lanesByDir[myCurrentLaneDirection].back();
00896                 l.predecessor = no;
00897             }
00898         }
00899         break;
00900         case OPENDRIVE_TAG_SUCCESSOR: {
00901             if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_ROAD) {
00902                 std::string elementType = attrs.getStringReporting(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok);
00903                 std::string elementID = attrs.getStringReporting(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok);
00904                 std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT)
00905                                            ? attrs.getStringReporting(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentEdge.id.c_str(), ok)
00906                                            : "start";
00907                 addLink(OPENDRIVE_LT_SUCCESSOR, elementType, elementID, contactPoint);
00908             }
00909             if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_LANE) {
00910                 int no = attrs.getIntReporting(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
00911                 OpenDriveLane& l = myCurrentEdge.laneSections[myCurrentEdge.laneSections.size() - 1].lanesByDir[myCurrentLaneDirection].back();
00912                 l.successor = no;
00913             }
00914         }
00915         break;
00916         case OPENDRIVE_TAG_GEOMETRY: {
00917             SUMOReal length = attrs.getSUMORealReporting(OPENDRIVE_ATTR_LENGTH, myCurrentEdge.id.c_str(), ok);
00918             SUMOReal s = attrs.getSUMORealReporting(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
00919             SUMOReal x = attrs.getSUMORealReporting(OPENDRIVE_ATTR_X, myCurrentEdge.id.c_str(), ok);
00920             SUMOReal y = attrs.getSUMORealReporting(OPENDRIVE_ATTR_Y, myCurrentEdge.id.c_str(), ok);
00921             SUMOReal hdg = attrs.getSUMORealReporting(OPENDRIVE_ATTR_HDG, myCurrentEdge.id.c_str(), ok);
00922             myCurrentEdge.geometries.push_back(OpenDriveGeometry(length, s, x, y, hdg));
00923         }
00924         break;
00925         case OPENDRIVE_TAG_LINE: {
00926             std::vector<SUMOReal> vals;
00927             addGeometryShape(OPENDRIVE_GT_LINE, vals);
00928         }
00929         break;
00930         case OPENDRIVE_TAG_SPIRAL: {
00931             std::vector<SUMOReal> vals;
00932             vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_CURVSTART, myCurrentEdge.id.c_str(), ok));
00933             vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_CURVEND, myCurrentEdge.id.c_str(), ok));
00934             addGeometryShape(OPENDRIVE_GT_SPIRAL, vals);
00935         }
00936         break;
00937         case OPENDRIVE_TAG_ARC: {
00938             std::vector<SUMOReal> vals;
00939             vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_CURVATURE, myCurrentEdge.id.c_str(), ok));
00940             addGeometryShape(OPENDRIVE_GT_ARC, vals);
00941         }
00942         break;
00943         case OPENDRIVE_TAG_POLY3: {
00944             std::vector<SUMOReal> vals;
00945             vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok));
00946             vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_B, myCurrentEdge.id.c_str(), ok));
00947             vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_C, myCurrentEdge.id.c_str(), ok));
00948             vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_D, myCurrentEdge.id.c_str(), ok));
00949             addGeometryShape(OPENDRIVE_GT_POLY3, vals);
00950         }
00951         break;
00952         case OPENDRIVE_TAG_LANESECTION: {
00953             SUMOReal s = attrs.getSUMORealReporting(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
00954             myCurrentEdge.laneSections.push_back(OpenDriveLaneSection(s));
00955         }
00956         break;
00957         case OPENDRIVE_TAG_LEFT:
00958             myCurrentLaneDirection = OPENDRIVE_TAG_LEFT;
00959             break;
00960         case OPENDRIVE_TAG_CENTER:
00961             myCurrentLaneDirection = OPENDRIVE_TAG_CENTER;
00962             break;
00963         case OPENDRIVE_TAG_RIGHT:
00964             myCurrentLaneDirection = OPENDRIVE_TAG_RIGHT;
00965             break;
00966         case OPENDRIVE_TAG_LANE: {
00967             std::string type = attrs.getStringReporting(OPENDRIVE_ATTR_TYPE, myCurrentEdge.id.c_str(), ok);
00968             int id = attrs.getIntReporting(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
00969             std::string level = attrs.hasAttribute(OPENDRIVE_ATTR_LEVEL)
00970                                 ? attrs.getStringReporting(OPENDRIVE_ATTR_LEVEL, myCurrentEdge.id.c_str(), ok)
00971                                 : "";
00972             OpenDriveLaneSection& ls = myCurrentEdge.laneSections[myCurrentEdge.laneSections.size() - 1];
00973             ls.lanesByDir[myCurrentLaneDirection].push_back(OpenDriveLane(id, level, type));
00974         }
00975         break;
00976         default:
00977             break;
00978     }
00979     myElementStack.push_back(element);
00980 }
00981 
00982 
00983 void
00984 NIImporter_OpenDrive::myCharacters(int element,
00985                                    const std::string& chars) {
00986     UNUSED_PARAMETER(element);
00987     UNUSED_PARAMETER(chars);
00988 }
00989 
00990 
00991 
00992 void
00993 NIImporter_OpenDrive::myEndElement(int element) {
00994     myElementStack.pop_back();
00995     switch (element) {
00996         case OPENDRIVE_TAG_ROAD:
00997             if (myCurrentEdge.junction == "" || myCurrentEdge.junction == "-1") {
00998                 myOuterEdges.push_back(myCurrentEdge);
00999             } else {
01000                 myInnerEdges.push_back(myCurrentEdge);
01001             }
01002             break;
01003         default:
01004             break;
01005     }
01006 }
01007 
01008 
01009 
01010 void
01011 NIImporter_OpenDrive::addLink(LinkType lt, const std::string& elementType,
01012                               const std::string& elementID,
01013                               const std::string& contactPoint) {
01014     OpenDriveLink l(lt, elementID);
01015     // elementType
01016     if (elementType == "road") {
01017         l.elementType = OPENDRIVE_ET_ROAD;
01018     } else if (elementType == "junction") {
01019         l.elementType = OPENDRIVE_ET_JUNCTION;
01020     }
01021     // contact point
01022     if (contactPoint == "start") {
01023         l.contactPoint = OPENDRIVE_CP_START;
01024     } else if (contactPoint == "end") {
01025         l.contactPoint = OPENDRIVE_CP_END;
01026     }
01027     // add
01028     myCurrentEdge.links.push_back(l);
01029 }
01030 
01031 
01032 void
01033 NIImporter_OpenDrive::addGeometryShape(GeometryType type, const std::vector<SUMOReal> &vals) {
01034     // checks
01035     if (myCurrentEdge.geometries.size() == 0) {
01036         throw ProcessError("Mismatching paranthesis in geometry definition for road '" + myCurrentEdge.id + "'");
01037     }
01038     OpenDriveGeometry& last = myCurrentEdge.geometries[myCurrentEdge.geometries.size() - 1];
01039     if (last.type != OPENDRIVE_GT_UNKNOWN) {
01040         throw ProcessError("Double geometry information for road '" + myCurrentEdge.id + "'");
01041     }
01042     // set
01043     last.type = type;
01044     last.params = vals;
01045 }
01046 
01047 
01048 /****************************************************************************/
01049 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines