public bool MoveNext()
 {
     if (counter != tree.updateCounter)
     {
         throw new InvalidOperationException("Tree was modified");
     }
     while (true)
     {
         Neighbor neighbor = list;
         if (neighbor == null)
         {
             return(false);
         }
         if (neighbor.level == 0)
         {
             curr = neighbor.child;
             list = neighbor.next;
             return(true);
         }
         list = neighbor.next;
         RtreePage pg = (RtreePage)neighbor.child;
         for (int i = 0, n = pg.n; i < n; i++)
         {
             Insert(new Neighbor(pg.branch[i], pg.b[i].Distance(x, y), neighbor.level - 1));
         }
     }
 }
예제 #2
0
 public void Clear()
 {
     if (root != null)
     {
         root.purge(height);
         root = null;
     }
     height = 0;
     n      = 0;
     Modify();
 }
예제 #3
0
 internal RtreePage(RtreePage root, RtreePage p)
 {
     b    = new Branch[card];
     n    = 2;
     b[0] = new Branch(root.cover(), root);
     b[1] = new Branch(p.cover(), p);
     for (int i = 2; i < card; i++)
     {
         b[i] = new Branch();
     }
 }
 public override void Clear()
 {
     if (root != null)
     {
         root.purge(height);
         root = null;
     }
     height         = 0;
     n              = 0;
     updateCounter += 1;
     Modify();
 }
예제 #5
0
 internal RtreePage(Storage storage, RtreePage root, RtreePage p)
 {
     branch = storage.CreateLink(card);
     branch.Length = card;
     b = new Rectangle[card];
     n = 2;
     setBranch(0, root.cover(), root);
     setBranch(1, p.cover(), p);
     for (int i = 2; i < card; i++)
     {
         b[i] = new Rectangle();
     }
 }
예제 #6
0
 internal RtreePage(Storage storage, RtreePage root, RtreePage p)
 {
     branch        = storage.CreateLink(card);
     branch.Length = card;
     b             = new Rectangle[card];
     n             = 2;
     setBranch(0, root.cover(), root);
     setBranch(1, p.cover(), p);
     for (int i = 2; i < card; i++)
     {
         b[i] = new Rectangle();
     }
 }
            internal RtreeEnumerator(Rtree tree, Rectangle r)
#endif
            {
                counter   = tree.updateCounter;
                height    = tree.height;
                this.tree = tree;
                if (height == 0)
                {
                    return;
                }
                this.r    = r;
                pageStack = new RtreePage[height];
                posStack  = new int[height];
                Reset();
            }
 private bool gotoFirstItem(int sp, RtreePage pg)
 {
     for (int i = 0, n = pg.n; i < n; i++)
     {
         if (r.Intersects(pg.b[i]))
         {
             if (sp + 1 == height || gotoFirstItem(sp + 1, (RtreePage)pg.branch[i]))
             {
                 pageStack[sp] = pg;
                 posStack[sp]  = i;
                 return(true);
             }
         }
     }
     return(false);
 }
예제 #9
0
 internal RtreePage insert(Rectangle r, IPersistent obj, int level)
 {
     Load();
     Modify();
     if (--level != 0)
     {
         // not leaf page
         int  i, mini = 0;
         long minIncr = Int64.MaxValue;
         long minArea = Int64.MaxValue;
         for (i = 0; i < n; i++)
         {
             long area = b[i].r.Area();
             long incr = Rectangle.JoinArea(b[i].r, r) - area;
             if (incr < minIncr)
             {
                 minIncr = incr;
                 minArea = area;
                 mini    = i;
             }
             else if (incr == minIncr && area < minArea)
             {
                 minArea = area;
                 mini    = i;
             }
         }
         RtreePage p = (RtreePage)b[mini].p;
         RtreePage q = p.insert(r, obj, level);
         if (q == null)
         {
             // child was not split
             b[mini].r.Join(r);
             return(null);
         }
         else
         {
             // child was split
             b[mini] = new Branch(p.cover(), p);
             return(addBranch(new Branch(q.cover(), q)));
         }
     }
     else
     {
         return(addBranch(new Branch(r, obj)));
     }
 }
