public R_Tree(CacheManager cache) { Cache = cache; Leaf rootNode = new Leaf(Address.Empty); root = rootNode.Address; Cache.WritePageData(rootNode); TreeHeight = 1; Cache.FlushCache(); }
protected virtual PageData LookupPageData(Address address) { PageData data; Page page = LookupPage(address); Byte type = page.Data[0], childType = page.Data[1]; if (type == (Byte)PageDataType.Node || type == (Byte)PageDataType.Leaf) if (childType == (Byte)NodeChildType.Leaf) data = new Node(address, typeof(Leaf), page.Data); else if (childType == (Byte)NodeChildType.Node) data = new Node(address, typeof(Node), page.Data); else if (childType == (Byte)NodeChildType.Record) data = new Leaf(address, page.Data); else throw new Exception("Not a node"); else if (type == (Byte)PageDataType.Record) data = new Record(address, page.Data); else if (type == (Byte)PageDataType.IndexUnitSector) data = new Sector(address, page.Data); else throw new Exception("Not valid Page Data"); CacheOverflowCheck(); return data; }
protected override List<Node> Split(Node nodeToBeSplit) { // //Determine Axis // //Sort each axis by upper and lower corners List<NodeEntry> xLowerSorted = new List<NodeEntry>(nodeToBeSplit.NodeEntries), xUpperSorted = new List<NodeEntry>(nodeToBeSplit.NodeEntries), yLowerSorted = new List<NodeEntry>(nodeToBeSplit.NodeEntries), yUpperSorted = new List<NodeEntry>(nodeToBeSplit.NodeEntries); xLowerSorted.Sort(new NodeEntryLowerAxisComparerX()); xUpperSorted.Sort(new NodeEntryUpperAxisComparerX()); yLowerSorted.Sort(new NodeEntryLowerAxisComparerY()); yUpperSorted.Sort(new NodeEntryUpperAxisComparerY()); //Generate Distributions List<Pair<Node, Node>> xLowerDistributions = new List<Pair<Node, Node>>(), xUpperDistributions = new List<Pair<Node, Node>>(), yLowerDistributions = new List<Pair<Node, Node>>(), yUpperDistributions = new List<Pair<Node, Node>>(); Dictionary<List<NodeEntry>, List<Pair<Node, Node>>> axii = new Dictionary<List<NodeEntry>, List<Pair<Node, Node>>>(); axii.Add(xLowerSorted, xLowerDistributions); axii.Add(xUpperSorted, xUpperDistributions); axii.Add(yLowerSorted, yLowerDistributions); axii.Add(yUpperSorted, yUpperDistributions); foreach (KeyValuePair<List<NodeEntry>, List<Pair<Node, Node>>> axis in axii) for (int i = 0; i < Constants.MAXIMUM_ENTRIES_PER_NODE - 2 * Constants.MINIMUM_ENTRIES_PER_NODE + 2; i++) { Node group1, group2; if (nodeToBeSplit is Leaf) { group1 = new Leaf(nodeToBeSplit.Parent); group2 = new Leaf(nodeToBeSplit.Parent); } else { group1 = new Node(nodeToBeSplit.Parent, nodeToBeSplit.ChildType); group2 = new Node(nodeToBeSplit.Parent, nodeToBeSplit.ChildType); } foreach (NodeEntry entry in axis.Key.GetRange(0, Constants.MINIMUM_ENTRIES_PER_NODE+ i)) group1.AddNodeEntry(entry); foreach (NodeEntry entry in axis.Key.GetRange(Constants.MINIMUM_ENTRIES_PER_NODE + i, axis.Key.Count - (Constants.MINIMUM_ENTRIES_PER_NODE+ i))) group2.AddNodeEntry(entry); axis.Value.Add(new Pair<Node, Node>(group1, group2)); } //Sum margins Single xLowerMarginSum = 0, xUpperMarginSum = 0, yLowerMarginSum = 0, yUpperMarginSum = 0; foreach (Pair<Node, Node> distribution in xLowerDistributions) xLowerMarginSum += GetMargin(distribution.Value1, distribution.Value2); foreach (Pair<Node, Node> distribution in xUpperDistributions) xUpperMarginSum += GetMargin(distribution.Value1, distribution.Value2); foreach (Pair<Node, Node> distribution in yLowerDistributions) yLowerMarginSum += GetMargin(distribution.Value1, distribution.Value2); foreach (Pair<Node, Node> distribution in yUpperDistributions) yUpperMarginSum += GetMargin(distribution.Value1, distribution.Value2); //Choose Axis List<Pair<Node, Node>> chosenAxis; if (xLowerMarginSum <= xUpperMarginSum && xLowerMarginSum <= yLowerMarginSum && xLowerMarginSum <= yUpperMarginSum) chosenAxis = xLowerDistributions; else if (xUpperMarginSum <= xLowerMarginSum && xUpperMarginSum <= yLowerMarginSum && xUpperMarginSum <= yUpperMarginSum) chosenAxis = xUpperDistributions; else if (yLowerMarginSum <= xUpperMarginSum && yLowerMarginSum <= xLowerMarginSum && yLowerMarginSum <= yUpperMarginSum) chosenAxis = yLowerDistributions; else chosenAxis = yUpperDistributions; // //Determine Distribution // Pair<Node, Node> chosenDistribution = chosenAxis[0]; Single minimumOverlapArea = GetOverlap(chosenDistribution.Value1, chosenDistribution.Value2); foreach (Pair<Node, Node> distribution in chosenAxis) { Single overlapArea = GetOverlap(distribution.Value1, distribution.Value2); if ((overlapArea == minimumOverlapArea && GetFutureSize(distribution.Value1.CalculateMinimumBoundingBox(), distribution.Value2.CalculateMinimumBoundingBox()) < GetFutureSize(chosenDistribution.Value1.CalculateMinimumBoundingBox(), chosenDistribution.Value2.CalculateMinimumBoundingBox()) ) || overlapArea < minimumOverlapArea) { chosenDistribution = distribution; minimumOverlapArea = overlapArea; } } // //Distribute // List<Node> newNodes = new List<Node>(); newNodes.Add(chosenDistribution.Value1); newNodes.Add(chosenDistribution.Value2); foreach (Node newNode in newNodes) { if (!(newNode is Leaf)) foreach (NodeEntry entry in newNode.NodeEntries) { Node child = Cache.LookupNode(entry.Child); child.Parent = newNode.Address; Cache.WritePageData(child); } Cache.WritePageData(newNode); } return newNodes; }
protected virtual List<Node> Split(Node nodeToBeSplit) { List<NodeEntry> entries = new List<NodeEntry>(nodeToBeSplit.NodeEntries); List<NodeEntry> seeds = PickSeeds(entries); entries.Remove(seeds[0]); entries.Remove(seeds[1]); Node node1, node2; if (nodeToBeSplit is Leaf) { node1 = new Leaf(nodeToBeSplit.Parent); node2 = new Leaf(nodeToBeSplit.Parent); } else { node1 = new Node(nodeToBeSplit.Parent, nodeToBeSplit.ChildType); node2 = new Node(nodeToBeSplit.Parent, nodeToBeSplit.ChildType); } node1.AddNodeEntry(seeds[0]); node2.AddNodeEntry(seeds[1]); if (!(seeds[0] is LeafEntry)) { Node child = Cache.LookupNode(seeds[0].Child); child.Parent = node1.Address; Cache.WritePageData(child); } if (!(seeds[1] is LeafEntry)) { Node child = Cache.LookupNode(seeds[1].Child); child.Parent = node2.Address; Cache.WritePageData(child); } while (entries.Count > 0) { if (node1.NodeEntries.Count + entries.Count == Constants.MINIMUM_ENTRIES_PER_NODE) { foreach (NodeEntry entry in entries) { node1.AddNodeEntry(entry); if(!(entry is LeafEntry)) { Node child = Cache.LookupNode(entry.Child); child.Parent = node1.Address; Cache.WritePageData(child); } } break; } else if (node2.NodeEntries.Count + entries.Count == Constants.MINIMUM_ENTRIES_PER_NODE) { foreach (NodeEntry entry in entries) { node2.AddNodeEntry(entry); if (!(entry is LeafEntry)) { Node child = Cache.LookupNode(entry.Child); child.Parent = node2.Address; Cache.WritePageData(child); } } break; } MinimumBoundingBox minimumBoundingBox1 = node1.CalculateMinimumBoundingBox(), minimumBoundingBox2 = node2.CalculateMinimumBoundingBox(); NodeEntry nextEntry = PickNext(entries, minimumBoundingBox1, minimumBoundingBox2); entries.Remove(nextEntry); Node nodeToEnter; if (GetFutureSize(nextEntry.MinimumBoundingBox, minimumBoundingBox1) == GetFutureSize(nextEntry.MinimumBoundingBox, minimumBoundingBox2)) { if (minimumBoundingBox1.GetArea() == minimumBoundingBox2.GetArea()) if (node1.NodeEntries.Count <= node2.NodeEntries.Count) nodeToEnter = node1; else nodeToEnter = node2; else if (minimumBoundingBox1.GetArea() < minimumBoundingBox2.GetArea()) nodeToEnter = node1; else nodeToEnter = node2; } else if (GetFutureSize(nextEntry.MinimumBoundingBox, minimumBoundingBox1) < GetFutureSize(nextEntry.MinimumBoundingBox, minimumBoundingBox2)) nodeToEnter = node1; else nodeToEnter = node2; nodeToEnter.AddNodeEntry(nextEntry); if (!(nextEntry is LeafEntry)) { Node child = Cache.LookupNode(nextEntry.Child); child.Parent = nodeToEnter.Address; Cache.WritePageData(child); } } List<Node> newNodes = new List<Node>(); newNodes.Add(node1); newNodes.Add(node2); return newNodes; }
protected virtual void Insert(Record record, Leaf leaf) { leaf.AddNodeEntry(new LeafEntry(record.BoundingBox, record.Address)); }