Constructs a Quad-tree node from a object list and creates its children recursively
Наследование: IDisposable
Пример #1
0
 /// <summary>
 /// Reads a node from a stream recursively
 /// </summary>
 /// <param name="depth">Current depth</param>
 /// <param name="br">Binary reader reference</param>
 /// <returns></returns>
 private static QuadTree ReadNode(uint depth, BinaryReader br)
 {
     var bbox = new Envelope(new Coordinate(br.ReadDouble(), br.ReadDouble()),
                             new Coordinate(br.ReadDouble(), br.ReadDouble()));
     var node = new QuadTree(bbox, depth);
     
     var isLeaf = br.ReadBoolean();
     if (isLeaf)
     {
         var featureCount = br.ReadInt32();
         node._objList = new List<BoxObjects>();
         for (int i = 0; i < featureCount; i++)
         {
             var box = new BoxObjects();
             box.Box = new Envelope(new Coordinate(br.ReadDouble(), br.ReadDouble()),
                                    new Coordinate(br.ReadDouble(), br.ReadDouble()));
             box.ID = (uint) br.ReadInt32();
             node._objList.Add(box);
         }
     }
     else
     {
         node.Child0 = ReadNode(depth + 1, br);
         node.Child1 = ReadNode(depth + 1, br);
     }
     return node;
 }
Пример #2
0
        /// <summary>
        /// Saves a node to a stream recursively
        /// </summary>
        /// <param name="node">Node to save</param>
        /// <param name="sw">Reference to BinaryWriter</param>
        private static void SaveNode(QuadTree node, BinaryWriter sw)
        {
            //Write node boundingbox
            var box = node.Box;
            sw.Write(box.MinX);
            sw.Write(box.MinY);
            sw.Write(box.MaxX);
            sw.Write(box.MaxY);
            sw.Write(node.IsLeaf);
            if (node.IsLeaf || node.Child0 == null)
            {
                if (node._objList == null)
                {
                    sw.Write(0);
                    return;
                }

                sw.Write(node._objList.Count); //Write number of features at node
                for (int i = 0; i < node._objList.Count; i++) //Write each featurebox
                {
                    var bo = node._objList[i];
                    box = bo.Box;
                    sw.Write(box.MinX);
                    sw.Write(box.MinY);
                    sw.Write(box.MaxX);
                    sw.Write(box.MaxY);
                    sw.Write(bo.ID);
                }
            }
            else if (!node.IsLeaf) //Save next node
            {
                SaveNode(node.Child0, sw);
                SaveNode(node.Child1, sw);
            }
        }
Пример #3
0
        /// <summary>
        /// Recursive function that traverses the tree and looks for intersections with a boundingbox
        /// </summary>
        /// <param name="box">Boundingbox to intersect with</param>
        /// <param name="node">Node to search from</param>
        /// <param name="list">List of found intersections</param>
        private void IntersectTreeRecursive(BoundingBox box, QuadTree node, ref Collection<uint> list)
        {
            if (node.IsLeaf) //Leaf has been reached
            {
                foreach (BoxObjects boxObject in node._objList)
                {
                    if(box.Intersects(boxObject.box))
                        list.Add(boxObject.ID);

                }
                /*
                for (int i = 0; i < node._objList.Count; i++)
                {
                    list.Add(node._objList[i].ID);
                }
                */
            }
            else
            {
                if (node.Box.Intersects(box))
                {
                    IntersectTreeRecursive(box, node.Child0, ref list);
                    IntersectTreeRecursive(box, node.Child1, ref list);
                }
            }
        }
