SUMO - Simulation of Urban MObility

NIImporter_OpenDrive.cpp

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