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 override List<Record> Search(KNearestNeighborQuery kNN, Node node)
 {
     return Search(kNN, node, Condense(Buffer.Buffer));
 }
 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 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;
 }
        public void ExecuteQueryPlan()
        {
            List<Record> pooledResults = new List<Record>(1000);
            Int32 headIndex = 0;
            StreamReader reader = new StreamReader(QueryPlanFileLocation);
            StreamWriter qwriter = new StreamWriter(ResultSaveFileLocation + ".q");
            StreamWriter iwriter = new StreamWriter(ResultSaveFileLocation + ".i");
            StreamWriter dwriter = new StreamWriter(ResultSaveFileLocation + ".d");
            StreamWriter uwriter = new StreamWriter(ResultSaveFileLocation + ".u");
            Console.WriteLine("Loading Complete");
            Cache.FlushCache();
            while (!reader.EndOfStream)
            {
                PerformanceAnalyzer.ClearStatistics();
                String[] values = reader.ReadLine().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                Int32 queryNumber = Int32.Parse(values[0]);
                if (queryNumber % 500 == 0)
                    Console.WriteLine(queryNumber.ToString());
                if (queryNumber == 5000)
                    break;
                Char queryType = Char.Parse(values[1]);
                if (queryType == 'Q')
                {
                    //writer.WriteLine();
                    Query query;
                    Char searchType = Char.Parse(values[2]);
                    switch (searchType)
                    {
                        case 'R':
                            {
                                Single x = Single.Parse(values[3]), y = Single.Parse(values[4]), r = Single.Parse(values[5]);
                                query = new RangeQuery(x, y, r*2);
                                //writer.WriteLine("Traditional Range Search");
                                //writer.WriteLine("Point: ({0:F2},{1:F2})", x, y);
                                //writer.WriteLine("Range: {0:F2}", r);
                                break;
                            }
                        case 'W':
                            {
                                Single x = Single.Parse(values[3]), y = Single.Parse(values[4]), r = Single.Parse(values[5]);
                                query = new WindowQuery(x - r, y - r, x+r, y+r);
                                //writer.WriteLine("Traditional Window Search");
                                //writer.WriteLine("Lower Point: ({0:F2},{1:F2})", x - r, y - r);
                                //writer.WriteLine("Upper Point: ({0:F2},{1:F2})", x, y);
                                break;
                            }
                        case 'K':
                            {
                                Single x = Single.Parse(values[3]), y = Single.Parse(values[4]);
                                Int32 k = Int32.Parse(values[5]);
                                query = new KNearestNeighborQuery(k, x, y);
                                //writer.WriteLine("Traditional Nearest Neighbor Search");
                                //writer.WriteLine("Point: ({0:F2},{1:F2})", x, y);
                                //writer.WriteLine("Items: {0}", k);
                                break;
                            }
                        default: continue;
                    }
                    PerformanceAnalyzer.OperationBegan();
                    List<Record> results = TreeIndex.Search(query);
                    Cache.FlushCache();
                    while (results.Contains(null))
                        results.Remove(null);
                    PerformanceAnalyzer.OperationEnded();
                    //writer.WriteLine("Result Objects:");
                    foreach (Record result in results)
                    {
                        if (pooledResults.Count >= 1000)
                            pooledResults.RemoveAt(0);
                        pooledResults.Add(result);
                        //writer.WriteLine("{0} {1:F2} {2:F2}", result.RecordID + 1000000 - 1, result.BoundingBox.MinX, result.BoundingBox.MinY);
                    }
                    //writer.WriteLine("Complementary Objects:");
                    //writer.WriteLine("Statistics");
                    //writer.WriteLine("Page Loads:\t{0}\tPage Writes:\t{1}\tExecution Time:\t{2}\tCPU Time:\t{3}", PerformanceAnalyzer.PageFaults, PerformanceAnalyzer.PageWrites, PerformanceAnalyzer.ExecutionTime.Ticks, PerformanceAnalyzer.CPUTime.Ticks);
                    qwriter.WriteLine("{0}\t{1}\t{2}\t{3}", PerformanceAnalyzer.PageFaults, PerformanceAnalyzer.PageWrites, PerformanceAnalyzer.ExecutionTime.Ticks, PerformanceAnalyzer.CPUTime.Ticks);
                }
                else if (queryType == 'I')
                {
                    Int32 recordID = Int32.Parse(values[2]);
                    Single x = Single.Parse(values[3]), y = Single.Parse(values[4]);
                    Record recordToInsert = new Record(recordID, new MinimumBoundingBox(x, y, x, y));
                    PerformanceAnalyzer.OperationBegan();
                    TreeIndex.Insert(recordToInsert);
                    Cache.FlushCache();
                    PerformanceAnalyzer.OperationEnded();
                    //writer.WriteLine();
                    //writer.WriteLine("Inserting new Record");
                    //writer.WriteLine("{0}, {1:F2} {2:F2}", recordID + 1000000 - 1, x, y);
                    //writer.WriteLine("Statistics");
                    //writer.WriteLine("Page Loads:\t{0}\tPage Writes:\t{1}\tExecution Time:\t{2}\tCPU Time:\t{3}", PerformanceAnalyzer.PageFaults, PerformanceAnalyzer.PageWrites, PerformanceAnalyzer.ExecutionTime.Ticks, PerformanceAnalyzer.CPUTime.Ticks);
                    iwriter.WriteLine("{0}\t{1}\t{2}\t{3}", PerformanceAnalyzer.PageFaults, PerformanceAnalyzer.PageWrites, PerformanceAnalyzer.ExecutionTime.Ticks, PerformanceAnalyzer.CPUTime.Ticks);

                }
                else if (queryType == 'U')
                {
                    /*Int32 recordIndex = Int32.Parse(values[2]);
                    if (pooledResults.Count == 0)
                        continue;
                    while (recordIndex >= pooledResults.Count)
                        recordIndex -= pooledResults.Count;
                    Record recordToUpdate = pooledResults[recordIndex];
                    while (pooledResults.Count > 0 && recordIndex-- > 0)
                        pooledResults.RemoveAt(0);
                    for(int i = 0; i < pooledResults.Count; i++)
                        if(pooledResults[i].RecordID == recordToUpdate.RecordID)
                            pooledResults.RemoveAt(i--);
                    Single x = Single.Parse(values[3]), y = Single.Parse(values[4]);
                    Record updatedRecord = new Record(recordToUpdate.RecordID, new MinimumBoundingBox(x, y, x, y));
                    if (recordToUpdate.Address.ToString().Equals("18336"))
                    {
                        Console.WriteLine("Updated");
                        Console.ReadLine();
                    }
                    PerformanceAnalyzer.OperationBegan();

                    TreeIndex.Update(recordToUpdate, updatedRecord);
                    Cache.FlushCache();
                    PerformanceAnalyzer.OperationEnded();
                    //writer.WriteLine();
                    //writer.WriteLine("Updating Record");
                    //writer.WriteLine("From: {0}, {1:F2} {2:F2}", recordToUpdate.RecordID + 1000000 - 1, recordToUpdate.BoundingBox.MinX, recordToUpdate.BoundingBox.MinY);
                    //writer.WriteLine("To: {0}, {1:F2} {2:F2}", updatedRecord.RecordID + 1000000 - 1, x, y);
                    //writer.WriteLine("Statistics");
                    //writer.WriteLine("Page Loads:\t{0}\tPage Writes:\t{1}\tExecution Time:\t{2}\tCPU Time:\t{3}", PerformanceAnalyzer.PageFaults, PerformanceAnalyzer.PageWrites, PerformanceAnalyzer.ExecutionTime.Ticks, PerformanceAnalyzer.CPUTime.Ticks);
                    uwriter.WriteLine("{0}\t{1}\t{2}\t{3}", PerformanceAnalyzer.PageFaults, PerformanceAnalyzer.PageWrites, PerformanceAnalyzer.ExecutionTime.Ticks, PerformanceAnalyzer.CPUTime.Ticks);
               */ }
                else if (queryType == 'D')
                {
                   /* Int32 recordIndex = Int32.Parse(values[2]);
                    if (pooledResults.Count == 0)
                        continue;
                    while (recordIndex >= pooledResults.Count)
                        recordIndex -= pooledResults.Count;
                    Record recordToDelete = pooledResults[recordIndex];
                    while (pooledResults.Count > 0 && recordIndex-- > 0)
                        pooledResults.RemoveAt(0);
                    for (int i = 0; i < pooledResults.Count; i++)
                        if (pooledResults[i].RecordID == recordToDelete.RecordID)
                            pooledResults.RemoveAt(i--);
                    if (recordToDelete.Address.ToString().Equals("18336"))
                    {
                        Console.WriteLine("Deleted");
                        Console.ReadLine();
                    }
                    PerformanceAnalyzer.OperationBegan();
                    TreeIndex.Delete(recordToDelete);
                    Cache.FlushCache();
                    PerformanceAnalyzer.OperationEnded();
                    //writer.WriteLine();
                    //writer.WriteLine("Deleted Record");
                    //writer.WriteLine("{0}, {1:F2} {2:F2}", recordToDelete.RecordID + 1000000 - 1, recordToDelete.BoundingBox.MinX, recordToDelete.BoundingBox.MinY);
                    //writer.WriteLine("Statistics");
                    //writer.WriteLine("Page Loads:\t{0}\tPage Writes:\t{1}\tExecution Time:\t{2}\tCPU Time:\t{3}", PerformanceAnalyzer.PageFaults, PerformanceAnalyzer.PageWrites, PerformanceAnalyzer.ExecutionTime.Ticks, PerformanceAnalyzer.CPUTime.Ticks);
                    dwriter.WriteLine("{0}\t{1}\t{2}\t{3}", PerformanceAnalyzer.PageFaults, PerformanceAnalyzer.PageWrites, PerformanceAnalyzer.ExecutionTime.Ticks, PerformanceAnalyzer.CPUTime.Ticks);
               */ }
            }
            reader.Close();
            qwriter.Close();
            iwriter.Close();
            dwriter.Close();
            uwriter.Close();
        }