Constructs a Quad-tree node from a object list and creates its children recursively
상속: IDisposable
예제 #1
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
             {
                 _tree = !loadFromFile ? CreateSpatialIndex() : 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();
         else
             _tree = CreateSpatialIndexFromFile(_filename);
     }
 }
예제 #2
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();
     if (HttpContext.Current != null)
         //TODO: Remove this when connection pooling is implemented:
         HttpContext.Current.Cache.Insert(_filename, _tree, null, Cache.NoAbsoluteExpiration, TimeSpan.FromDays(1));
 }
예제 #3
0
 private void Dispose(bool disposing)
 {
     if (!_disposed)
     {
         if (disposing)
         {
             Close();
             _envelope = null;
             _tree = null;
         }
         _disposed = true;
     }
 }
예제 #4
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;
            }
        }
예제 #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 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
        /// <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);

                }
            }
            else
            {
                if (node.Box.Intersects(box))
                {
                    IntersectTreeRecursive(box, node.Child0, ref list);
                    IntersectTreeRecursive(box, node.Child1, ref list);
                }
            }
        }
예제 #7
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 BinaryReader br)
 {
     QuadTree node = new QuadTree
     {
         _depth = depth,
         Box = new BoundingBox(br.ReadDouble(), br.ReadDouble(), br.ReadDouble(), br.ReadDouble())
     };
     var 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 = new BoundingBox(
                     br.ReadDouble(), br.ReadDouble(),
                     br.ReadDouble(), br.ReadDouble()),
                 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;
 }
예제 #8
0
 /// <summary>
 /// Disposes the node
 /// </summary>
 public void Dispose()
 {
     //this._box = null;
     _child0 = null;
     _child1 = null;
     _objList = null;
 }