void
NIImporter_OpenDrive::addViaConnectionSecure(const NBEdgeCont &ec,
        const NBNode * const node, const OpenDriveEdge &e,
        LinkType lt, const std::string &via,
        std::vector<NIImporter_OpenDrive::Connection> &connections) {
    NBEdge *from = 0;
    NBEdge *to = 0;
    if (node==e.to) {
        // the connection is at the end of the "positive" direction
        if (lt==OPENDRIVE_LT_PREDECESSOR) {
            // via -> edge
            to = ec.retrieve(e.id);
        } else {
            // -edge -> via
            //  "ambigous?"
            from = ec.retrieve("-" + e.id);
        }
    } else {
        // the connection is at the begin of the "positive" direction
        if (lt==OPENDRIVE_LT_PREDECESSOR) {
            // via -> -edge
            to = ec.retrieve("-" + e.id);
        } else {
            // edge -> via
            //  "ambigous?"
            from = ec.retrieve(e.id);
        }
    }
    if (from==0&&to==0) {
        throw ProcessError("Missing edge");
    }
    Connection c(from, via, to);
    connections.push_back(c);
}
Beispiel #2
0
void
NWWriter_SUMO::writeRoundabout(OutputDevice& into, const std::vector<std::string>& edgeIDs,
                               const NBEdgeCont& ec) {
    std::vector<std::string> validEdgeIDs;
    std::vector<std::string> invalidEdgeIDs;
    std::vector<std::string> nodeIDs;
    for (std::vector<std::string>::const_iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) {
        const NBEdge* edge = ec.retrieve(*i);
        if (edge != 0) {
            nodeIDs.push_back(edge->getToNode()->getID());
            validEdgeIDs.push_back(edge->getID());
        } else {
            invalidEdgeIDs.push_back(*i);
        }
    }
    std::sort(nodeIDs.begin(), nodeIDs.end());
    if (validEdgeIDs.size() > 0) {
        into.openTag(SUMO_TAG_ROUNDABOUT);
        into.writeAttr(SUMO_ATTR_NODES, joinToString(nodeIDs, " "));
        into.writeAttr(SUMO_ATTR_EDGES, joinToString(validEdgeIDs, " "));
        into.closeTag();
        if (invalidEdgeIDs.size() > 0) {
            WRITE_WARNING("Writing incomplete roundabout. Edges: '"
                          + joinToString(invalidEdgeIDs, " ") + "' no longer exist'");
        }
    }
}
void
NBJoinedEdgesMap::init(NBEdgeCont& ec) {
    const std::vector<std::string> edgeNames = ec.getAllNames();
    myMap.clear();
    for (std::vector<std::string>::const_iterator i = edgeNames.begin(); i != edgeNames.end(); i++) {
        MappedEdgesVector e;
        e.push_back(*i);
        myMap[*i] = e;
        myLengths[*i] = ec.retrieve(*i)->getLength();
    }
}
Beispiel #4
0
void NBPTLine::write(OutputDevice& device, NBEdgeCont& ec) {
    device.openTag(SUMO_TAG_PT_LINE);
    device.writeAttr(SUMO_ATTR_ID, myPTLineId);
    if (!myName.empty()) {
        device.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(myName));
    }

    device.writeAttr(SUMO_ATTR_LINE, StringUtils::escapeXML(myRef));
    device.writeAttr(SUMO_ATTR_TYPE, myType);
    if (myInterval > 0) {
        // write seconds 
        device.writeAttr(SUMO_ATTR_PERIOD, 60 * myInterval);
    }
    if (myNightService != "") {
        device.writeAttr("nightService", myNightService);
    }
    device.writeAttr("completeness", toString((double)myPTStops.size() / (double)myNumOfStops));

    std::vector<std::string> validEdgeIDs;
    // filter out edges that have been removed due to joining junctions
    // (therest of the route is valid)
    for (NBEdge* e : myRoute) {
        if (ec.retrieve(e->getID())) {
            validEdgeIDs.push_back(e->getID());
        }
    }
    if (!myRoute.empty()) {
        device.openTag(SUMO_TAG_ROUTE);
        device.writeAttr(SUMO_ATTR_EDGES, validEdgeIDs);
        device.closeTag();
    }

    for (auto& myPTStop : myPTStops) {
        device.openTag(SUMO_TAG_BUS_STOP);
        device.writeAttr(SUMO_ATTR_ID, myPTStop->getID());
        device.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(myPTStop->getName()));
        device.closeTag();
    }