Пример #4
0
        /// <summary>
        /// Adds a new <see cref="BoxObjects"/> to this node.
        /// </summary>
        /// <param name="o">The boxed object</param>
        /// <param name="h">The child node creation heuristic</param>
        public void AddNode(BoxObjects o, Heuristic h)
        {
          /* -------------------------------------------------------------------- */
          /*      If there are subnodes, then consider whether this object        */
          /*      will fit in them.                                               */
          /* -------------------------------------------------------------------- */
            if (_child0 != null && _depth < h.maxdepth)
            {
                if (_child0.Box.Contains(o.Box.Centre))
                    _child0.AddNode(o, h);
                else if (_child1.Box.Contains(o.Box.Centre))
                    _child1.AddNode(o, h);
                return;
            }
        
            /* -------------------------------------------------------------------- */
            /*      Otherwise, consider creating two subnodes if could fit into     */
            /*      them, and adding to the appropriate subnode.                    */
            /* -------------------------------------------------------------------- */
            if( h.maxdepth > _depth && !IsLeaf )
            {
                Envelope half1, half2;
                SplitBoundingBox(Box, out half1, out half2);
            

                if( half1.Contains(o.Box.Centre)) 
                {
                    _child0 = new QuadTree(half1, _depth + 1);
                    _child1 = new QuadTree(half2, _depth + 1);
                    _child0.AddNode(o, h);
                    return;
                }    
	            if(half2.Contains(o.Box.Centre))
	            {
                    _child0 = new QuadTree(half1, _depth + 1);
                    _child1 = new QuadTree(half2, _depth + 1);
	                _child1.AddNode(o, h);
	                return;
	            }
            }
        
            /* -------------------------------------------------------------------- */
            /*      If none of that worked, just add it to this nodes list.         */
            /* -------------------------------------------------------------------- */
            //Debug.Assert(_child0 == null);
            
            if (_objList == null)
                _objList = new List<BoxObjects>();

            Box.ExpandToInclude(o.Box); 
            
            _objList.Add(o);

        }
Пример #5
0
 /// <summary>
 /// Saves a node to a stream recursively
 /// </summary>
 /// <param name="node">Node to save</param>
 /// <param name="sw">Reference to BinaryWriter</param>
 private void SaveNode(QuadTree node, ref System.IO.BinaryWriter sw)
 {
     //Write node boundingbox
     sw.Write(node.Box.Min.X);
     sw.Write(node.Box.Min.Y);
     sw.Write(node.Box.Max.X);
     sw.Write(node.Box.Max.Y);
     sw.Write(node.IsLeaf);
     if (node.IsLeaf)
     {
         sw.Write(node._objList.Count); //Write number of features at node
         for (int i = 0; i < node._objList.Count;i++ ) //Write each featurebox
         {
             sw.Write(node._objList[i].box.Min.X);
             sw.Write(node._objList[i].box.Min.Y);
             sw.Write(node._objList[i].box.Max.X);
             sw.Write(node._objList[i].box.Max.Y);
             sw.Write(node._objList[i].ID);
         }
     }
     else if (!node.IsLeaf) //Save next node
     {
         SaveNode(node.Child0, ref sw);
         SaveNode(node.Child1, ref sw);
     }
 }
Пример #6
0
 public void TryAddValue(string key, QuadTree quadTree, TimeSpan fromDays)
 {
     HttpCacheUtility.TryAddValue(key, quadTree, fromDays);
 }
Пример #7
0
        /// <summary>
        /// Creates a node and either splits the objects recursively into sub-nodes, or stores them at the node depending on the heuristics.
        /// Tree is built top-&gt;down
        /// </summary>
        /// <param name="objList">Geometries to index</param>
        /// <param name="depth">Current depth of tree</param>
        /// <param name="heurdata">Heuristics data</param>
        public QuadTree(List <BoxObjects> objList, uint depth, Heuristic heurdata)
        {
            _depth = depth;

            _box = new Envelope(objList[0].Box);
            for (var i = 1; i < objList.Count; i++)
            {
                _box.ExpandToInclude(objList[i].Box);
            }

            // test our build heuristic - if passes, make children
            if (depth < heurdata.maxdepth && objList.Count > heurdata.mintricnt &&
                (objList.Count > heurdata.tartricnt || ErrorMetric(_box) > heurdata.minerror))
            {
                var objBuckets = new List <BoxObjects> [2]; // buckets of geometries
                objBuckets[0] = new List <BoxObjects>();
                objBuckets[1] = new List <BoxObjects>();

                var longaxis = _box.LongestAxis(); // longest axis
                var geoavg   = 0d;                 // geometric average - midpoint of ALL the objects

                // go through all bbox and calculate the average of the midpoints
                var frac = 1.0d / objList.Count;
                for (var i = 0; i < objList.Count; i++)
                {
                    geoavg += objList[i].Box.Centre[longaxis] * frac;
                }

                // bucket bbox based on their midpoint's side of the geo average in the longest axis
                for (var i = 0; i < objList.Count; i++)
                {
                    objBuckets[geoavg > objList[i].Box.Centre[longaxis] ? 1 : 0].Add(objList[i]);
                }

                //If objects couldn't be splitted, just store them at the leaf
                //TODO: Try splitting on another axis
                if (objBuckets[0].Count == 0 || objBuckets[1].Count == 0)
                {
                    _child0 = null;
                    _child1 = null;
                    // copy object list
                    _objList = objList;
                }
                else
                {
                    //We don't need the list anymore;
                    objList.Clear();

                    // create new children using the buckets
                    _child0 = new QuadTree(objBuckets[0], depth + 1, heurdata);
                    _child1 = new QuadTree(objBuckets[1], depth + 1, heurdata);
                }
            }
            else
            {
                // otherwise the build heuristic failed, this is
                // set the first child to null (identifies a leaf)
                _child0 = null;
                _child1 = null;
                // copy object list
                _objList = objList;
            }
        }
