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