protected virtual void AdjustTree(Node node1, Node node2, Int32 level)
 {
     if (node1.Address.Equals(Root))
     {
         Cache.WritePageData(node1);
         return;
     }
     if (Root.Equals(Address.Empty))
     {
         Type childType = node1 is Leaf ? typeof(Leaf) : typeof(Node);
         Node rootNode = new Node(Address.Empty, childType);
         Root = rootNode.Address;
         node1.Parent = Root;
         node2.Parent = Root;
         Cache.WritePageData(rootNode);
         TreeHeight++;
     }
     Node parent = Cache.LookupNode(node1.Parent);
     NodeEntry entryToUpdate = null;
     foreach (NodeEntry entry in parent.NodeEntries)
         if (entry.Child.Equals(node1.Address))
             entryToUpdate = entry;
     if (entryToUpdate == null)
         parent.AddNodeEntry(new NodeEntry(node1.CalculateMinimumBoundingBox(), node1.Address));
     else
         entryToUpdate.MinimumBoundingBox = node1.CalculateMinimumBoundingBox();
     Cache.WritePageData(node1);
     if (node2 != null)
     {
         parent.AddNodeEntry(new NodeEntry(node2.CalculateMinimumBoundingBox(), node2.Address));
         Cache.WritePageData(node2);
         if (parent.NodeEntries.Count > Constants.MAXIMUM_ENTRIES_PER_NODE)
         {
             List<Node> splitNodes = OverFlowTreatment(parent, level - 1);
             if (splitNodes != null)
             {
                 if (parent.Address.Equals(Root))
                     Root = Address.Empty;
                 RemoveFromParent(parent);
                 AdjustTree(splitNodes[0], splitNodes[1], level - 1);
             }
             return;
         }
     }
     AdjustTree(parent, null, level - 1);
 }
 protected virtual void CondenseTree(Node node)
 {
     List<Node> eliminatedNodes = new List<Node>();
     while (!node.Address.Equals(Root))
     {
         Node parent = Cache.LookupNode(node.Parent);
         NodeEntry nodeEntry = null;
         foreach (NodeEntry entry in parent.NodeEntries)
             if (entry.Child.Equals(node.Address))
                 nodeEntry = entry;
         if (node.NodeEntries.Count < Constants.MINIMUM_ENTRIES_PER_NODE)
         {
             parent.RemoveNodeEntry(nodeEntry);
             eliminatedNodes.Add(node);
             Cache.DeletePageData(node);
         }
         else
             nodeEntry.MinimumBoundingBox = node.CalculateMinimumBoundingBox();
         Cache.WritePageData(parent);
         node = parent;
     }
     for (int i = 0; i < eliminatedNodes.Count; i++)
     {
         Node eliminatedNode = eliminatedNodes[i];
         if (eliminatedNode is Leaf)
             foreach (LeafEntry leafEntry in eliminatedNode.NodeEntries)
                 Insert(Cache.LookupRecord(leafEntry.Child));
         else
             foreach (NodeEntry entry in eliminatedNode.NodeEntries)
                 Insert(Cache.LookupNode(entry.Child));
     }
 }
 protected override void AdjustTree(Node node1, Node node2)
 {
     AdjustTree(node1, node2, TreeHeight - CalculateHeight(node1) + 1);
 }
 protected virtual Single GetOverlap(Node node1, Node node2)
 {
     MinimumBoundingBox overlapArea =
         IntersectMinimumBoundingBoxes(node1.CalculateMinimumBoundingBox(), node2.CalculateMinimumBoundingBox());
     return
         (overlapArea.MaxX - overlapArea.MinX) *
         (overlapArea.MaxY - overlapArea.MinY);
 }
 protected virtual void ReInsert(Node node, Int32 level)
 {
     MinimumBoundingBox nodeBox = node.CalculateMinimumBoundingBox();
     PriorityQueue<NodeEntry, Single> distances = new PriorityQueue<NodeEntry, Single>(),
     reInsertions = new PriorityQueue<NodeEntry, Single>();
     foreach (NodeEntry entry in node.NodeEntries)
         distances.Enqueue(entry, GetCenterDistance(nodeBox, entry.MinimumBoundingBox) * -1);
     for (int i = 0; i < Constants.NODES_FOR_REINSERT; i++)
         reInsertions.Enqueue(distances.Peek().Value, distances.Dequeue().Priority * -1);
     foreach (PriorityQueueItem<NodeEntry, Single> entry in reInsertions)
         node.RemoveNodeEntry(entry.Value);
     AdjustTree(node, level);
     while(reInsertions.Count > 0)
         Insert(reInsertions.Dequeue().Value, level);
 }
 protected virtual Single GetMargin(Node node1, Node node2)
 {
     return GetMargin(node1) + GetMargin(node2);
 }
 protected virtual Single GetOverlap(NodeEntry insertionEntry, Node node)
 {
     return GetOverlap(insertionEntry, insertionEntry.MinimumBoundingBox, node);
 }
 protected virtual List<Record> Search(KNearestNeighborQuery kNN, Node node)
 {
     PriorityQueue<NodeEntry, Single> proximityQueue = new PriorityQueue<NodeEntry, Single>();
     List<Record> results = new List<Record>(kNN.K);
     EnqueNodeEntries(kNN, node, proximityQueue);
     while (results.Count < kNN.K && proximityQueue.Count > 0)
     {
         NodeEntry closestEntry = proximityQueue.Dequeue().Value;
         if (closestEntry is LeafEntry)
         {
             Record closestRecord = Cache.LookupRecord(closestEntry.Child);
             results.Add(closestRecord);
         }
         else
         {
             Node closestNode = Cache.LookupNode(closestEntry.Child);
             EnqueNodeEntries(kNN, closestNode, proximityQueue);
         }
     }
     for(int i = 0; i < results.Count; i++)
         for(int j = i; j < results.Count; j++)
     {
         if (results[i].BoundingBox.MinX == results[j].BoundingBox.MinX &&
             results[i].BoundingBox.MinY == results[j].BoundingBox.MinY &&
             results[i].BoundingBox.MaxX == results[j].BoundingBox.MaxX &&
             results[i].BoundingBox.MaxY == results[j].BoundingBox.MaxY)
         {
             if (results[i].RecordID.CompareTo(results[j].RecordID) > 0)
             {
                 Record temp = results[i];
                 results[i] = results[j];
                 results[j] = temp;
             }
         }
         else
             break;
     }
     return results;
 }
        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 RemoveFromParent(Node node)
 {
     if (!node.Parent.Equals(Address.Empty))
     {
         Node parent = Cache.LookupNode(node.Parent);
         NodeEntry entryToRemove = null;
         foreach (NodeEntry entry in parent.NodeEntries)
             if (entry.Child.Equals(node.Address))
                 entryToRemove = entry;
         parent.RemoveNodeEntry(entryToRemove);
         Cache.WritePageData(parent);
     }
     else
         Root = Address.Empty;
     Cache.DeletePageData(node);
 }
 protected virtual List<Record> Search(RegionQuery window, Node node)
 {
     List<Record> records = new List<Record>();
     foreach (NodeEntry nodeEntry in node.NodeEntries)
     {
         if (window is RangeQuery && Overlaps((RangeQuery)window, nodeEntry.MinimumBoundingBox) ||
             window is WindowQuery && Overlaps((WindowQuery)window, nodeEntry.MinimumBoundingBox))
             if (nodeEntry is LeafEntry)
                 records.Add(Cache.LookupRecord(nodeEntry.Child));
             else
                 records.AddRange(Search(window, Cache.LookupNode(nodeEntry.Child)));
     }
     return records;
 }
 protected virtual void Insert(Node newNode, Node node)
 {
     node.AddNodeEntry(new NodeEntry(newNode.CalculateMinimumBoundingBox(), newNode.Address));
     newNode.Parent = node.Address;
     Cache.WritePageData(node);
     Cache.WritePageData(newNode);
 }
 protected virtual Leaf FindLeaf(Record record, Node node)
 {
     if (node is Leaf)
     {
         foreach (LeafEntry entry in node.NodeEntries)
             if (entry.Child.Equals(record.Address))
                 return node as Leaf;
     }
     else
         foreach (NodeEntry entry in node.NodeEntries)
             if (Overlaps(entry.MinimumBoundingBox, record.BoundingBox))
             {
                 Leaf leaf = FindLeaf(record, Cache.LookupNode(entry.Child));
                 if (leaf != null)
                     return leaf;
             }
     return null;
 }
 protected virtual void EnqueNodeEntries(KNearestNeighborQuery kNN, Node node, PriorityQueue<NodeEntry, Single> proximityQueue)
 {
     foreach (NodeEntry entry in node.NodeEntries)
         proximityQueue.Enqueue(entry, GetDistance(kNN.X, kNN.Y, entry.MinimumBoundingBox) * -1);
 }
 protected override Node ChooseNode(Node node)
 {
     NodeEntry nodeEntry = new NodeEntry(node.CalculateMinimumBoundingBox(), node.Address);
     return ChooseNode(nodeEntry, TreeHeight - CalculateHeight(node) + 1);
 }
 protected override void AdjustTree(Node node1, Node node2)
 {
     if (node1.Address.Equals(Root))
         return;
     if (Root.Equals(Address.Empty))
     {
         Type childType = node1 is Leaf ? typeof(Leaf) : typeof(Node);
         Node rootNode = new Node(Address.Empty, childType);
         Root = rootNode.Address;
         node1.Parent = Root;
         node2.Parent = Root;
         rootNode.AddNodeEntry(new NodeEntry(node1.CalculateMinimumBoundingBox(), node1.Address));
         rootNode.AddNodeEntry(new NodeEntry(node2.CalculateMinimumBoundingBox(), node2.Address));
         Cache.WritePageData(rootNode);
         //Node temp = Cache.LookupNode(rootNode.Address);
         Cache.WritePageData(node1);
         Cache.WritePageData(node2);
         TreeHeight++;
         return;
     }
     Node parent = Cache.LookupNode(node1.Parent);
     NodeEntry entryToUpdate = null;
     foreach (NodeEntry entry in parent.NodeEntries)
         if (entry.Child.Equals(node1.Address))
             entryToUpdate = entry;
     if (entryToUpdate == null)
     {
         MinimumBoundingBox mbb = node1.CalculateMinimumBoundingBox();
         IndexUnit indexUnit = new IndexUnit(parent.Address, node1.Address, mbb, Operation.Insert);
         NodeTranslationTable.Add(indexUnit);
         parent.AddNodeEntry(new NodeEntry(mbb, node1.Address));
     }
     else
     {
         MinimumBoundingBox mbb = node1.CalculateMinimumBoundingBox();
         IndexUnit indexUnit = new IndexUnit(parent.Address, entryToUpdate.Child, mbb, Operation.Update);
         NodeTranslationTable.Add(indexUnit);
         entryToUpdate.MinimumBoundingBox = mbb;
     }
     if (node2 != null)
     {
         MinimumBoundingBox mbb = node2.CalculateMinimumBoundingBox();
         IndexUnit indexUnit = new IndexUnit(parent.Address, node2.Address, mbb, Operation.Insert);
         NodeTranslationTable.Add(indexUnit);
         parent.AddNodeEntry(new NodeEntry(mbb, node2.Address));
         Cache.WritePageData(node2);
         Cache.WritePageData(node1);
         if (parent.NodeEntries.Count > Constants.MAXIMUM_ENTRIES_PER_NODE)
         {
             List<Node> splitNodes = Split(parent);
             if (parent.Address.Equals(Root))
                 Root = Address.Empty;
             RemoveFromParent(parent);
             AdjustTree(splitNodes[0], splitNodes[1]);
             return;
         }
     }
     AdjustTree(parent, null);
 }
 protected virtual Single GetFutureOverlap(NodeEntry entry, NodeEntry insertionEntry, Node node)
 {
     MinimumBoundingBox overlapMinimumBoundingBox =
         CombineMinimumBoundingBoxes(entry.MinimumBoundingBox, insertionEntry.MinimumBoundingBox);
     return GetOverlap(insertionEntry, overlapMinimumBoundingBox, node);
 }
        protected override void CondenseTree(Node node)
        {
            List<Node> eliminatedNodes = new List<Node>();
            while (!node.Address.Equals(Root))
            {

                if (node.NodeEntries.Count < Constants.MINIMUM_ENTRIES_PER_NODE)
                {
                    RemoveFromParent(node);
                    eliminatedNodes.Add(node);
                }
                else
                    NodeTranslationTable.Add(new IndexUnit(node.Parent, node.Address, node.CalculateMinimumBoundingBox(), Operation.Update));
                node = Cache.LookupNode(node.Parent);
            }
            foreach(Node eliminatedNode in eliminatedNodes)
            {
                if (eliminatedNode is Leaf)
                    foreach (LeafEntry leafEntry in eliminatedNode.NodeEntries)
                        InsertRecord(new BufferItem(leafEntry, Operation.Insert));
                else
                    foreach (NodeEntry entry in eliminatedNode.NodeEntries)
                        Insert(Cache.LookupNode(entry.Child));
            }
        }
 protected virtual Single GetMargin(Node node)
 {
     MinimumBoundingBox box = node.CalculateMinimumBoundingBox();
     return (box.MaxX - box.MinX) + (box.MaxY - box.MinY);
 }
 protected override void Insert(Node node)
 {
     Node nodeToInsertInto = ChooseNode(node);
     Insert(node, nodeToInsertInto);
     if (nodeToInsertInto.NodeEntries.Count > Constants.MAXIMUM_ENTRIES_PER_NODE)
     {
         List<Node> splitNodes = Split(nodeToInsertInto);
         RemoveFromParent(nodeToInsertInto);
         AdjustTree(splitNodes[0], splitNodes[1]);
     }
     else
         AdjustTree(nodeToInsertInto);
 }
 protected virtual Single GetOverlap(NodeEntry insertionEntry, MinimumBoundingBox overlapMinimumBoundingBox, Node node)
 {
     foreach (NodeEntry nodeEntry in node.NodeEntries)
         if (nodeEntry != insertionEntry)
             overlapMinimumBoundingBox = IntersectMinimumBoundingBoxes(overlapMinimumBoundingBox, nodeEntry.MinimumBoundingBox);
     return
         (overlapMinimumBoundingBox.MaxX - overlapMinimumBoundingBox.MinX) *
         (overlapMinimumBoundingBox.MaxY - overlapMinimumBoundingBox.MinY);
 }
 protected override void Insert(Node newNode, Node node)
 {
     MinimumBoundingBox mbb = newNode.CalculateMinimumBoundingBox();
     IndexUnit indexUnit = new IndexUnit(node.Address, newNode.Address, mbb, Operation.Insert);
     NodeTranslationTable.Add(indexUnit);
     node.AddNodeEntry(new NodeEntry(mbb, newNode.Address));
     newNode.Parent = node.Address;
     Cache.WritePageData(newNode);
 }
 protected virtual List<Node> OverFlowTreatment(Node nodeToInsertInto, Int32 level)
 {
     if (nodeToInsertInto.Address.Equals(Root) || OverflowMarkers.Contains(level))
     {
         return Split(nodeToInsertInto);
     }
     else
     {
         OverflowMarkers.Add(level);
         ReInsert(nodeToInsertInto, level);
         return null;
     }
 }
 protected override void RemoveFromParent(Node node)
 {
     if (!node.Parent.Equals(Address.Empty))
     {
         Node parent = Cache.LookupNode(node.Parent);
         NodeEntry entryToRemove = null;
         foreach (NodeEntry entry in parent.NodeEntries)
             if (entry.Child.Equals(node.Address))
                 entryToRemove = entry;
         IndexUnit indexUnit = new IndexUnit(parent.Address, node.Address, entryToRemove.MinimumBoundingBox, Operation.Delete);
         NodeTranslationTable.Add(indexUnit);
     }
     else
         Root = Address.Empty;
     Cache.DeletePageData(node);
 }
        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 override List<Record> Search(KNearestNeighborQuery kNN, Node node)
 {
     return Search(kNN, node, Condense(Buffer.Buffer));
 }
 protected virtual void AdjustTree(Node node1, Int32 level)
 {
     AdjustTree(node1, null, level);
 }
        protected virtual List<Record> Search(KNearestNeighborQuery kNN, Node node, List<BufferItem> changeList)
        {
            PriorityQueue<NodeEntry, Single> proximityQueue = new PriorityQueue<NodeEntry, Single>();
            List<Record> results = new List<Record>(kNN.K);

            List<BufferItem> deletions = new List<BufferItem>();
            foreach(BufferItem change in changeList)
                if(change.Operation == Operation.Delete)
                    deletions.Add(change);
            foreach(BufferItem deletion in deletions)
                changeList.Remove(deletion);
            foreach (BufferItem insertion in changeList)
                proximityQueue.Enqueue(insertion.Entry, GetDistance(kNN.X, kNN.Y, insertion.Entry.MinimumBoundingBox) * -1);

            EnqueNodeEntries(kNN, node, proximityQueue);
            while (results.Count < kNN.K && proximityQueue.Count > 0)
            {
                NodeEntry closestEntry = proximityQueue.Dequeue().Value;
                if (closestEntry is LeafEntry)
                {
                    Boolean entryDeleted = false;
                    foreach (BufferItem deletion in deletions)
                        if (closestEntry.Child.Equals(deletion.Entry.Child))
                            entryDeleted = true;
                    if (!entryDeleted)
                        results.Add(Cache.LookupRecord(closestEntry.Child));
                }
                else
                    EnqueNodeEntries(kNN, Cache.LookupNode(closestEntry.Child), proximityQueue);
            }
            while (results.Contains(null))
                results.Remove(null);
            for(int i = 0; i < results.Count; i++)
                for(int j = i; j < results.Count; j++)
            {
                if (results[i].BoundingBox.MinX == results[j].BoundingBox.MinX &&
                    results[i].BoundingBox.MinY == results[j].BoundingBox.MinY &&
                    results[i].BoundingBox.MaxX == results[j].BoundingBox.MaxX &&
                    results[i].BoundingBox.MaxY == results[j].BoundingBox.MaxY)
                {
                    if (results[i].RecordID.CompareTo(results[j].RecordID) > 0)
                    {
                        Record temp = results[i];
                        results[i] = results[j];
                        results[j] = temp;
                    }
                }
                else
                    break;
            }
            return results;
        }
 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 virtual Node ChooseNode(Node node)
 {
     Node insertionNode = Cache.LookupNode(Root);
     MinimumBoundingBox nodeBoundingBox = node.CalculateMinimumBoundingBox();
     Int32 nodeHeight = CalculateHeight(node), currentDepth = 1;
     while (currentDepth + nodeHeight < TreeHeight)
     {
         NodeEntry minEnlargment = insertionNode.NodeEntries[0];
         Single minEnlargedArea = GetFutureSize(nodeBoundingBox, minEnlargment.MinimumBoundingBox) - minEnlargment.MinimumBoundingBox.GetArea();
         foreach (NodeEntry nodeEntry in insertionNode.NodeEntries)
         {
             Single enlargment = GetFutureSize(nodeBoundingBox, nodeEntry.MinimumBoundingBox) - nodeEntry.MinimumBoundingBox.GetArea();
             if ((enlargment == minEnlargedArea && nodeEntry.MinimumBoundingBox.GetArea() < minEnlargment.MinimumBoundingBox.GetArea()) ||
                 enlargment < minEnlargedArea)
             {
                 minEnlargedArea = enlargment;
                 minEnlargment = nodeEntry;
             }
         }
         insertionNode = Cache.LookupNode(minEnlargment.Child);
         currentDepth++;
     }
     return insertionNode;
 }