Пример #8
0
 /// <summary>
 /// Reads a node from a stream recursively
 /// </summary>
 /// <param name="depth">Current depth</param>
 /// <param name="br">Binary reader reference</param>
 /// <returns></returns>
 private static QuadTree ReadNode(uint depth, ref System.IO.BinaryReader br)
 {
     QuadTree node = new QuadTree();
     node._Depth = depth;
     node.Box = new SharpMap.Geometries.BoundingBox(br.ReadDouble(),br.ReadDouble(),br.ReadDouble(),br.ReadDouble());
     bool IsLeaf = br.ReadBoolean();
     if (IsLeaf)
     {
         int FeatureCount = br.ReadInt32();
         node._objList = new List<BoxObjects>();
         for (int i = 0; i < FeatureCount; i++)
         {
             BoxObjects box = new BoxObjects();
             box.box = new SharpMap.Geometries.BoundingBox(br.ReadDouble(), br.ReadDouble(), br.ReadDouble(), br.ReadDouble());
             box.ID = (uint)br.ReadInt32();
             node._objList.Add(box);
         }
     }
     else
     {
         node.Child0 = ReadNode(node._Depth + 1, ref br);
         node.Child1 = ReadNode(node._Depth + 1, ref br);
     }
     return node;
 }
Пример #9
0
		/// <summary>
		/// Recursive function that traverses the tree and looks for intersections with a boundingbox
		/// </summary>
		/// <param name="box">Boundingbox to intersect with</param>
		/// <param name="node">Node to search from</param>
		/// <param name="list">List of found intersections</param>
		private void IntersectTreeRecursive(IEnvelope box, QuadTree node, ref Collection<uint> list)
		{
			if (node.IsLeaf) //Leaf has been reached
			{
				for (int i = 0; i < node._objList.Count;i++ )
					list.Add(node._objList[i].ID);
			}
			else
			{
				if(node.Box.Intersects(box))
				{
					IntersectTreeRecursive(box, node.Child0, ref list);
					IntersectTreeRecursive(box, node.Child1, ref list);
				}
			}
		}
Пример #10
0
 /// <summary>
 /// Build the grid based on Quadtree algorithm
 /// </summary>
 /// <param name="envelop">Full extent envelop</param>
 private void BuildGrid(IEnvelope envelop)
 {
     if (this._indexBound == null)
     {
         this._indexBound = this.CreateSpatialIndex(envelop);
     }
 }
Пример #11
0
 public bool TryGetValue(string key, out QuadTree quadTree)
 {
     quadTree = null;
     return false;
 }
Пример #12
0
 public void TryAddValue(string key, QuadTree quadTree, TimeSpan fromDays) { }
