/// <summary>
        /// Cosmetic katmanýn içinde Rectangular Query yapar ve sonuçlarý Callback olarak bildirir.
        /// </summary>
        /// <param name="minx">Rectangle MinX</param>
        /// <param name="miny">Rectangle MinY</param>
        /// <param name="maxx">Rectangle MaxX</param>
        /// <param name="maxy">Rectangle MaxY</param>
        /// <param name="cb">Callback yapýlacak delege</param>
        public void QueryRect(int minx, int miny, int maxx, int maxy, RTreeMemoryCallBack cb)
        {
            Mbr mbr = new Mbr(minx, miny, maxx, maxy);

            stack.Clear();
            stack.Push(RootNode);

            while (stack.Count != 0)
            {
                Node n = stack.Pop();

                if (n.Mbr.IntersectsMbr(mbr))
                {
                    for (int i = 0; i < n.Items.Count; i++)
                    {
                        if (n.Items[i].Mbr.IntersectsMbr(mbr))
                        {
                            if (n.Type == NodeType.Directory)
                            {
                                stack.Push((Node)n.Items[i].Item);
                            }
                            else
                            {
                                cb(n.Items[i].Item);
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Cosmetic katmanda çizilecek olan objenin MBR'ý ve RouteIndex + LineID karýþýmý
        /// </summary>
        /// <param name="M">MBR of object</param>
        /// <param name="id">sol 32 bit RouteIndex, sað 32 bit LineID</param>
        public void Insert(Mbr M, object tag)
        {
            Node N = FindAContainer(M);
            N.Add(M, tag);

            if (N.Items.Count > MAXOBJ)
            {
                SplitAndAdjust(N);
            }
            else
            {
                AdjustPath(N);
            }
        }
        /// <summary>
        /// Cosmetic katmanýn içinde Rectangular Query yapar ve sonuçlarý Liste olarak döndürür.
        /// </summary>
        /// <param name="minx">Rectangle MinX</param>
        /// <param name="miny">Rectangle MinY</param>
        /// <param name="maxx">Rectangle MaxX</param>
        /// <param name="maxy">Rectangle MaxY</param>
        public List<object> QueryRect(int minx, int miny, int maxx, int maxy)
        {
            List<object> list = new List<object>();
            Mbr mbr = new Mbr(minx, miny, maxx, maxy);

            stack.Clear();
            stack.Push(RootNode);

            while (stack.Count != 0)
            {
                Node n = stack.Pop();

                if (n.Mbr.IntersectsMbr(mbr))
                {
                    for (int i = 0; i < n.Items.Count; i++)
                    {
                        if (n.Items[i].Mbr.IntersectsMbr(mbr))
                        {
                            if (n.Type == NodeType.Directory)
                            {
                                stack.Push((Node)n.Items[i].Item);
                            }
                            else
                            {
                                list.Add(n.Items[i].Item);
                            }
                        }
                    }
                }
            }
            return list;
        }
        private Node FindAContainer(Mbr M)
        {
            Node N = RootNode;

            while (N.Type == NodeType.Directory)
            {
                object sel = N.Items[0].Item;
                long MinArea = N.Items[0].Mbr.Union(M).Area() - M.Area() - N.Items[0].Mbr.Area();

                for (int x = 1; x < N.Items.Count; x++)
                {
                    long min = N.Items[x].Mbr.Union(M).Area() - M.Area() - N.Items[x].Mbr.Area();
                    if (min < MinArea)
                    {
                        MinArea = min;
                        sel = N.Items[x].Item;
                    }
                }

                N = (Node)sel;
            }

            return N;
        }
        public void Add(Mbr M, object Link)
        {
            Items.Add(new NodeItem(M, Link));

            if (Items.Count == 1)
            {
                Mbr = M;
            }
            else
            {
                Mbr = Mbr.Union(M);
            }
        }
 public NodeItem(Mbr m, object l)
 {
     this.Mbr = m;
     this.Item = l;
 }
        /// <summary>
        /// Ýki MBR'ýn birleþimini verir.
        /// </summary>
        /// <param name="m">Birleþtirilecek ikinci MBR</param>
        /// <returns>Sonuç yeni bir MBR'dýr.</returns>
        public Mbr Union(Mbr m)
        {
            Mbr r = this;

            if (m.minx < minx) r.minx = m.minx;
            if (m.miny < miny) r.miny = m.miny;
            if (m.maxx > maxx) r.maxx = m.maxx;
            if (m.maxy > maxy) r.maxy = m.maxy;

            return r;
        }
        /// <summary>
        /// Ýki MBR'ýn ayný olup olmadýðýný kontrol eder.
        /// </summary>
        /// <param name="m">Kontrol edilecek ikinci MBR</param>
        /// <returns>Ayný ise TRUE döner.</returns>
        public bool IsSame(Mbr m)
        {
            if (minx != m.minx) { return false; }
            if (maxx != m.maxx) { return false; }
            if (miny != m.miny) { return false; }
            if (maxy != m.maxy) { return false; }

            return true;
        }
        /// <summary>
        /// Ýki MBR'in kesiþip kesiþmediðini kontrol eder.
        /// </summary>
        /// <param name="m">Ýkinci MBR</param>
        /// <returns>Kesiþiyor ise TRUE döner</returns>
        public bool IntersectsMbr(Mbr m)
        {
            int Rminx = minx, Rmaxx = maxx, Rmaxy = maxy, Rminy = miny;

            if (m.minx > Rminx) Rminx = m.minx;
            if (m.miny > Rminy) Rminy = m.miny;
            if (m.maxx < Rmaxx) Rmaxx = m.maxx;
            if (m.maxy < Rmaxy) Rmaxy = m.maxy;

            return (Rmaxx > Rminx) && (Rmaxy > Rminy);
        }