// ----------- (Helper) methods for joining nodes
void
NBNodeCont::generateNodeClusters(SUMOReal maxDist, NodeClusters& into) const {
    std::set<NBNode*> visited;
    for (NodeCont::const_iterator i = myNodes.begin(); i != myNodes.end(); i++) {
        std::vector<NBNode*> toProc;
        if (visited.find((*i).second) != visited.end()) {
            continue;
        }
        toProc.push_back((*i).second);
        std::set<NBNode*> c;
        while (!toProc.empty()) {
            NBNode* n = toProc.back();
            toProc.pop_back();
            if (visited.find(n) != visited.end()) {
                continue;
            }
            c.insert(n);
            visited.insert(n);
            const EdgeVector& edges = n->getEdges();
            for (EdgeVector::const_iterator j = edges.begin(); j != edges.end(); ++j) {
                NBEdge* e = *j;
                NBNode* s = 0;
                if (n->hasIncoming(e)) {
                    s = e->getFromNode();
                } else {
                    s = e->getToNode();
                }
                if (visited.find(s) != visited.end()) {
                    continue;
                }
                if (e->getLoadedLength() < maxDist) {
                    toProc.push_back(s);
                }
            }
        }
        if (c.size() < 2) {
            continue;
        }
        into.push_back(c);
    }
}
unsigned int
NBNodeCont::joinLoadedClusters(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc) {
    NodeClusters clusters;
    for (std::vector<std::set<std::string> >::iterator it = myClusters2Join.begin(); it != myClusters2Join.end(); it++) {
        // verify loaded cluster
        std::set<NBNode*> cluster;
        for (std::set<std::string>::iterator it_id = it->begin(); it_id != it->end(); it_id++) {
            NBNode* node = retrieve(*it_id);
            if (node == 0) {
                WRITE_WARNING("Ignoring unknown node '" + *it_id + "' while joining");
            } else {
                cluster.insert(node);
            }
        }
        if (cluster.size() > 1) {
            clusters.push_back(cluster);
        }
    }
    joinNodeClusters(clusters, dc, ec, tlc);
    myClusters2Join.clear(); // make save for recompute
    return (int)clusters.size();
}
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();
}
Exemplo n.º 4
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();
}