예제 #1
0
 /// <summary> Create copy of the rectangle</summary>
 public RectangleR2(RectangleR2 r)
 {
     this.top = r.top;
     this.left = r.left;
     this.bottom = r.bottom;
     this.right = r.right;
 }
예제 #2
0
 internal virtual void Find(RectangleR2 r, ArrayList result, int level)
 {
     if (--level != 0)
     {
         /* this is an internal node in the tree */
         for (int i = 0; i < n; i++)
         {
             if (r.Intersects(b[i]))
             {
                 ((RtreeR2Page) branch.Get(i)).Find(r, result, level);
             }
         }
     }
     else
     {
         /* this is a leaf node */
         for (int i = 0; i < n; i++)
         {
             if (r.Intersects(b[i]))
             {
                 result.Add(branch.Get(i));
             }
         }
     }
 }
예제 #3
0
 internal RectangleR2 Cover()
 {
     RectangleR2 r = new RectangleR2(b[0]);
     for (int i = 1; i < n; i++)
     {
         r.Join(b[i]);
     }
     return r;
 }
예제 #4
0
 internal RtreeR2Page AddBranch(Storage storage, RectangleR2 r, IPersistent obj)
 {
     if (n < card)
     {
         SetBranch(n++, r, obj);
         return null;
     }
     else
     {
         return SplitPage(storage, r, obj);
     }
 }
예제 #5
0
 internal RtreeR2Page(Storage storage, IPersistent obj, RectangleR2 r)
 {
     branch = storage.CreateLink(card);
     branch.Size = card;
     b = new RectangleR2[card];
     SetBranch(0, new RectangleR2(r), obj);
     n = 1;
     for (int i = 1; i < card; i++)
     {
         b[i] = new RectangleR2();
     }
 }
예제 #6
0
 internal RtreeR2Page(Storage storage, RtreeR2Page root, RtreeR2Page p)
 {
     branch = storage.CreateLink(card);
     branch.Size = card;
     b = new RectangleR2[card];
     n = 2;
     SetBranch(0, root.Cover(), root);
     SetBranch(1, p.Cover(), p);
     for (int i = 2; i < card; i++)
     {
         b[i] = new RectangleR2();
     }
 }
예제 #7
0
파일: TestR2.cs 프로젝트: kjk/tenderbase
    public static void Main(string[] args)
    {
        Storage db = StorageFactory.Instance.CreateStorage();
        long start = (DateTime.Now.Ticks - 621355968000000000) / 10000;
        if (args.Length > 0 && "noflush".Equals(args[0]))
            db.SetProperty("perst.file.noflush", true);

        db.Open("testr2.dbs");
        TestR2 root = (TestR2) db.GetRoot();
        if (root == null)
        {
            root = new TestR2();
            root.index = db.CreateSpatialIndexR2();
            db.SetRoot(root);
        }

        RectangleR2[] rectangles = new RectangleR2[nObjectsInTree];
        long key = 1999;
        for (int i = 0; i < nIterations; i++)
        {
            int j = i % nObjectsInTree;
            if (i >= nObjectsInTree)
            {
                RectangleR2 r = rectangles[j];
                IPersistent[] sos = root.index.Get(r);
                IPersistent po = null;
                int n = 0;
                for (int k = 0; k < sos.Length; k++)
                {
                    SpatialObject so = (SpatialObject) sos[k];
                    if (r.Equals(so.rect))
                    {
                        po = so;
                    }
                    else
                    {
                        Assert.That(r.Intersects(so.rect));
                    }
                }

                Assert.That(po != null);
                for (int k = 0; k < nObjectsInTree; k++)
                {
                    if (r.Intersects(rectangles[k]))
                    {
                        n += 1;
                    }
                }

                Assert.That(n == sos.Length);

                System.Collections.IEnumerator iterator = root.index.GetEnumerator(r);
                for (int k = 0; iterator.MoveNext(); k++)
                {
                    n -= 1;
                    Assert.That(iterator.Current == sos[k]);
                }

                Assert.That(n == 0);

                root.index.Remove(r, po);
                po.Deallocate();
            }

            key = (3141592621L * key + 2718281829L) % 1000000007L;
            int top = (int) (key % 1000);
            int left = (int) (key / 1000 % 1000);
            key = (3141592621L * key + 2718281829L) % 1000000007L;
            int bottom = top + (int) (key % 100);
            int right = left + (int) (key / 100 % 100);
            SpatialObject so2 = new SpatialObject();
            RectangleR2 r2 = new RectangleR2(top, left, bottom, right);
            so2.rect = r2;
            rectangles[j] = r2;
            root.index.Put(r2, so2);

            if (i % 100 == 0)
            {
                Console.Out.Write("Iteration " + i + "\r");
                Console.Out.Flush();
                db.Commit();
            }

        }
        root.index.Clear();
        Console.Out.WriteLine("\nElapsed time " + ((DateTime.Now.Ticks - 621355968000000000) / 10000 - start));
        db.Close();
    }
