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; RtreeRnPage pg = (RtreeRnPage)neighbor.child; for (int i = 0, n = pg.n; i < n; i++) { Insert(new Neighbor(pg.branch[i], pg.b[i].Distance(center), neighbor.level - 1)); } } }
internal RtreeRnPage(Storage storage, RtreeRnPage root, RtreeRnPage p) { branch = storage.CreateLink(card); branch.Length = card; b = new RectangleRn[card]; n = 2; setBranch(0, root.cover(), root); setBranch(1, p.cover(), p); }
public override void Clear() { if (root != null) { root.purge(height); root = null; } height = 0; n = 0; updateCounter += 1; Modify(); }
internal RtreeEnumerator(RtreeRn tree, RectangleRn r) #endif { counter = tree.updateCounter; height = tree.height; this.tree = tree; if (height == 0) { return; } this.r = r; pageStack = new RtreeRnPage[height]; posStack = new int[height]; Reset(); }
private bool gotoFirstItem(int sp, RtreeRnPage pg) { for (int i = 0, n = pg.n; i < n; i++) { if (r.Intersects(pg.b[i])) { if (sp + 1 == height || gotoFirstItem(sp + 1, (RtreeRnPage)pg.branch[i])) { pageStack[sp] = pg; posStack[sp] = i; return(true); } } } return(false); }
internal RtreeRnPage insert(Storage storage, RectangleRn 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 = RectangleRn.JoinArea(b[i], r) - area; if (incr < minIncr) { minIncr = incr; minArea = area; mini = i; } else if (incr == minIncr && area < minArea) { minArea = area; mini = i; } } RtreeRnPage p = (RtreeRnPage)branch[mini]; RtreeRnPage 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 RectangleRn(r), obj)); } }
private bool gotoNextItem(int sp) { RtreeRnPage 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, (RtreeRnPage)pg.branch[i])) { pageStack[sp] = pg; posStack[sp] = i; return(true); } } } pageStack[sp] = null; return((sp > 0) ? gotoNextItem(sp - 1) : false); }
internal int remove(RectangleRn r, object obj, int level, ArrayList reinsertList) { if (--level != 0) { for (int i = 0; i < n; i++) { if (r.Intersects(b[i])) { RtreeRnPage pg = (RtreeRnPage)branch[i]; int reinsertLevel = pg.remove(r, obj, level, reinsertList); if (reinsertLevel >= 0) { if (pg.n >= card / 2) { 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(RectangleRn 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;) { RtreeRnPage p = (RtreeRnPage)reinsertList[i]; for (int j = 0, pn = p.n; j < pn; j++) { RtreeRnPage q = root.insert(Storage, p.b[j], p.branch[j], height - reinsertLevel); if (q != null) { // root splitted root = new RtreeRnPage(Storage, root, q); height += 1; } } reinsertLevel -= 1; p.Deallocate(); } if (root.n == 1 && height > 1) { RtreeRnPage newRoot = (RtreeRnPage)root.branch[0]; root.Deallocate(); root = newRoot; height -= 1; } n -= 1; updateCounter += 1; Modify(); }
public void Put(RectangleRn r, object obj) #endif { if (root == null) { root = new RtreeRnPage(Storage, obj, r); height = 1; } else { RtreeRnPage p = root.insert(Storage, r, obj, height); if (p != null) { root = new RtreeRnPage(Storage, root, p); height += 1; } } n += 1; updateCounter += 1; Modify(); }
RtreeRnPage splitPage(Storage storage, RectangleRn 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(); } RectangleRn bp = r; for (i = 0; i < card; i++) { for (j = i + 1; j <= card; j++) { waste = RectangleRn.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]; RectangleRn group0, group1; double groupArea0, groupArea1; int groupCard0, groupCard1; RtreeRnPage pg; taken[seed1 - 1] = 2; group1 = new RectangleRn(b[seed1 - 1]); if (seed0 == 0) { group0 = new RectangleRn(r); pg = new RtreeRnPage(storage, obj, r); } else { group0 = new RectangleRn(b[seed0 - 1]); pg = new RtreeRnPage(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 - card / 2 && groupCard1 < card + 1 - card / 2) { int betterGroup = -1, chosen = -1; double biggestDiff = -1; for (i = 0; i < card; i++) { if (taken[i] == 0) { double diff = (RectangleRn.JoinArea(group0, b[i]) - groupArea0) - (RectangleRn.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); }
RtreeRnPage splitPage(Storage storage, RectangleRn 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(); } RectangleRn bp = r; for (i = 0; i < card; i++) { for (j = i+1; j <= card; j++) { waste = RectangleRn.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]; RectangleRn group0, group1; double groupArea0, groupArea1; int groupCard0, groupCard1; RtreeRnPage pg; taken[seed1-1] = 2; group1 = new RectangleRn(b[seed1-1]); if (seed0 == 0) { group0 = new RectangleRn(r); pg = new RtreeRnPage(storage, obj, r); } else { group0 = new RectangleRn(b[seed0-1]); pg = new RtreeRnPage(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 - card/2 && groupCard1 < card + 1 - card/2) { int betterGroup = -1, chosen = -1; double biggestDiff = -1; for (i = 0; i < card; i++) { if (taken[i] == 0) { double diff = (RectangleRn.JoinArea(group0, b[i]) - groupArea0) - (RectangleRn.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; }