예제 #10
0
 internal RtreePage insert(Storage storage, Rectangle r, object obj, int level)
 {
     Modify();
     if (--level != 0)
     {
         // not leaf page
         int  i, mini = 0;
         long minIncr = long.MaxValue;
         long minArea = long.MaxValue;
         for (i = 0; i < n; i++)
         {
             long area = b[i].Area();
             long incr = Rectangle.JoinArea(b[i], r) - area;
             if (incr < minIncr)
             {
                 minIncr = incr;
                 minArea = area;
                 mini    = i;
             }
             else if (incr == minIncr && area < minArea)
             {
                 minArea = area;
                 mini    = i;
             }
         }
         RtreePage p = (RtreePage)branch[mini];
         RtreePage q = p.insert(storage, r, obj, level);
         if (q == null)
         {
             // child was not split
             b[mini].Join(r);
             return(null);
         }
         else
         {
             // child was split
             setBranch(mini, p.cover(), p);
             return(addBranch(storage, q.cover(), q));
         }
     }
     else
     {
         return(addBranch(storage, new Rectangle(r), obj));
     }
 }
예제 #11
0
 internal int remove(Rectangle r, IPersistent obj, int level, ArrayList reinsertList)
 {
     Load();
     if (--level != 0)
     {
         for (int i = 0; i < n; i++)
         {
             if (r.Intersects(b[i].r))
             {
                 RtreePage pg            = (RtreePage)b[i].p;
                 int       reinsertLevel = pg.remove(r, obj, level, reinsertList);
                 if (reinsertLevel >= 0)
                 {
                     if (pg.n >= minFill)
                     {
                         b[i] = new Branch(pg.cover(), pg);
                         Modify();
                     }
                     else
                     {
                         // not enough entries in child
                         reinsertList.Add(pg);
                         reinsertLevel = level - 1;
                         removeBranch(i);
                     }
                     return(reinsertLevel);
                 }
             }
         }
     }
     else
     {
         for (int i = 0; i < n; i++)
         {
             if (b[i].p == obj)
             {
                 removeBranch(i);
                 return(0);
             }
         }
     }
     return(-1);
 }
            private bool gotoNextItem(int sp)
            {
                RtreePage pg = pageStack[sp];

                for (int i = posStack[sp], n = pg.n; ++i < n;)
                {
                    if (r.Intersects(pg.b[i]))
                    {
                        if (sp + 1 == height || gotoFirstItem(sp + 1, (RtreePage)pg.branch[i]))
                        {
                            pageStack[sp] = pg;
                            posStack[sp]  = i;
                            return(true);
                        }
                    }
                }
                pageStack[sp] = null;
                return((sp > 0) ? gotoNextItem(sp - 1) : false);
            }
예제 #13
0
 internal int remove(Rectangle r, object obj, int level, ArrayList reinsertList)
 {
     if (--level != 0)
     {
         for (int i = 0; i < n; i++)
         {
             if (r.Intersects(b[i]))
             {
                 RtreePage pg            = (RtreePage)branch[i];
                 int       reinsertLevel = pg.remove(r, obj, level, reinsertList);
                 if (reinsertLevel >= 0)
                 {
                     if (pg.n >= minFill)
                     {
                         setBranch(i, pg.cover(), pg);
                         Modify();
                     }
                     else
                     {
                         // not enough entries in child
                         reinsertList.Add(pg);
                         reinsertLevel = level - 1;
                         removeBranch(i);
                     }
                     return(reinsertLevel);
                 }
             }
         }
     }
     else
     {
         for (int i = 0; i < n; i++)
         {
             if (branch.ContainsElement(i, obj))
             {
                 removeBranch(i);
                 return(0);
             }
         }
     }
     return(-1);
 }
        public void Remove(Rectangle r, object obj)
#endif
        {
            if (root == null)
            {
                throw new StorageError(StorageError.ErrorCode.KEY_NOT_FOUND);
            }
            ArrayList reinsertList  = new ArrayList();
            int       reinsertLevel = root.remove(r, obj, height, reinsertList);

            if (reinsertLevel < 0)
            {
                throw new StorageError(StorageError.ErrorCode.KEY_NOT_FOUND);
            }
            for (int i = reinsertList.Count; --i >= 0;)
            {
                RtreePage p = (RtreePage)reinsertList[i];
                for (int j = 0, pn = p.n; j < pn; j++)
                {
                    RtreePage q = root.insert(Storage, p.b[j], p.branch[j], height - reinsertLevel);
                    if (q != null)
                    {
                        // root splitted
                        root    = new RtreePage(Storage, root, q);
                        height += 1;
                    }
                }
                reinsertLevel -= 1;
                p.Deallocate();
            }
            if (root.n == 1 && height > 1)
            {
                RtreePage newRoot = (RtreePage)root.branch[0];
                root.Deallocate();
                root    = newRoot;
                height -= 1;
            }
            n             -= 1;
            updateCounter += 1;
            Modify();
        }
        public void Put(Rectangle r, object obj)