예제 #8
0
        internal RtreeR2Page SplitPage(Storage storage, RectangleR2 r, IPersistent obj)
        {
            int i, j, seed0 = 0, seed1 = 0;
            double[] rectArea = new double[card + 1];
            double waste;
            //UPGRADE_TODO: The equivalent in .NET for field 'java.lang.Double.MIN_VALUE' may return a different value.
            double worstWaste = Double.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();
            }
            RectangleR2 bp = r;
            for (i = 0; i < card; i++)
            {
                for (j = i + 1; j <= card; j++)
                {
                    waste = RectangleR2.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];
            RectangleR2 group0, group1;
            double groupArea0, groupArea1;
            int groupCard0, groupCard1;
            RtreeR2Page pg;

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

            if (seed0 == 0)
            {
                group0 = new RectangleR2(r);
                pg = new RtreeR2Page(storage, obj, r);
            }
            else
            {
                group0 = new RectangleR2(b[seed0 - 1]);
                pg = new RtreeR2Page(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;
                double biggestDiff = -1;
                for (i = 0; i < card; i++)
                {
                    if (taken[i] == 0)
                    {
                        double diff = (RectangleR2.JoinArea(group0, b[i]) - groupArea0) - (RectangleR2.JoinArea(group1, b[i]) - groupArea1);
                        if (diff > biggestDiff || -diff > biggestDiff)
                        {
                            chosen = i;
                            if (diff < 0)
                            {
                                betterGroup = 0;
                                biggestDiff = -diff;
                            }
                            else
                            {
                                betterGroup = 1;
                                biggestDiff = diff;
                            }
                        }
                    }
                }
                Assert.That(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));
                }
            }
            return pg;
        }
예제 #9
0
 internal void SetBranch(int i, RectangleR2 r, IPersistent obj)
 {
     b[i] = r;
     branch.Set(i, obj);
 }
예제 #10
0
 internal virtual int Remove(RectangleR2 r, IPersistent obj, int level, ArrayList reinsertList)
 {
     if (--level != 0)
     {
         for (int i = 0; i < n; i++)
         {
             if (r.Intersects(b[i]))
             {
                 RtreeR2Page pg = (RtreeR2Page) branch.Get(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;
 }
예제 #11
0
 internal virtual RtreeR2Page Insert(Storage storage, RectangleR2 r, IPersistent obj, int level)
 {
     Modify();
     if (--level != 0)
     {
         // not leaf page
         int i, mini = 0;
         double minIncr = Double.MaxValue;
         double minArea = Double.MaxValue;
         for (i = 0; i < n; i++)
         {
             double area = b[i].Area();
             double incr = RectangleR2.JoinArea(b[i], r) - area;
             if (incr < minIncr)
             {
                 minIncr = incr;
                 minArea = area;
                 mini = i;
             }
             else if (incr == minIncr && area < minArea)
             {
                 minArea = area;
                 mini = i;
             }
         }
         RtreeR2Page p = (RtreeR2Page) branch.Get(mini);
         RtreeR2Page 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 RectangleR2(r), obj);
     }
 }
예제 #12
0
 /// <summary> Non destructive join of two rectangles. </summary>
 /// <param name="a">first joined rectangle
 /// </param>
 /// <param name="b">second joined rectangle
 /// </param>
 /// <returns> rectangle containing Cover of these two rectangles
 /// </returns>
 public static RectangleR2 Join(RectangleR2 a, RectangleR2 b)
 {
     RectangleR2 r = new RectangleR2(a);
     r.Join(b);
     return r;
 }
예제 #13
0
 /// <summary> Join two rectangles. This rectangle is updates to contain Cover of this and specified rectangle.</summary>
 /// <param name="r">rectangle to be joined with this rectangle
 /// </param>
 public void Join(RectangleR2 r)
 {
     if (left > r.left)
     {
         left = r.left;
     }
     if (right < r.right)
     {
         right = r.right;
     }
     if (top > r.top)
     {
         top = r.top;
     }
     if (bottom < r.bottom)
     {
         bottom = r.bottom;
     }
 }
예제 #14
0
 /// <summary> Checks if this rectangle intersects with specified rectangle</summary>
 public bool Intersects(RectangleR2 r)
 {
     return left <= r.right && top <= r.bottom && right >= r.left && bottom >= r.top;
 }
예제 #15
0
 /// <summary> Checks if this rectangle contains the specified rectangle</summary>
 public bool Contains(RectangleR2 r)
 {
     return left <= r.left && top <= r.top && right >= r.right && bottom >= r.bottom;
 }
예제 #16
0
 /// <summary> Area of covered rectangle for two sepcified rectangles</summary>
 public static double JoinArea(RectangleR2 a, RectangleR2 b)
 {
     double left = (a.left < b.left) ? a.left : b.left;
     double right = (a.right > b.right) ? a.right : b.right;
     double top = (a.top < b.top) ? a.top : b.top;
     double bottom = (a.bottom > b.bottom) ? a.bottom : b.bottom;
     return (bottom - top) * (right - left);
 }