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)); } } }
public void Clear() { if (root != null) { root.purge(height); root = null; } height = 0; n = 0; Modify(); }
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(); }
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); }
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))); } }
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)); } }
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); }
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(); }
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(); }
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; }
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); }
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); }