Skip to content

Commit

Permalink
Fix very rare case producing line tree cycle.
Browse files Browse the repository at this point in the history
In the unprecedented case of the root of the tree
being next to a low runoff, a cycle was produced in
the line tree, causing an infinite loop during pruning.
Now we check for this case and break the cycle.
  • Loading branch information
akirmse committed Jun 2, 2024
1 parent 2938ad0 commit 30cf30f
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 2 deletions.
37 changes: 35 additions & 2 deletions code/line_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ void LineTree::build() {
mNodes[index].lowestElevationSaddleParentDir = UNDEFINED_ELEVATION;
mNodes[index].runoffId = Node::Null;
}

mSaddleInfo.resize(mDivideTree.saddles().size());
for (SaddleInfo &info : mSaddleInfo) {
info.saddleProminence = UNDEFINED_ELEVATION;
}

VLOG(3) << "Computing off-map saddle prominence";
computeOffMapSaddleProminence();

VLOG(3) << "Computing on-map saddle prominence";
computeOnMapSaddleProminence();
}
Expand Down Expand Up @@ -237,6 +237,14 @@ void LineTree::computeOnMapSaddleProminence() {
if (startingPeakId != nodeId) { // Can happen if node is top of tree
reversePath(startingPeakId, lowestSaddleOwner);
mNodes[startingPeakId].parentId = nodeId;

// This very rare case can happen if the top of the tree is next to a low
// runoff, making the root and the saddle owner the same. Here the normal
// code path produces a cycle, which we break here by restoring the top
// of the tree.
if (nodeId == lowestSaddleOwner) {
mNodes[nodeId].parentId = Node::Null;
}
}
}
}
Expand Down Expand Up @@ -314,3 +322,28 @@ int LineTree::peakIdForRunoff(int runoffId) const {
const vector<LineTree::Node> &LineTree::nodes() const {
return mNodes;
}

bool LineTree::hasCycle(int maxLength) const {
for (int i = 1; i < (int) mNodes.size(); ++i) {
const Node *node = &mNodes[i];

int length = 0;
while (node->parentId != Node::Null && length <= maxLength) {
if (node->parentId == i) {
printf("Found cycle starting at %d\n", i);
const Node *cycle = &mNodes[i];
while (cycle->parentId != i) {
printf("Parent ID is %d\n", cycle->parentId);
cycle = &mNodes[cycle->parentId];
}
return true;
}

node = &mNodes[node->parentId];
length += 1;
}
}

return false;
}

3 changes: 3 additions & 0 deletions code/line_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ class LineTree {
// chain of childId until we reach a lower saddle.
void propagateLowestInterveningSaddle(int originNodeId);

// For debugging: Look for cycles in the tree and print them out
bool hasCycle(int maxLength) const;

const Peak &getPeak(int peakId) const;
const Saddle &getSaddle(int saddleId) const;
const Runoff &getRunoff(int runoffId) const;
Expand Down

0 comments on commit 30cf30f

Please sign in to comment.