Skip to content

Commit

Permalink
reducing oversized join. refs #14769
Browse files Browse the repository at this point in the history
  • Loading branch information
namdre committed Apr 25, 2024
1 parent ba9fe0c commit 63d0c85
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 18 deletions.
54 changes: 39 additions & 15 deletions src/netbuild/NBNodeCont.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -775,12 +775,12 @@ NBNodeCont::joinJunctions(double maxDist, NBDistrictCont& dc, NBEdgeCont& ec, NB
}
std::string origCluster = joinNamedToString(cluster, ',');
// remove nodes that can be eliminated by geometry.remove
pruneClusterFringe(cluster);
pruneClusterFringe(cluster, maxDist);
if (cluster.size() < 2) {
continue;
}
// remove nodes that are part of a bypass lane (typically for turning right without waiting at a traffic light)
pruneSlipLaneNodes(cluster);
pruneSlipLaneNodes(cluster, maxDist);
if (cluster.size() < 2) {
WRITE_WARNINGF(TL("Not joining junctions % (%)."), origCluster, "slip lane");
continue;
Expand All @@ -799,7 +799,7 @@ NBNodeCont::joinJunctions(double maxDist, NBDistrictCont& dc, NBEdgeCont& ec, NB
std::cout << " try to reduce to 4-circle nodes=" << joinNamedToString(cluster, ',') << "\n";
}
#endif
if (reduceToCircle(cluster, 4, cluster)) {
if (reduceToCircle(cluster, 4, cluster, maxDist)) {
feasible = feasibleCluster(cluster, ptStopEnds, maxDist, reason);
if (feasible) {
WRITE_WARNINGF(TL("Reducing junction cluster % (%)."), origCluster, origReason);
Expand All @@ -813,7 +813,7 @@ NBNodeCont::joinJunctions(double maxDist, NBDistrictCont& dc, NBEdgeCont& ec, NB
}
#endif
origCluster = joinNamedToString(cluster, ',');
if (reduceToCircle(cluster, 2, cluster)) {
if (reduceToCircle(cluster, 2, cluster, maxDist)) {
feasible = feasibleCluster(cluster, ptStopEnds, maxDist, reason);
if (feasible) {
WRITE_WARNINGF(TL("Reducing junction cluster % (%)."), origCluster, origReason);
Expand All @@ -828,12 +828,12 @@ NBNodeCont::joinJunctions(double maxDist, NBDistrictCont& dc, NBEdgeCont& ec, NB
}
// after pruning long edges we have to recheck
if (numPruned > 0) {
pruneClusterFringe(cluster);
pruneClusterFringe(cluster, maxDist);
if (cluster.size() < 2) {
WRITE_WARNINGF(TL("Not joining junctions % (%)."), origCluster, "long edge");
continue;
}
pruneSlipLaneNodes(cluster);
pruneSlipLaneNodes(cluster, maxDist);
if (cluster.size() < 2) {
WRITE_WARNINGF(TL("Not joining junctions % (%)."), origCluster, "slip lane");
continue;
Expand Down Expand Up @@ -919,14 +919,15 @@ NBNodeCont::joinSameJunctions(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLight
}

void
NBNodeCont::pruneClusterFringe(NodeSet& cluster) const {
NBNodeCont::pruneClusterFringe(NodeSet& cluster, double maxDist) const {
#ifdef DEBUG_JOINJUNCTIONS
if (gDebugFlag1) {
std::cout << "pruning cluster=" << joinNamedToString(cluster, ' ') << "\n";
}
#endif
// iteratively remove the fringe
bool pruneFringe = true;
bool pruneNoisyFringe = false;
// collect nodes that shall be joined due to distance but are not connected
// to the cluster for passenger traffic
while (pruneFringe) {
Expand Down Expand Up @@ -963,7 +964,13 @@ NBNodeCont::pruneClusterFringe(NodeSet& cluster) const {
if (cluster.count(neighbor) == 0) {
if ((e->getPermissions() & SVC_PASSENGER) != 0
|| isRailway(e->getPermissions()) // join railway crossings
|| clusterDist <= pedestrianFringeThreshold
|| (clusterDist <= pedestrianFringeThreshold
&& (!pruneNoisyFringe
|| ((e->getPermissions() & SVC_WEAK) != 0 &&
(e->getPermissions() & ~SVC_WEAK) == 0)
// permit joining small opposite merges
|| getDiameter(cluster) < maxDist
|| cluster.size() == 2))
|| touchingCluster) {
outsideNeighbors.insert(neighbor);
}
Expand All @@ -978,6 +985,7 @@ NBNodeCont::pruneClusterFringe(NodeSet& cluster) const {
<< " touching=" << touchingCluster
<< " out=" << joinNamedToString(outsideNeighbors, ',')
<< " in=" << joinNamedToString(clusterNeighbors, ',')
<< " dia=" << getDiameter(cluster)
<< "\n";
#endif
if (clusterNeighbors.size() == 0
Expand All @@ -993,9 +1001,25 @@ NBNodeCont::pruneClusterFringe(NodeSet& cluster) const {
#endif
}
}
if (!pruneFringe && !pruneNoisyFringe) {
// run once more and prune more things (with a look at cluster size)
pruneFringe = true;
pruneNoisyFringe = true;

}
}
}

double
NBNodeCont::getDiameter(const NodeSet& cluster) {
double result = 0;
for (const NBNode* n1 : cluster) {
for (const NBNode* n2 : cluster) {
result = MAX2(result, n1->getPosition().distanceTo2D(n2->getPosition()));
}
}
return result;
}

int
NBNodeCont::pruneLongEdges(NodeSet& cluster, double maxDist, const bool dryRun) {
Expand Down Expand Up @@ -1089,7 +1113,7 @@ NBNodeCont::getClusterNeighbors(const NBNode* n, double longThreshold, NodeSet&


void
NBNodeCont::pruneSlipLaneNodes(NodeSet& cluster) const {
NBNodeCont::pruneSlipLaneNodes(NodeSet& cluster, double maxDist) const {
#ifdef DEBUG_JOINJUNCTIONS
if (gDebugFlag1) {
std::cout << "pruning slip-lanes at cluster=" << joinNamedToString(cluster, ' ') << "\n";
Expand Down Expand Up @@ -1286,7 +1310,7 @@ NBNodeCont::pruneSlipLaneNodes(NodeSet& cluster) const {
std::cout << " removed " << numRemoved << " nodes from cluster: " << joinNamedToString(toRemove, ' ') << "\n";
}
#endif
pruneClusterFringe(cluster);
pruneClusterFringe(cluster, maxDist);
}
}

Expand Down Expand Up @@ -1583,15 +1607,15 @@ NBNodeCont::feasibleCluster(const NodeSet& cluster, const std::map<const NBNode*


bool
NBNodeCont::reduceToCircle(NodeSet& cluster, int circleSize, NodeSet startNodes, std::vector<NBNode*> cands) const {
NBNodeCont::reduceToCircle(NodeSet& cluster, int circleSize, NodeSet startNodes, double maxDist, std::vector<NBNode*> cands) const {
//std::cout << "reduceToCircle cs=" << circleSize << " cands=" << toString(cands, ',') << " startNodes=" << joinNamedToString(startNodes, ',') << "\n";
assert(circleSize >= 2);
if ((int)cands.size() == circleSize) {
if (cands.back()->getConnectionTo(cands.front()) != nullptr) {
// cluster found
NodeSet candCluster;
candCluster.insert(cands.begin(), cands.end());
pruneClusterFringe(candCluster);
pruneClusterFringe(candCluster, maxDist);
const bool feasible = (int)candCluster.size() == circleSize;
if (feasible) {
cluster.clear();
Expand All @@ -1613,11 +1637,11 @@ NBNodeCont::reduceToCircle(NodeSet& cluster, int circleSize, NodeSet startNodes,
if (e != nullptr) {
cands.push_back(e->getFromNode());
startNodes.erase(e->getFromNode());
if (reduceToCircle(cluster, circleSize, startNodes, cands)) {
if (reduceToCircle(cluster, circleSize, startNodes, maxDist, cands)) {
return true;
} else {
// try another start node
return reduceToCircle(cluster, circleSize, startNodes);
return reduceToCircle(cluster, circleSize, startNodes, maxDist);
}
}
} else {
Expand All @@ -1627,7 +1651,7 @@ NBNodeCont::reduceToCircle(NodeSet& cluster, int circleSize, NodeSet startNodes,
if (e != nullptr) {
std::vector<NBNode*> cands2(cands);
cands2.push_back(e->getToNode());
if (reduceToCircle(cluster, circleSize, startNodes, cands2)) {
if (reduceToCircle(cluster, circleSize, startNodes, maxDist, cands2)) {
return true;
}
}
Expand Down
9 changes: 6 additions & 3 deletions src/netbuild/NBNodeCont.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ class NBNodeCont {
bool maybeSlipLaneEnd(const NBNode* n, EdgeVector& incoming, double& outAngle) const;

/// @brief try to find a joinable subset (recursively)
bool reduceToCircle(NodeSet& cluster, int circleSize, NodeSet startNodes, std::vector<NBNode*> cands = std::vector<NBNode*>()) const;
bool reduceToCircle(NodeSet& cluster, int circleSize, NodeSet startNodes, double maxDist, std::vector<NBNode*> cands = std::vector<NBNode*>()) const;

/// @brief find closest neighbor for building circle
NBEdge* shortestEdge(const NodeSet& cluster, const NodeSet& startNodes, const std::vector<NBNode*>& exclude) const;
Expand Down Expand Up @@ -386,13 +386,16 @@ class NBNodeCont {
void generateNodeClusters(double maxDist, NodeClusters& into) const;

/// @brief remove geometry-like fringe nodes from cluster
void pruneClusterFringe(NodeSet& cluster) const;
void pruneClusterFringe(NodeSet& cluster, double maxDist) const;

/// @brief avoid removal of long edges when joining junction clusters
static int pruneLongEdges(NodeSet& cluster, double maxDist, const bool dryRun = false);

/// @brief compute the maximum distance between any two cluster nodes
static double getDiameter(const NodeSet& cluster);

/// @brief remove nodes that form a slip lane from cluster
void pruneSlipLaneNodes(NodeSet& cluster) const;
void pruneSlipLaneNodes(NodeSet& cluster, double maxDist) const;

/// @brief determine wether the cluster is not too complex for joining
bool feasibleCluster(const NodeSet& cluster, const std::map<const NBNode*, std::vector<NBNode*> >& ptStopEnds,
Expand Down

0 comments on commit 63d0c85

Please sign in to comment.