Пример #13
0
        /// <summary>
        /// Adds a new <see cref="BoxObjects"/> to this node.
        /// </summary>
        /// <param name="o">The boxed object</param>
        /// <param name="h">The child node creation heuristic</param>
        public void AddNode(BoxObjects o, Heuristic h)
        {
            /* -------------------------------------------------------------------- */
            /*      If there are subnodes, then consider whether this object        */
            /*      will fit in them.                                               */
            /* -------------------------------------------------------------------- */
            if (_child0 != null && _depth < h.maxdepth)
            {
                if (_child0.Box.Contains(o.Box.GetCentroid()))
                {
                    _child0.AddNode(o, h);
                }
                else if (_child1.Box.Contains(o.Box.GetCentroid()))
                {
                    _child1.AddNode(o, h);
                }
                return;
            }

            /* -------------------------------------------------------------------- */
            /*      Otherwise, consider creating two subnodes if could fit into     */
            /*      them, and adding to the appropriate subnode.                    */
            /* -------------------------------------------------------------------- */
            if (h.maxdepth > _depth && !IsLeaf)
            {
                BoundingBox half1, half2;
                SplitBoundingBox(Box, out half1, out half2);


                if (half1.Contains(o.Box.GetCentroid()))
                {
                    _child0 = new QuadTree(half1, _depth + 1);
                    _child1 = new QuadTree(half2, _depth + 1);
                    _child0.AddNode(o, h);
                    return;
                }
                if (half2.Contains(o.Box.GetCentroid()))
                {
                    _child0 = new QuadTree(half1, _depth + 1);
                    _child1 = new QuadTree(half2, _depth + 1);
                    _child1.AddNode(o, h);
                    return;
                }
            }

            /* -------------------------------------------------------------------- */
            /*      If none of that worked, just add it to this nodes list.         */
            /* -------------------------------------------------------------------- */
            //Debug.Assert(_child0 == null);

            if (_objList == null)
            {
                _objList = new List <BoxObjects>();
            }

            if (!Box.Contains(o.Box))
            {
                Box = Box.Join(o.Box);
            }

            _objList.Add(o);
        }
Пример #14
0
        /// <summary>
        /// Recursive function that traverses the tree and looks for intersections with a boundingbox
        /// </summary>
        /// <param name="box">Boundingbox to intersect with</param>
        /// <param name="node">Node to search from</param>
        /// <param name="list">List of found intersections</param>
        private static void IntersectTreeRecursive(Envelope box, QuadTree node, /*ref*/ ICollection<uint> list)
        {
            if (node.IsLeaf) //Leaf has been reached
            {
                foreach (var boxObject in node._objList)
                {
                    if(box.Intersects(boxObject.Box))
                        list.Add(boxObject.ID);

                }
                /*
                for (int i = 0; i < node._objList.Count; i++)
                {
                    list.Add(node._objList[i].ID);
                }
                */
            }
            else
            {
                if (node.Box.Intersects(box))
                {
                    if (node.Child0 != null)
                        IntersectTreeRecursive(box, node.Child0, /*ref*/ list);
                    if (node.Child1 != null)
                        IntersectTreeRecursive(box, node.Child1, /*ref*/ list);
                }
            }
        }
Пример #15
0
 private void Dispose(bool disposing)
 {
     if (!disposed)
     {
         if (disposing)
         {
             Close();
             _Envelope = null;
             tree = null;
         }
         disposed = true;
     }
 }
Пример #16
0
 /// <summary>
 /// Disposes the node
 /// </summary>
 public void Dispose()
 {
     //this._box = null;
     this._child0 = null;
     this._child1 = null;
     this._objList = null;
 }
Пример #17
0
 private void LoadSpatialIndex(bool ForceRebuild, bool LoadFromFile)
 {
     //Only load the tree if we haven't already loaded it, or if we want to force a rebuild
     if (tree == null || ForceRebuild)
     {
         // Is this a web application? If so lets store the index in the cache so we don't
         // need to rebuild it for each request
         if (HttpContext.Current != null)
         {
             //Check if the tree exists in the cache
             if (HttpContext.Current.Cache[_Filename] != null)
                 tree = (QuadTree) HttpContext.Current.Cache[_Filename];
             else
             {
                 if (!LoadFromFile)
                     tree = CreateSpatialIndex(_Filename);
                 else
                     tree = CreateSpatialIndexFromFile(_Filename);
                 //Store the tree in the web cache
                 //TODO: Remove this when connection pooling is implemented
                 HttpContext.Current.Cache.Insert(_Filename, tree, null, Cache.NoAbsoluteExpiration,
                                                  TimeSpan.FromDays(1));
             }
         }
         else if (!LoadFromFile)
             tree = CreateSpatialIndex(_Filename);
         else
             tree = CreateSpatialIndexFromFile(_Filename);
     }
 }