#endif
        {
            if (root == null)
            {
                root   = new RtreePage(Storage, obj, r);
                height = 1;
            }
            else
            {
                RtreePage p = root.insert(Storage, r, obj, height);
                if (p != null)
                {
                    root    = new RtreePage(Storage, root, p);
                    height += 1;
                }
            }
            n             += 1;
            updateCounter += 1;
            Modify();
        }
예제 #16
0
 public void Put(Rectangle r, IPersistent obj)
 {
     if (!obj.IsPersistent())
     {
         ((StorageImpl)Storage).storeObject(obj);
     }
     if (root == null)
     {
         root   = new RtreePage(obj, r);
         height = 1;
     }
     else
     {
         RtreePage p = root.insert(r, obj, height);
         if (p != null)
         {
             root    = new RtreePage(root, p);
             height += 1;
         }
     }
     n += 1;
     Modify();
 }
예제 #17
0
        RtreePage splitPage(Storage storage, Rectangle r, object obj)
        {
            int i, j, seed0 = 0, seed1 = 0;
            long[] rectArea = new long[card+1];
            long   waste;
            long   worstWaste = long.MinValue;
            //
            // As the seeds for the two groups, find two rectangles which waste
            // the most area if covered by a single rectangle.
            //
            rectArea[0] = r.Area();
            for (i = 0; i < card; i++)
            {
                rectArea[i+1] = b[i].Area();
            }
            Rectangle bp = r;
            for (i = 0; i < card; i++)
            {
                for (j = i+1; j <= card; j++)
                {
                    waste = Rectangle.JoinArea(bp, b[j-1]) - rectArea[i] - rectArea[j];
                    if (waste > worstWaste)
                    {
                        worstWaste = waste;
                        seed0 = i;
                        seed1 = j;
                    }
                }
                bp = b[i];
            }
            byte[] taken = new byte[card];
            Rectangle group0, group1;
            long      groupArea0, groupArea1;
            int         groupCard0, groupCard1;
            RtreePage pg;

            taken[seed1-1] = 2;
            group1 = new Rectangle(b[seed1-1]);

            if (seed0 == 0)
            {
                group0 = new Rectangle(r);
                pg = new RtreePage(storage, obj, r);
            }
            else
            {
                group0 = new Rectangle(b[seed0-1]);
                pg = new RtreePage(storage, branch.GetRaw(seed0-1), group0);
                setBranch(seed0-1, r, obj);
            }
            groupCard0 = groupCard1 = 1;
            groupArea0 = rectArea[seed0];
            groupArea1 = rectArea[seed1];
            //
            // Split remaining rectangles between two groups.
            // The one chosen is the one with the greatest difference in area
            // expansion depending on which group - the rect most strongly
            // attracted to one group and repelled from the other.
            //
            while (groupCard0 + groupCard1 < card + 1
                && groupCard0 < card + 1 - minFill
                && groupCard1 < card + 1 - minFill)
            {
                int betterGroup = -1, chosen = -1;
                long biggestDiff = -1;
                for (i = 0; i < card; i++)
                {
                    if (taken[i] == 0)
                    {
                        long diff = (Rectangle.JoinArea(group0, b[i]) - groupArea0)
                            - (Rectangle.JoinArea(group1, b[i]) - groupArea1);
                        if (diff > biggestDiff || -diff > biggestDiff)
                        {
                            chosen = i;
                            if (diff < 0)
                            {
                                betterGroup = 0;
                                biggestDiff = -diff;
                            }
                            else
                            {
                                betterGroup = 1;
                                biggestDiff = diff;
                            }
                        }
                    }
                }
                Debug.Assert(chosen >= 0);
                if (betterGroup == 0)
                {
                    group0.Join(b[chosen]);
                    groupArea0 = group0.Area();
                    taken[chosen] = 1;
                    pg.setBranch(groupCard0++, b[chosen], branch.GetRaw(chosen));
                }
                else
                {
                    groupCard1 += 1;
                    group1.Join(b[chosen]);
                    groupArea1 = group1.Area();
                    taken[chosen] = 2;
                }
            }
            //
            // If one group gets too full, then remaining rectangle are
            // split between two groups in such way to balance cards of two groups.
            //
            if (groupCard0 + groupCard1 < card + 1)
            {
                for (i = 0; i < card; i++)
                {
                    if (taken[i] == 0)
                    {
                        if (groupCard0 >= groupCard1)
                        {
                            taken[i] = 2;
                            groupCard1 += 1;
                        }
                        else
                        {
                            taken[i] = 1;
                            pg.setBranch(groupCard0++, b[i], branch.GetRaw(i));
                        }
                    }
                }
            }
            pg.n = groupCard0;
            n = groupCard1;
            for (i = 0, j = 0; i < groupCard1; j++)
            {
                if (taken[j] == 2)
                {
                    setBranch(i++, b[j], branch.GetRaw(j));
                }
            }
            // truncate rest of link
            branch.Length = groupCard1;
            branch.Length = card;
            return pg;
        }
