From 16585efe71bec66047d55dbe0e837b6d15d64c44 Mon Sep 17 00:00:00 2001 From: AlexRyanUSACE Date: Tue, 1 Sep 2026 13:31:40 -0400 Subject: [PATCH] Fixed issue with inconsistent upward propagation of RTreeNode MBR size increases --- Nsi.Geospatial/Spatial/RTreeNode.cs | 30 ++++++++++++++---------- tests/Nsi.Geospatial.Tests/RTreeTests.cs | 8 +++++-- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/Nsi.Geospatial/Spatial/RTreeNode.cs b/Nsi.Geospatial/Spatial/RTreeNode.cs index af1df4e..474634f 100644 --- a/Nsi.Geospatial/Spatial/RTreeNode.cs +++ b/Nsi.Geospatial/Spatial/RTreeNode.cs @@ -56,18 +56,18 @@ public void split() { _parent._children.Remove(this); newKidsOntheBlock[0].UpdateParents(_parent); - newKidsOntheBlock[1].UpdateParents(_parent); - _parent.addChild(newKidsOntheBlock[0], true); - _parent.addChild(newKidsOntheBlock[1], false); + newKidsOntheBlock[1].UpdateParents(_parent); + _parent.addChild(newKidsOntheBlock[0], false, true); + _parent.addChild(newKidsOntheBlock[1], true, true); } else { RTreeNode newRoot = new RTreeNode(_treeManager, maxChidrens, minChidrens); newKidsOntheBlock[0].UpdateParents(newRoot); newKidsOntheBlock[1].UpdateParents(newRoot); - newRoot.addChild(newKidsOntheBlock[0], true); - newRoot.addChild(newKidsOntheBlock[1], false); - _treeManager._root = newRoot; + newRoot.addChild(newKidsOntheBlock[0], false, true); + newRoot.addChild(newKidsOntheBlock[1], true, true); + _treeManager._root = newRoot; } } private void buildChildOptions(List<(RTreeNode[], double[])> options, bool xAxis, bool min) @@ -93,11 +93,11 @@ private void buildChildOptions(List<(RTreeNode[], double[])> options, bool xAxis var Child = sortedChidrens[i]; if (i < split) { - node1.addChild(Child, true); + node1.addChild(Child, false, false); } else { - node2.addChild(Child, true); + node2.addChild(Child, false, false); } } double overlapWidth = Math.Max(0, Math.Min(node1.MBRXMax, node2.MBRXMax) - Math.Max(node1.MBRXMin, node2.MBRXMin)); @@ -118,7 +118,7 @@ public void addFeatureChild(RTreeNode feature) { if(getIsEndNode) { - addChild(feature, false); + addChild(feature, true, true); } else { @@ -157,9 +157,9 @@ public void addFeatureChildEnforceIntersect(RTreeNode feature) minExtension = extensionReq; } } - bestCandidate.addChild(feature, false); + bestCandidate.addChild(feature, true, true); } - public void addChild(RTreeNode child, bool evaluation) + public void addChild(RTreeNode child, bool canSplit, bool canPropagateMBRup) { _children.Add(child); child._parent = this; @@ -167,10 +167,14 @@ public void addChild(RTreeNode child, bool evaluation) if(child.MBRXMax > MBRXMax) { MBRXMax = child.MBRXMax; } if(child.MBRYMin < MBRYMin) { MBRYMin = child.MBRYMin; } if(child.MBRYMax > MBRYMax) { MBRYMax = child.MBRYMax; } - if(_children.Count > maxChidrens && !evaluation) + if(_children.Count > maxChidrens && canSplit) { split(); } + else if(canPropagateMBRup) + { + RecomputeMBR(); + } } public void RecomputeMBR() { @@ -318,4 +322,4 @@ public double getPerimeter get { return 2 * ((MBRXMax - MBRXMin) + (MBRYMax - MBRYMin)); } } } -} \ No newline at end of file +} diff --git a/tests/Nsi.Geospatial.Tests/RTreeTests.cs b/tests/Nsi.Geospatial.Tests/RTreeTests.cs index 45b0ecd..755e0be 100644 --- a/tests/Nsi.Geospatial.Tests/RTreeTests.cs +++ b/tests/Nsi.Geospatial.Tests/RTreeTests.cs @@ -55,7 +55,7 @@ public void FindByInd_ReturnsLeafToRootPath() Assert.NotNull(featureIndex); } - [Fact(Skip = "Fails by design: asserts correct behavior that the original (unfixed) RTree split/overlap defects violate. Re-enable once the RTree defects are fixed.")] + [Fact] //(Skip = "Fails by design: asserts correct behavior that the original (unfixed) RTree split/overlap defects violate. Re-enable once the RTree defects are fixed.")] public void BulkInsert_AllFeaturesFindableByPoint() { var tree = new RTreeManager(minChilds: 3, maxChilds: 6); @@ -65,6 +65,10 @@ public void BulkInsert_AllFeaturesFindableByPoint() for (int i = 0; i < 500; i++) { var hits = FeatureIndicesAt(tree, i * 10 + 2.5, i * 10 + 2.5); + if (!hits.Contains(i)) + { + string test = "WTF"; + } Assert.Contains(i, hits); } } @@ -107,4 +111,4 @@ private static List FeatureIndicesAt(RTreeManager tree, double x, double y) } return indices; } -} \ No newline at end of file +}