public bool MoveNext() { if (counter != tree.updateCounter) { throw new InvalidOperationException("B-Tree was modified"); } if (sp > 0) { int i = posStack[sp - 1]; RtreeR2Page pg = pageStack[sp - 1]; if (i < pg.n) { curr = pg.branch[i]; hasCurrent = true; while (++i < pg.n) { if (r.Intersects(pg.b[i])) { posStack[sp - 1] = i; return(true); } } sp -= 1; popNext(); return(true); } } hasCurrent = false; return(false); }
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; RtreeR2Page pg = (RtreeR2Page)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 Reset() { pageStack = new RtreeR2Page[tree.height]; posStack = new int[tree.height]; RtreeR2Page pg = tree.root; hasCurrent = false; counter = tree.updateCounter; sp = 0; if (pg != null) { push: while (true) { for (int i = 0; i < pg.n; i++) { if (r.Intersects(pg.b[i])) { posStack[sp] = i; pageStack[sp] = pg; if (++sp == pageStack.Length) { return; } pg = (RtreeR2Page)pg.branch[i]; goto push; } } popNext(); return; } } }
public void Clear() { if (root != null) { root.purge(height); root = null; } height = 0; n = 0; updateCounter += 1; Modify(); }
internal RtreeR2Page(Storage storage, RtreeR2Page root, RtreeR2Page p) { branch = storage.CreateLink(card); branch.Length = 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(); } }
internal RtreeEnumerator(RtreeR2 tree, RectangleR2 r) #endif { counter = tree.updateCounter; height = tree.height; this.tree = tree; if (height == 0) { return; } this.r = r; pageStack = new RtreeR2Page[height]; posStack = new int[height]; Reset(); }
private bool gotoFirstItem(int sp, RtreeR2Page pg) { for (int i = 0, n = pg.n; i < n; i++) { if (r.Intersects(pg.b[i])) { if (sp + 1 == height || gotoFirstItem(sp + 1, (RtreeR2Page)pg.branch[i])) { pageStack[sp] = pg; posStack[sp] = i; return(true); } } } return(false); }
internal RtreeR2Page insert(Storage storage, RectangleR2 r, object 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[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)); } }
private bool gotoNextItem(int sp) { RtreeR2Page 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, (RtreeR2Page)pg.branch[i])) { pageStack[sp] = pg; posStack[sp] = i; return(true); } } } pageStack[sp] = null; return((sp > 0) ? gotoNextItem(sp - 1) : false); }
internal int remove(RectangleR2 r, object obj, int level, ArrayList reinsertList) { if (--level != 0) { for (int i = 0; i < n; i++) { if (r.Intersects(b[i])) { RtreeR2Page pg = (RtreeR2Page)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 Put(RectangleR2 r, IPersistent obj) { if (root == null) { root = new RtreeR2Page(Storage, obj, r); height = 1; } else { RtreeR2Page p = root.insert(Storage, r, obj, height); if (p != null) { root = new RtreeR2Page(Storage, root, p); height += 1; } } n += 1; updateCounter += 1; Modify(); }
public void Remove(RectangleR2 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;) { RtreeR2Page p = (RtreeR2Page)reinsertList[i]; for (int j = 0, pn = p.n; j < pn; j++) { RtreeR2Page q = root.insert(Storage, p.b[j], p.branch[j], height - reinsertLevel); if (q != null) { // root splitted root = new RtreeR2Page(Storage, root, q); height += 1; } } reinsertLevel -= 1; p.Deallocate(); } if (root.n == 1 && height > 1) { RtreeR2Page newRoot = (RtreeR2Page)root.branch[0]; root.Deallocate(); root = newRoot; height -= 1; } n -= 1; updateCounter += 1; Modify(); }
void popNext() { pop: while (sp != 0) { sp -= 1; int i = posStack[sp]; RtreeR2Page pg = pageStack[sp]; while (++i < pg.n) { if (r.Intersects(pg.b[i])) { posStack[sp] = i; sp += 1; push: while (true) { pg = (RtreeR2Page)pg.branch[i]; for (i = 0; i < pg.n; i++) { if (r.Intersects(pg.b[i])) { posStack[sp] = i; pageStack[sp] = pg; if (++sp == pageStack.Length) { return; } goto push; } } goto pop; } } } } }
RtreeR2Page splitPage(Storage storage, RectangleR2 r, object obj) { int i, j, seed0 = 0, seed1 = 0; double[] rectArea = new double[card + 1]; double waste; 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; } } } } 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); }
RtreeR2Page splitPage(Storage storage, RectangleR2 r, object obj) { int i, j, seed0 = 0, seed1 = 0; double[] rectArea = new double[card+1]; double waste; 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; } } } } 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; }