예제 #18
0
        RtreePage splitPage(Storage storage, Rectangle r, object obj)
        {
            int i, j, seed0 = 0, seed1 = 0;

            long[] rectArea = new long[card + 1];
            long   waste;
            long   worstWaste = long.MinValue;

            //
            // As the seeds for the two groups, find two rectangles which waste
            // the most area if covered by a single rectangle.
            //
            rectArea[0] = r.Area();
            for (i = 0; i < card; i++)
            {
                rectArea[i + 1] = b[i].Area();
            }
            Rectangle bp = r;

            for (i = 0; i < card; i++)
            {
                for (j = i + 1; j <= card; j++)
                {
                    waste = Rectangle.JoinArea(bp, b[j - 1]) - rectArea[i] - rectArea[j];
                    if (waste > worstWaste)
                    {
                        worstWaste = waste;
                        seed0      = i;
                        seed1      = j;
                    }
                }
                bp = b[i];
            }
            byte[]    taken = new byte[card];
            Rectangle group0, group1;
            long      groupArea0, groupArea1;
            int       groupCard0, groupCard1;
            RtreePage pg;

            taken[seed1 - 1] = 2;
            group1           = new Rectangle(b[seed1 - 1]);

            if (seed0 == 0)
            {
                group0 = new Rectangle(r);
                pg     = new RtreePage(storage, obj, r);
            }
            else
            {
                group0 = new Rectangle(b[seed0 - 1]);
                pg     = new RtreePage(storage, branch.GetRaw(seed0 - 1), group0);
                setBranch(seed0 - 1, r, obj);
            }
            groupCard0 = groupCard1 = 1;
            groupArea0 = rectArea[seed0];
            groupArea1 = rectArea[seed1];
            //
            // Split remaining rectangles between two groups.
            // The one chosen is the one with the greatest difference in area
            // expansion depending on which group - the rect most strongly
            // attracted to one group and repelled from the other.
            //
            while (groupCard0 + groupCard1 < card + 1 &&
                   groupCard0 < card + 1 - minFill &&
                   groupCard1 < card + 1 - minFill)
            {
                int  betterGroup = -1, chosen = -1;
                long biggestDiff = -1;
                for (i = 0; i < card; i++)
                {
                    if (taken[i] == 0)
                    {
                        long diff = (Rectangle.JoinArea(group0, b[i]) - groupArea0)
                                    - (Rectangle.JoinArea(group1, b[i]) - groupArea1);
                        if (diff > biggestDiff || -diff > biggestDiff)
                        {
                            chosen = i;
                            if (diff < 0)
                            {
                                betterGroup = 0;
                                biggestDiff = -diff;
                            }
                            else
                            {
                                betterGroup = 1;
                                biggestDiff = diff;
                            }
                        }
                    }
                }
                Debug.Assert(chosen >= 0);
                if (betterGroup == 0)
                {
                    group0.Join(b[chosen]);
                    groupArea0    = group0.Area();
                    taken[chosen] = 1;
                    pg.setBranch(groupCard0++, b[chosen], branch.GetRaw(chosen));
                }
                else
                {
                    groupCard1 += 1;
                    group1.Join(b[chosen]);
                    groupArea1    = group1.Area();
                    taken[chosen] = 2;
                }
            }
            //
            // If one group gets too full, then remaining rectangle are
            // split between two groups in such way to balance cards of two groups.
            //
            if (groupCard0 + groupCard1 < card + 1)
            {
                for (i = 0; i < card; i++)
                {
                    if (taken[i] == 0)
                    {
                        if (groupCard0 >= groupCard1)
                        {
                            taken[i]    = 2;
                            groupCard1 += 1;
                        }
                        else
                        {
                            taken[i] = 1;
                            pg.setBranch(groupCard0++, b[i], branch.GetRaw(i));
                        }
                    }
                }
            }
            pg.n = groupCard0;
            n    = groupCard1;
            for (i = 0, j = 0; i < groupCard1; j++)
            {
                if (taken[j] == 2)
                {
                    setBranch(i++, b[j], branch.GetRaw(j));
                }
            }
            // truncate rest of link
            branch.Length = groupCard1;
            branch.Length = card;
            return(pg);
        }
