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

Generated on Wed May 5 00:06:34 2010 for Sumo - Simulation of Urban MObility by  doxygen 1.5.6