Пример #18
0
 /// <summary>
 /// Recursive function that traverses the tree and looks for intersections with a boundingbox
 /// </summary>
 /// <param name="box">Boundingbox to intersect with</param>
 /// <param name="node">Node to search from</param>
 /// <param name="list">List of found intersections</param>
 private void IntersectTreeRecursive(SharpMap.Geometries.BoundingBox box, QuadTree node, ref List<uint> list)
 {
     if (node.IsLeaf) //Leaf has been reached
     {
         for (int i = 0; i < node._objList.Count;i++ )
             list.Add(node._objList[i].ID);
     }
     else
     {
         if(node.Box.Intersects(box))
         {
             IntersectTreeRecursive(box, node.Child0, ref list);
             IntersectTreeRecursive(box, node.Child1, ref list);
         }
     }
 }
Пример #19
0
 /// <summary>
 /// Forces a rebuild of the spatial index. If the instance of the ShapeFile provider
 /// uses a file-based index the file is rewritten to disk.
 /// </summary>
 public void RebuildSpatialIndex()
 {
     if (_FileBasedIndex)
     {
         if (File.Exists(_Filename + ".sidx"))
             File.Delete(_Filename + ".sidx");
         tree = CreateSpatialIndexFromFile(_Filename);
     }
     else
         tree = CreateSpatialIndex(_Filename);
     if (HttpContext.Current != null)
         //TODO: Remove this when connection pooling is implemented:
         HttpContext.Current.Cache.Insert(_Filename, tree, null, Cache.NoAbsoluteExpiration, TimeSpan.FromDays(1));
 }
Пример #20
0
        /// <summary>
        /// Creates a node and either splits the objects recursively into sub-nodes, or stores them at the node depending on the heuristics.
        /// Tree is built top->down
        /// </summary>
        /// <param name="objList">Geometries to index</param>
        /// <param name="depth">Current depth of tree</param>
        /// <param name="heurdata">Heuristics data</param>
        public QuadTree(List<BoxObjects> objList, uint depth, Heuristic heurdata)
        {
            _Depth = depth;

            _box = objList[0].box;
            for (int i = 0; i < objList.Count;i++ )
                _box = _box.Join(objList[i].box);

            // test our build heuristic - if passes, make children
            if (depth < heurdata.maxdepth && objList.Count > heurdata.mintricnt &&
                (objList.Count > heurdata.tartricnt || ErrorMetric(_box) > heurdata.minerror))
            {
                List<BoxObjects>[] objBuckets = new List<BoxObjects>[2]; // buckets of geometries
                objBuckets[0] = new List<BoxObjects>();
                objBuckets[1] = new List<BoxObjects>();

                uint longaxis = _box.LongestAxis; // longest axis
                double geoavg = 0; // geometric average - midpoint of ALL the objects

                // go through all bbox and calculate the average of the midpoints
                double frac = 1.0f / objList.Count;
                for (int i = 0; i < objList.Count;i++ )
                    geoavg += objList[i].box.GetCentroid()[longaxis] * frac;

                // bucket bbox based on their midpoint's side of the geo average in the longest axis
                for (int i = 0; i < objList.Count;i++ )
                    objBuckets[geoavg > objList[i].box.GetCentroid()[longaxis] ? 1 : 0].Add(objList[i]);

                //If objects couldn't be splitted, just store them at the leaf
                //TODO: Try splitting on another axis
                if (objBuckets[0].Count == 0 || objBuckets[1].Count == 0)
                {
                    _child0 = null;
                    _child1 = null;
                    // copy object list
                    _objList = objList;
                }
                else
                {
                    // create new children using the buckets
                    _child0 = new QuadTree(objBuckets[0], depth + 1, heurdata);
                    _child1 = new QuadTree(objBuckets[1], depth + 1, heurdata);
                }
            }
            else
            {
                // otherwise the build heuristic failed, this is
                // set the first child to null (identifies a leaf)
                _child0 = null;
                _child1 = null;
                // copy object list
                _objList = objList;
            }
        }
Пример #21
0
 public bool TryGetValue(string key, out QuadTree quadTree)
 {
     return HttpCacheUtility.TryGetValue(key, out quadTree);
 }