//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Tests to see whether <B>h</B> is inside this HyperCube. * If <B>h</B> is exactly the same shape as this object, it is considered * to be inside. * * @return True if <B>h</B> is inside, false otherwise. */ public bool Enclosure(HyperCube h) { if (h == null) { throw new ArgumentException("HyperCube cannot be null."); } if (h.GetDimension() != GetDimension()) { throw new ArgumentException ("HyperCube dimension is different from current dimension."); } bool inside = true; for (int i = 0; i < GetDimension(); i++) { if (_p1.GetFloatCoordinate(i) > h._p1.GetFloatCoordinate(i) || _p2.GetFloatCoordinate(i) < h._p2.GetFloatCoordinate(i)) { inside = false; break; } } return(inside); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Return a new HyperCube representing the mbb of the Union of this * HyperCube and <B>h</B> * * @param h The HyperCube that we want to Union with this HyperCube. * @return A HyperCube representing the mbb of their Union. */ public HyperCube GetUnionMbb(HyperCube h) { if (h == null) { throw new ArgumentException("HyperCube cannot be null."); } if (h.GetDimension() != GetDimension()) { throw new ArgumentException ("HyperCubes must be of the same dimension."); } double[] min = new double[GetDimension()]; double[] max = new double[GetDimension()]; for (int i = 0; i < GetDimension(); i++) { min[i] = Math.Min(_p1.GetFloatCoordinate(i), h._p1.GetFloatCoordinate(i)); max[i] = Math.Max(_p2.GetFloatCoordinate(i), h._p2.GetFloatCoordinate(i)); } return(new HyperCube(new Point(min), new Point(max))); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * chooseLeaf finds the most appropriate leaf where the given HyperCube * should be stored. * * @param h The new HyperCube. * * @return The leaf where the new HyperCube should be inserted. */ internal override Leaf ChooseLeaf(HyperCube h) { int i; switch (Tree.GetTreeType()) { case RTree.RTREE_LINEAR: case RTree.RTREE_QUADRATIC: case RTree.RTREE_EXPONENTIAL: i = FindLeastEnlargement(h); break; case RTree.RSTAR: if (Level == 1) { // if this node points to leaves... i = FindLeastOverlap(h); } else { i = FindLeastEnlargement(h); } break; default: throw new Exception("Invalid tree type."); } return(GetChild(i).ChooseLeaf(h)); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Equals. */ public bool Equals(HyperCube h) { if (_p1.Equals(h.GetP1()) && _p2.Equals(h.GetP2())) { return(true); } return(false); }
public ContainEnum(HyperCube hh, RTree tree) { _cubes = tree.Enclosure(hh, tree._file.ReadNode(0)); if (_cubes.Count == 0) { _hasNext = false; } }
public IntersectionEnum(HyperCube hh, RTree tree) { _nodes = tree.Intersection(hh, tree._file.ReadNode(0)); if (_nodes.Count == 0) { _hasNext = false; } }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Return a copy of the HyperCubes present in this node. * @return An array of HyperCubes containing copies of the original data. */ public HyperCube[] GetHyperCubes() { HyperCube[] h = new HyperCube[UsedSpace]; for (int i = 0; i < UsedSpace; i++) { h[i] = (HyperCube)Data[i].Clone(); } return(h); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Returns the mbb of all HyperCubes present in this node. * * @return A new HyperCube object, representing the mbb of this node. */ public HyperCube GetNodeMbb() { if (UsedSpace > 0) { HyperCube[] h = new HyperCube[UsedSpace]; Array.Copy(Data, 0, h, 0, UsedSpace); return(HyperCube.GetUnionMbb(h)); } return(new HyperCube(new Point(new double[] { 0, 0 }), new Point(new double[] { 0, 0 }))); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Returns the area of the intersecting region between this HyperCube and * the argument. * * Below, all possible situations are depicted. * * ------- ------- --------- --------- ------ ------ * |2 | |2 | |2 | |1 | |2 | |1 | * --|-- | | --|-- | ------ | | ------ | --|------|-- --|------|-- * |1 | | | | |1 | | ||1 | | ||2 | | |1 | | | |2 | | | * --|-- | | --|-- | ------ | | ------ | --|------|-- --|------|-- * ------- ------- --------- --------- ------ ------ * * @param h Given HyperCube. * @return Area of intersecting region. */ public double IntersectingArea(HyperCube h) { if (!Intersection(h)) { return(0); } double ret = 1; for (int i = 0; i < GetDimension(); i++) { double l1 = _p1.GetFloatCoordinate(i); double h1 = _p2.GetFloatCoordinate(i); double l2 = h._p1.GetFloatCoordinate(i); double h2 = h._p2.GetFloatCoordinate(i); if (l1 <= l2 && h1 <= h2) { // cube1 left of cube2. ret *= (h1 - l1) - (l2 - l1); } else if (l2 <= l1 && h2 <= h1) { // cube1 right of cube2. ret *= (h2 - l2) - (l1 - l2); } else if (l2 <= l1 && h1 <= h2) { // cube1 inside cube2. ret *= h1 - l1; } else if (l1 <= l2 && h2 <= h1) { // cube1 Contains cube2. ret *= h2 - l2; } else if (l1 <= l2 && h2 <= h1) { // cube1 crosses cube2. ret *= h2 - l2; } else if (l2 <= l1 && h1 <= h2) { // cube1 crossed by cube2. ret *= h1 - l1; } } if (ret <= 0) { throw new ArithmeticException("Intersecting area cannot be negative!"); } return(ret); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * findLeaf. */ internal override Leaf FindLeaf(HyperCube h) { for (int i = 0; i < UsedSpace; i++) { if (Data[i].Enclosure(h)) { return(this); } } return(null); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * findLeaf returns the leaf that Contains the given hypercube, null if the * hypercube is not contained in any of the leaves of this node. * @param h The HyperCube to search for. * @return The leaf where the HyperCube is contained, null if such a leaf * is not found. */ internal override Leaf FindLeaf(HyperCube h) { for (int i = 0; i < UsedSpace; i++) { if (Data[i].Enclosure(h)) { Leaf l = GetChild(i).FindLeaf(h); if (l != null) { return(l); } } } return(null); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Static impementation. Takes an array of HyperCubes and calculates the * mbb of their Union. * * @param a The array of HyperCubes. * @return The mbb of their Union. */ public static HyperCube GetUnionMbb(HyperCube[] a) { if (a == null || a.Length == 0) { throw new ArgumentException("HyperCube array is empty."); } HyperCube h = (HyperCube)a[0].Clone(); for (int i = 1; i < a.Length; i++) { h = h.GetUnionMbb(a[i]); } return(h); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Add the new HyperCube to all mbbs present in this node. Calculate the * area difference and choose the entry with the least enlargement. Based * on that metric we choose the path that leads to the leaf that will * hold the new HyperCube. * [A. Guttman 'R-trees a dynamic index structure for spatial searching'] * * @return The index of the branch of the path that leads to the Leaf where * the new HyperCube should be inserted. */ private int FindLeastEnlargement(HyperCube h) { double area = Double.PositiveInfinity; int sel = -1; for (int i = 0; i < UsedSpace; i++) { double enl = Data[i].GetUnionMbb(h).GetArea() - Data[i].GetArea(); if (enl < area) { area = enl; sel = i; } else if (enl == area) { sel = (Data[sel].GetArea() <= Data[i].GetArea()) ? sel : i; } } return(sel); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Returns a ArrayList with all Hypercubes that completely contain HyperCube * <B>h</B>. * The HyperCubes are returned in post order traversing, according to the * Nodes where they belong. * * @param h The given HyperCube. * @param root The node where the search should begin. * @return A ArrayList containing the appropriate HyperCubes in the correct * order. */ public ArrayList Enclosure(HyperCube h, AbstractNode root) { if (h == null || root == null) { throw new ArgumentException("Arguments cannot be null."); } if (h.GetDimension() != _file.Dimension) { throw new ArgumentException("HyperCube dimension " + "different than RTree dimension."); } ArrayList v = new ArrayList(); if (root.GetNodeMbb().Enclosure(h)) { v.Add(root); if (!root.IsLeaf()) { for (int i = 0; i < root.UsedSpace; i++) { if (root.Data[i].Enclosure(h)) { ArrayList a = Enclosure(h, ((Index)root).GetChild(i)); for (int j = 0; j < a.Count; j++) { v.Add(a[j]); } } } } } return(v); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * R*-tree criterion for choosing the best branch to follow. * [Beckmann, Kriegel, Schneider, Seeger 'The R*-tree: An efficient and * Robust Access Method for Points and Rectangles] * * @return The index of the branch of the path that leads to the Leaf where * the new HyperCube should be inserted. */ private int FindLeastOverlap(HyperCube h) { float overlap = float.PositiveInfinity; int sel = -1; for (int i = 0; i < UsedSpace; i++) { AbstractNode n = GetChild(i); float o = 0; for (int j = 0; j < n.Data.Length; j++) { o += (float)h.IntersectingArea(n.Data[j]); } if (o < overlap) { overlap = o; sel = i; } else if (o == overlap) { double area1 = Data[i].GetUnionMbb(h).GetArea() - Data[i].GetArea(); double area2 = Data[sel].GetUnionMbb(h).GetArea() - Data[sel].GetArea(); if (area1 == area2) { sel = (Data[sel].GetArea() <= Data[i].GetArea()) ? sel : i; } else { sel = (area1 < area2) ? i : sel; } } } return(sel); }
//////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS -------------------------- // Date Name Tracking # Description // --------- ------------------- ------------- ------------------ // 21JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////// /** * Returns an Enumeration with all nodes present in the tree that Intersect with the given * HyperCube. The nodes are returned in post order traversing * * @param h The given HyperCube that is tested for overlapping. * @return An Enumeration containing the appropriate nodes in the correct order. */ public IEnumeration Intersection(HyperCube h) { return(new IntersectionEnum(h, this)); }
//////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS -------------------------- // Date Name Tracking # Description // --------- ------------------- ------------- ------------------ // 21JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////// /** * Returns an Enumeration with all Hypercubes present in the tree that contain the given * HyperCube. The HyperCubes are returned in post order traversing, according to the Nodes where * they belong. * * @param h The given HyperCube. * @param root The node where the search should begin. * @return An Enumeration containing the appropriate HyperCubes in the correct order. */ public IEnumeration Enclosure(HyperCube h) { return(new ContainEnum(h, this)); }
//////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS -------------------------- // Date Name Tracking # Description // --------- ------------------- ------------- ------------------ // 21JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////// /** * Returns an Enumeration with all nodes present in the tree that Intersect with the given * HyperCube. The nodes are returned in post order traversing * * @param h The given HyperCube that is tested for overlapping. * @return An Enumeration containing the appropriate nodes in the correct order. */ public IEnumeration Intersection(HyperCube h) { return new IntersectionEnum(h, this); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Returns a ArrayList with all nodes that Intersect with the given HyperCube. * The nodes are returned in post order traversing * * @param h The given HyperCube that is tested for overlapping. * @param root The node where the search should begin. * @return A ArrayList containing the appropriate nodes in the correct order. */ public ArrayList Intersection(HyperCube h, AbstractNode root) { if (h == null || root == null) { throw new ArgumentException("Arguments cannot be null."); } if (h.GetDimension() != _file.Dimension) { throw new ArgumentException ("HyperCube dimension different than RTree dimension."); } ArrayList v = new ArrayList(); if (root.GetNodeMbb().Intersection(h)) { v.Add(root); if (!root.IsLeaf()) { for (int i = 0; i < root.UsedSpace; i++) { if (root.Data[i].Intersection(h)) { ArrayList a = Intersection(h, ((Index)root).GetChild(i)); for (int j = 0; j < a.Count; j++) { v.Add(a[j]); } } } } } return v; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * * Tests to see whether <B>h</B> has any common points with this HyperCube. * If <B>h</B> is inside this object (or vice versa), it returns true. * * @return True if <B>h</B> and this HyperCube Intersect, false otherwise. */ public bool Intersection(HyperCube h) { if (h == null) throw new ArgumentException("HyperCube cannot be null."); if (h.GetDimension() != GetDimension()) throw new ArgumentException ("HyperCube dimension is different from current dimension."); bool intersect = true; for (int i = 0; i < GetDimension(); i++) { if (_p1.GetFloatCoordinate(i) > h._p2.GetFloatCoordinate(i) || _p2.GetFloatCoordinate(i) < h._p1.GetFloatCoordinate(i)) { intersect = false; break; } } return intersect; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * R*-tree criterion for choosing the best branch to follow. * [Beckmann, Kriegel, Schneider, Seeger 'The R*-tree: An efficient and * Robust Access Method for Points and Rectangles] * * @return The index of the branch of the path that leads to the Leaf where * the new HyperCube should be inserted. */ private int FindLeastOverlap(HyperCube h) { float overlap = float.PositiveInfinity; int sel = -1; for (int i = 0; i < UsedSpace; i++) { AbstractNode n = GetChild(i); float o = 0; for (int j = 0; j < n.Data.Length; j++) { o += (float)h.IntersectingArea(n.Data[j]); } if (o < overlap) { overlap = o; sel = i; } else if (o == overlap) { double area1 = Data[i].GetUnionMbb(h).GetArea() - Data[i].GetArea(); double area2 = Data[sel].GetUnionMbb(h).GetArea() - Data[sel].GetArea(); if (area1 == area2) { sel = (Data[sel].GetArea() <= Data[i].GetArea()) ? sel : i; } else { sel = (area1 < area2) ? i : sel; } } } return sel; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Returns the mbb of all HyperCubes present in this node. * * @return A new HyperCube object, representing the mbb of this node. */ public HyperCube GetNodeMbb() { if (UsedSpace > 0) { HyperCube[] h = new HyperCube[UsedSpace]; Array.Copy(Data, 0, h, 0, UsedSpace); return HyperCube.GetUnionMbb(h); } return new HyperCube(new Point(new double[] { 0, 0 }), new Point(new double[] { 0, 0 })); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * findLeaf returns the leaf that Contains the given hypercube, null if the * hypercube is not contained in any of the leaves of this node. * @param h The HyperCube to search for. * @return The leaf where the HyperCube is contained, null if such a leaf * is not found. */ internal override Leaf FindLeaf(HyperCube h) { for (int i = 0; i < UsedSpace; i++) { if (Data[i].Enclosure(h)) { Leaf l = GetChild(i).FindLeaf(h); if (l != null) { return l; } } } return null; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * findLeaf returns the leaf that Contains the given hypercube, null if the * hypercube is not contained in any of the leaves of this node. * * @param h The HyperCube to search for. * * @return The leaf where the HyperCube is contained, null if such a leaf is not found. */ internal abstract Leaf FindLeaf(HyperCube h);
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * chooseLeaf finds the most appropriate leaf where the given HyperCube * should be stored. * * @param h The new HyperCube. * * @return The leaf where the new HyperCube should be inserted. */ internal abstract Leaf ChooseLeaf(HyperCube h);
//////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS -------------------------- // Date Name Tracking # Description // --------- ------------------- ------------- ------------------ // 21JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////// /** * Returns an Enumeration with all Hypercubes present in the tree that contain the given * HyperCube. The HyperCubes are returned in post order traversing, according to the Nodes where * they belong. * * @param h The given HyperCube. * @param root The node where the search should begin. * @return An Enumeration containing the appropriate HyperCubes in the correct order. */ public IEnumeration Enclosure(HyperCube h) { return new ContainEnum(h, this); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * chooseLeaf. */ internal override Leaf ChooseLeaf(HyperCube h) { return this; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * chooseLeaf. */ internal override Leaf ChooseLeaf(HyperCube h) { return(this); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * findLeaf. */ internal override Leaf FindLeaf(HyperCube h) { for (int i = 0; i < UsedSpace; i++) { if (Data[i].Enclosure(h)) { return this; } } return null; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Static impementation. Takes an array of HyperCubes and calculates the * mbb of their Union. * * @param a The array of HyperCubes. * @return The mbb of their Union. */ public static HyperCube GetUnionMbb(HyperCube[] a) { if (a == null || a.Length == 0) throw new ArgumentException("HyperCube array is empty."); HyperCube h = (HyperCube)a[0].Clone(); for (int i = 1; i < a.Length; i++) { h = h.GetUnionMbb(a[i]); } return h; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Equals. */ public bool Equals(HyperCube h) { if (_p1.Equals(h.GetP1()) && _p2.Equals(h.GetP2())) { return true; } return false; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * get all records based on given rectangle. * @param rectGeo the boundary.. * @return a hashtable of all matched record.the key is the mapInfo ID. */ public Hashtable SearchMapObjectsInRect(GeoLatLngBounds rectGeo) { Point pt1, pt2; pt1 = new Point(new[]{ (int) (rectGeo.X * DOUBLE_PRECISION+0.5), (int) (rectGeo.Y * DOUBLE_PRECISION+0.5)}); pt2 = new Point(new int[]{ (int) ((rectGeo.X + rectGeo.Width) * DOUBLE_PRECISION+0.5), (int) ((rectGeo.Y + rectGeo.Height) * DOUBLE_PRECISION+0.5)}); HyperCube h1 = new HyperCube(pt1, pt2); Hashtable retArrayList = new Hashtable(); Point p11, p12; for (IEnumeration e1 = _tree.Intersection(h1); e1.HasMoreElements(); ) { AbstractNode node = (AbstractNode)(e1.NextElement()); if (node.IsLeaf()) { int index = 0; HyperCube[] data = node.GetHyperCubes(); HyperCube cube; for (int cubeIndex = 0; cubeIndex < data.Length; cubeIndex++) { cube = data[cubeIndex]; if (cube.Intersection(h1)) { p11 = cube.GetP1(); p12 = cube.GetP2(); int mapinfoId = ((Leaf)node).GetDataPointer(index); int mapInfoId = mapinfoId; GeoLatLngBounds mbr = new GeoLatLngBounds(); mbr.X = p11.GetFloatCoordinate(0) / DOUBLE_PRECISION; mbr.Y = p11.GetFloatCoordinate(1) / DOUBLE_PRECISION; mbr.Width = ((p12.GetFloatCoordinate(0) - p11.GetFloatCoordinate(0))) / DOUBLE_PRECISION; mbr.Height = ((p12.GetFloatCoordinate(1) - p11.GetFloatCoordinate(1))) / DOUBLE_PRECISION; if (!retArrayList.Contains(mapInfoId)) { retArrayList.Add(mapInfoId, mbr); } } index++; } } } return retArrayList; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Return a new HyperCube representing the mbb of the Union of this * HyperCube and <B>h</B> * * @param h The HyperCube that we want to Union with this HyperCube. * @return A HyperCube representing the mbb of their Union. */ public HyperCube GetUnionMbb(HyperCube h) { if (h == null) throw new ArgumentException("HyperCube cannot be null."); if (h.GetDimension() != GetDimension()) throw new ArgumentException ("HyperCubes must be of the same dimension."); double[] min = new double[GetDimension()]; double[] max = new double[GetDimension()]; for (int i = 0; i < GetDimension(); i++) { min[i] = Math.Min(_p1.GetFloatCoordinate(i), h._p1.GetFloatCoordinate(i)); max[i] = Math.Max(_p2.GetFloatCoordinate(i), h._p2.GetFloatCoordinate(i)); } return new HyperCube(new Point(min), new Point(max)); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Add the new HyperCube to all mbbs present in this node. Calculate the * area difference and choose the entry with the least enlargement. Based * on that metric we choose the path that leads to the leaf that will * hold the new HyperCube. * [A. Guttman 'R-trees a dynamic index structure for spatial searching'] * * @return The index of the branch of the path that leads to the Leaf where * the new HyperCube should be inserted. */ private int FindLeastEnlargement(HyperCube h) { double area = Double.PositiveInfinity; int sel = -1; for (int i = 0; i < UsedSpace; i++) { double enl = Data[i].GetUnionMbb(h).GetArea() - Data[i].GetArea(); if (enl < area) { area = enl; sel = i; } else if (enl == area) { sel = (Data[sel].GetArea() <= Data[i].GetArea()) ? sel : i; } } return sel; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Returns the area of the intersecting region between this HyperCube and * the argument. * * Below, all possible situations are depicted. * * ------- ------- --------- --------- ------ ------ * |2 | |2 | |2 | |1 | |2 | |1 | * --|-- | | --|-- | ------ | | ------ | --|------|-- --|------|-- * |1 | | | | |1 | | ||1 | | ||2 | | |1 | | | |2 | | | * --|-- | | --|-- | ------ | | ------ | --|------|-- --|------|-- * ------- ------- --------- --------- ------ ------ * * @param h Given HyperCube. * @return Area of intersecting region. */ public double IntersectingArea(HyperCube h) { if (!Intersection(h)) { return 0; } double ret = 1; for (int i = 0; i < GetDimension(); i++) { double l1 = _p1.GetFloatCoordinate(i); double h1 = _p2.GetFloatCoordinate(i); double l2 = h._p1.GetFloatCoordinate(i); double h2 = h._p2.GetFloatCoordinate(i); if (l1 <= l2 && h1 <= h2) { // cube1 left of cube2. ret *= (h1 - l1) - (l2 - l1); } else if (l2 <= l1 && h2 <= h1) { // cube1 right of cube2. ret *= (h2 - l2) - (l1 - l2); } else if (l2 <= l1 && h1 <= h2) { // cube1 inside cube2. ret *= h1 - l1; } else if (l1 <= l2 && h2 <= h1) { // cube1 Contains cube2. ret *= h2 - l2; } else if (l1 <= l2 && h2 <= h1) { // cube1 crosses cube2. ret *= h2 - l2; } else if (l2 <= l1 && h1 <= h2) { // cube1 crossed by cube2. ret *= h1 - l1; } } if (ret <= 0) throw new ArithmeticException("Intersecting area cannot be negative!"); return ret; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * chooseLeaf finds the most appropriate leaf where the given HyperCube * should be stored. * * @param h The new HyperCube. * * @return The leaf where the new HyperCube should be inserted. */ internal override Leaf ChooseLeaf(HyperCube h) { int i; switch (Tree.GetTreeType()) { case RTree.RTREE_LINEAR: case RTree.RTREE_QUADRATIC: case RTree.RTREE_EXPONENTIAL: i = FindLeastEnlargement(h); break; case RTree.RSTAR: if (Level == 1) { // if this node points to leaves... i = FindLeastOverlap(h); } else { i = FindLeastEnlargement(h); } break; default: throw new Exception("Invalid tree type."); } return GetChild(i).ChooseLeaf(h); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 21DEC2008 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Return a copy of the HyperCubes present in this node. * @return An array of HyperCubes containing copies of the original data. */ public HyperCube[] GetHyperCubes() { HyperCube[] h = new HyperCube[UsedSpace]; for (int i = 0; i < UsedSpace; i++) { h[i] = (HyperCube)Data[i].Clone(); } return h; }