/// <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(RectangleRn r) { for (int i = 0, n = coords.Length / 2; i < n; i++) { coords[i] = Math.Min(coords[i], r.coords[i]); coords[i + n] = Math.Max(coords[i + n], r.coords[i + n]); } }
internal RtreeRnPage(Storage storage, object obj, RectangleRn r) { branch = storage.CreateLink(card); branch.Length = card; b = new RectangleRn[card]; setBranch(0, new RectangleRn(r), obj); n = 1; }
/// <summary> /// Area of covered rectangle for two sepcified rectangles /// </summary> public static double JoinArea(RectangleRn a, RectangleRn b) { double area = 1.0; for (int i = 0, n = a.coords.Length/2; i < n; i++) { double min = Math.Min(a.coords[i], b.coords[i]); double max = Math.Max(a.coords[n + i], b.coords[n + i]); area *= max - min; } return area; }
/// <summary> /// Checks if this rectangle contains the specified rectangle /// </summary> public bool Contains(RectangleRn r) { for (int i = 0, n = coords.Length / 2; i < n; i++) { if (coords[i] > r.coords[i] || coords[i + n] < r.coords[i + n]) { return(false); } } return(true); }
/// <summary> /// Area of covered rectangle for two sepcified rectangles /// </summary> public static double JoinArea(RectangleRn a, RectangleRn b) { double area = 1.0; for (int i = 0, n = a.coords.Length / 2; i < n; i++) { double min = Math.Min(a.coords[i], b.coords[i]); double max = Math.Max(a.coords[n + i], b.coords[n + i]); area *= max - min; } return(area); }
public RectangleRn WrappingRectangle() { Line line = new Line(points[0], points[1]); RectangleRn wr = line.WrappingRectangle(); for (int i = 1; i < points.Length; i++) { line = new Line(points[i], points[(i + 1) % points.Length]); wr.Join(line.WrappingRectangle()); } return(wr); }
public void Unpack(ObjectReader reader) { n = reader.ReadInt32(); branch = (Link)reader.ReadObject(); card = branch.Count; int nDims = ((Page.pageSize-ObjectHeader.Sizeof-12)/card - 4) / 16; double[] coords = new double[nDims*2]; b = new RectangleRn[card]; for (int i = 0; i < n; i++) { for (int j = 0; j < nDims; j++) { coords[j] = reader.ReadDouble(); coords[j+nDims] = reader.ReadDouble(); } b[i] = new RectangleRn(coords); } }
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); } }
public RectangleRn WrappingRectangle() { Euler euler = new Euler(); euler.phi = phi; euler.theta = theta; euler.psi = psi; euler.psi_a = Euler.AXIS_Z; euler.theta_a = Euler.AXIS_X; euler.phi_a = Euler.AXIS_Z; if (FP.zero(length)) { Point3D beg3d = new Point3D(); Point3D end3d = new Point3D(); euler.transform(beg3d, new Point3D(0.0, 0.0)); euler.transform(end3d, new Point3D(length, 0.0)); RectangleRn r = beg3d.toRectangle(); end3d.addToRectangle(r); return(r); } else { double l, ls, lc; Point3D[] v = new Point3D[4]; Point3D tv = new Point3D(); l = length / 2.0; ls = Math.Sin(l); lc = Math.Cos(l); euler.phi += l; v[0] = new Point3D(lc, lc < 0 ? -1.0 : -ls, 0.0); v[1] = new Point3D(1.0, lc < 0 ? -1.0 : -ls, 0.0); v[2] = new Point3D(lc, lc < 0 ? +1.0 : +ls, 0.0); v[3] = new Point3D(1.0, lc < 0 ? +1.0 : +ls, 0.0); Point3D min = new Point3D(1.0, 1.0, 1.0); Point3D max = new Point3D(-1.0, -1.0, -1.0); for (int i = 0; i < 4; i++) { euler.transform(tv, v[i]); if (tv.x < -1.0) { min.x = -1.0; } else if (tv.x > 1.0) { max.x = 1.0; } else { if (tv.x < min.x) { min.x = tv.x; } if (tv.x > max.x) { max.x = tv.x; } } if (tv.y < -1.0) { min.y = -1.0; } else if (tv.y > 1.0) { max.y = 1.0; } else { if (tv.y < min.y) { min.y = tv.y; } if (tv.y > max.y) { max.y = tv.y; } } if (tv.z < -1.0) { min.z = -1.0; } else if (tv.z > 1.0) { max.z = 1.0; } else { if (tv.z < min.z) { min.z = tv.z; } if (tv.z > max.z) { max.z = tv.z; } } } return(new RectangleRn(new double[] { min.x, min.y, min.z, max.x, max.y, max.z })); } }
internal void addToRectangle(RectangleRn r) { addToRectangle(r, x, y, z); }
/// <summary> /// Create copy of the rectangle /// </summary> public RectangleRn(RectangleRn r) { coords = new double[r.coords.Length]; Array.Copy(r.coords, 0, coords, 0, coords.Length); }
void setBranch(int i, RectangleRn r, object obj) { b[i] = r; branch[i] = obj; }
/// <summary> /// Checks if this rectangle contains the specified rectangle /// </summary> public bool Contains(RectangleRn r) { for (int i = 0, n = coords.Length/2; i < n; i++) { if (coords[i] > r.coords[i] || coords[i+n] < r.coords[i+n]) { return false; } } return true; }
/// <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 RectangleRn Join(RectangleRn a, RectangleRn b) { RectangleRn r = new RectangleRn(a); r.Join(b); return r; }
/// <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(RectangleRn r) { for (int i = 0, n = coords.Length/2; i < n; i++) { coords[i] = Math.Min(coords[i], r.coords[i]); coords[i+n] = Math.Max(coords[i+n], r.coords[i+n]); } }
internal void find(RectangleRn 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])) { ((RtreeRnPage)branch[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[i]); } } } }
internal static void addToRectangle(RectangleRn r, double ra, double dec) { double x = Math.Cos(ra)*Math.Cos(dec); double y = Math.Sin(ra)*Math.Cos(dec); double z = Math.Sin(dec); addToRectangle(r, x, y, z); }
RtreeRnPage addBranch(Storage storage, RectangleRn r, object obj) { if (n < card) { setBranch(n++, r, obj); return null; } else { return splitPage(storage, r, obj); } }
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; }
internal RectangleRn cover() { RectangleRn r = new RectangleRn(b[0]); for (int i = 1; i < n; i++) { r.Join(b[i]); } return r; }
internal static void addToRectangle(RectangleRn r, double x, double y, double z) { if (x < r.coords[0]) { r.coords[0] = x; } if (y < r.coords[1]) { r.coords[1] = y; } if (z < r.coords[2]) { r.coords[2] = z; } if (x > r.coords[3]) { r.coords[3] = x; } if (y > r.coords[4]) { r.coords[4] = y; } if (z > r.coords[5]) { r.coords[5] = z; } }
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; }