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.");
    }
}
unsigned int
NBNodeCont::joinJunctions(SUMOReal maxdist, NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc) {
    NodeClusters cands;
    NodeClusters clusters;
    generateNodeClusters(maxdist, cands);
    for (NodeClusters::iterator i = cands.begin(); i != cands.end(); ++i) {
        std::set<NBNode*> cluster = (*i);
        // remove join exclusions
        for (std::set<NBNode*>::iterator j = cluster.begin(); j != cluster.end();) {
            std::set<NBNode*>::iterator check = j;
            ++j;
            if (myJoinExclusions.count((*check)->getID()) > 0) {
                cluster.erase(check);
            }
        }
        // iteratively remove the fringe
        bool pruneFringe = true;
        while (pruneFringe) {
            pruneFringe = false;
            for (std::set<NBNode*>::iterator j = cluster.begin(); j != cluster.end();) {
                std::set<NBNode*>::iterator check = j;
                NBNode* n = *check;
                ++j;
                // remove nodes with degree <= 2 at fringe of the cluster (at least one edge leads to a non-cluster node)
                if (
                    (n->getIncomingEdges().size() <= 1 && n->getOutgoingEdges().size() <= 1) &&
                    ((n->getIncomingEdges().size() == 0 ||
                      (n->getIncomingEdges().size() == 1 && cluster.count(n->getIncomingEdges()[0]->getFromNode()) == 0)) ||
                     (n->getOutgoingEdges().size() == 0 ||
                      (n->getOutgoingEdges().size() == 1 && cluster.count(n->getOutgoingEdges()[0]->getToNode()) == 0)))
                ) {
                    cluster.erase(check);
                    pruneFringe = true; // other nodes could belong to the fringe now
                }
            }
        }
        if (cluster.size() > 1) {
            // check for clusters which are to complex and probably won't work very well
            // we count the incoming edges of the final junction
            std::set<NBEdge*> finalIncoming;
            std::vector<std::string> nodeIDs;
            for (std::set<NBNode*>::const_iterator j = cluster.begin(); j != cluster.end(); ++j) {
                nodeIDs.push_back((*j)->getID());
                const EdgeVector& edges = (*j)->getIncomingEdges();
                for (EdgeVector::const_iterator it_edge = edges.begin(); it_edge != edges.end(); ++it_edge) {
                    NBEdge* edge = *it_edge;
                    if (cluster.count(edge->getFromNode()) == 0) {
                        // incoming edge, does not originate in the cluster
                        finalIncoming.insert(edge);
                    }
                }

            }
            if (finalIncoming.size() > 4) {
                WRITE_WARNING("Not joining junctions " + joinToString(nodeIDs, ',') + " because the cluster is too complex");
            } else {
                clusters.push_back(cluster);
            }
        }
    }
    joinNodeClusters(clusters, dc, ec, tlc);
    return (int)clusters.size();
}
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 = potHighway->getNumLanes();
    int toAdd = (potRamp->getNumLanes() + firstLaneNumber) - prev->getNumLanes();
    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 {
                // 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().positionAtLengthPosition(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");
            curr->invalidateConnections(true);
            incremented.insert(curr);
            last = curr;
            moveRampRight(curr, toAdd);
            if (wasFirst) {
                first = curr;
            }
        }
    }
    // 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);
    // set connections from previous highway to added ramp
    NBNode* prevN = last->getFromNode();
    if (prevN->getIncomingEdges().size() == 1) {
        NBEdge* prev = prevN->getIncomingEdges()[0];//const EdgeVector& o1 = cont->getToNode()->getOutgoingEdges();
        if (prev->getNumLanes() < last->getNumLanes()) {
            last->addLane2LaneConnections(last->getNumLanes() - prev->getNumLanes(), last, 0, prev->getNumLanes(), NBEdge::L2L_VALIDATED);
        }
    }
}
Beispiel #4
0
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
NIImporter_VISUM::parse_Connectors() {
    if (OptionsCont::getOptions().getBool("visum.no-connectors")) {
        // do nothing, if connectors shall not be imported
        return;
    }
    // get the source district
    std::string bez = NBHelpers::normalIDRepresentation(myLineParser.get("BezNr"));
    // get the destination node
    NBNode* dest = getNamedNode("KnotNr");
    if (dest == 0) {
        return;
    }
    // get the weight of the connection
    SUMOReal proz = getWeightedFloat("Proz");
    if (proz > 0) {
        proz /= 100.;
    } else {
        proz = 1;
    }
    // get the duration to wait (unused)
//     SUMOReal retard = -1;
//     if (myLineParser.know("t0-IV")) {
//         retard = getNamedFloat("t0-IV", -1);
//     }
    // get the type;
    //  use a standard type with a large speed when a type is not given
    std::string type = myLineParser.know("Typ")
                       ? NBHelpers::normalIDRepresentation(myLineParser.get("Typ"))
                       : "";
    // add the connectors as an edge
    std::string id = bez + "-" + dest->getID();
    // get the information whether this is a sink or a source
    std::string dir = myLineParser.get("Richtung");
    if (dir.length() == 0) {
        dir = "QZ";
    }
    // build the source when needed
    if (dir.find('Q') != std::string::npos) {
        const EdgeVector& edges = dest->getOutgoingEdges();
        bool hasContinuation = false;
        for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
            if (!(*i)->isMacroscopicConnector()) {
                hasContinuation = true;
            }
        }
        if (!hasContinuation) {
            // obviously, there is no continuation on the net
            WRITE_WARNING("Incoming connector '" + id + "' will not be build - would be not connected to network.");
        } else {
            NBNode* src = buildDistrictNode(bez, dest, true);
            if (src == 0) {
                WRITE_ERROR("The district '" + bez + "' could not be built.");
                return;
            }
            NBEdge* edge = new NBEdge(id, src, dest, "VisumConnector",
                                      OptionsCont::getOptions().getFloat("visum.connector-speeds"),
                                      OptionsCont::getOptions().getInt("visum.connectors-lane-number"),
                                      -1, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET,
                                      "", LANESPREAD_RIGHT);
            edge->setAsMacroscopicConnector();
            if (!myNetBuilder.getEdgeCont().insert(edge)) {
                WRITE_ERROR("A duplicate edge id occured (ID='" + id + "').");
                return;
            }
            edge = myNetBuilder.getEdgeCont().retrieve(id);
            if (edge != 0) {
                myNetBuilder.getDistrictCont().addSource(bez, edge, proz);
            }
        }
    }
    // build the sink when needed
    if (dir.find('Z') != std::string::npos) {
        const EdgeVector& edges = dest->getIncomingEdges();
        bool hasPredeccessor = false;
        for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
            if (!(*i)->isMacroscopicConnector()) {
                hasPredeccessor = true;
            }
        }
        if (!hasPredeccessor) {
            // obviously, the network is not connected to this node
            WRITE_WARNING("Outgoing connector '" + id + "' will not be build - would be not connected to network.");
        } else {
            NBNode* src = buildDistrictNode(bez, dest, false);
            if (src == 0) {
                WRITE_ERROR("The district '" + bez + "' could not be built.");
                return;
            }
            id = "-" + id;
            NBEdge* edge = new NBEdge(id, dest, src, "VisumConnector",
                                      OptionsCont::getOptions().getFloat("visum.connector-speeds"),
                                      OptionsCont::getOptions().getInt("visum.connectors-lane-number"),
                                      -1, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET,
                                      "", LANESPREAD_RIGHT);
            edge->setAsMacroscopicConnector();
            if (!myNetBuilder.getEdgeCont().insert(edge)) {
                WRITE_ERROR("A duplicate edge id occured (ID='" + id + "').");
                return;
            }
            edge = myNetBuilder.getEdgeCont().retrieve(id);
            if (edge != 0) {
                myNetBuilder.getDistrictCont().addSink(bez, edge, proz);
            }
        }
    }
}
Beispiel #6
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 == 0 && bc == 0) {
        // 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 = 0;
        assert(node1 == 0 || node2 == 0);
        if (node1 == 0 && node2 == 0) {
            refusedProhibits++;
            return false;
            /*            node = new NBNode(id1, pos.x(), pos.y(), "priority");
                        if(!myNodeCont.insert(node)) {
                             "nope, NIVissimDisturbance" << endl;
                            throw 1;
                        }*/
        } else {
            node = node1 == 0 ? 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 != 0 && mayDriveTo != 0 && mustStopFrom != 0 && mustStopTo != 0) {
            node->addSortedLinkFoes(
                NBConnection(mayDriveFrom, mayDriveTo),
                NBConnection(mayDriveFrom, mayDriveTo));
        } else {
            refusedProhibits++;
            return false;
            // !!! warning
        }
//        }
    } else if (pc != 0 && bc == 0) {
        // 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 == 0) {
            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 != 0 && pcie != 0 && 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 != 0 && pc == 0) {
        // 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 == 0) {
            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 != 0 && bcie != 0 && 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;
}
Beispiel #7
0
void
NWWriter_SUMO::writeJunction(OutputDevice& into, const NBNode& n, const bool checkLaneFoes) {
    // write the attributes
    into.openTag(SUMO_TAG_JUNCTION).writeAttr(SUMO_ATTR_ID, n.getID());
    into.writeAttr(SUMO_ATTR_TYPE, n.getType());
    NWFrame::writePositionLong(n.getPosition(), into);
    // write the incoming lanes
    std::string incLanes;
    const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
    for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) {
        unsigned int noLanes = (*i)->getNumLanes();
        for (unsigned int j = 0; j < noLanes; j++) {
            incLanes += (*i)->getLaneID(j);
            if (i != incoming.end() - 1 || j < noLanes - 1) {
                incLanes += ' ';
            }
        }
    }
    const std::vector<NBNode::Crossing>& crossings = n.getCrossings();
    for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) {
        incLanes += ' ' + (*it).prevWalkingArea + "_0";
    }
    into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
    // write the internal lanes
    std::string intLanes;
    if (!OptionsCont::getOptions().getBool("no-internal-links")) {
        unsigned int l = 0;
        for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
            const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
            for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
                if ((*k).toEdge == 0) {
                    continue;
                }
                if (l != 0) {
                    intLanes += ' ';
                }
                if (!(*k).haveVia) {
                    intLanes += (*k).getInternalLaneID();
                } else {
                    intLanes += (*k).viaID + "_0";
                }
                l++;
            }
        }
    }
    if (n.getType() != NODETYPE_DEAD_END && n.getType() != NODETYPE_NOJUNCTION) {
        for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) {
            intLanes += ' ' + (*it).id + "_0";
        }
    }
    into.writeAttr(SUMO_ATTR_INTLANES, intLanes);
    // close writing
    into.writeAttr(SUMO_ATTR_SHAPE, n.getShape());
    // write optional radius
    if (n.getRadius() != NBNode::UNSPECIFIED_RADIUS) {
        into.writeAttr(SUMO_ATTR_RADIUS, n.getRadius());
    }
    // specify whether a custom shape was used
    if (n.hasCustomShape()) {
        into.writeAttr(SUMO_ATTR_CUSTOMSHAPE, true);
    }
    if (n.getType() == NODETYPE_DEAD_END) {
        into.closeTag();
    } else {
        // write right-of-way logics
        n.writeLogic(into, checkLaneFoes);
        into.closeTag();
    }
}
void
NIXMLConnectionsHandler::addCrossing(const SUMOSAXAttributes& attrs) {
    bool ok = true;
    NBNode* node = 0;
    EdgeVector edges;
    const std::string nodeID = attrs.get<std::string>(SUMO_ATTR_NODE, 0, ok);
    const double width = attrs.getOpt<double>(SUMO_ATTR_WIDTH, nodeID.c_str(), ok, NBEdge::UNSPECIFIED_WIDTH, true);
    const bool discard = attrs.getOpt<bool>(SUMO_ATTR_DISCARD, nodeID.c_str(), ok, false, true);
    int tlIndex = attrs.getOpt<int>(SUMO_ATTR_TLLINKINDEX, 0, ok, -1);
    int tlIndex2 = attrs.getOpt<int>(SUMO_ATTR_TLLINKINDEX2, 0, ok, -1);
    std::vector<std::string> edgeIDs;
    if (!attrs.hasAttribute(SUMO_ATTR_EDGES)) {
        if (discard) {
            node = myNodeCont.retrieve(nodeID);
            if (node == 0) {
                WRITE_ERROR("Node '" + nodeID + "' in crossing is not known.");
                return;
            }
            node->discardAllCrossings(true);
            return;
        } else {
            WRITE_ERROR("No edges specified for crossing at node '" + nodeID + "'.");
            return;
        }
    }
    SUMOSAXAttributes::parseStringVector(attrs.get<std::string>(SUMO_ATTR_EDGES, 0, ok), edgeIDs);
    if (!ok) {
        return;
    }
    for (std::vector<std::string>::const_iterator it = edgeIDs.begin(); it != edgeIDs.end(); ++it) {
        NBEdge* edge = myEdgeCont.retrieve(*it);
        if (edge == 0) {
            WRITE_ERROR("Edge '" + (*it) + "' for crossing at node '" + nodeID + "' is not known.");
            return;
        }
        if (node == 0) {
            if (edge->getToNode()->getID() == nodeID) {
                node = edge->getToNode();
            } else if (edge->getFromNode()->getID() == nodeID) {
                node = edge->getFromNode();
            } else {
                WRITE_ERROR("Edge '" + (*it) + "' does not touch node '" + nodeID + "'.");
                return;
            }
        } else {
            if (edge->getToNode() != node && edge->getFromNode() != node) {
                WRITE_ERROR("Edge '" + (*it) + "' does not touch node '" + nodeID + "'.");
                return;
            }
        }
        edges.push_back(edge);
    }
    bool priority = attrs.getOpt<bool>(SUMO_ATTR_PRIORITY, nodeID.c_str(), ok, node->isTLControlled(), true);
    if (node->isTLControlled() && !priority) {
        // traffic_light nodes should always have priority crossings
        WRITE_WARNING("Crossing at controlled node '" + nodeID + "' must be prioritized");
        priority = true;
    }
    PositionVector customShape = attrs.getOpt<PositionVector>(SUMO_ATTR_SHAPE, 0, ok, PositionVector::EMPTY);
    if (!NBNetBuilder::transformCoordinates(customShape)) {
        WRITE_ERROR("Unable to project shape for crossing at node '" + node->getID() + "'.");
    }
    if (discard) {
        node->removeCrossing(edges);
    } else {
        if (node->checkCrossingDuplicated(edges)) {
            WRITE_ERROR("Crossing with edges '" + toString(edges) + "' already exists at node '" + node->getID() + "'.");
            return;
        }
        node->addCrossing(edges, width, priority, tlIndex, tlIndex2, customShape);
    }
}
Beispiel #9
0
// ===========================================================================
// method definitions
// ===========================================================================
// ---------------------------------------------------------------------------
// static methods
// ---------------------------------------------------------------------------
void
NWWriter_OpenDrive::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) {
    // check whether an opendrive-file shall be generated
    if (!oc.isSet("opendrive-output")) {
        return;
    }
    const NBNodeCont& nc = nb.getNodeCont();
    const NBEdgeCont& ec = nb.getEdgeCont();
    const bool origNames = oc.getBool("output.original-names");
    const SUMOReal straightThresh = DEG2RAD(oc.getFloat("opendrive-output.straight-threshold"));
    // some internal mapping containers
    int nodeID = 1;
    int edgeID = nc.size() * 10; // distinct from node ids
    StringBijection<int> edgeMap;
    StringBijection<int> nodeMap;
    //
    OutputDevice& device = OutputDevice::getDevice(oc.getString("opendrive-output"));
    device << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
    device.openTag("OpenDRIVE");
    time_t now = time(0);
    std::string dstr(ctime(&now));
    const Boundary& b = GeoConvHelper::getFinal().getConvBoundary();
    // write header
    device.openTag("header");
    device.writeAttr("revMajor", "1");
    device.writeAttr("revMinor", "4");
    device.writeAttr("name", "");
    device.writeAttr("version", "1.00");
    device.writeAttr("date", dstr.substr(0, dstr.length() - 1));
    device.writeAttr("north", b.ymax());
    device.writeAttr("south", b.ymin());
    device.writeAttr("east", b.xmax());
    device.writeAttr("west", b.xmin());
    /* @note obsolete in 1.4
    device.writeAttr("maxRoad", ec.size());
    device.writeAttr("maxJunc", nc.size());
    device.writeAttr("maxPrg", 0);
    */
    device.closeTag();

    // write normal edges (road)
    for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
        const NBEdge* e = (*i).second;

        // buffer output because some fields are computed out of order
        OutputDevice_String elevationOSS(false, 3);
        elevationOSS.setPrecision(8);
        OutputDevice_String planViewOSS(false, 2);
        planViewOSS.setPrecision(8);
        SUMOReal length = 0;

        planViewOSS.openTag("planView");
        planViewOSS.setPrecision(8); // geometry hdg requires higher precision
        // for the shape we need to use the leftmost border of the leftmost lane
        const std::vector<NBEdge::Lane>& lanes = e->getLanes();
        PositionVector ls = getLeftLaneBorder(e);
#ifdef DEBUG_SMOOTH_GEOM
        if (DEBUGCOND) {
            std::cout << "write planview for edge " << e->getID() << "\n";
        }
#endif

        if (ls.size() == 2 || e->getPermissions() == SVC_PEDESTRIAN) {
            // foot paths may contain sharp angles
            length = writeGeomLines(ls, planViewOSS, elevationOSS);
        } else {
            bool ok = writeGeomSmooth(ls, e->getSpeed(), planViewOSS, elevationOSS, straightThresh, length);
            if (!ok) {
                WRITE_WARNING("Could not compute smooth shape for edge '" + e->getID() + "'.");
            }
        }
        planViewOSS.closeTag();

        device.openTag("road");
        device.writeAttr("name", StringUtils::escapeXML(e->getStreetName()));
        device.setPrecision(8); // length requires higher precision
        device.writeAttr("length", MAX2(POSITION_EPS, length));
        device.setPrecision(OUTPUT_ACCURACY); 
        device.writeAttr("id", getID(e->getID(), edgeMap, edgeID));
        device.writeAttr("junction", -1);
        const bool hasSucc = e->getConnections().size() > 0;
        const bool hasPred = e->getIncomingEdges().size() > 0;
        if (hasPred || hasSucc) {
            device.openTag("link");
            if (hasPred) {
                device.openTag("predecessor");
                device.writeAttr("elementType", "junction");
                device.writeAttr("elementId", getID(e->getFromNode()->getID(), nodeMap, nodeID));
                device.closeTag();
            }
            if (hasSucc) {
                device.openTag("successor");
                device.writeAttr("elementType", "junction");
                device.writeAttr("elementId", getID(e->getToNode()->getID(), nodeMap, nodeID));
                device.closeTag();
            }
            device.closeTag();
        }
        device.openTag("type").writeAttr("s", 0).writeAttr("type", "town").closeTag();
        device << planViewOSS.getString();
        writeElevationProfile(ls, device, elevationOSS);
        device << "        <lateralProfile/>\n";
        device << "        <lanes>\n";
        device << "            <laneSection s=\"0\">\n";
        writeEmptyCenterLane(device, "solid", 0.13);
        device << "                <right>\n";
        for (int j = e->getNumLanes(); --j >= 0;) {
            device << "                    <lane id=\"-" << e->getNumLanes() - j << "\" type=\"" << getLaneType(e->getPermissions(j)) << "\" level=\"true\">\n";
            device << "                        <link/>\n";
            // this could be used for geometry-link junctions without u-turn,
            // predecessor and sucessors would be lane indices,
            // road predecessor / succesfors would be of type 'road' rather than
            // 'junction'
            //device << "                            <predecessor id=\"-1\"/>\n";
            //device << "                            <successor id=\"-1\"/>\n";
            //device << "                        </link>\n";
            device << "                        <width sOffset=\"0\" a=\"" << e->getLaneWidth(j) << "\" b=\"0\" c=\"0\" d=\"0\"/>\n";
            std::string markType = "broken";
            if (j == 0) {
                markType = "solid";
            }
            device << "                        <roadMark sOffset=\"0\" type=\"" << markType << "\" weight=\"standard\" color=\"standard\" width=\"0.13\"/>\n";
            device << "                        <speed sOffset=\"0\" max=\"" << lanes[j].speed << "\"/>\n";
            device << "                    </lane>\n";
        }
        device << "                 </right>\n";
        device << "            </laneSection>\n";
        device << "        </lanes>\n";
        device << "        <objects/>\n";
        device << "        <signals/>\n";
        if (origNames) {
            device << "        <userData code=\"sumoId\" value=\"" << e->getID() << "\"/>\n";
        }
        device.closeTag();
        checkLaneGeometries(e);
    }
    device.lf();

    // write junction-internal edges (road). In OpenDRIVE these are called 'paths' or 'connecting roads'
    for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
        NBNode* n = (*i).second;
        const std::vector<NBEdge*>& incoming = (*i).second->getIncomingEdges();
        for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) {
            const NBEdge* inEdge = *j;
            const std::vector<NBEdge::Connection>& elv = inEdge->getConnections();
            for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
                const NBEdge::Connection& c = *k;
                const NBEdge* outEdge = c.toEdge;
                if (outEdge == 0) {
                    continue;
                }
                const SUMOReal width = c.toEdge->getLaneWidth(c.toLane);
                const PositionVector begShape = getLeftLaneBorder(inEdge, c.fromLane);
                const PositionVector endShape = getLeftLaneBorder(outEdge, c.toLane);
                //std::cout << "computing reference line for internal lane " << c.getInternalLaneID() << " begLane=" << inEdge->getLaneShape(c.fromLane) << " endLane=" << outEdge->getLaneShape(c.toLane) << "\n";

                SUMOReal length;
                PositionVector fallBackShape;
                fallBackShape.push_back(begShape.back());
                fallBackShape.push_back(endShape.front());
                const bool turnaround = inEdge->isTurningDirectionAt(outEdge);
                bool ok = true;
                PositionVector init = NBNode::bezierControlPoints(begShape, endShape, turnaround, 25, 25, ok, 0, straightThresh);
                if (init.size() == 0) {
                    length = fallBackShape.length2D();
                    // problem with turnarounds is known, method currently returns 'ok' (#2539)
                    if (!ok) {
                        WRITE_WARNING("Could not compute smooth shape from lane '" + inEdge->getLaneID(c.fromLane) + "' to lane '" + outEdge->getLaneID(c.toLane) + "'. Use option 'junctions.scurve-stretch' or increase radius of junction '" + inEdge->getToNode()->getID() + "' to fix this.");
                    }
                } else {
                    length = bezier(init, 12).length2D();
                }

                device.openTag("road");
                device.writeAttr("name", c.getInternalLaneID());
                device.setPrecision(8); // length requires higher precision
                device.writeAttr("length", MAX2(POSITION_EPS, length));
                device.setPrecision(OUTPUT_ACCURACY); 
                device.writeAttr("id", getID(c.getInternalLaneID(), edgeMap, edgeID));
                device.writeAttr("junction", getID(n->getID(), nodeMap, nodeID));
                device.openTag("link");
                device.openTag("predecessor");
                device.writeAttr("elementType", "road");
                device.writeAttr("elementId", getID(inEdge->getID(), edgeMap, edgeID));
                device.writeAttr("contactPoint", "end");
                device.closeTag();
                device.openTag("successor");
                device.writeAttr("elementType", "road");
                device.writeAttr("elementId", getID(outEdge->getID(), edgeMap, edgeID));
                device.writeAttr("contactPoint", "start");
                device.closeTag();
                device.closeTag();
                device.openTag("type").writeAttr("s", 0).writeAttr("type", "town").closeTag();
                device.openTag("planView");
                device.setPrecision(8); // geometry hdg requires higher precision
                OutputDevice_String elevationOSS(false, 3);
#ifdef DEBUG_SMOOTH_GEOM
                if (DEBUGCOND) {
                    std::cout << "write planview for internal edge " << c.getInternalLaneID() << " init=" << init << " fallback=" << fallBackShape << "\n";
                }
#endif
                if (init.size() == 0) {
                    writeGeomLines(fallBackShape, device, elevationOSS);
                } else {
                    writeGeomPP3(device, elevationOSS, init, length);
                }
                device.setPrecision(OUTPUT_ACCURACY);
                device.closeTag();
                writeElevationProfile(fallBackShape, device, elevationOSS);
                device << "        <lateralProfile/>\n";
                device << "        <lanes>\n";
                device << "            <laneSection s=\"0\">\n";
                writeEmptyCenterLane(device, "none", 0);
                device << "                <right>\n";
                device << "                    <lane id=\"-1\" type=\"" << getLaneType(outEdge->getPermissions(c.toLane)) << "\" level=\"true\">\n";
                device << "                        <link>\n";
                device << "                            <predecessor id=\"-" << inEdge->getNumLanes() - c.fromLane << "\"/>\n";
                device << "                            <successor id=\"-" << outEdge->getNumLanes() - c.toLane << "\"/>\n";
                device << "                        </link>\n";
                device << "                        <width sOffset=\"0\" a=\"" << width << "\" b=\"0\" c=\"0\" d=\"0\"/>\n";
                device << "                        <roadMark sOffset=\"0\" type=\"none\" weight=\"standard\" color=\"standard\" width=\"0.13\"/>\n";
                device << "                    </lane>\n";
                device << "                 </right>\n";
                device << "            </laneSection>\n";
                device << "        </lanes>\n";
                device << "        <objects/>\n";
                device << "        <signals/>\n";
                device.closeTag();
            }
        }
    }

    // write junctions (junction)
    for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
        NBNode* n = (*i).second;
        const std::vector<NBEdge*>& incoming = n->getIncomingEdges();
        // check if any connections must be written
        int numConnections = 0;
        for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) {
            numConnections += (int)((*j)->getConnections().size());
        }
        if (numConnections == 0) {
            continue;
        }
        device << "    <junction name=\"" << n->getID() << "\" id=\"" << getID(n->getID(), nodeMap, nodeID) << "\">\n";
        int index = 0;
        for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) {
            const NBEdge* inEdge = *j;
            const std::vector<NBEdge::Connection>& elv = inEdge->getConnections();
            for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
                const NBEdge::Connection& c = *k;
                const NBEdge* outEdge = c.toEdge;
                if (outEdge == 0) {
                    continue;
                }
                device << "    <connection id=\""
                       << index << "\" incomingRoad=\"" << getID(inEdge->getID(), edgeMap, edgeID)
                       << "\" connectingRoad=\""
                       << getID(c.getInternalLaneID(), edgeMap, edgeID)
                       << "\" contactPoint=\"start\">\n";
                device << "        <laneLink from=\"-" << inEdge->getNumLanes() - c.fromLane
                       << "\" to=\"-1"  // every connection has its own edge
                       << "\"/>\n";
                device << "    </connection>\n";
                ++index;
            }
        }
        device << "    </junction>\n";
    }

    device.closeTag();
    device.close();
}
Beispiel #10
0
bool
NWWriter_SUMO::writeInternalEdges(OutputDevice& into, const NBNode& n, bool origNames) {
    bool ret = false;
    const EdgeVector& incoming = n.getIncomingEdges();
    for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
        const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
        if (elv.size() > 0) {
            bool haveVia = false;
            NBEdge* toEdge = 0;
            std::string internalEdgeID = "";
            // first pass: compute average lengths of non-via edges
            std::map<NBEdge*, SUMOReal> lengthSum;
            std::map<NBEdge*, int> numLanes;
            for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
                lengthSum[(*k).toEdge] += MAX2((*k).shape.length(), POSITION_EPS);
                numLanes[(*k).toEdge] += 1;
            }
            // second pass: write non-via edges
            for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
                if ((*k).toEdge == 0) {
                    assert(false); // should never happen. tell me when it does
                    continue;
                }
                if (toEdge != (*k).toEdge) {
                    internalEdgeID = (*k).id;
                    if (toEdge != 0) {
                        // close the previous edge
                        into.closeTag();
                    }
                    toEdge = (*k).toEdge;
                    into.openTag(SUMO_TAG_EDGE);
                    into.writeAttr(SUMO_ATTR_ID, internalEdgeID);
                    into.writeAttr(SUMO_ATTR_FUNCTION, EDGEFUNC_INTERNAL);
                    // open a new edge
                }
                // to avoid changing to an internal lane which has a successor
                // with the wrong permissions we need to inherit them from the successor
                const NBEdge::Lane& successor = (*k).toEdge->getLanes()[(*k).toLane];
                const SUMOReal length = lengthSum[toEdge] / numLanes[toEdge];
                // @note the actual length should be used once sumo supports lanes of
                // varying length within the same edge
                //const SUMOReal length = MAX2((*k).shape.length(), POSITION_EPS);
                writeLane(into, internalEdgeID, (*k).getInternalLaneID(), (*k).vmax,
                          successor.permissions, successor.preferred,
                          NBEdge::UNSPECIFIED_OFFSET, successor.width, (*k).shape, (*k).origID,
                          length, (*k).internalLaneIndex, origNames, &n);
                haveVia = haveVia || (*k).haveVia;
            }
            ret = true;
            into.closeTag(); // close the last edge
            // third pass: write via edges
            if (haveVia) {
                for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
                    if (!(*k).haveVia) {
                        continue;
                    }
                    if ((*k).toEdge == 0) {
                        assert(false); // should never happen. tell me when it does
                        continue;
                    }
                    const NBEdge::Lane& successor = (*k).toEdge->getLanes()[(*k).toLane];
                    into.openTag(SUMO_TAG_EDGE);
                    into.writeAttr(SUMO_ATTR_ID, (*k).viaID);
                    into.writeAttr(SUMO_ATTR_FUNCTION, EDGEFUNC_INTERNAL);
                    writeLane(into, (*k).viaID, (*k).viaID + "_0", (*k).viaVmax, SVCAll, SVCAll,
                              NBEdge::UNSPECIFIED_OFFSET, successor.width, (*k).viaShape, (*k).origID,
                              MAX2((*k).viaShape.length(), POSITION_EPS), // microsim needs positive length
                              0, origNames, &n);
                    into.closeTag();
                }
            }
        }
    }
    // write pedestrian crossings
    const std::vector<NBNode::Crossing>& crossings = n.getCrossings();
    for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) {
        into.openTag(SUMO_TAG_EDGE);
        into.writeAttr(SUMO_ATTR_ID, (*it).id);
        into.writeAttr(SUMO_ATTR_FUNCTION, EDGEFUNC_CROSSING);
        into.writeAttr(SUMO_ATTR_CROSSING_EDGES, (*it).edges);
        writeLane(into, (*it).id, (*it).id + "_0", 1, SVC_PEDESTRIAN, 0,
                  NBEdge::UNSPECIFIED_OFFSET, (*it).width, (*it).shape, "", (*it).shape.length(), 0, false, &n);
        into.closeTag();
    }
    // write pedestrian walking areas
    const std::vector<NBNode::WalkingArea>& WalkingAreas = n.getWalkingAreas();
    for (std::vector<NBNode::WalkingArea>::const_iterator it = WalkingAreas.begin(); it != WalkingAreas.end(); it++) {
        const NBNode::WalkingArea& wa = *it;
        into.openTag(SUMO_TAG_EDGE);
        into.writeAttr(SUMO_ATTR_ID, wa.id);
        into.writeAttr(SUMO_ATTR_FUNCTION, EDGEFUNC_WALKINGAREA);
        writeLane(into, wa.id, wa.id + "_0", 1, SVC_PEDESTRIAN, 0,
                  NBEdge::UNSPECIFIED_OFFSET, wa.width, wa.shape, "", wa.length, 0, false, &n);
        into.closeTag();
    }
    return ret;
}
Beispiel #11
0
void
NBNodeCont::guessTLs(OptionsCont& oc, NBTrafficLightLogicCont& tlc) {
    // build list of definitely not tls-controlled junctions
    std::vector<NBNode*> ncontrolled;
    if (oc.isSet("tls.unset")) {
        std::vector<std::string> notTLControlledNodes = oc.getStringVector("tls.unset");
        for (std::vector<std::string>::const_iterator i = notTLControlledNodes.begin(); i != notTLControlledNodes.end(); ++i) {
            NBNode* n = NBNodeCont::retrieve(*i);
            if (n == 0) {
                throw ProcessError(" The node '" + *i + "' to set as not-controlled is not known.");
            }
            std::set<NBTrafficLightDefinition*> tls = n->getControllingTLS();
            for (std::set<NBTrafficLightDefinition*>::const_iterator j = tls.begin(); j != tls.end(); ++j) {
                (*j)->removeNode(n);
            }
            n->removeTrafficLights();
            ncontrolled.push_back(n);
        }
    }

    TrafficLightType type = SUMOXMLDefinitions::TrafficLightTypes.get(OptionsCont::getOptions().getString("tls.default-type"));
    // loop#1 checking whether the node shall be tls controlled,
    //  because it is assigned to a district
    if (oc.exists("tls.taz-nodes") && oc.getBool("tls.taz-nodes")) {
        for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
            NBNode* cur = (*i).second;
            if (cur->isNearDistrict() && find(ncontrolled.begin(), ncontrolled.end(), cur) == ncontrolled.end()) {
                setAsTLControlled(cur, tlc, type);
            }
        }
    }

    // figure out which nodes mark the locations of TLS signals
    // This assumes nodes are already joined
    if (oc.exists("tls.guess-signals") && oc.getBool("tls.guess-signals")) {
        // prepare candidate edges
        const SUMOReal signalDist = oc.getFloat("tls.guess-signals.dist");
        for (std::map<std::string, NBNode*>::const_iterator i = myNodes.begin(); i != myNodes.end(); ++i) {
            NBNode* node = (*i).second;
            if (node->isTLControlled() && node->geometryLike()) {
                const EdgeVector& outgoing = node->getOutgoingEdges();
                for (EdgeVector::const_iterator it_o = outgoing.begin(); it_o != outgoing.end(); ++it_o) {
                    (*it_o)->setSignalOffset((*it_o)->getLength());
                }
            }
        }
        // check which nodes should be controlled
        for (std::map<std::string, NBNode*>::const_iterator i = myNodes.begin(); i != myNodes.end(); ++i) {
            NBNode* node = i->second;
            const EdgeVector& incoming = node->getIncomingEdges();
            if (!node->isTLControlled() && incoming.size() > 1 && !node->geometryLike()) {
                std::vector<NBNode*> signals;
                bool isTLS = true;
                for (EdgeVector::const_iterator it_i = incoming.begin(); it_i != incoming.end(); ++it_i) {
                    const NBEdge* inEdge = *it_i;
                    if (inEdge->getSignalOffset() == NBEdge::UNSPECIFIED_SIGNAL_OFFSET || inEdge->getSignalOffset() > signalDist) {
                        isTLS = false;
                        break;
                    }
                    if (inEdge->getSignalOffset() == inEdge->getLength()) {
                        signals.push_back(inEdge->getFromNode());
                    }
                }
                if (isTLS) {
                    for (std::vector<NBNode*>::iterator j = signals.begin(); j != signals.end(); ++j) {
                        std::set<NBTrafficLightDefinition*> tls = (*j)->getControllingTLS();
                        (*j)->removeTrafficLights();
                        for (std::set<NBTrafficLightDefinition*>::iterator k = tls.begin(); k != tls.end(); ++k) {
                            tlc.removeFully((*j)->getID());
                        }
                    }
                    NBTrafficLightDefinition* tlDef = new NBOwnTLDef("GS_" + node->getID(), node, 0, TLTYPE_STATIC);
                    // @todo patch endOffset for all incoming lanes according to the signal positions
                    if (!tlc.insert(tlDef)) {
                        // actually, nothing should fail here
                        WRITE_WARNING("Could not build joined tls '" + node->getID() + "'.");
                        delete tlDef;
                        return;
                    }
                }
            }
        }
    }

    // maybe no tls shall be guessed
    if (!oc.getBool("tls.guess")) {
        return;
    }

    // guess joined tls first, if wished
    if (oc.getBool("tls.join")) {
        // get node clusters
        std::vector<std::set<NBNode*> > cands;
        generateNodeClusters(oc.getFloat("tls.join-dist"), cands);
        // check these candidates (clusters) whether they should be controlled by a tls
        for (std::vector<std::set<NBNode*> >::iterator i = cands.begin(); i != cands.end();) {
            std::set<NBNode*>& c = (*i);
            // regard only junctions which are not yet controlled and are not
            //  forbidden to be controlled
            for (std::set<NBNode*>::iterator j = c.begin(); j != c.end();) {
                if ((*j)->isTLControlled() || find(ncontrolled.begin(), ncontrolled.end(), *j) != ncontrolled.end()) {
                    c.erase(j++);
                } else {
                    ++j;
                }
            }
            // check whether the cluster should be controlled
            if (!shouldBeTLSControlled(c)) {
                i = cands.erase(i);
            } else {
                ++i;
            }
        }
        // cands now only contain sets of junctions that shall be joined into being tls-controlled
        unsigned int index = 0;
        for (std::vector<std::set<NBNode*> >::iterator i = cands.begin(); i != cands.end(); ++i) {
            std::vector<NBNode*> nodes;
            for (std::set<NBNode*>::iterator j = (*i).begin(); j != (*i).end(); j++) {
                nodes.push_back(*j);
            }
            std::string id = "joinedG_" + toString(index++);
            NBTrafficLightDefinition* tlDef = new NBOwnTLDef(id, nodes, 0, type);
            if (!tlc.insert(tlDef)) {
                // actually, nothing should fail here
                WRITE_WARNING("Could not build guessed, joined tls");
                delete tlDef;
                return;
            }
        }
    }

    // guess tls
    for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
        NBNode* cur = (*i).second;
        //  do nothing if already is tl-controlled
        if (cur->isTLControlled()) {
            continue;
        }
        // do nothing if in the list of explicit non-controlled junctions
        if (find(ncontrolled.begin(), ncontrolled.end(), cur) != ncontrolled.end()) {
            continue;
        }
        std::set<NBNode*> c;
        c.insert(cur);
        if (!shouldBeTLSControlled(c) || cur->getIncomingEdges().size() < 3) {
            continue;
        }
        setAsTLControlled((*i).second, tlc, type);
    }
}
Beispiel #12
0
unsigned int
NBNodeCont::joinJunctions(SUMOReal maxDist, NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc) {
    NodeClusters cands;
    NodeClusters clusters;
    generateNodeClusters(maxDist, cands);
    for (NodeClusters::iterator i = cands.begin(); i != cands.end(); ++i) {
        std::set<NBNode*> cluster = (*i);
        // remove join exclusions
        for (std::set<NBNode*>::iterator j = cluster.begin(); j != cluster.end();) {
            std::set<NBNode*>::iterator check = j;
            ++j;
            if (myJoinExclusions.count((*check)->getID()) > 0) {
                cluster.erase(check);
            }
        }
        // iteratively remove the fringe
        bool pruneFringe = true;
        while (pruneFringe) {
            pruneFringe = false;
            for (std::set<NBNode*>::iterator j = cluster.begin(); j != cluster.end();) {
                std::set<NBNode*>::iterator check = j;
                NBNode* n = *check;
                ++j;
                // remove geometry-like nodes at fringe of the cluster
                // (they have 1 neighbor in the cluster and at most 1 neighbor outside the cluster)
                std::set<NBNode*> neighbors;
                std::set<NBNode*> clusterNeigbors;
                for (EdgeVector::const_iterator it_edge = n->getOutgoingEdges().begin(); it_edge != n->getOutgoingEdges().end(); ++it_edge) {
                    NBNode* neighbor = (*it_edge)->getToNode();
                    if (cluster.count(neighbor) == 0) {
                        neighbors.insert(neighbor);
                    } else {
                        clusterNeigbors.insert(neighbor);
                    }
                }
                for (EdgeVector::const_iterator it_edge = n->getIncomingEdges().begin(); it_edge != n->getIncomingEdges().end(); ++it_edge) {
                    NBNode* neighbor = (*it_edge)->getFromNode();
                    if (cluster.count(neighbor) == 0) {
                        neighbors.insert(neighbor);
                    } else {
                        clusterNeigbors.insert(neighbor);
                    }
                }
                if (neighbors.size() <= 1 && clusterNeigbors.size() == 1) {
                    cluster.erase(check);
                    pruneFringe = true; // other nodes could belong to the fringe now
                }
            }
        }
        // exclude the fromNode of a long edge if the toNode is in the cluster (and they were both added via an alternative path).
        std::set<NBNode*> toRemove;
        for (std::set<NBNode*>::iterator j = cluster.begin(); j != cluster.end(); ++j) {
            NBNode* n = *j;
            const EdgeVector& edges = n->getOutgoingEdges();
            for (EdgeVector::const_iterator it_edge = edges.begin(); it_edge != edges.end(); ++it_edge) {
                NBEdge* edge = *it_edge;
                if (cluster.count(edge->getToNode()) != 0 && edge->getLoadedLength() > maxDist) {
                    //std::cout << "long edge " << edge->getID() << " (" << edge->getLoadedLength() << ", max=" << maxDist << ")\n";
                    toRemove.insert(n);
                    toRemove.insert(edge->getToNode());
                }
            }
        }
        for (std::set<NBNode*>::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
            cluster.erase(*j);
        }
        if (cluster.size() > 1) {
            // check for clusters which are to complex and probably won't work very well
            // we count the incoming edges of the final junction
            std::set<NBEdge*> finalIncoming;
            std::set<NBEdge*> finalOutgoing;
            std::vector<std::string> nodeIDs;
            for (std::set<NBNode*>::const_iterator j = cluster.begin(); j != cluster.end(); ++j) {
                nodeIDs.push_back((*j)->getID());
                for (EdgeVector::const_iterator it_edge = (*j)->getIncomingEdges().begin(); it_edge != (*j)->getIncomingEdges().end(); ++it_edge) {
                    NBEdge* edge = *it_edge;
                    if (cluster.count(edge->getFromNode()) == 0) {
                        // incoming edge, does not originate in the cluster
                        finalIncoming.insert(edge);
                    }
                }
                for (EdgeVector::const_iterator it_edge = (*j)->getOutgoingEdges().begin(); it_edge != (*j)->getOutgoingEdges().end(); ++it_edge) {
                    NBEdge* edge = *it_edge;
                    if (cluster.count(edge->getToNode()) == 0) {
                        // outgoing edge, does not end in the cluster
                        finalOutgoing.insert(edge);
                    }
                }

            }
            if (finalIncoming.size() > 4) {
                std::sort(nodeIDs.begin(), nodeIDs.end());
                WRITE_WARNING("Not joining junctions " + joinToStringSorting(nodeIDs, ',') + " because the cluster is too complex (" + toString(finalIncoming.size()) + " incoming edges)");
            } else {
                // check for incoming parallel edges
                const SUMOReal PARALLEL_INCOMING_THRESHOLD = 10.0;
                bool foundParallel = false;
                for (std::set<NBEdge*>::const_iterator j = finalIncoming.begin(); j != finalIncoming.end() && !foundParallel; ++j) {
                    for (std::set<NBEdge*>::const_iterator k = finalIncoming.begin(); k != finalIncoming.end() && !foundParallel; ++k) {
                        if ((*j) != (*k) && fabs((*j)->getAngleAtNode((*j)->getToNode()) - (*k)->getAngleAtNode((*k)->getToNode())) < PARALLEL_INCOMING_THRESHOLD) {
                            std::vector<std::string> parallelEdgeIDs;
                            parallelEdgeIDs.push_back((*j)->getID());
                            parallelEdgeIDs.push_back((*k)->getID());
                            std::sort(parallelEdgeIDs.begin(), parallelEdgeIDs.end());
                            WRITE_WARNING("Not joining junctions " + joinToStringSorting(nodeIDs, ',') + " because the cluster is too complex (parallel incoming "
                                          + joinToString(parallelEdgeIDs, ',') + ")");
                            foundParallel = true;
                        }
                    }
                }
                // check for outgoing parallel edges
                for (std::set<NBEdge*>::const_iterator j = finalOutgoing.begin(); j != finalOutgoing.end() && !foundParallel; ++j) {
                    for (std::set<NBEdge*>::const_iterator k = finalOutgoing.begin(); k != finalOutgoing.end() && !foundParallel; ++k) {
                        if ((*j) != (*k) && fabs((*j)->getAngleAtNode((*j)->getFromNode()) - (*k)->getAngleAtNode((*k)->getFromNode())) < PARALLEL_INCOMING_THRESHOLD) {
                            std::vector<std::string> parallelEdgeIDs;
                            parallelEdgeIDs.push_back((*j)->getID());
                            parallelEdgeIDs.push_back((*k)->getID());
                            std::sort(parallelEdgeIDs.begin(), parallelEdgeIDs.end());
                            WRITE_WARNING("Not joining junctions " + joinToStringSorting(nodeIDs, ',') + " because the cluster is too complex (parallel outgoing "
                                          + joinToStringSorting(parallelEdgeIDs, ',') + ")");
                            foundParallel = true;
                        }
                    }
                }
                if (!foundParallel && cluster.size() > 1) {
                    // compute all connected components of this cluster
                    // (may be more than 1 if intermediate nodes were removed)
                    NodeClusters components;
                    for (std::set<NBNode*>::iterator j = cluster.begin(); j != cluster.end(); ++j) {
                        // merge all connected components into newComp
                        std::set<NBNode*> newComp;
                        NBNode* current = *j;
                        //std::cout << "checking connectivity for " << current->getID() << "\n";
                        newComp.insert(current);
                        for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end();) {
                            NodeClusters::iterator check = it_comp;
                            //std::cout << "   connected with " << toString(*check) << "?\n";
                            bool connected = false;
                            for (std::set<NBNode*>::iterator k = (*check).begin(); k != (*check).end(); ++k) {
                                if (current->getConnectionTo(*k) != 0 || (*k)->getConnectionTo(current) != 0) {
                                    //std::cout << "joining with connected component " << toString(*check) << "\n";
                                    newComp.insert((*check).begin(), (*check).end());
                                    it_comp = components.erase(check);
                                    connected = true;
                                    break;
                                }
                            }
                            if (!connected) {
                                it_comp++;
                            }
                        }
                        //std::cout << "adding new component " << toString(newComp) << "\n";
                        components.push_back(newComp);
                    }
                    for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end(); ++it_comp) {
                        if ((*it_comp).size() > 1) {
                            //std::cout << "adding cluster " << toString(*it_comp) << "\n";
                            clusters.push_back(*it_comp);
                        }
                    }
                }
            }
        }
    }
    joinNodeClusters(clusters, dc, ec, tlc);
    return (int)clusters.size();
}
void
NIImporter_SUMO::_loadNetwork(const OptionsCont& oc) {
    // check whether the option is set (properly)
    if (!oc.isUsableFileList("sumo-net-file")) {
        return;
    }
    // parse file(s)
    std::vector<std::string> files = oc.getStringVector("sumo-net-file");
    for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
        if (!FileHelpers::exists(*file)) {
            WRITE_ERROR("Could not open sumo-net-file '" + *file + "'.");
            return;
        }
        setFileName(*file);
        PROGRESS_BEGIN_MESSAGE("Parsing sumo-net from '" + *file + "'");
        XMLSubSys::runParser(*this, *file);
        PROGRESS_DONE_MESSAGE();
    }
    // build edges
    for (std::map<std::string, EdgeAttrs*>::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
        EdgeAttrs* ed = (*i).second;
        // skip internal edges
        if (ed->func == EDGEFUNC_INTERNAL) {
            continue;
        }
        // get and check the nodes
        NBNode* from = myNodeCont.retrieve(ed->fromNode);
        NBNode* to = myNodeCont.retrieve(ed->toNode);
        if (from == 0) {
            WRITE_ERROR("Edge's '" + ed->id + "' from-node '" + ed->fromNode + "' is not known.");
            continue;
        }
        if (to == 0) {
            WRITE_ERROR("Edge's '" + ed->id + "' to-node '" + ed->toNode + "' is not known.");
            continue;
        }
        // edge shape
        PositionVector geom;
        if (ed->shape.size() > 0) {
            geom = ed->shape;
            mySuspectKeepShape = false; // no problem with reconstruction if edge shape is given explicit
        } else {
            // either the edge has default shape consisting only of the two node
            // positions or we have a legacy network
            geom = reconstructEdgeShape(ed, from->getPosition(), to->getPosition());
        }
        // build and insert the edge
        NBEdge* e = new NBEdge(ed->id, from, to,
                               ed->type, ed->maxSpeed,
                               (unsigned int) ed->lanes.size(),
                               ed->priority, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET,
                               geom, ed->streetName, ed->lsf, true); // always use tryIgnoreNodePositions to keep original shape
        e->setLoadedLength(ed->length);
        if (!myNetBuilder.getEdgeCont().insert(e)) {
            WRITE_ERROR("Could not insert edge '" + ed->id + "'.");
            delete e;
            continue;
        }
        ed->builtEdge = myNetBuilder.getEdgeCont().retrieve(ed->id);
    }
    // assign further lane attributes (edges are built)
    for (std::map<std::string, EdgeAttrs*>::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
        EdgeAttrs* ed = (*i).second;
        NBEdge* nbe = ed->builtEdge;
        if (nbe == 0) { // inner edge or removed by explicit list, vclass, ...
            continue;
        }
        for (unsigned int fromLaneIndex = 0; fromLaneIndex < (unsigned int) ed->lanes.size(); ++fromLaneIndex) {
            LaneAttrs* lane = ed->lanes[fromLaneIndex];
            // connections
            const std::vector<Connection>& connections = lane->connections;
            for (std::vector<Connection>::const_iterator c_it = connections.begin(); c_it != connections.end(); c_it++) {
                const Connection& c = *c_it;
                if (myEdges.count(c.toEdgeID) == 0) {
                    WRITE_ERROR("Unknown edge '" + c.toEdgeID + "' given in connection.");
                    continue;
                }
                NBEdge* toEdge = myEdges[c.toEdgeID]->builtEdge;
                if (toEdge == 0) { // removed by explicit list, vclass, ...
                    continue;
                }
                nbe->addLane2LaneConnection(
                    fromLaneIndex, toEdge, c.toLaneIdx, NBEdge::L2L_VALIDATED,
                    false, c.mayDefinitelyPass);

                // maybe we have a tls-controlled connection
                if (c.tlID != "" && !OptionsCont::getOptions().getBool("tls.discard-loaded")) {
                    const std::map<std::string, NBTrafficLightDefinition*>& programs = myTLLCont.getPrograms(c.tlID);
                    if (programs.size() > 0) {
                        std::map<std::string, NBTrafficLightDefinition*>::const_iterator it;
                        for (it = programs.begin(); it != programs.end(); it++) {
                            NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(it->second);
                            if (tlDef) {
                                tlDef->addConnection(nbe, toEdge, fromLaneIndex, c.toLaneIdx, c.tlLinkNo);
                            } else {
                                throw ProcessError("Corrupt traffic light definition '" + c.tlID + "' (program '" + it->first + "')");
                            }
                        }
                    } else {
                        WRITE_ERROR("The traffic light '" + c.tlID + "' is not known.");
                    }
                }
            }
            // allow/disallow XXX preferred
            nbe->setPermissions(parseVehicleClasses(lane->allow, lane->disallow), fromLaneIndex);
            // width, offset
            nbe->setWidth(fromLaneIndex, lane->width);
            nbe->setOffset(fromLaneIndex, lane->offset);
            nbe->setSpeed(fromLaneIndex, lane->maxSpeed);
        }
        nbe->declareConnectionsAsLoaded();
    }
    // insert loaded prohibitions
    for (std::vector<Prohibition>::const_iterator it = myProhibitions.begin(); it != myProhibitions.end(); it++) {
        NBEdge* prohibitedFrom = myEdges[it->prohibitedFrom]->builtEdge;
        if (prohibitedFrom == 0) {
            WRITE_ERROR("Edge '" + it->prohibitedFrom + "' in prohibition was not built");
        } else {
            NBNode* n = prohibitedFrom->getToNode();
            n->addSortedLinkFoes(
                NBConnection(myEdges[it->prohibitorFrom]->builtEdge, myEdges[it->prohibitorTo]->builtEdge),
                NBConnection(prohibitedFrom, myEdges[it->prohibitedTo]->builtEdge));
        }
    }

    // final warning
    if (mySuspectKeepShape) {
        WRITE_WARNING("The input network may have been built using option 'xml.keep-shape'.\n... Accuracy of junction positions cannot be guaranteed.");
    }

}
void
NBNodeCont::guessTLs(OptionsCont& oc, NBTrafficLightLogicCont& tlc) {
    // build list of definitely not tls-controlled junctions
    std::vector<NBNode*> ncontrolled;
    if (oc.isSet("tls.unset")) {
        std::vector<std::string> notTLControlledNodes = oc.getStringVector("tls.unset");
        for (std::vector<std::string>::const_iterator i = notTLControlledNodes.begin(); i != notTLControlledNodes.end(); ++i) {
            NBNode* n = NBNodeCont::retrieve(*i);
            if (n == 0) {
                throw ProcessError(" The node '" + *i + "' to set as not-controlled is not known.");
            }
            std::set<NBTrafficLightDefinition*> tls = n->getControllingTLS();
            for (std::set<NBTrafficLightDefinition*>::const_iterator j = tls.begin(); j != tls.end(); ++j) {
                (*j)->removeNode(n);
            }
            n->removeTrafficLights();
            ncontrolled.push_back(n);
        }
    }

    TrafficLightType type = SUMOXMLDefinitions::TrafficLightTypes.get(OptionsCont::getOptions().getString("tls.default-type"));
    // loop#1 checking whether the node shall be tls controlled,
    //  because it is assigned to a district
    if (oc.exists("tls.taz-nodes") && oc.getBool("tls.taz-nodes")) {
        for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
            NBNode* cur = (*i).second;
            if (cur->isNearDistrict() && find(ncontrolled.begin(), ncontrolled.end(), cur) == ncontrolled.end()) {
                setAsTLControlled(cur, tlc, type);
            }
        }
    }

    // maybe no tls shall be guessed
    if (!oc.getBool("tls.guess")) {
        return;
    }

    // guess joined tls first, if wished
    if (oc.getBool("tls.join")) {
        // get node clusters
        std::vector<std::set<NBNode*> > cands;
        generateNodeClusters(oc.getFloat("tls.join-dist"), cands);
        // check these candidates (clusters) whether they should be controlled by a tls
        for (std::vector<std::set<NBNode*> >::iterator i = cands.begin(); i != cands.end();) {
            std::set<NBNode*>& c = (*i);
            // regard only junctions which are not yet controlled and are not
            //  forbidden to be controlled
            for (std::set<NBNode*>::iterator j = c.begin(); j != c.end();) {
                if ((*j)->isTLControlled() || find(ncontrolled.begin(), ncontrolled.end(), *j) != ncontrolled.end()) {
                    c.erase(j++);
                } else {
                    ++j;
                }
            }
            // check whether the cluster should be controlled
            if (!shouldBeTLSControlled(c)) {
                i = cands.erase(i);
            } else {
                ++i;
            }
        }
        // cands now only contain sets of junctions that shall be joined into being tls-controlled
        unsigned int index = 0;
        for (std::vector<std::set<NBNode*> >::iterator i = cands.begin(); i != cands.end(); ++i) {
            std::vector<NBNode*> nodes;
            for (std::set<NBNode*>::iterator j = (*i).begin(); j != (*i).end(); j++) {
                nodes.push_back(*j);
            }
            std::string id = "joinedG_" + toString(index++);
            NBTrafficLightDefinition* tlDef = new NBOwnTLDef(id, nodes, 0, type);
            if (!tlc.insert(tlDef)) {
                // actually, nothing should fail here
                WRITE_WARNING("Could not build guessed, joined tls");
                delete tlDef;
                return;
            }
        }
    }

    // guess tls
    for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
        NBNode* cur = (*i).second;
        //  do nothing if already is tl-controlled
        if (cur->isTLControlled()) {
            continue;
        }
        // do nothing if in the list of explicit non-controlled junctions
        if (find(ncontrolled.begin(), ncontrolled.end(), cur) != ncontrolled.end()) {
            continue;
        }
        std::set<NBNode*> c;
        c.insert(cur);
        if (!shouldBeTLSControlled(c) || cur->getIncomingEdges().size() < 3) {
            continue;
        }
        setAsTLControlled((*i).second, tlc, type);
    }
}
Beispiel #15
0
// ===========================================================================
// method definitions
// ===========================================================================
// ---------------------------------------------------------------------------
// static methods
// ---------------------------------------------------------------------------
void
NWWriter_SUMO::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) {
    // check whether a sumo net-file shall be generated
    if (!oc.isSet("output-file")) {
        return;
    }
    OutputDevice& device = OutputDevice::getDevice(oc.getString("output-file"));
    const std::string lefthand = oc.getBool("lefthand") ? " " + toString(SUMO_ATTR_LEFTHAND) + "=\"true\"" : "";
    const int cornerDetail = oc.getInt("junctions.corner-detail");
    const int linkDetail = oc.getInt("junctions.internal-link-detail");
    const std::string junctionCornerDetail = (cornerDetail > 0
            ? " " + toString(SUMO_ATTR_CORNERDETAIL) + "=\"" + toString(cornerDetail) + "\"" : "");
    const std::string junctionLinkDetail = (oc.isDefault("junctions.internal-link-detail") ? "" :
                                            " " + toString(SUMO_ATTR_LINKDETAIL) + "=\"" + toString(linkDetail) + "\"");
    device.writeXMLHeader("net", NWFrame::MAJOR_VERSION + lefthand + junctionCornerDetail + junctionLinkDetail +
                          " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.dlr.de/xsd/net_file.xsd\""); // street names may contain non-ascii chars
    device.lf();
    // get involved container
    const NBNodeCont& nc = nb.getNodeCont();
    const NBEdgeCont& ec = nb.getEdgeCont();
    const NBDistrictCont& dc = nb.getDistrictCont();

    // write network offsets and projection
    GeoConvHelper::writeLocation(device);

    // write edge types and restrictions
    nb.getTypeCont().writeTypes(device);

    // write inner lanes
    bool origNames = oc.getBool("output.original-names");
    if (!oc.getBool("no-internal-links")) {
        bool hadAny = false;
        for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
            hadAny |= writeInternalEdges(device, *(*i).second, origNames);
        }
        if (hadAny) {
            device.lf();
        }
    }

    // write edges with lanes and connected edges
    bool noNames = !oc.getBool("output.street-names");
    for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
        writeEdge(device, *(*i).second, noNames, origNames);
    }
    device.lf();

    // write tls logics
    writeTrafficLights(device, nb.getTLLogicCont());

    // write the nodes (junctions)
    std::set<NBNode*> roundaboutNodes;
    const bool checkLaneFoesAll = oc.getBool("check-lane-foes.all");
    const bool checkLaneFoesRoundabout = !checkLaneFoesAll && oc.getBool("check-lane-foes.roundabout");
    if (checkLaneFoesRoundabout) {
        const std::set<EdgeSet>& roundabouts = ec.getRoundabouts();
        for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
            for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
                roundaboutNodes.insert((*j)->getToNode());
            }
        }
    }
    for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
        const bool checkLaneFoes = checkLaneFoesAll || (checkLaneFoesRoundabout && roundaboutNodes.count((*i).second) > 0);
        writeJunction(device, *(*i).second, checkLaneFoes);
    }
    device.lf();
    const bool includeInternal = !oc.getBool("no-internal-links");
    if (includeInternal) {
        // ... internal nodes if not unwanted
        bool hadAny = false;
        for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
            hadAny |= writeInternalNodes(device, *(*i).second);
        }
        if (hadAny) {
            device.lf();
        }
    }

    // write the successors of lanes
    unsigned int numConnections = 0;
    for (std::map<std::string, NBEdge*>::const_iterator it_edge = ec.begin(); it_edge != ec.end(); it_edge++) {
        NBEdge* from = it_edge->second;
        from->sortOutgoingConnectionsByIndex();
        const std::vector<NBEdge::Connection> connections = from->getConnections();
        numConnections += (unsigned int)connections.size();
        for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); it_c++) {
            writeConnection(device, *from, *it_c, includeInternal);
        }
    }
    if (numConnections > 0) {
        device.lf();
    }
    if (includeInternal) {
        // ... internal successors if not unwanted
        bool hadAny = false;
        for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
            hadAny |= writeInternalConnections(device, *(*i).second);
        }
        if (hadAny) {
            device.lf();
        }
    }
    for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
        NBNode* node = (*i).second;
        // write connections from pedestrian crossings
        const std::vector<NBNode::Crossing>& crossings = node->getCrossings();
        for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) {
            NWWriter_SUMO::writeInternalConnection(device, (*it).id, (*it).nextWalkingArea, 0, 0, "");
        }
        // write connections from pedestrian walking areas
        const std::vector<NBNode::WalkingArea>& WalkingAreas = node->getWalkingAreas();
        for (std::vector<NBNode::WalkingArea>::const_iterator it = WalkingAreas.begin(); it != WalkingAreas.end(); it++) {
            if ((*it).nextCrossing != "") {
                const NBNode::Crossing& nextCrossing = node->getCrossing((*it).nextCrossing);
                // connection to next crossing (may be tls-controlled)
                device.openTag(SUMO_TAG_CONNECTION);
                device.writeAttr(SUMO_ATTR_FROM, (*it).id);
                device.writeAttr(SUMO_ATTR_TO, (*it).nextCrossing);
                device.writeAttr(SUMO_ATTR_FROM_LANE, 0);
                device.writeAttr(SUMO_ATTR_TO_LANE, 0);
                if (node->isTLControlled()) {
                    device.writeAttr(SUMO_ATTR_TLID, (*node->getControllingTLS().begin())->getID());
                    assert(nextCrossing.tlLinkNo >= 0);
                    device.writeAttr(SUMO_ATTR_TLLINKINDEX, nextCrossing.tlLinkNo);
                }
                device.writeAttr(SUMO_ATTR_DIR, LINKDIR_STRAIGHT);
                device.writeAttr(SUMO_ATTR_STATE, nextCrossing.priority ? LINKSTATE_MAJOR : LINKSTATE_MINOR);
                device.closeTag();
            }
            // optional connections from/to sidewalk
            for (std::vector<std::string>::const_iterator it_sw = (*it).nextSidewalks.begin(); it_sw != (*it).nextSidewalks.end(); ++it_sw) {
                NWWriter_SUMO::writeInternalConnection(device, (*it).id, (*it_sw), 0, 0, "");
            }
            for (std::vector<std::string>::const_iterator it_sw = (*it).prevSidewalks.begin(); it_sw != (*it).prevSidewalks.end(); ++it_sw) {
                NWWriter_SUMO::writeInternalConnection(device, (*it_sw), (*it).id, 0, 0, "");
            }
        }
    }

    // write loaded prohibitions
    for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
        writeProhibitions(device, i->second->getProhibitions());
    }

    // write roundabout information
    writeRoundabouts(device, ec.getRoundabouts(), ec);

    // write the districts
    for (std::map<std::string, NBDistrict*>::const_iterator i = dc.begin(); i != dc.end(); i++) {
        writeDistrict(device, *(*i).second);
    }
    if (dc.size() != 0) {
        device.lf();
    }
    device.close();
}
bool
NBTrafficLightDefinition::forbids(const NBEdge* const possProhibitorFrom,
                                  const NBEdge* const possProhibitorTo,
                                  const NBEdge* const possProhibitedFrom,
                                  const NBEdge* const possProhibitedTo,
                                  bool regardNonSignalisedLowerPriority,
                                  bool sameNodeOnly) const {
    if (possProhibitorFrom == 0 || possProhibitorTo == 0 || possProhibitedFrom == 0 || possProhibitedTo == 0) {
        return false;
    }
    // retrieve both nodes
    std::vector<NBNode*>::const_iterator incoming =
        find_if(myControlledNodes.begin(), myControlledNodes.end(), NBContHelper::node_with_incoming_finder(possProhibitorFrom));
    std::vector<NBNode*>::const_iterator outgoing =
        find_if(myControlledNodes.begin(), myControlledNodes.end(), NBContHelper::node_with_outgoing_finder(possProhibitedTo));
    assert(incoming != myControlledNodes.end());
    NBNode* incnode = *incoming;
    NBNode* outnode = *outgoing;
    EdgeVector::const_iterator i;

    if (incnode != outnode) {
        if (sameNodeOnly) {
            return false;
        }
        // the links are located at different nodes
        const EdgeVector& ev1 = possProhibitedTo->getConnectedEdges();
        // go through the following edge,
        //  check whether one of these connections is prohibited
        for (i = ev1.begin(); i != ev1.end(); ++i) {
            std::vector<NBNode*>::const_iterator outgoing2 =
                find_if(myControlledNodes.begin(), myControlledNodes.end(), NBContHelper::node_with_outgoing_finder(*i));
            if (outgoing2 == myControlledNodes.end()) {
                continue;
            }
            NBNode* outnode2 = *outgoing2;
            if (incnode != outnode2) {
                continue;
            }
            if (incnode->getDirection(possProhibitedTo, *i) != LINKDIR_STRAIGHT) {
                continue;
            }
            bool ret1 = incnode->foes(possProhibitorFrom, possProhibitorTo,
                                      possProhibitedTo, *i);
            bool ret2 = incnode->forbids(possProhibitorFrom, possProhibitorTo,
                                         possProhibitedTo, *i,
                                         regardNonSignalisedLowerPriority);
            bool ret = ret1 || ret2;
            if (ret) {
                return true;
            }
        }

        const EdgeVector& ev2 = possProhibitorTo->getConnectedEdges();
        // go through the following edge,
        //  check whether one of these connections is prohibited
        for (i = ev2.begin(); i != ev2.end(); ++i) {
            std::vector<NBNode*>::const_iterator incoming2 =
                find_if(myControlledNodes.begin(), myControlledNodes.end(), NBContHelper::node_with_incoming_finder(possProhibitorTo));
            if (incoming2 == myControlledNodes.end()) {
                continue;
            }
            NBNode* incnode2 = *incoming2;
            if (incnode2 != outnode) {
                continue;
            }
            if (incnode2->getDirection(possProhibitorTo, *i) != LINKDIR_STRAIGHT) {
                continue;
            }
            bool ret1 = incnode2->foes(possProhibitorTo, *i,
                                       possProhibitedFrom, possProhibitedTo);
            bool ret2 = incnode2->forbids(possProhibitorTo, *i,
                                          possProhibitedFrom, possProhibitedTo,
                                          regardNonSignalisedLowerPriority);
            bool ret = ret1 || ret2;
            if (ret) {
                return true;
            }
        }
        return false;
    }
    // both links are located at the same node
    //  check using this node's information
    return incnode->forbids(possProhibitorFrom, possProhibitorTo,
                            possProhibitedFrom, possProhibitedTo,
                            regardNonSignalisedLowerPriority);
}
Beispiel #17
0
void
GNELane::drawArrows() const {
    const Position& end = getShape().back();
    const Position& f = getShape()[-2];
    SUMOReal rot = (SUMOReal) atan2((end.x() - f.x()), (f.y() - end.y())) * (SUMOReal) 180.0 / (SUMOReal) PI;
    glPushMatrix();
    glPushName(0);
    glTranslated(0, 0, GLO_JUNCTION + .1); // must draw on top of junction shape
    glColor3d(1, 1, 1);
    glTranslated(end.x(), end.y(), 0);
    glRotated(rot, 0, 0, 1);

    // draw all links
    const std::vector<NBEdge::Connection>& edgeCons = myParentEdge.getNBEdge()->myConnections;
    NBNode* dest = myParentEdge.getNBEdge()->myTo;
    for (std::vector<NBEdge::Connection>::const_iterator i = edgeCons.begin(); i != edgeCons.end(); ++i) {
        if ((*i).fromLane == myIndex) {
            LinkDirection dir = dest->getDirection(myParentEdge.getNBEdge(), i->toEdge, OptionsCont::getOptions().getBool("lefthand"));
            switch (dir) {
                case LINKDIR_STRAIGHT:
                    GLHelper::drawBoxLine(Position(0, 4), 0, 2, .05);
                    GLHelper::drawTriangleAtEnd(Position(0, 4), Position(0, 1), (SUMOReal) 1, (SUMOReal) .25);
                    break;
                case LINKDIR_LEFT:
                    GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
                    GLHelper::drawBoxLine(Position(0, 2.5), 90, 1, .05);
                    GLHelper::drawTriangleAtEnd(Position(0, 2.5), Position(1.5, 2.5), (SUMOReal) 1, (SUMOReal) .25);
                    break;
                case LINKDIR_RIGHT:
                    GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
                    GLHelper::drawBoxLine(Position(0, 2.5), -90, 1, .05);
                    GLHelper::drawTriangleAtEnd(Position(0, 2.5), Position(-1.5, 2.5), (SUMOReal) 1, (SUMOReal) .25);
                    break;
                case LINKDIR_TURN:
                    GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
                    GLHelper::drawBoxLine(Position(0, 2.5), 90, .5, .05);
                    GLHelper::drawBoxLine(Position(0.5, 2.5), 180, 1, .05);
                    GLHelper::drawTriangleAtEnd(Position(0.5, 2.5), Position(0.5, 4), (SUMOReal) 1, (SUMOReal) .25);
                    break;
                case LINKDIR_TURN_LEFTHAND:
                    GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
                    GLHelper::drawBoxLine(Position(0, 2.5), -90, 1, .05);
                    GLHelper::drawBoxLine(Position(-0.5, 2.5), -180, 1, .05);
                    GLHelper::drawTriangleAtEnd(Position(-0.5, 2.5), Position(-0.5, 4), (SUMOReal) 1, (SUMOReal) .25);
                    break;
                case LINKDIR_PARTLEFT:
                    GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
                    GLHelper::drawBoxLine(Position(0, 2.5), 45, .7, .05);
                    GLHelper::drawTriangleAtEnd(Position(0, 2.5), Position(1.2, 1.3), (SUMOReal) 1, (SUMOReal) .25);
                    break;
                case LINKDIR_PARTRIGHT:
                    GLHelper::drawBoxLine(Position(0, 4), 0, 1.5, .05);
                    GLHelper::drawBoxLine(Position(0, 2.5), -45, .7, .05);
                    GLHelper::drawTriangleAtEnd(Position(0, 2.5), Position(-1.2, 1.3), (SUMOReal) 1, (SUMOReal) .25);
                    break;
                case LINKDIR_NODIR:
                    GLHelper::drawBoxLine(Position(1, 5.8), 245, 2, .05);
                    GLHelper::drawBoxLine(Position(-1, 5.8), 115, 2, .05);
                    glTranslated(0, 5, 0);
                    GLHelper::drawOutlineCircle(0.9, 0.8, 32);
                    glTranslated(0, -5, 0);
                    break;
            }
        }
    }
    glPopName();
    glPopMatrix();
}
void
NIXMLConnectionsHandler::myStartElement(int element,
                                        const SUMOSAXAttributes& attrs) {
    if (element == SUMO_TAG_DELETE) {
        bool ok = true;
        std::string from = attrs.get<std::string>(SUMO_ATTR_FROM, 0, ok);
        std::string to = attrs.get<std::string>(SUMO_ATTR_TO, 0, ok);
        if (!ok) {
            return;
        }
        // these connections were removed when the edge was deleted
        if (myEdgeCont.wasRemoved(from) || myEdgeCont.wasRemoved(to)) {
            return;
        }
        NBEdge* fromEdge = myEdgeCont.retrieve(from);
        NBEdge* toEdge = myEdgeCont.retrieve(to);
        if (fromEdge == 0) {
            myErrorMsgHandler->inform("The connection-source edge '" + from + "' to reset is not known.");
            return;
        }
        if (toEdge == 0) {
            myErrorMsgHandler->inform("The connection-destination edge '" + to + "' to reset is not known.");
            return;
        }
        if (!fromEdge->isConnectedTo(toEdge) && fromEdge->getStep() >= NBEdge::EDGE2EDGES) {
            WRITE_WARNING("Target edge '" + toEdge->getID() + "' is not connected with '" + fromEdge->getID() + "'; the connection cannot be reset.");
            return;
        }
        int fromLane = -1; // Assume all lanes are to be reset.
        int toLane = -1;
        if (attrs.hasAttribute(SUMO_ATTR_LANE)
                || attrs.hasAttribute(SUMO_ATTR_FROM_LANE)
                || attrs.hasAttribute(SUMO_ATTR_TO_LANE)) {
            if (!parseLaneInfo(attrs, fromEdge, toEdge, &fromLane, &toLane)) {
                return;
            }
            // we could be trying to reset a connection loaded from a sumo net and which has become obsolete.
            // In this case it's ok to encounter invalid lance indices
            if (!fromEdge->hasConnectionTo(toEdge, toLane) && fromEdge->getStep() >= NBEdge::LANES2EDGES) {
                WRITE_WARNING("Edge '" + fromEdge->getID() + "' has no connection to lane " + toString(toLane) + " of edge '" + toEdge->getID() + "'; the connection cannot be reset.");
            }
        }
        fromEdge->removeFromConnections(toEdge, fromLane, toLane, true);
    }

    if (element == SUMO_TAG_CONNECTION) {
        bool ok = true;
        std::string from = attrs.get<std::string>(SUMO_ATTR_FROM, "connection", ok);
        std::string to = attrs.getOpt<std::string>(SUMO_ATTR_TO, "connection", ok, "");
        if (!ok || myEdgeCont.wasIgnored(from) || myEdgeCont.wasIgnored(to)) {
            return;
        }
        // extract edges
        NBEdge* fromEdge = myEdgeCont.retrieve(from);
        NBEdge* toEdge = to.length() != 0 ? myEdgeCont.retrieve(to) : 0;
        // check whether they are valid
        if (fromEdge == 0) {
            myErrorMsgHandler->inform("The connection-source edge '" + from + "' is not known.");
            return;
        }
        if (toEdge == 0 && to.length() != 0) {
            myErrorMsgHandler->inform("The connection-destination edge '" + to + "' is not known.");
            return;
        }
        fromEdge->getToNode()->invalidateTLS(myTLLogicCont, true, false);
        // parse optional lane information
        if (attrs.hasAttribute(SUMO_ATTR_LANE) || attrs.hasAttribute(SUMO_ATTR_FROM_LANE) || attrs.hasAttribute(SUMO_ATTR_TO_LANE)) {
            parseLaneBound(attrs, fromEdge, toEdge);
        } else {
            fromEdge->addEdge2EdgeConnection(toEdge);
        }
    }
    if (element == SUMO_TAG_PROHIBITION) {
        bool ok = true;
        std::string prohibitor = attrs.getOpt<std::string>(SUMO_ATTR_PROHIBITOR, 0, ok, "");
        std::string prohibited = attrs.getOpt<std::string>(SUMO_ATTR_PROHIBITED, 0, ok, "");
        if (!ok) {
            return;
        }
        NBConnection prohibitorC = parseConnection("prohibitor", prohibitor);
        NBConnection prohibitedC = parseConnection("prohibited", prohibited);
        if (prohibitorC == NBConnection::InvalidConnection || prohibitedC == NBConnection::InvalidConnection) {
            // something failed
            return;
        }
        NBNode* n = prohibitorC.getFrom()->getToNode();
        n->addSortedLinkFoes(prohibitorC, prohibitedC);
    }
    if (element == SUMO_TAG_CROSSING) {
        addCrossing(attrs);
    }
    if (element == SUMO_TAG_WALKINGAREA) {
        addWalkingArea(attrs);
    }
}
void
NIImporter_SUMO::_loadNetwork(OptionsCont& oc) {
    // check whether the option is set (properly)
    if (!oc.isUsableFileList("sumo-net-file")) {
        return;
    }
    // parse file(s)
    std::vector<std::string> files = oc.getStringVector("sumo-net-file");
    for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
        if (!FileHelpers::isReadable(*file)) {
            WRITE_ERROR("Could not open sumo-net-file '" + *file + "'.");
            return;
        }
        setFileName(*file);
        PROGRESS_BEGIN_MESSAGE("Parsing sumo-net from '" + *file + "'");
        XMLSubSys::runParser(*this, *file, true);
        PROGRESS_DONE_MESSAGE();
    }
    // build edges
    for (std::map<std::string, EdgeAttrs*>::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
        EdgeAttrs* ed = (*i).second;
        // skip internal edges
        if (ed->func == EDGEFUNC_INTERNAL || ed->func == EDGEFUNC_CROSSING || ed->func == EDGEFUNC_WALKINGAREA) {
            continue;
        }
        // get and check the nodes
        NBNode* from = myNodeCont.retrieve(ed->fromNode);
        NBNode* to = myNodeCont.retrieve(ed->toNode);
        if (from == 0) {
            WRITE_ERROR("Edge's '" + ed->id + "' from-node '" + ed->fromNode + "' is not known.");
            continue;
        }
        if (to == 0) {
            WRITE_ERROR("Edge's '" + ed->id + "' to-node '" + ed->toNode + "' is not known.");
            continue;
        }
        // edge shape
        PositionVector geom;
        if (ed->shape.size() > 0) {
            geom = ed->shape;
        } else {
            // either the edge has default shape consisting only of the two node
            // positions or we have a legacy network
            geom = reconstructEdgeShape(ed, from->getPosition(), to->getPosition());
        }
        // build and insert the edge
        NBEdge* e = new NBEdge(ed->id, from, to,
                               ed->type, ed->maxSpeed,
                               (unsigned int) ed->lanes.size(),
                               ed->priority, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET,
                               geom, ed->streetName, "", ed->lsf, true); // always use tryIgnoreNodePositions to keep original shape
        e->setLoadedLength(ed->length);
        if (!myNetBuilder.getEdgeCont().insert(e)) {
            WRITE_ERROR("Could not insert edge '" + ed->id + "'.");
            delete e;
            continue;
        }
        ed->builtEdge = myNetBuilder.getEdgeCont().retrieve(ed->id);
    }
    // assign further lane attributes (edges are built)
    for (std::map<std::string, EdgeAttrs*>::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
        EdgeAttrs* ed = (*i).second;
        NBEdge* nbe = ed->builtEdge;
        if (nbe == 0) { // inner edge or removed by explicit list, vclass, ...
            continue;
        }
        for (unsigned int fromLaneIndex = 0; fromLaneIndex < (unsigned int) ed->lanes.size(); ++fromLaneIndex) {
            LaneAttrs* lane = ed->lanes[fromLaneIndex];
            // connections
            const std::vector<Connection>& connections = lane->connections;
            for (std::vector<Connection>::const_iterator c_it = connections.begin(); c_it != connections.end(); c_it++) {
                const Connection& c = *c_it;
                if (myEdges.count(c.toEdgeID) == 0) {
                    WRITE_ERROR("Unknown edge '" + c.toEdgeID + "' given in connection.");
                    continue;
                }
                NBEdge* toEdge = myEdges[c.toEdgeID]->builtEdge;
                if (toEdge == 0) { // removed by explicit list, vclass, ...
                    continue;
                }
                if (nbe->hasConnectionTo(toEdge, c.toLaneIdx)) {
                    WRITE_WARNING("Target lane '" + toEdge->getLaneID(c.toLaneIdx) + "' has multiple connections from '" + nbe->getID() + "'.");
                }
                nbe->addLane2LaneConnection(
                    fromLaneIndex, toEdge, c.toLaneIdx, NBEdge::L2L_VALIDATED,
                    true, c.mayDefinitelyPass, c.keepClear, c.contPos);

                // maybe we have a tls-controlled connection
                if (c.tlID != "" && myRailSignals.count(c.tlID) == 0) {
                    const std::map<std::string, NBTrafficLightDefinition*>& programs = myTLLCont.getPrograms(c.tlID);
                    if (programs.size() > 0) {
                        std::map<std::string, NBTrafficLightDefinition*>::const_iterator it;
                        for (it = programs.begin(); it != programs.end(); it++) {
                            NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(it->second);
                            if (tlDef) {
                                tlDef->addConnection(nbe, toEdge, fromLaneIndex, c.toLaneIdx, c.tlLinkNo);
                            } else {
                                throw ProcessError("Corrupt traffic light definition '" + c.tlID + "' (program '" + it->first + "')");
                            }
                        }
                    } else {
                        WRITE_ERROR("The traffic light '" + c.tlID + "' is not known.");
                    }
                }
            }
            // allow/disallow XXX preferred
            nbe->setPermissions(parseVehicleClasses(lane->allow, lane->disallow), fromLaneIndex);
            // width, offset
            nbe->setLaneWidth(fromLaneIndex, lane->width);
            nbe->setEndOffset(fromLaneIndex, lane->endOffset);
            nbe->setSpeed(fromLaneIndex, lane->maxSpeed);
        }
        nbe->declareConnectionsAsLoaded();
        if (!nbe->hasLaneSpecificWidth() && nbe->getLanes()[0].width != NBEdge::UNSPECIFIED_WIDTH) {
            nbe->setLaneWidth(-1, nbe->getLaneWidth(0));
        }
        if (!nbe->hasLaneSpecificEndOffset() && nbe->getEndOffset(0) != NBEdge::UNSPECIFIED_OFFSET) {
            nbe->setEndOffset(-1, nbe->getEndOffset(0));
        }
    }
    // insert loaded prohibitions
    for (std::vector<Prohibition>::const_iterator it = myProhibitions.begin(); it != myProhibitions.end(); it++) {
        NBEdge* prohibitedFrom = myEdges[it->prohibitedFrom]->builtEdge;
        NBEdge* prohibitedTo = myEdges[it->prohibitedTo]->builtEdge;
        NBEdge* prohibitorFrom = myEdges[it->prohibitorFrom]->builtEdge;
        NBEdge* prohibitorTo = myEdges[it->prohibitorTo]->builtEdge;
        if (prohibitedFrom == 0) {
            WRITE_WARNING("Edge '" + it->prohibitedFrom + "' in prohibition was not built");
        } else if (prohibitedTo == 0) {
            WRITE_WARNING("Edge '" + it->prohibitedTo + "' in prohibition was not built");
        } else if (prohibitorFrom == 0) {
            WRITE_WARNING("Edge '" + it->prohibitorFrom + "' in prohibition was not built");
        } else if (prohibitorTo == 0) {
            WRITE_WARNING("Edge '" + it->prohibitorTo + "' in prohibition was not built");
        } else {
            NBNode* n = prohibitedFrom->getToNode();
            n->addSortedLinkFoes(
                NBConnection(prohibitorFrom, prohibitorTo),
                NBConnection(prohibitedFrom, prohibitedTo));
        }
    }
    if (!myHaveSeenInternalEdge) {
        myNetBuilder.haveLoadedNetworkWithoutInternalEdges();
    }
    if (oc.isDefault("lefthand")) {
        oc.set("lefthand", toString(myAmLefthand));
    }
    if (oc.isDefault("junctions.corner-detail")) {
        oc.set("junctions.corner-detail", toString(myCornerDetail));
    }
    if (oc.isDefault("junctions.internal-link-detail") && myLinkDetail > 0) {
        oc.set("junctions.internal-link-detail", toString(myLinkDetail));
    }
    if (!deprecatedVehicleClassesSeen.empty()) {
        WRITE_WARNING("Deprecated vehicle class(es) '" + toString(deprecatedVehicleClassesSeen) + "' in input network.");
        deprecatedVehicleClassesSeen.clear();
    }
    // add loaded crossings
    if (!oc.getBool("no-internal-links")) {
        for (std::map<std::string, std::vector<Crossing> >::const_iterator it = myPedestrianCrossings.begin(); it != myPedestrianCrossings.end(); ++it) {
            NBNode* node = myNodeCont.retrieve((*it).first);
            for (std::vector<Crossing>::const_iterator it_c = (*it).second.begin(); it_c != (*it).second.end(); ++it_c) {
                const Crossing& crossing = (*it_c);
                EdgeVector edges;
                for (std::vector<std::string>::const_iterator it_e = crossing.crossingEdges.begin(); it_e != crossing.crossingEdges.end(); ++it_e) {
                    NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(*it_e);
                    // edge might have been removed due to options
                    if (edge != 0) {
                        edges.push_back(edge);
                    }
                }
                if (edges.size() > 0) {
                    node->addCrossing(edges, crossing.width, crossing.priority, true);
                }
            }
        }
    }
    // add roundabouts
    for (std::vector<std::vector<std::string> >::const_iterator it = myRoundabouts.begin(); it != myRoundabouts.end(); ++it) {
        EdgeSet roundabout;
        for (std::vector<std::string>::const_iterator it_r = it->begin(); it_r != it->end(); ++it_r) {
            NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(*it_r);
            if (edge == 0) {
                if (!myNetBuilder.getEdgeCont().wasIgnored(*it_r)) {
                    WRITE_ERROR("Unknown edge '" + (*it_r) + "' in roundabout");
                }
            } else {
                roundabout.insert(edge);
            }
        }
        myNetBuilder.getEdgeCont().addRoundabout(roundabout);
    }
}
void
NIImporter_VISUM::parse_Lanes() {
    // get the node
    NBNode* node = getNamedNode("KNOTNR");
    // get the edge
    NBEdge* baseEdge = getNamedEdge("STRNR");
    NBEdge* edge = getNamedEdgeContinuating("STRNR", node);
    // check
    if (node == 0 || edge == 0) {
        return;
    }
    // get the lane
    std::string laneS = myLineParser.know("FSNR")
                        ? NBHelpers::normalIDRepresentation(myLineParser.get("FSNR"))
                        : NBHelpers::normalIDRepresentation(myLineParser.get("NR"));
    int lane = -1;
    try {
        lane = TplConvert::_2int(laneS.c_str());
    } catch (NumberFormatException&) {
        WRITE_ERROR("A lane number for edge '" + edge->getID() + "' is not numeric (" + laneS + ").");
        return;
    }
    lane -= 1;
    if (lane < 0) {
        WRITE_ERROR("A lane number for edge '" + edge->getID() + "' is not positive (" + laneS + ").");
        return;
    }
    // get the direction
    std::string dirS = NBHelpers::normalIDRepresentation(myLineParser.get("RICHTTYP"));
    int prevLaneNo = baseEdge->getNumLanes();
    if ((dirS == "1" && !(node->hasIncoming(edge))) || (dirS == "0" && !(node->hasOutgoing(edge)))) {
        // get the last part of the turnaround direction
        edge = getReversedContinuating(edge, node);
    }
    // get the length
    std::string lengthS = NBHelpers::normalIDRepresentation(myLineParser.get("LAENGE"));
    SUMOReal length = -1;
    try {
        length = TplConvert::_2SUMOReal(lengthS.c_str());
    } catch (NumberFormatException&) {
        WRITE_ERROR("A lane length for edge '" + edge->getID() + "' is not numeric (" + lengthS + ").");
        return;
    }
    if (length < 0) {
        WRITE_ERROR("A lane length for edge '" + edge->getID() + "' is not positive (" + lengthS + ").");
        return;
    }
    //
    if (dirS == "1") {
        lane -= prevLaneNo;
    }
    //
    if (length == 0) {
        if ((int) edge->getNumLanes() > lane) {
            // ok, we know this already...
            return;
        }
        // increment by one
        edge->incLaneNo(1);
    } else {
        // check whether this edge already has been created
        if (edge->getID().substr(edge->getID().length() - node->getID().length() - 1) == "_" + node->getID()) {
            if (edge->getID().substr(edge->getID().find('_')) == "_" + toString(length) + "_" + node->getID()) {
                if ((int) edge->getNumLanes() > lane) {
                    // ok, we know this already...
                    return;
                }
                // increment by one
                edge->incLaneNo(1);
                return;
            }
        }
        // nope, we have to split the edge...
        //  maybe it is not the proper edge to split - VISUM seems not to sort the splits...
        bool mustRecheck = true;
        SUMOReal seenLength = 0;
        while (mustRecheck) {
            if (edge->getID().substr(edge->getID().length() - node->getID().length() - 1) == "_" + node->getID()) {
                // ok, we have a previously created edge here
                std::string sub = edge->getID();
                sub = sub.substr(sub.rfind('_', sub.rfind('_') - 1));
                sub = sub.substr(1, sub.find('_', 1) - 1);
                SUMOReal dist = TplConvert::_2SUMOReal(sub.c_str());
                if (dist < length) {
                    seenLength += edge->getLength();
                    if (dirS == "1") {
                        // incoming -> move back
                        edge = edge->getFromNode()->getIncomingEdges()[0];
                    } else {
                        // outgoing -> move forward
                        edge = edge->getToNode()->getOutgoingEdges()[0];
                    }
                } else {
                    mustRecheck = false;
                }
            } else {
                // we have the center edge - do not continue...
                mustRecheck = false;
            }
        }
        // compute position
        Position p;
        SUMOReal useLength = length - seenLength;
        useLength = edge->getLength() - useLength;
        std::string edgeID = edge->getID();
        p = edge->getGeometry().positionAtLengthPosition(useLength);
        if (edgeID.substr(edgeID.length() - node->getID().length() - 1) == "_" + node->getID()) {
            edgeID = edgeID.substr(0, edgeID.find('_'));
        }
        NBNode* rn = new NBNode(edgeID + "_" +  toString((size_t) length) + "_" + node->getID(), p);
        if (!myNetBuilder.getNodeCont().insert(rn)) {
            throw ProcessError("Ups - could not insert node!");
        }
        std::string nid = edgeID + "_" +  toString((size_t) length) + "_" + node->getID();
        myNetBuilder.getEdgeCont().splitAt(myNetBuilder.getDistrictCont(), edge, useLength, rn,
                                           edge->getID(), nid, edge->getNumLanes() + 0, edge->getNumLanes() + 1);
        NBEdge* nedge = myNetBuilder.getEdgeCont().retrieve(nid);
        nedge = nedge->getToNode()->getOutgoingEdges()[0];
        while (nedge->getID().substr(nedge->getID().length() - node->getID().length() - 1) == "_" + node->getID()) {
            assert(nedge->getToNode()->getOutgoingEdges().size() > 0);
            nedge->incLaneNo(1);
            nedge = nedge->getToNode()->getOutgoingEdges()[0];
        }
    }
}
Beispiel #21
0
void
NWWriter_DlrNavteq::writeNodesUnsplitted(const OptionsCont& oc, NBNodeCont& nc, NBEdgeCont& ec, std::map<NBEdge*, std::string>& internalNodes) {
    // For "real" nodes we simply use the node id.
    // For internal nodes (geometry vectors describing edge geometry in the parlance of this format)
    // we use the id of the edge and do not bother with
    // compression (each direction gets its own internal node).
    OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_nodes_unsplitted.txt");
    writeHeader(device, oc);
    const GeoConvHelper& gch = GeoConvHelper::getFinal();
    const bool haveGeo = gch.usingGeoProjection();
    const double geoScale = pow(10.0f, haveGeo ? 5 : 2); // see NIImporter_DlrNavteq::GEO_SCALE
    device.setPrecision(oc.getInt("dlr-navteq.precision"));
    if (!haveGeo) {
        WRITE_WARNING("DlrNavteq node data will be written in (floating point) cartesian coordinates");
    }
    // write format specifier
    device << "# NODE_ID\tIS_BETWEEN_NODE\tamount_of_geocoordinates\tx1\ty1\t[x2 y2  ... xn  yn]\n";
    // write header
    Boundary boundary = gch.getConvBoundary();
    Position min(boundary.xmin(), boundary.ymin());
    Position max(boundary.xmax(), boundary.ymax());
    gch.cartesian2geo(min);
    min.mul(geoScale);
    gch.cartesian2geo(max);
    max.mul(geoScale);
    int multinodes = 0;
    for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
        if ((*i).second->getGeometry().size() > 2) {
            multinodes++;
        }
    }
    device << "# [xmin_region] " << min.x() << "\n";
    device << "# [xmax_region] " << max.x() << "\n";
    device << "# [ymin_region] " << min.y() << "\n";
    device << "# [ymax_region] " << max.y() << "\n";
    device << "# [elements_multinode] " << multinodes << "\n";
    device << "# [elements_normalnode] " << nc.size() << "\n";
    device << "# [xmin] " << min.x() << "\n";
    device << "# [xmax] " << max.x() << "\n";
    device << "# [ymin] " << min.y() << "\n";
    device << "# [ymax] " << max.y() << "\n";
    // write normal nodes
    for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
        NBNode* n = (*i).second;
        Position pos = n->getPosition();
        gch.cartesian2geo(pos);
        pos.mul(geoScale);
        device << n->getID() << "\t0\t1\t" << pos.x() << "\t" << pos.y() << "\n";
    }
    // write "internal" nodes
    std::vector<std::string> avoid;
    std::set<std::string> reservedNodeIDs;
    const bool numericalIDs = oc.getBool("numerical-ids");
    if (oc.isSet("reserved-ids")) {
        NBHelpers::loadPrefixedIDsFomFile(oc.getString("reserved-ids"), "node:", reservedNodeIDs); // backward compatibility
        NBHelpers::loadPrefixedIDsFomFile(oc.getString("reserved-ids"), "junction:", reservedNodeIDs); // selection format
    }
    if (numericalIDs) {
        avoid = nc.getAllNames();
        std::vector<std::string> avoid2 = ec.getAllNames();
        avoid.insert(avoid.end(), avoid2.begin(), avoid2.end());
        avoid.insert(avoid.end(), reservedNodeIDs.begin(), reservedNodeIDs.end());
    }
    IDSupplier idSupplier("", avoid);
    for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
        NBEdge* e = (*i).second;
        PositionVector geom = e->getGeometry();
        if (geom.size() > 2) {
            // the import NIImporter_DlrNavteq checks for the presence of a
            // negated edge id to determine spread type. We may need to do some
            // shifting to make this consistent
            const bool hasOppositeID = ec.getOppositeByID(e->getID()) != nullptr;
            if (e->getLaneSpreadFunction() == LANESPREAD_RIGHT && !hasOppositeID) {
                // need to write center-line geometry instead
                try {
                    geom.move2side(e->getTotalWidth() / 2);
                } catch (InvalidArgument& exception) {
                    WRITE_WARNING("Could not reconstruct shape for edge:'" + e->getID() + "' (" + exception.what() + ").");
                }
            } else if (e->getLaneSpreadFunction() == LANESPREAD_CENTER && hasOppositeID) {
                // need to write left-border geometry instead
                try {
                    geom.move2side(-e->getTotalWidth() / 2);
                } catch (InvalidArgument& exception) {
                    WRITE_WARNING("Could not reconstruct shape for edge:'" + e->getID() + "' (" + exception.what() + ").");
                }
            }

            std::string internalNodeID = e->getID();
            if (internalNodeID == UNDEFINED
                    || (nc.retrieve(internalNodeID) != nullptr)
                    || reservedNodeIDs.count(internalNodeID) > 0
               ) {
                // need to invent a new name to avoid clashing with the id of a 'real' node or a reserved name
                if (numericalIDs) {
                    internalNodeID = idSupplier.getNext();
                } else {
                    internalNodeID += "_geometry";
                }
            }
            internalNodes[e] = internalNodeID;
            device << internalNodeID << "\t1\t" << geom.size() - 2;
            for (int ii = 1; ii < (int)geom.size() - 1; ++ii) {
                Position pos = geom[(int)ii];
                gch.cartesian2geo(pos);
                pos.mul(geoScale);
                device << "\t" << pos.x() << "\t" << pos.y();
            }
            device << "\n";
        }
    }
    device.close();
}