예제 #1
0
void
GLHelper::drawShapeDottedContour(const int type, const PositionVector& shape, const double width) {
    glPushMatrix();
    // build contour using shapes of first and last lane shapes
    PositionVector contourFront = shape;
    // only add an contourback if width is greather of 0
    if (width > 0) {
        PositionVector contourback = contourFront;
        contourFront.move2side(width);
        contourback.move2side(-width);
        contourback = contourback.reverse();
        for (auto i : contourback) {
            contourFront.push_back(i);
        }
        contourFront.push_back(shape.front());
    }
    // resample shape
    PositionVector resampledShape = contourFront.resample(1);
    // draw contour over shape
    glTranslated(0, 0, type + 2);
    // set custom line width
    glLineWidth(3);
    // draw contour
    drawLine(resampledShape, getDottedcontourColors((int)resampledShape.size()));
    //restore line width
    glLineWidth(1);
    glPopMatrix();
}
예제 #2
0
void
GLHelper::drawShapeDottedContour(const int type, const PositionVector& frontShape, const double offsetFrontShape, const PositionVector& backShape, const double offsetBackShape) {
    glPushMatrix();
    // build contour using shapes of first and last lane shapes
    PositionVector contourFront = frontShape;
    PositionVector contourback = backShape;
    contourFront.move2side(offsetFrontShape);
    contourback.move2side(offsetBackShape);
    contourback = contourback.reverse();
    for (auto i : contourback) {
        contourFront.push_back(i);
    }
    contourFront.push_back(frontShape.front());
    // resample shape
    PositionVector resampledShape = contourFront.resample(1);
    // draw contour over shape
    glTranslated(0, 0, type + 2);
    // set custom line width
    glLineWidth(3);
    // draw contour
    GLHelper::drawLine(resampledShape, getDottedcontourColors((int)resampledShape.size()));
    //restore line width
    glLineWidth(1);
    glPopMatrix();
}
예제 #3
0
파일: GNENet.cpp 프로젝트: cbrafter/sumo
GNEEdge*
GNENet::addReversedEdge(GNEEdge* edge, GNEUndoList* undoList) {
    undoList->p_begin("add reversed edge");
    GNEEdge* reversed = 0;
    if (edge->getNBEdge()->getLaneSpreadFunction() == LANESPREAD_RIGHT) {
        GNEEdge* reversed = createEdge(edge->getDest(), edge->getSource(), edge, undoList, "-" + edge->getID(), false, true);
        assert(reversed != 0);
        reversed->setAttribute(SUMO_ATTR_SHAPE, toString(edge->getNBEdge()->getInnerGeometry().reverse()), undoList);
    } else {
        // if the edge is centered it should probably connect somewhere else
        // make it easy to move and reconnect it
        PositionVector orig = edge->getNBEdge()->getGeometry();
        PositionVector origInner = edge->getNBEdge()->getInnerGeometry();
        const SUMOReal tentativeShift = edge->getNBEdge()->getTotalWidth() + 2;
        orig.move2side(-tentativeShift);
        origInner.move2side(-tentativeShift);
        GNEJunction* src = createJunction(orig.back(), undoList);
        GNEJunction* dest = createJunction(orig.front(), undoList);
        GNEEdge* reversed = createEdge(src, dest, edge, undoList, "-" + edge->getID(), false, true);
        assert(reversed != 0);
        reversed->setAttribute(SUMO_ATTR_SHAPE, toString(origInner.reverse()), undoList);
        // select the new edge and its nodes
        std::set<GUIGlID> toSelect;
        toSelect.insert(reversed->getGlID());
        toSelect.insert(src->getGlID());
        toSelect.insert(dest->getGlID());
        undoList->add(new GNEChange_Selection(toSelect, gSelected.getSelected(), true), true);
    }
    undoList->p_end();
    return reversed;
}
예제 #4
0
void
GNECrossing::drawTLSLinkNo(const GUIVisualizationSettings& s) const {
    auto crossing = myParentJunction->getNBNode()->getCrossing(myCrossingEdges);
    glPushMatrix();
    glTranslated(0, 0, GLO_JUNCTION + 0.5);
    PositionVector shape = crossing->shape;
    shape.extrapolate(0.5); // draw on top of the walking area
    int linkNo = crossing->tlLinkIndex;
    int linkNo2 = crossing->tlLinkIndex2 > 0 ? crossing->tlLinkIndex2 : linkNo;
    GLHelper::drawTextAtEnd(toString(linkNo2), shape, 0, s.drawLinkTLIndex.size, s.drawLinkTLIndex.color);
    GLHelper::drawTextAtEnd(toString(linkNo), shape.reverse(), 0, s.drawLinkTLIndex.size, s.drawLinkTLIndex.color);
    glPopMatrix();
}
void
NIImporter_VISUM::parse_AreaSubPartElement() {
    SUMOLong id = TplConvert::_2long(myLineParser.get("TFLAECHEID").c_str());
    SUMOLong edgeid = TplConvert::_2long(myLineParser.get("KANTEID").c_str());
    if (myEdges.find(edgeid) == myEdges.end()) {
        WRITE_ERROR("Unknown edge in TEILFLAECHENELEMENT");
        return;
    }
    std::string dir = myLineParser.get("RICHTUNG");
// get index (unused)
//     std::string indexS = NBHelpers::normalIDRepresentation(myLineParser.get("INDEX"));
//     int index = -1;
//     try {
//         index = TplConvert::_2int(indexS.c_str()) - 1;
//     } catch (NumberFormatException&) {
//         WRITE_ERROR("An index for a TEILFLAECHENELEMENT is not numeric (id='" + toString(id) + "').");
//         return;
//     }
    PositionVector shape;
    shape.push_back(myPoints[myEdges[edgeid].first]);
    shape.push_back(myPoints[myEdges[edgeid].second]);
    if (dir.length() > 0 && dir[0] == '1') {
        shape = shape.reverse();
    }
    if (mySubPartsAreas.find(id) == mySubPartsAreas.end()) {
        WRITE_ERROR("Unkown are for area part '" + myCurrentID + "'.");
        return;
    }

    const std::vector<SUMOLong>& areas = mySubPartsAreas.find(id)->second;
    for (std::vector<SUMOLong>::const_iterator i = areas.begin(); i != areas.end(); ++i) {
        NBDistrict* d = myShapeDistrictMap[*i];
        if (d == 0) {
            continue;
        }
        if (myDistrictShapes.find(d) == myDistrictShapes.end()) {
            myDistrictShapes[d] = PositionVector();
        }
        if (dir.length() > 0 && dir[0] == '1') {
            myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].second]);
            myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].first]);
        } else {
            myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].first]);
            myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].second]);
        }
    }
}
예제 #6
0
bool
NIImporter_DlrNavteq::EdgesHandler::report(const std::string& result) {
    // parse version number from first comment line and initialize column definitions
    if (result[0] == '#') {
        if (!myColumns.empty()) {
            return true;
        }
        const double version = readVersion(result, myFile);
        if (version > 0) {
            myVersion = version;
            // init columns
            const int NUM_COLUMNS = 25; // @note arrays must match this size!
            const int MC = MISSING_COLUMN;
            if (myVersion < 3) {
                const int columns[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, MC, 12, 13, 14, 15, 16, 17, 18, 19, 20, MC, MC, -21};
                myColumns = std::vector<int>(columns, columns + NUM_COLUMNS);
            } else if (myVersion < 6) {
                const int columns[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, MC, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, -23};
                myColumns = std::vector<int>(columns, columns + NUM_COLUMNS);
            } else {
                const int columns[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
                myColumns = std::vector<int>(columns, columns + NUM_COLUMNS);
            }
        }
        return true;
    }
    if (myColumns.empty()) {
        throw ProcessError("Missing version string in file '" + myFile + "'.");
    }
    // interpret link attributes
    StringTokenizer st(result, StringTokenizer::WHITECHARS);
    const std::string id = getColumn(st, LINK_ID);
    // form of way (for priority and permissions)
    int form_of_way;
    try {
        form_of_way = StringUtils::toInt(getColumn(st, FORM_OF_WAY));
    } catch (NumberFormatException&) {
        throw ProcessError("Non-numerical value for form_of_way of link '" + id + "'.");
    }
    // brunnel type (bridge/tunnel/ferry (for permissions)
    int brunnel_type;
    try {
        brunnel_type = StringUtils::toInt(getColumn(st, BRUNNEL_TYPE));
    } catch (NumberFormatException&) {
        throw ProcessError("Non-numerical value for brunnel_type of link '" + id + "'.");
    }
    // priority based on street_type / frc
    int priority;
    try {
        priority = -StringUtils::toInt(getColumn(st, FUNCTIONAL_ROAD_CLASS));
        // lower priority using form_of_way
        if (form_of_way == 11) {
            priority -= 1; // frontage road, very often with lowered curb
        } else if (form_of_way > 11) {
            priority -= 2; // parking/service access assume lowered curb
        }
    } catch (NumberFormatException&) {
        throw ProcessError("Non-numerical value for street_type of link '" + id + "').");
    }
    // street name
    std::string streetName = getStreetNameFromIDs(
                                 getColumn(st, NAME_ID1_REGIONAL),
                                 getColumn(st, NAME_ID2_LOCAL));
    // try to get the nodes
    const std::string fromID = getColumn(st, NODE_ID_FROM);
    const std::string toID = getColumn(st, NODE_ID_TO);
    NBNode* from = myNodeCont.retrieve(fromID);
    NBNode* to = myNodeCont.retrieve(toID);
    if (from == nullptr) {
        throw ProcessError("The from-node '" + fromID + "' of link '" + id + "' could not be found");
    }
    if (to == nullptr) {
        throw ProcessError("The to-node '" + toID + "' of link '" + id + "' could not be found");
    }
    // speed
    double speed;
    try {
        speed = StringUtils::toInt(getColumn(st, SPEED_RESTRICTION, "-1")) / 3.6;
    } catch (NumberFormatException&) {
        throw ProcessError("Non-numerical value for the SPEED_RESTRICTION of link '" + id + "'.");
    }
    if (speed < 0) {
        // speed category as fallback
        speed = NINavTeqHelper::getSpeed(id, getColumn(st, SPEED_CATEGORY));
    }
    // number of lanes
    int numLanes;
    try {
        // EXTENDED_NUMBER_OF_LANES is prefered but may not be defined
        numLanes = StringUtils::toInt(getColumn(st, EXTENDED_NUMBER_OF_LANES, "-1"));
        if (numLanes == -1) {
            numLanes = NINavTeqHelper::getLaneNumber(id, getColumn(st, NUMBER_OF_LANES), speed);
        }
    } catch (NumberFormatException&) {
        throw ProcessError("Non-numerical value for the number of lanes of link '" + id + "'.");
    }

    const std::string navTeqTypeId = getColumn(st, VEHICLE_TYPE) + "_" + getColumn(st, FORM_OF_WAY);
    // build the edge
    NBEdge* e = nullptr;
    const std::string interID = getColumn(st, BETWEEN_NODE_ID);
    if (interID == "-1") {
        e = new NBEdge(id, from, to, myTypeCont.knows(navTeqTypeId) ? navTeqTypeId : "", speed, numLanes, priority,
                       NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET, streetName);
    } else {
        PositionVector geoms = myGeoms[interID];
        if (getColumn(st, CONNECTION, "0") == "1") {
            geoms = geoms.reverse();
        }
        geoms.insert(geoms.begin(), from->getPosition());
        geoms.push_back(to->getPosition());
        const std::string origID = OptionsCont::getOptions().getBool("output.original-names") ? id : "";
        e = new NBEdge(id, from, to, myTypeCont.knows(navTeqTypeId) ? navTeqTypeId : "", speed, numLanes, priority,
                       NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET, geoms, streetName, origID, LANESPREAD_CENTER);
    }

    // NavTeq imports can be done with a typemap (if supplied), if not, the old defaults are used
    if (myTypeCont.knows(navTeqTypeId)) {
        e->setPermissions(myTypeCont.getPermissions(navTeqTypeId));
    } else {
        // add vehicle type information to the edge
        if (myVersion < 6.0) {
            NINavTeqHelper::addVehicleClasses(*e, getColumn(st, VEHICLE_TYPE));
        } else {
            NINavTeqHelper::addVehicleClassesV6(*e, getColumn(st, VEHICLE_TYPE));
        }
        if (e->getPermissions() == SVCAll) {
            e->setPermissions(myTypeCont.getPermissions(""));
        }
        // permission modifications based on form_of_way
        if (form_of_way == 14) { // pedestrian area (fussgaengerzone)
            // unfortunately, the veh_type string is misleading in this case
            e->disallowVehicleClass(-1, SVC_PASSENGER);
        }
        // permission modifications based on brunnel_type
        if (brunnel_type == 10) { // ferry
            e->setPermissions(SVC_SHIP, -1);
        }
    }

    // insert the edge to the network
    if (!myEdgeCont.insert(e)) {
        delete e;
        throw ProcessError("Could not add edge '" + id + "'.");
    }
    return true;
}
예제 #7
0
void
NIImporter_ArcView::load() {
#ifdef HAVE_GDAL
    PROGRESS_BEGIN_MESSAGE("Loading data from '" + mySHPName + "'");
#if GDAL_VERSION_MAJOR < 2
    OGRRegisterAll();
    OGRDataSource* poDS = OGRSFDriverRegistrar::Open(mySHPName.c_str(), FALSE);
#else
    GDALAllRegister();
    GDALDataset* poDS = (GDALDataset*)GDALOpenEx(mySHPName.c_str(), GDAL_OF_VECTOR | GA_ReadOnly, NULL, NULL, NULL);
#endif
    if (poDS == NULL) {
        WRITE_ERROR("Could not open shape description '" + mySHPName + "'.");
        return;
    }

    // begin file parsing
    OGRLayer*  poLayer = poDS->GetLayer(0);
    poLayer->ResetReading();

    // build coordinate transformation
    OGRSpatialReference* origTransf = poLayer->GetSpatialRef();
    OGRSpatialReference destTransf;
    // use wgs84 as destination
    destTransf.SetWellKnownGeogCS("WGS84");
    OGRCoordinateTransformation* poCT = OGRCreateCoordinateTransformation(origTransf, &destTransf);
    if (poCT == NULL) {
        if (myOptions.isSet("shapefile.guess-projection")) {
            OGRSpatialReference origTransf2;
            origTransf2.SetWellKnownGeogCS("WGS84");
            poCT = OGRCreateCoordinateTransformation(&origTransf2, &destTransf);
        }
        if (poCT == 0) {
            WRITE_WARNING("Could not create geocoordinates converter; check whether proj.4 is installed.");
        }
    }

    OGRFeature* poFeature;
    poLayer->ResetReading();
    while ((poFeature = poLayer->GetNextFeature()) != NULL) {
        // read in edge attributes
        std::string id, name, from_node, to_node;
        if (!getStringEntry(poFeature, "shapefile.street-id", "LINK_ID", true, id)) {
            WRITE_ERROR("Needed field '" + id + "' (from node id) is missing.");
        }
        if (id == "") {
            WRITE_ERROR("Could not obtain edge id.");
            return;
        }

        getStringEntry(poFeature, "shapefile.street-id", "ST_NAME", true, name);
        name = StringUtils::replace(name, "&", "&amp;");

        if (!getStringEntry(poFeature, "shapefile.from-id", "REF_IN_ID", true, from_node)) {
            WRITE_ERROR("Needed field '" + from_node + "' (from node id) is missing.");
        }
        if (!getStringEntry(poFeature, "shapefile.to-id", "NREF_IN_ID", true, to_node)) {
            WRITE_ERROR("Needed field '" + to_node + "' (to node id) is missing.");
        }

        if (from_node == "" || to_node == "") {
            from_node = toString(myRunningNodeID++);
            to_node = toString(myRunningNodeID++);
        }

        std::string type;
        if (myOptions.isSet("shapefile.type-id") && poFeature->GetFieldIndex(myOptions.getString("shapefile.type-id").c_str()) >= 0) {
            type = poFeature->GetFieldAsString(myOptions.getString("shapefile.type-id").c_str());
        } else if (poFeature->GetFieldIndex("ST_TYP_AFT") >= 0) {
            type = poFeature->GetFieldAsString("ST_TYP_AFT");
        }
        SUMOReal width = myTypeCont.getWidth(type);
        SUMOReal speed = getSpeed(*poFeature, id);
        int nolanes = getLaneNo(*poFeature, id, speed);
        int priority = getPriority(*poFeature, id);
        if (nolanes == 0 || speed == 0) {
            if (myOptions.getBool("shapefile.use-defaults-on-failure")) {
                nolanes = myTypeCont.getNumLanes("");
                speed = myTypeCont.getSpeed("");
            } else {
                OGRFeature::DestroyFeature(poFeature);
                WRITE_ERROR("The description seems to be invalid. Please recheck usage of types.");
                return;
            }
        }
        if (mySpeedInKMH) {
            speed = speed / (SUMOReal) 3.6;
        }


        // read in the geometry
        OGRGeometry* poGeometry = poFeature->GetGeometryRef();
        OGRwkbGeometryType gtype = poGeometry->getGeometryType();
        assert(gtype == wkbLineString);
        UNUSED_PARAMETER(gtype); // ony used for assertion
        OGRLineString* cgeom = (OGRLineString*) poGeometry;
        if (poCT != 0) {
            // try transform to wgs84
            cgeom->transform(poCT);
        }

        PositionVector shape;
        for (int j = 0; j < cgeom->getNumPoints(); j++) {
            Position pos((SUMOReal) cgeom->getX(j), (SUMOReal) cgeom->getY(j));
            if (!NBNetBuilder::transformCoordinate(pos)) {
                WRITE_WARNING("Unable to project coordinates for edge '" + id + "'.");
            }
            shape.push_back_noDoublePos(pos);
        }

        // build from-node
        NBNode* from = myNodeCont.retrieve(from_node);
        if (from == 0) {
            Position from_pos = shape[0];
            from = myNodeCont.retrieve(from_pos);
            if (from == 0) {
                from = new NBNode(from_node, from_pos);
                if (!myNodeCont.insert(from)) {
                    WRITE_ERROR("Node '" + from_node + "' could not be added");
                    delete from;
                    continue;
                }
            }
        }
        // build to-node
        NBNode* to = myNodeCont.retrieve(to_node);
        if (to == 0) {
            Position to_pos = shape[-1];
            to = myNodeCont.retrieve(to_pos);
            if (to == 0) {
                to = new NBNode(to_node, to_pos);
                if (!myNodeCont.insert(to)) {
                    WRITE_ERROR("Node '" + to_node + "' could not be added");
                    delete to;
                    continue;
                }
            }
        }

        if (from == to) {
            WRITE_WARNING("Edge '" + id + "' connects identical nodes, skipping.");
            continue;
        }

        // retrieve the information whether the street is bi-directional
        std::string dir;
        int index = poFeature->GetDefnRef()->GetFieldIndex("DIR_TRAVEL");
        if (index >= 0 && poFeature->IsFieldSet(index)) {
            dir = poFeature->GetFieldAsString(index);
        }
        // add positive direction if wanted
        if (dir == "B" || dir == "F" || dir == "" || myOptions.getBool("shapefile.all-bidirectional")) {
            if (myEdgeCont.retrieve(id) == 0) {
                LaneSpreadFunction spread = dir == "B" || dir == "FALSE" ? LANESPREAD_RIGHT : LANESPREAD_CENTER;
                NBEdge* edge = new NBEdge(id, from, to, type, speed, nolanes, priority, width, NBEdge::UNSPECIFIED_OFFSET, shape, name, id, spread);
                myEdgeCont.insert(edge);
                checkSpread(edge);
            }
        }
        // add negative direction if wanted
        if (dir == "B" || dir == "T" || myOptions.getBool("shapefile.all-bidirectional")) {
            if (myEdgeCont.retrieve("-" + id) == 0) {
                LaneSpreadFunction spread = dir == "B" || dir == "FALSE" ? LANESPREAD_RIGHT : LANESPREAD_CENTER;
                NBEdge* edge = new NBEdge("-" + id, to, from, type, speed, nolanes, priority, width, NBEdge::UNSPECIFIED_OFFSET, shape.reverse(), name, id, spread);
                myEdgeCont.insert(edge);
                checkSpread(edge);
            }
        }
        //
        OGRFeature::DestroyFeature(poFeature);
    }
#if GDAL_VERSION_MAJOR < 2
    OGRDataSource::DestroyDataSource(poDS);
#else
    GDALClose(poDS);
#endif
    PROGRESS_DONE_MESSAGE();
#else
    WRITE_ERROR("SUMO was compiled without GDAL support.");
#endif
}
void
NIImporter_OpenStreetMap::insertEdge(Edge* e, int index, NBNode* from, NBNode* to,
                                     const std::vector<int> &passed, NBEdgeCont& ec, NBTypeCont& tc) {
    // patch the id
    std::string id = e->id;
    if (index >= 0) {
        id = id + "#" + toString(index);
    }
    // convert the shape
    PositionVector shape;
    for (std::vector<int>::const_iterator i = passed.begin(); i != passed.end(); ++i) {
        NIOSMNode* n = myOSMNodes.find(*i)->second;
        Position pos(n->lon, n->lat);
        if (!NILoader::transformCoordinates(pos, true)) {
            throw ProcessError("Unable to project coordinates for edge " + id + ".");
        }
        shape.push_back_noDoublePos(pos);
    }

    std::string type = e->myHighWayType;
    if (!tc.knows(type)) {
        if (type.find(compoundTypeSeparator) != std::string::npos) {
            // this edge has a combination type which does not yet exist in the TypeContainer
            StringTokenizer tok = StringTokenizer(type, compoundTypeSeparator);
            std::set<std::string> types;
            while (tok.hasNext()) {
                std::string t = tok.next();
                if (tc.knows(t)) {
                    types.insert(t);
                } else {
                    WRITE_WARNING("Discarding edge " + id + " with type \"" + type + "\" (unknown compound \"" + t + "\").");
                    return;
                }
            }

            if (types.size() == 2 &&
                    types.count("railway.tram") == 1) {
                // compound types concern mostly the special case of tram tracks on a normal road.
                // in this case we simply discard the tram information since the default for road is to allow all vclasses
                types.erase("railway.tram");
                std::string otherCompound = *(types.begin());
                // XXX if otherCompound does not allow all vehicles (e.g. SVC_DELIVERY), tram will still not be allowed
                type = otherCompound;
            } else {
                // other cases not implemented yet
                WRITE_WARNING("Discarding edge " + id + " with unknown type \"" + type + "\".");
                return;
            }
        } else {
            // we do not know the type -> something else, ignore
            //WRITE_WARNING("Discarding edge " + id + " with unknown type \"" + type + "\".");
            return;
        }
    }



    // otherwise it is not an edge and will be ignored
    int noLanes = tc.getNumLanes(type);
    SUMOReal speed = tc.getSpeed(type);
    bool defaultsToOneWay = tc.getIsOneWay(type);
    SUMOVehicleClasses allowedClasses = tc.getAllowedClasses(type);
    SUMOVehicleClasses disallowedClasses = tc.getDisallowedClasses(type);
    // check directions
    bool addSecond = true;
    if (e->myIsOneWay == "true" || e->myIsOneWay == "yes" || e->myIsOneWay == "1" || (defaultsToOneWay && e->myIsOneWay != "no" && e->myIsOneWay != "false" && e->myIsOneWay != "0")) {
        addSecond = false;
    }
    // if we had been able to extract the number of lanes, override the highway type default
    if (e->myNoLanes >= 0) {
        if (!addSecond) {
            noLanes = e->myNoLanes;
        } else {
            noLanes = e->myNoLanes / 2;
        }
    }
    // if we had been able to extract the maximum speed, override the type's default
    if (e->myMaxSpeed != MAXSPEED_UNGIVEN) {
        speed = (SUMOReal)(e->myMaxSpeed / 3.6);
    }

    if (noLanes != 0 && speed != 0) {
        if (e->myIsOneWay != "" && e->myIsOneWay != "false" && e->myIsOneWay != "no" && e->myIsOneWay != "true" && e->myIsOneWay != "yes" && e->myIsOneWay != "-1" && e->myIsOneWay != "1") {
            WRITE_WARNING("New value for oneway found: " + e->myIsOneWay);
        }
        LaneSpreadFunction lsf = addSecond ? LANESPREAD_RIGHT : LANESPREAD_CENTER;
        if (e->myIsOneWay != "-1") {
            NBEdge* nbe = new NBEdge(id, from, to, type, speed, noLanes, tc.getPriority(type),
                                     tc.getWidth(type), NBEdge::UNSPECIFIED_OFFSET, shape, e->streetName, lsf);
            nbe->setVehicleClasses(allowedClasses, disallowedClasses);
            if (!ec.insert(nbe)) {
                delete nbe;
                throw ProcessError("Could not add edge '" + id + "'.");
            }
        }
        if (addSecond) {
            if (e->myIsOneWay != "-1") {
                id = "-" + id;
            }
            NBEdge* nbe = new NBEdge(id, to, from, type, speed, noLanes, tc.getPriority(type),
                                     tc.getWidth(type), NBEdge::UNSPECIFIED_OFFSET, shape.reverse(), e->streetName, lsf);
            nbe->setVehicleClasses(allowedClasses, disallowedClasses);
            if (!ec.insert(nbe)) {
                delete nbe;
                throw ProcessError("Could not add edge '-" + id + "'.");
            }
        }
    }
}