//    device.writeAttr(SUMO_ATTR_LANE, myLaneId);
//    device.writeAttr(SUMO_ATTR_STARTPOS, myStartPos);
//    device.writeAttr(SUMO_ATTR_ENDPOS, myEndPos);
//    device.writeAttr(SUMO_ATTR_FRIENDLY_POS, "true");
    device.closeTag();

}
void
NIImporter_OpenDrive::addE2EConnectionsSecure(const NBEdgeCont &ec, const NBNode * const node,
        const NIImporter_OpenDrive::OpenDriveEdge &from, const NIImporter_OpenDrive::OpenDriveEdge &to,
        std::vector<NIImporter_OpenDrive::Connection> &connections) {
    // positive direction (from is incoming, to is outgoing)
    NBEdge *fromEdge = ec.retrieve("-" + from.id);
    if (fromEdge==0||!node->hasIncoming(fromEdge)) {
        fromEdge = ec.retrieve(from.id);
    }
    NBEdge *toEdge = ec.retrieve("-" + to.id);
    if (toEdge==0||!node->hasOutgoing(toEdge)) {
        toEdge = ec.retrieve(to.id);
    }
    if (fromEdge!=0&&toEdge!=0) {
        Connection c(fromEdge, "", toEdge);
        setLaneConnections(c,
                           from, c.from->getID()[0]!='-', c.from->getID()[0]=='-' ? SUMO_TAG_OPENDRIVE_RIGHT : SUMO_TAG_OPENDRIVE_LEFT,
                           to, c.to->getID()[0]!='-', c.to->getID()[0]=='-' ? SUMO_TAG_OPENDRIVE_RIGHT : SUMO_TAG_OPENDRIVE_LEFT);
        connections.push_back(c);
    }
    // negative direction (to is incoming, from is outgoing)
    fromEdge = ec.retrieve("-" + from.id);
    if (fromEdge==0||!node->hasOutgoing(fromEdge)) {
        fromEdge = ec.retrieve(from.id);
    }
    toEdge = ec.retrieve("-" + to.id);
    if (toEdge==0||!node->hasIncoming(toEdge)) {
        toEdge = ec.retrieve(to.id);
    }
    if (fromEdge!=0&&toEdge!=0) {
        Connection c(toEdge, "", fromEdge);
        setLaneConnections(c,
                           to, c.to->getID()[0]!='-', c.to->getID()[0]=='-' ? SUMO_TAG_OPENDRIVE_RIGHT : SUMO_TAG_OPENDRIVE_LEFT,
                           from, c.from->getID()[0]!='-', c.from->getID()[0]=='-' ? SUMO_TAG_OPENDRIVE_RIGHT : SUMO_TAG_OPENDRIVE_LEFT);
        connections.push_back(c);
    }
}
Beispiel #6
0
void
NIVissimEdge::buildNBEdge(NBDistrictCont& dc, NBNodeCont& nc, NBEdgeCont& ec,
                          SUMOReal sameNodesOffset) {
    // build the edge
    std::pair<NIVissimConnectionCluster*, NBNode*> fromInf, toInf;
    NBNode* fromNode, *toNode;
    fromNode = toNode = 0;
    sort(myConnectionClusters.begin(), myConnectionClusters.end(), connection_cluster_position_sorter(myID));
    sort(myDistrictConnections.begin(), myDistrictConnections.end());
    ConnectionClusters tmpClusters = myConnectionClusters;
    if (tmpClusters.size() != 0) {
        sort(tmpClusters.begin(), tmpClusters.end(), connection_cluster_position_sorter(myID));
        // get or build the from-node
        //  A node may have to be build when the edge starts or ends at
        //  a parking place or something like this
        fromInf = getFromNode(nc, tmpClusters);
        fromNode = fromInf.second;
        // get or build the to-node
        //if(tmpClusters.size()>0) {
        toInf = getToNode(nc, tmpClusters);
        toNode = toInf.second;
        if (fromInf.first != 0 && toNode != 0 && fromInf.first->around(toNode->getPosition())) {
            WRITE_WARNING("Will not build edge '" + toString(myID) + "'.");
            myAmWithinJunction = true;
            return;
        }
        //}
        // if both nodes are the same, resolve the problem otherwise
        if (fromNode == toNode) {
            std::pair<NBNode*, NBNode*> tmp = resolveSameNode(nc, sameNodesOffset, fromNode, toNode);
            if (fromNode != tmp.first) {
                fromInf.first = 0;
            }
            if (toNode != tmp.second) {
                toInf.first = 0;
            }
            fromNode = tmp.first;
            toNode = tmp.second;
        }
    }

    //
    if (fromNode == 0) {
        fromInf.first = 0;
        Position pos = myGeom[0];
        fromNode = new NBNode(toString<int>(myID) + "-SourceNode", pos, NODETYPE_NOJUNCTION);
        if (!nc.insert(fromNode)) {
            throw ProcessError("Could not insert node '" + fromNode->getID() + "' to nodes container.");
        }
    }
    if (toNode == 0) {
        toInf.first = 0;
        Position pos = myGeom[-1];
        toNode = new NBNode(toString<int>(myID) + "-DestinationNode", pos, NODETYPE_NOJUNCTION);
        if (!nc.insert(toNode)) {
            throw ProcessError("Could not insert node '" + toNode->getID() + "' to nodes container.");
        }
    }

    // build the edge
    SUMOReal avgSpeed = 0;
    int i;
    for (i = 0; i < (int) myNoLanes; i++) {
        if (myLaneSpeeds.size() <= (size_t) i || myLaneSpeeds[i] == -1) {
            myLanesWithMissingSpeeds.push_back(toString(myID) + "_" + toString(i));
            avgSpeed += OptionsCont::getOptions().getFloat("vissim.default-speed");
        } else {
            avgSpeed += myLaneSpeeds[i];
        }
    }
    avgSpeed /= (SUMOReal) myLaneSpeeds.size();
    avgSpeed *= OptionsCont::getOptions().getFloat("vissim.speed-norm");

    if (fromNode == toNode) {
        WRITE_WARNING("Could not build edge '" + toString(myID) + "'; would connect same node.");
        return;
    }

    NBEdge* buildEdge = new NBEdge(toString<int>(myID), fromNode, toNode, myType,
                                   avgSpeed / (SUMOReal) 3.6, myNoLanes, -1,
                                   NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET,
                                   myGeom, myName, LANESPREAD_CENTER, true);
    for (i = 0; i < (int) myNoLanes; i++) {
        if ((int) myLaneSpeeds.size() <= i || myLaneSpeeds[i] == -1) {
            buildEdge->setSpeed(i, OptionsCont::getOptions().getFloat("vissim.default-speed") / (SUMOReal) 3.6);
        } else {
            buildEdge->setSpeed(i, myLaneSpeeds[i] / (SUMOReal) 3.6);
        }
    }
    ec.insert(buildEdge);
    // check whether the edge contains any other clusters
    if (tmpClusters.size() > 0) {
        bool cont = true;
        for (ConnectionClusters::iterator j = tmpClusters.begin(); cont && j != tmpClusters.end(); ++j) {
            // split the edge at the previously build node
            std::string nextID = buildEdge->getID() + "[1]";
            cont = ec.splitAt(dc, buildEdge, (*j)->getNBNode());
            // !!! what to do if the edge could not be split?
            buildEdge = ec.retrieve(nextID);
        }
    }
}
Beispiel #7
0
bool
NIVissimDisturbance::addToNode(NBNode* node, NBDistrictCont& dc,
                               NBNodeCont& nc, NBEdgeCont& ec) {
    myNode = 0;
    NIVissimConnection* pc =
        NIVissimConnection::dictionary(myEdge.getEdgeID());
    NIVissimConnection* bc =
        NIVissimConnection::dictionary(myDisturbance.getEdgeID());
    if (pc == nullptr && bc == nullptr) {
        // This has not been tested completely, yet
        // Both competing abstract edges are normal edges
        // We have to find a crossing point, build a node here,
        //  split both edges and add the connections
        NIVissimEdge* e1 = NIVissimEdge::dictionary(myEdge.getEdgeID());
        NIVissimEdge* e2 = NIVissimEdge::dictionary(myDisturbance.getEdgeID());
        WRITE_WARNING("Ugly split to prohibit '" + toString<int>(e1->getID()) + "' by '" + toString<int>(e2->getID()) + "'.");
        Position pos = e1->crossesEdgeAtPoint(e2);
        std::string id1 = toString<int>(e1->getID()) + "x" + toString<int>(e2->getID());
        std::string id2 = toString<int>(e2->getID()) + "x" + toString<int>(e1->getID());
        NBNode* node1 = nc.retrieve(id1);
        NBNode* node2 = nc.retrieve(id2);
        NBNode* node = nullptr;
        assert(node1 == 0 || node2 == 0);
        if (node1 == nullptr && node2 == nullptr) {
            refusedProhibits++;
            return false;
            /*            node = new NBNode(id1, pos.x(), pos.y(), "priority");
                        if(!myNodeCont.insert(node)) {
                             "nope, NIVissimDisturbance" << endl;
                            throw 1;
                        }*/
        } else {
            node = node1 == nullptr ? node2 : node1;
        }
        ec.splitAt(dc, ec.retrievePossiblySplit(toString<int>(e1->getID()), myEdge.getPosition()), node);
        ec.splitAt(dc, ec.retrievePossiblySplit(toString<int>(e2->getID()), myDisturbance.getPosition()), node);
        // !!! in some cases, one of the edges is not being build because it's too short
        // !!! what to do in these cases?
        NBEdge* mayDriveFrom = ec.retrieve(toString<int>(e1->getID()) + "[0]");
        NBEdge* mayDriveTo = ec.retrieve(toString<int>(e1->getID()) + "[1]");
        NBEdge* mustStopFrom = ec.retrieve(toString<int>(e2->getID()) + "[0]");
        NBEdge* mustStopTo = ec.retrieve(toString<int>(e2->getID()) + "[1]");
        if (mayDriveFrom != nullptr && mayDriveTo != nullptr && mustStopFrom != nullptr && mustStopTo != nullptr) {
            node->addSortedLinkFoes(
                NBConnection(mayDriveFrom, mayDriveTo),
                NBConnection(mayDriveFrom, mayDriveTo));
        } else {
            refusedProhibits++;
            return false;
            // !!! warning
        }
//        }
    } else if (pc != nullptr && bc == nullptr) {
        // The prohibited abstract edge is a connection, the other
        //  is not;
        // The connection will be prohibitesd by all connections
        //  outgoing from the "real" edge

        NBEdge* e = ec.retrievePossiblySplit(toString<int>(myDisturbance.getEdgeID()), myDisturbance.getPosition());
        if (e == nullptr) {
            WRITE_WARNING("Could not prohibit '" + toString<int>(myEdge.getEdgeID()) + "' by '" + toString<int>(myDisturbance.getEdgeID()) + "'. Have not found disturbance.");
            refusedProhibits++;
            return false;
        }
        if (e->getFromNode() == e->getToNode()) {
            WRITE_WARNING("Could not prohibit '" + toString<int>(myEdge.getEdgeID()) + "' by '" + toString<int>(myDisturbance.getEdgeID()) + "'. Disturbance connects same node.");
            refusedProhibits++;
            // What to do with self-looping edges?
            return false;
        }
        // get the begin of the prohibited connection
        std::string id_pcoe = toString<int>(pc->getFromEdgeID());
        std::string id_pcie = toString<int>(pc->getToEdgeID());
        NBEdge* pcoe = ec.retrievePossiblySplit(id_pcoe, id_pcie, true);
        NBEdge* pcie = ec.retrievePossiblySplit(id_pcie, id_pcoe, false);
        // check whether it's ending node is the node the prohibited
        //  edge end at
        if (pcoe != nullptr && pcie != nullptr && pcoe->getToNode() == e->getToNode()) {
            // if so, simply prohibit the connections
            NBNode* node = e->getToNode();
            const EdgeVector& connected = e->getConnectedEdges();
            for (EdgeVector::const_iterator i = connected.begin(); i != connected.end(); i++) {
                node->addSortedLinkFoes(
                    NBConnection(e, *i),
                    NBConnection(pcoe, pcie));
            }
        } else {
            WRITE_WARNING("Would have to split edge '" + e->getID() + "' to build a prohibition");
            refusedProhibits++;
            // quite ugly - why was it not build?
            return false;
            /*
            std::string nid1 = e->getID() + "[0]";
            std::string nid2 = e->getID() + "[1]";

            if(ec.splitAt(e, node)) {
                node->addSortedLinkFoes(
                        NBConnection(
                            ec.retrieve(nid1),
                            ec.retrieve(nid2)
                        ),
                        getConnection(node, myEdge.getEdgeID())
                    );
            }
            */
        }
    } else if (bc != nullptr && pc == nullptr) {
        // The prohibiting abstract edge is a connection, the other
        //  is not;
        // We have to split the other one and add the prohibition
        //  description

        NBEdge* e = ec.retrievePossiblySplit(toString<int>(myEdge.getEdgeID()), myEdge.getPosition());
        if (e == nullptr) {
            WRITE_WARNING("Could not prohibit '" + toString<int>(myEdge.getEdgeID()) + "' - it was not built.");
            return false;
        }
        std::string nid1 = e->getID() + "[0]";
        std::string nid2 = e->getID() + "[1]";
        if (e->getFromNode() == e->getToNode()) {
            WRITE_WARNING("Could not prohibit '" + toString<int>(myEdge.getEdgeID()) + "' by '" + toString<int>(myDisturbance.getEdgeID()) + "'.");
            refusedProhibits++;
            // What to do with self-looping edges?
            return false;
        }
        // get the begin of the prohibiting connection
        std::string id_bcoe = toString<int>(bc->getFromEdgeID());
        std::string id_bcie = toString<int>(bc->getToEdgeID());
        NBEdge* bcoe = ec.retrievePossiblySplit(id_bcoe, id_bcie, true);
        NBEdge* bcie = ec.retrievePossiblySplit(id_bcie, id_bcoe, false);
        // check whether it's ending node is the node the prohibited
        //  edge end at
        if (bcoe != nullptr && bcie != nullptr && bcoe->getToNode() == e->getToNode()) {
            // if so, simply prohibit the connections
            NBNode* node = e->getToNode();
            const EdgeVector& connected = e->getConnectedEdges();
            for (EdgeVector::const_iterator i = connected.begin(); i != connected.end(); i++) {
                node->addSortedLinkFoes(
                    NBConnection(bcoe, bcie),
                    NBConnection(e, *i));
            }
        } else {
            WRITE_WARNING("Would have to split edge '" + e->getID() + "' to build a prohibition");
            refusedProhibits++;
            return false;
            /*
            // quite ugly - why was it not build?
            if(ec.splitAt(e, node)) {
                node->addSortedLinkFoes(
                        getConnection(node, myDisturbance.getEdgeID()),
                        NBConnection(
                            ec.retrieve(nid1),
                            ec.retrieve(nid2)
                        )
                    );
            }
            */
        }
    } else {
        // both the prohibiting and the prohibited abstract edges
        //  are connections
        // We can retrieve the conected edges and add the desription
        NBConnection conn1 = getConnection(node, myDisturbance.getEdgeID());
        NBConnection conn2 = getConnection(node, myEdge.getEdgeID());
        if (!conn1.check(ec) || !conn2.check(ec)) {
            refusedProhibits++;
            return false;
        }
        node->addSortedLinkFoes(conn1, conn2);
    }
    return true;
}
void
NBRampsComputer::buildOffRamp(NBNode* cur, NBNodeCont& nc, NBEdgeCont& ec, NBDistrictCont& dc, SUMOReal rampLength, bool dontSplit, std::set<NBEdge*>& incremented) {
    NBEdge* potHighway, *potRamp, *prev;
    getOffRampEdges(cur, &potHighway, &potRamp, &prev);
    // compute the number of lanes to append
    const unsigned int firstLaneNumber = prev->getNumLanes();
    int toAdd = (potRamp->getNumLanes() + potHighway->getNumLanes()) - firstLaneNumber;
    NBEdge* first = prev;
    NBEdge* last = prev;
    NBEdge* curr = prev;
    if (toAdd > 0 && find(incremented.begin(), incremented.end(), prev) == incremented.end()) {
        SUMOReal currLength = 0;
        while (curr != 0 && currLength + curr->getGeometry().length() - POSITION_EPS < rampLength) {
            if (find(incremented.begin(), incremented.end(), curr) == incremented.end()) {
                curr->incLaneNo(toAdd);
                curr->invalidateConnections(true);
                incremented.insert(curr);
                moveRampRight(curr, toAdd);
                currLength += curr->getLength(); // !!! loaded length?
                last = curr;
            }
            NBNode* prevN = curr->getFromNode();
            if (prevN->getIncomingEdges().size() == 1) {
                curr = prevN->getIncomingEdges()[0];
                if (curr->getNumLanes() != firstLaneNumber) {
                    // the number of lanes changes along the computation; we'll stop...
                    curr = 0;
                } else if (last->isTurningDirectionAt(curr)) {
                    // turnarounds certainly should not be included in a ramp
                    curr = 0;
                } else if (curr == potHighway || curr == potRamp) {
                    // circular connectivity. do not split!
                    curr = 0;
                }
            } else {
                // ambigous; and, in fact, what should it be? ...stop
                curr = 0;
            }
        }
        // check whether a further split is necessary
        if (curr != 0 && !dontSplit && currLength - POSITION_EPS < rampLength && curr->getNumLanes() == firstLaneNumber && find(incremented.begin(), incremented.end(), curr) == incremented.end()) {
            // there is enough place to build a ramp; do it
            bool wasFirst = first == curr;
            Position pos = curr->getGeometry().positionAtOffset(curr->getGeometry().length() - (rampLength  - currLength));
            NBNode* rn = new NBNode(curr->getID() + "-AddedOffRampNode", pos);
            if (!nc.insert(rn)) {
                throw ProcessError("Ups - could not build on-ramp for edge '" + curr->getID() + "' (node could not be build)!");
            }
            std::string name = curr->getID();
            bool ok = ec.splitAt(dc, curr, rn, curr->getID(), curr->getID() + "-AddedOffRampEdge", curr->getNumLanes(), curr->getNumLanes() + toAdd);
            if (!ok) {
                WRITE_ERROR("Ups - could not build on-ramp for edge '" + curr->getID() + "'!");
                return;
            }
            curr = ec.retrieve(name + "-AddedOffRampEdge");
            incremented.insert(curr);
            last = curr;
            moveRampRight(curr, toAdd);
            if (wasFirst) {
                first = curr;
            }
        }
        if (curr == prev && dontSplit) {
            WRITE_WARNING("Could not build off-ramp for edge '"  + curr->getID() + "' due to option '--ramps.no-split'");
            return;
        }
    }
    // set connections from added ramp to ramp/highway
    if (!first->addLane2LaneConnections(potRamp->getNumLanes(), potHighway, 0, MIN2(first->getNumLanes() - 1, potHighway->getNumLanes()), NBEdge::L2L_VALIDATED, true)) {
        throw ProcessError("Could not set connection!");
    }
    if (!first->addLane2LaneConnections(0, potRamp, 0, potRamp->getNumLanes(), NBEdge::L2L_VALIDATED, false)) {
        throw ProcessError("Could not set connection!");
    }
    // patch ramp geometry
    PositionVector p = potRamp->getGeometry();
    p.pop_front();
    p.push_front(first->getLaneShape(0)[-1]);
    potRamp->setGeometry(p);
}
void
NIVissimDistrictConnection::dict_BuildDistricts(NBDistrictCont& dc,
        NBEdgeCont& ec,
        NBNodeCont& nc/*,
                                                                                NBDistribution &distc*/) {
    // add the sources and sinks
    //  their normalised probability is computed within NBDistrict
    //   to avoid SUMOReal code writing and more securty within the converter
    //  go through the district table
    for (std::map<int, std::vector<int> >::iterator k = myDistrictsConnections.begin(); k != myDistrictsConnections.end(); k++) {
        // get the connections
        const std::vector<int>& connections = (*k).second;
        // retrieve the current district
        NBDistrict* district =
            dc.retrieve(toString<int>((*k).first));
        NBNode* districtNode = nc.retrieve("District" + district->getID());
        assert(district != 0 && districtNode != 0);

        for (std::vector<int>::const_iterator l = connections.begin(); l != connections.end(); l++) {
            NIVissimDistrictConnection* c = dictionary(*l);
            // get the edge to connect the parking place to
            NBEdge* e = ec.retrieve(toString<int>(c->myEdgeID));
            if (e == 0) {
                e = ec.retrievePossiblySplit(toString<int>(c->myEdgeID), c->myPosition);
            }
            if (e == 0) {
                WRITE_WARNING("Could not build district '" + toString<int>((*k).first) + "' - edge '" + toString<int>(c->myEdgeID) + "' is missing.");
                continue;
            }
            std::string id = "ParkingPlace" + toString<int>(*l);
            NBNode* parkingPlace = nc.retrieve(id);
            if (parkingPlace == 0) {
                SUMOReal pos = c->getPosition();
                if (pos < e->getLength() - pos) {
                    parkingPlace = e->getFromNode();
                    parkingPlace->invalidateIncomingConnections();
                } else {
                    parkingPlace = e->getToNode();
                    parkingPlace->invalidateOutgoingConnections();
                }
            }
            assert(
                e->getToNode() == parkingPlace
                ||
                e->getFromNode() == parkingPlace);

            // build the connection to the source
            if (e->getFromNode() == parkingPlace) {
                id = "VissimFromParkingplace" + toString<int>((*k).first) + "-" + toString<int>(c->myID);
                NBEdge* source =
                    new NBEdge(id, districtNode, parkingPlace,
                               "Connection", c->getMeanSpeed(/*distc*/) / (SUMOReal) 3.6, 3, -1,
                               NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET);
                if (!ec.insert(source)) { // !!! in den Konstruktor
                    throw 1; // !!!
                }
                SUMOReal percNormed =
                    c->myPercentages[(*k).first];
                if (!district->addSource(source, percNormed)) {
                    throw 1;
                }
            }

            // build the connection to the destination
            if (e->getToNode() == parkingPlace) {
                id = "VissimToParkingplace"  + toString<int>((*k).first) + "-" + toString<int>(c->myID);
                NBEdge* destination =
                    new NBEdge(id, parkingPlace, districtNode,
                               "Connection", (SUMOReal) 100 / (SUMOReal) 3.6, 2, -1,
                               NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET);
                if (!ec.insert(destination)) { // !!! (in den Konstruktor)
                    throw 1; // !!!
                }
                SUMOReal percNormed2 =
                    c->myPercentages[(*k).first];
                if (!district->addSink(destination, percNormed2)) {
                    throw 1; // !!!
                }
            }

            /*
            if(e->getToNode()==districtNode) {
            SUMOReal percNormed =
                c->myPercentages[(*k).first];
            district->addSink(e, percNormed);
            }
            if(e->getFromNode()==districtNode) {
            SUMOReal percNormed =
                c->myPercentages[(*k).first];
            district->addSource(e, percNormed);
            }
            */
        }

        /*
        // add them as sources and sinks to the current district
        for(std::vector<int>::const_iterator l=connections.begin(); l!=connections.end(); l++) {
            // get the current connections
            NIVissimDistrictConnection *c = dictionary(*l);
            // get the edge to connect the parking place to
            NBEdge *e = NBEdgeCont::retrieve(toString<int>(c->myEdgeID));
            Position edgepos = c->geomPosition();
            NBNode *edgeend = e->tryGetNodeAtPosition(c->myPosition,
                e->getLength()/4.0);
            if(edgeend==0) {
                // Edge splitting omitted on build district connections by now
                assert(false);
            }

            // build the district-node if not yet existing
            std::string id = "VissimParkingplace" + district->getID();
            NBNode *districtNode = nc.retrieve(id);
            assert(districtNode!=0);

            if(e->getToNode()==edgeend) {
                // build the connection to the source
                id = std::string("VissimFromParkingplace")
                    + toString<int>((*k).first) + "-"
                    + toString<int>(c->myID);
                NBEdge *source =
                    new NBEdge(id, id, districtNode, edgeend,
                    "Connection", 100/3.6, 2, 100, 0,
                    NBEdge::EDGEFUNCTION_SOURCE);
                NBEdgeCont::insert(source); // !!! (in den Konstruktor)
                SUMOReal percNormed =
                    c->myPercentages[(*k).first];
                district->addSource(source, percNormed);
            } else {
                // build the connection to the destination
                id = std::string("VissimToParkingplace")
                    + toString<int>((*k).first) + "-"
                    + toString<int>(c->myID);
                NBEdge *destination =
                    new NBEdge(id, id, edgeend, districtNode,
                    "Connection", 100/3.6, 2, 100, 0,
                    NBEdge::EDGEFUNCTION_SINK);
                NBEdgeCont::insert(destination); // !!! (in den Konstruktor)

                // add both the source and the sink to the district
                SUMOReal percNormed =
                    c->myPercentages[(*k).first];
                district->addSink(destination, percNormed);
            }
        }
        */
    }
}
void
NBNodeCont::removeIsolatedRoads(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tc) {
    UNUSED_PARAMETER(tc);
    // Warn of isolated edges, i.e. a single edge with no connection to another edge
    int edgeCounter = 0;
    const std::vector<std::string>& edgeNames = ec.getAllNames();
    for (std::vector<std::string>::const_iterator it = edgeNames.begin(); it != edgeNames.end(); ++it) {
        // Test whether this node starts at a dead end, i.e. it has only one adjacent node
        // to which an edge exists and from which an edge may come.
        NBEdge* e = ec.retrieve(*it);
        if (e == 0) {
            continue;
        }
        NBNode* from = e->getFromNode();
        const EdgeVector& outgoingEdges = from->getOutgoingEdges();
        if (outgoingEdges.size() != 1) {
            // At this node, several edges or no edge start; so, this node is no dead end.
            continue;
        }
        const EdgeVector& incomingEdges = from->getIncomingEdges();
        if (incomingEdges.size() > 1) {
            // At this node, several edges end; so, this node is no dead end.
            continue;
        } else if (incomingEdges.size() == 1) {
            NBNode* fromNodeOfIncomingEdge = incomingEdges[0]->getFromNode();
            NBNode* toNodeOfOutgoingEdge = outgoingEdges[0]->getToNode();
            if (fromNodeOfIncomingEdge != toNodeOfOutgoingEdge) {
                // At this node, an edge ends which is not the inverse direction of
                // the starting node.
                continue;
            }
        }
        // Now we know that the edge e starts a dead end.
        // Next we test if the dead end is isolated, i.e. does not lead to a junction
        bool hasJunction = false;
        EdgeVector road;
        NBEdge* eOld = 0;
        NBNode* to;
        std::set<NBNode*> adjacentNodes;
        do {
            road.push_back(e);
            eOld = e;
            from = e->getFromNode();
            to = e->getToNode();
            const EdgeVector& outgoingEdgesOfToNode = to->getOutgoingEdges();
            const EdgeVector& incomingEdgesOfToNode = to->getIncomingEdges();
            adjacentNodes.clear();
            for (EdgeVector::const_iterator itOfOutgoings = outgoingEdgesOfToNode.begin(); itOfOutgoings != outgoingEdgesOfToNode.end(); ++itOfOutgoings) {
                if ((*itOfOutgoings)->getToNode() != from        // The back path
                        && (*itOfOutgoings)->getToNode() != to   // A loop / dummy edge
                   ) {
                    e = *itOfOutgoings; // Probably the next edge
                }
                adjacentNodes.insert((*itOfOutgoings)->getToNode());
            }
            for (EdgeVector::const_iterator itOfIncomings = incomingEdgesOfToNode.begin(); itOfIncomings != incomingEdgesOfToNode.end(); ++itOfIncomings) {
                adjacentNodes.insert((*itOfIncomings)->getFromNode());
            }
            adjacentNodes.erase(to);  // Omit loops
            if (adjacentNodes.size() > 2) {
                hasJunction = true;
            }
        } while (!hasJunction && eOld != e);
        if (!hasJunction) {
            edgeCounter +=  int(road.size());
            std::string warningString = "Removed a road without junctions: ";
            for (EdgeVector::iterator roadIt = road.begin(); roadIt != road.end(); ++roadIt) {
                if (roadIt == road.begin()) {
                    warningString += (*roadIt)->getID();
                } else {
                    warningString += ", " + (*roadIt)->getID();
                }

                NBNode* fromNode = (*roadIt)->getFromNode();
                NBNode* toNode = (*roadIt)->getToNode();
                ec.erase(dc, *roadIt);
                if (fromNode->getIncomingEdges().size() == 0 && fromNode->getOutgoingEdges().size() == 0) {
                    // Node is empty; can be removed
                    erase(fromNode);
                }
                if (toNode->getIncomingEdges().size() == 0 && toNode->getOutgoingEdges().size() == 0) {
                    // Node is empty; can be removed
                    erase(toNode);
                }
            }
            WRITE_WARNING(warningString);
        }
    }
    if (edgeCounter > 0 && !OptionsCont::getOptions().getBool("remove-edges.isolated")) {
        WRITE_WARNING("Detected isolated roads. Use the option --remove-edges.isolated to get a list of all affected edges.");
    }
}
void
NBRampsComputer::buildOnRamp(NBNode* cur, NBNodeCont& nc, NBEdgeCont& ec, NBDistrictCont& dc, SUMOReal rampLength, bool dontSplit, std::set<NBEdge*>& incremented) {
    NBEdge* potHighway, *potRamp, *cont;
    getOnRampEdges(cur, &potHighway, &potRamp, &cont);
    // compute the number of lanes to append
    const unsigned int firstLaneNumber = potHighway->getNumLanes();
    int toAdd = (potRamp->getNumLanes() + firstLaneNumber) - cont->getNumLanes();
    NBEdge* first = cont;
    NBEdge* last = cont;
    NBEdge* curr = cont;
    if (toAdd > 0 && find(incremented.begin(), incremented.end(), cont) == incremented.end()) {
        SUMOReal currLength = 0;
        while (curr != 0 && currLength + curr->getGeometry().length() - POSITION_EPS < rampLength) {
            if (find(incremented.begin(), incremented.end(), curr) == incremented.end()) {
                curr->incLaneNo(toAdd);
                curr->invalidateConnections(true);
                incremented.insert(curr);
                moveRampRight(curr, toAdd);
                currLength += curr->getLength(); // !!! loaded length?
                last = curr;
            }
            NBNode* nextN = curr->getToNode();
            if (nextN->getOutgoingEdges().size() == 1) {
                curr = nextN->getOutgoingEdges()[0];
                if (curr->getNumLanes() != firstLaneNumber) {
                    // the number of lanes changes along the computation; we'll stop...
                    curr = 0;
                }
            } else {
                // ambigous; and, in fact, what should it be? ...stop
                curr = 0;
            }
        }
        // check whether a further split is necessary
        if (curr != 0 && !dontSplit && currLength - POSITION_EPS < rampLength && curr->getNumLanes() == firstLaneNumber && find(incremented.begin(), incremented.end(), curr) == incremented.end()) {
            // there is enough place to build a ramp; do it
            bool wasFirst = first == curr;
            NBNode* rn = new NBNode(curr->getID() + "-AddedOnRampNode", curr->getGeometry().positionAtLengthPosition(rampLength - currLength));
            if (!nc.insert(rn)) {
                throw ProcessError("Ups - could not build on-ramp for edge '" + curr->getID() + "' (node could not be build)!");
            }
            std::string name = curr->getID();
            bool ok = ec.splitAt(dc, curr, rn, curr->getID() + ADDED_ON_RAMP_EDGE, curr->getID(), curr->getNumLanes() + toAdd, curr->getNumLanes());
            if (!ok) {
                WRITE_ERROR("Ups - could not build on-ramp for edge '" + curr->getID() + "'!");
                return;
            }
            //ec.retrieve(name)->invalidateConnections();
            curr = ec.retrieve(name + ADDED_ON_RAMP_EDGE);
            curr->invalidateConnections(true);
            incremented.insert(curr);
            last = curr;
            moveRampRight(curr, toAdd);
            if (wasFirst) {
                first = curr;
            }
        }
    }
    // set connections from ramp/highway to added ramp
    if (!potHighway->addLane2LaneConnections(0, first, potRamp->getNumLanes(), MIN2(first->getNumLanes() - potRamp->getNumLanes(), potHighway->getNumLanes()), NBEdge::L2L_VALIDATED, true, true)) {
        throw ProcessError("Could not set connection!");
    }
    if (!potRamp->addLane2LaneConnections(0, first, 0, potRamp->getNumLanes(), NBEdge::L2L_VALIDATED, true, true)) {
        throw ProcessError("Could not set connection!");
    }
    // patch ramp geometry
    PositionVector p = potRamp->getGeometry();
    p.pop_back();
    p.push_back(first->getLaneShape(0)[0]);
    potRamp->setGeometry(p);
    // set connections from added ramp to following highway
    NBNode* nextN = last->getToNode();
    if (nextN->getOutgoingEdges().size() == 1) {
        NBEdge* next = nextN->getOutgoingEdges()[0];//const EdgeVector& o1 = cont->getToNode()->getOutgoingEdges();
        if (next->getNumLanes() < last->getNumLanes()) {
            last->addLane2LaneConnections(last->getNumLanes() - next->getNumLanes(), next, 0, next->getNumLanes(), NBEdge::L2L_VALIDATED);
        }
    }
}