/// <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);
                }
            }
        }
        /// <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;
            }
        }
 /// <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 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);
     }
 }
 /// <summary>
 /// Disposes the node
 /// </summary>
 public void Dispose()
 {
     //this._box = null;
     _child0 = null;
     _child1 = null;
     _objList = null;
 }
 /// <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 BinaryReader br)
 {
     QuadTree node = new QuadTree();
     node._Depth = depth;
     node.Box = new 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 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;
 }
示例#6
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));
 }
示例#7
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);
     }
 }
示例#8
0
 private void Dispose(bool disposing)
 {
     if (!disposed)
     {
         if (disposing)
         {
             Close();
             _Envelope = null;
             tree = null;
         }
         disposed = true;
     }
 }
示例#9
0
 private void Dispose(bool disposing)
 {
     if (!_disposed)
     {
         if (disposing)
         {
             Close();
             _envelope = null;
             _tree = null;
         }
         _disposed = true;
     }
 }