예제 #19
0
        internal RtreePage splitPage(Branch br)
        {
            int i, j, seed0 = 0, seed1 = 0;

            long[] rectArea = new long[card + 1];
            long   waste;
            long   worstWaste = Int64.MinValue;

            //
            // As the seeds for the two groups, find two rectangles which waste
            // the most area if covered by a single rectangle.
            //
            rectArea[0] = br.r.Area();
            for (i = 0; i < card; i++)
            {
                rectArea[i + 1] = b[i].r.Area();
            }
            Branch bp = br;

            for (i = 0; i < card; i++)
            {
                for (j = i + 1; j <= card; j++)
                {
                    waste = Rectangle.JoinArea(bp.r, b[j - 1].r) - rectArea[i] - rectArea[j];
                    if (waste > worstWaste)
                    {
                        worstWaste = waste;
                        seed0      = i;
                        seed1      = j;
                    }
                }
                bp = b[i];
            }
            byte[]    taken = new byte[card];
            Rectangle group0, group1;
            long      groupArea0, groupArea1;
            int       groupCard0, groupCard1;
            RtreePage pg;

            taken[seed1 - 1] = 2;
            group1           = b[seed1 - 1].r;

            if (seed0 == 0)
            {
                group0 = br.r;
                pg     = new RtreePage(br.p, br.r);
            }
            else
            {
                group0       = b[seed0 - 1].r;
                pg           = new RtreePage(b[seed0 - 1].p, group0);
                b[seed0 - 1] = br;
            }
            groupCard0 = groupCard1 = 1;
            groupArea0 = rectArea[seed0];
            groupArea1 = rectArea[seed1];
            //
            // Split remaining rectangles between two groups.
            // The one chosen is the one with the greatest difference in area
            // expansion depending on which group - the rect most strongly
            // attracted to one group and repelled from the other.
            //
            while (groupCard0 + groupCard1 < card + 1 &&
                   groupCard0 < card + 1 - minFill &&
                   groupCard1 < card + 1 - minFill)
            {
                int  betterGroup = -1, chosen = -1;
                long biggestDiff = -1;
                for (i = 0; i < card; i++)
                {
                    if (taken[i] == 0)
                    {
                        long diff = (Rectangle.JoinArea(group0, b[i].r) - groupArea0)
                                    - (Rectangle.JoinArea(group1, b[i].r) - groupArea1);
                        if (diff > biggestDiff || -diff > biggestDiff)
                        {
                            chosen = i;
                            if (diff < 0)
                            {
                                betterGroup = 0;
                                biggestDiff = -diff;
                            }
                            else
                            {
                                betterGroup = 1;
                                biggestDiff = diff;
                            }
                        }
                    }
                }
                Debug.Assert(chosen >= 0);
                if (betterGroup == 0)
                {
                    group0.Join(b[chosen].r);
                    groupArea0         = group0.Area();
                    taken[chosen]      = 1;
                    pg.b[groupCard0++] = b[chosen];
                }
                else
                {
                    groupCard1 += 1;
                    group1.Join(b[chosen].r);
                    groupArea1    = group1.Area();
                    taken[chosen] = 2;
                }
            }
            //
            // If one group gets too full, then remaining rectangle are
            // split between two groups in such way to balance cards of two groups.
            //
            if (groupCard0 + groupCard1 < card + 1)
            {
                for (i = 0; i < card; i++)
                {
                    if (taken[i] == 0)
                    {
                        if (groupCard0 >= groupCard1)
                        {
                            taken[i]    = 2;
                            groupCard1 += 1;
                        }
                        else
                        {
                            taken[i]           = 1;
                            pg.b[groupCard0++] = b[i];
                        }
                    }
                }
            }
            for (i = 0, j = 0; i < groupCard1; j++)
            {
                if (taken[j] == 2)
                {
                    b[i++] = b[j];
                }
            }
            for (j = n; i < j; i++)
            {
                b[i].p = null;
            }
            pg.n = groupCard0;
            n    = groupCard1;
            return(pg);
        }