zoukankan      html  css  js  c++  java
  • [SharpMap]二叉树索引

    读取shp文件建立二叉树索引的基本思路分析:

     

     1  /// <summary>
     2         /// Generates a spatial index for a specified shape file.
     3         /// 根据特定的shp文件构建空间索引
     4         /// </summary>
     5         /// <param name="filename"></param>
     6         private QuadTree CreateSpatialIndex(string filename)
     7         {
     8             List<QuadTree.BoxObjects> objList = new List<QuadTree.BoxObjects>();
     9             //Convert all the geometries to boundingboxes 
    10             uint i = 0;
    11             foreach (BoundingBox box in GetAllFeatureBoundingBoxes())
    12             {
    13                 if (!double.IsNaN(box.Left) && !double.IsNaN(box.Right) && !double.IsNaN(box.Bottom) &&
    14                     !double.IsNaN(box.Top))
    15                 {
    16                     QuadTree.BoxObjects g = new QuadTree.BoxObjects();
    17                     g.box = box;
    18                     g.ID = i;
    19                     objList.Add(g);
    20                     i++;
    21                 }
    22             }
    23 
    24             Heuristic heur;
    25             heur.maxdepth = (int) Math.Ceiling(Math.Log(GetFeatureCount(), 2));
    26             heur.minerror = 10;
    27             heur.tartricnt = 5;
    28             heur.mintricnt = 2;
    29             return new QuadTree(objList, 0, heur);
    30         }
    View Code

     

      1 // Copyright 2005, 2006 - Morten Nielsen (www.iter.dk)
      2 //
      3 // This file is part of SharpMap.
      4 // SharpMap is free software; you can redistribute it and/or modify
      5 // it under the terms of the GNU Lesser General Public License as published by
      6 // the Free Software Foundation; either version 2 of the License, or
      7 // (at your option) any later version.
      8 // 
      9 // SharpMap is distributed in the hope that it will be useful,
     10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 // GNU Lesser General Public License for more details.
     13 
     14 // You should have received a copy of the GNU Lesser General Public License
     15 // along with SharpMap; if not, write to the Free Software
     16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
     17 
     18 using System;
     19 using System.Collections.Generic;
     20 using System.Collections.ObjectModel;
     21 using System.IO;
     22 using SharpMap.Geometries;
     23 
     24 namespace SharpMap.Utilities.SpatialIndexing
     25 {
     26     /// <summary>
     27     /// Heuristics used for tree generation
     28     /// </summary>
     29     public struct Heuristic
     30     {
     31         /// <summary>
     32         /// Maximum tree depth
     33         /// </summary>
     34         public int maxdepth;
     35 
     36         /// <summary>
     37         /// Minimum Error metric ?the volume of a box + a unit cube.
     38         /// The unit cube in the metric prevents big boxes that happen to be flat having a zero result and muddling things up.
     39         /// </summary>
     40         public int minerror;
     41 
     42         /// <summary>
     43         /// Minimum object count at node
     44         /// </summary>
     45         public int mintricnt;
     46 
     47         /// <summary>
     48         /// Target object count at node
     49         /// </summary>
     50         public int tartricnt;
     51     }
     52 
     53     /// <summary>
     54     /// Constructs a Quad-tree node from a object list and creates its children recursively
     55     /// 二叉树?四叉树?
     56     /// </summary>
     57     public class QuadTree : IDisposable
     58     {
     59         private BoundingBox _box;
     60         private QuadTree _child0;
     61         private QuadTree _child1;
     62 
     63         /// <summary>
     64         /// Nodes depth in a tree
     65         /// </summary>
     66         protected uint _Depth;
     67 
     68         /// <summary>
     69         /// Node ID
     70         /// </summary>
     71         public uint? _ID;
     72 
     73         private List<BoxObjects> _objList;
     74 
     75         /// <summary>
     76         /// Creates a node and either splits the objects recursively into sub-nodes, or stores them at the node depending on the heuristics.
     77         /// Tree is built top->down
     78         /// </summary>
     79         /// <param name="objList">Geometries to index</param>
     80         /// <param name="depth">Current depth of tree树的深度</param>
     81         /// <param name="heurdata">Heuristics data</param>
     82         public QuadTree(List<BoxObjects> objList, uint depth, Heuristic heurdata)
     83         {
     84             _Depth = depth;
     85 
     86             _box = objList[0].box;
     87             for (int i = 0; i < objList.Count; i++)
     88                 _box = _box.Join(objList[i].box);
     89 
     90             // test our build heuristic探试性的- if passes, make children
     91             if (depth < heurdata.maxdepth && objList.Count > heurdata.mintricnt &&
     92                 (objList.Count > heurdata.tartricnt || ErrorMetric(_box) > heurdata.minerror))
     93             {
     94                 List<BoxObjects>[] objBuckets = new List<BoxObjects>[2]; // buckets of geometries大量的几何对象,一桶几何对象
     95                 objBuckets[0] = new List<BoxObjects>();
     96                 objBuckets[1] = new List<BoxObjects>();
     97 
     98                 uint longaxis = _box.LongestAxis; // longest axis
     99                 double geoavg = 0; // geometric average - midpoint of ALL the objects
    100 
    101                 // go through all bbox and calculate the average of the midpoints
    102                 double frac = 1.0f / objList.Count;
    103                 for (int i = 0; i < objList.Count; i++)
    104                     geoavg += objList[i].box.GetCentroid()[longaxis] * frac;
    105 
    106                 // bucket bbox based on their midpoint's side of the geo average in the longest axis
    107                 for (int i = 0; i < objList.Count; i++)
    108                     objBuckets[geoavg > objList[i].box.GetCentroid()[longaxis] ? 1 : 0].Add(objList[i]);
    109 
    110                 //If objects couldn't be splitted, just store them at the leaf
    111                 //TODO: Try splitting on another axis
    112                 if (objBuckets[0].Count == 0 || objBuckets[1].Count == 0)
    113                 {
    114                     _child0 = null;
    115                     _child1 = null;
    116                     // copy object list
    117                     _objList = objList;
    118                 }
    119                 else
    120                 {
    121                     // create new children using the buckets
    122                     _child0 = new QuadTree(objBuckets[0], depth + 1, heurdata);
    123                     _child1 = new QuadTree(objBuckets[1], depth + 1, heurdata);
    124                 }
    125             }
    126             else
    127             {
    128                 // otherwise the build heuristic failed, this is 
    129                 // set the first child to null (identifies a leaf)
    130                 _child0 = null;
    131                 _child1 = null;
    132                 // copy object list
    133                 _objList = objList;
    134             }
    135         }
    136 
    137         /// <summary>
    138         /// This instantiator is used internally for loading a tree from a file
    139         /// </summary>
    140         private QuadTree()
    141         {
    142         }
    143 
    144         #region Read/Write index to/from a file
    145 
    146         private const double INDEXFILEVERSION = 1.0;
    147 
    148         /// <summary>
    149         /// Loads a quadtree from a file
    150         /// </summary>
    151         /// <param name="filename"></param>
    152         /// <returns></returns>
    153         public static QuadTree FromFile(string filename)
    154         {
    155             FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
    156             BinaryReader br = new BinaryReader(fs);
    157             if (br.ReadDouble() != INDEXFILEVERSION) //Check fileindex version
    158             {
    159                 fs.Close();
    160                 fs.Dispose();
    161                 throw new ObsoleteFileFormatException(
    162                     "Invalid index file version. Please rebuild the spatial index by either deleting the index");
    163             }
    164             QuadTree node = ReadNode(0, ref br);
    165             br.Close();
    166             fs.Close();
    167             return node;
    168         }
    169 
    170         /// <summary>
    171         /// Reads a node from a stream recursively
    172         /// </summary>
    173         /// <param name="depth">Current depth</param>
    174         /// <param name="br">Binary reader reference</param>
    175         /// <returns></returns>
    176         private static QuadTree ReadNode(uint depth, ref BinaryReader br)
    177         {
    178             QuadTree node = new QuadTree();
    179             node._Depth = depth;
    180             node.Box = new BoundingBox(br.ReadDouble(), br.ReadDouble(), br.ReadDouble(), br.ReadDouble());
    181             bool IsLeaf = br.ReadBoolean();
    182             if (IsLeaf)
    183             {
    184                 int FeatureCount = br.ReadInt32();
    185                 node._objList = new List<BoxObjects>();
    186                 for (int i = 0; i < FeatureCount; i++)
    187                 {
    188                     BoxObjects box = new BoxObjects();
    189                     box.box = new BoundingBox(br.ReadDouble(), br.ReadDouble(), br.ReadDouble(), br.ReadDouble());
    190                     box.ID = (uint)br.ReadInt32();
    191                     node._objList.Add(box);
    192                 }
    193             }
    194             else
    195             {
    196                 node.Child0 = ReadNode(node._Depth + 1, ref br);
    197                 node.Child1 = ReadNode(node._Depth + 1, ref br);
    198             }
    199             return node;
    200         }
    201 
    202         /// <summary>
    203         /// Saves the Quadtree to a file
    204         /// </summary>
    205         /// <param name="filename"></param>
    206         public void SaveIndex(string filename)
    207         {
    208             FileStream fs = new FileStream(filename, FileMode.Create);
    209             BinaryWriter bw = new BinaryWriter(fs);
    210             bw.Write(INDEXFILEVERSION); //Save index version
    211             SaveNode(this, ref bw);
    212             bw.Close();
    213             fs.Close();
    214         }
    215 
    216         /// <summary>
    217         /// Saves a node to a stream recursively
    218         /// </summary>
    219         /// <param name="node">Node to save</param>
    220         /// <param name="sw">Reference to BinaryWriter</param>
    221         private void SaveNode(QuadTree node, ref BinaryWriter sw)
    222         {
    223             //Write node boundingbox
    224             sw.Write(node.Box.Min.X);
    225             sw.Write(node.Box.Min.Y);
    226             sw.Write(node.Box.Max.X);
    227             sw.Write(node.Box.Max.Y);
    228             sw.Write(node.IsLeaf);
    229             if (node.IsLeaf)
    230             {
    231                 sw.Write(node._objList.Count); //Write number of features at node
    232                 for (int i = 0; i < node._objList.Count; i++) //Write each featurebox
    233                 {
    234                     sw.Write(node._objList[i].box.Min.X);
    235                     sw.Write(node._objList[i].box.Min.Y);
    236                     sw.Write(node._objList[i].box.Max.X);
    237                     sw.Write(node._objList[i].box.Max.Y);
    238                     sw.Write(node._objList[i].ID);
    239                 }
    240             }
    241             else if (!node.IsLeaf) //Save next node
    242             {
    243                 SaveNode(node.Child0, ref sw);
    244                 SaveNode(node.Child1, ref sw);
    245             }
    246         }
    247 
    248         internal class ObsoleteFileFormatException : Exception
    249         {
    250             /// <summary>
    251             /// Exception thrown when layer rendering has failed
    252             /// </summary>
    253             /// <param name="message"></param>
    254             public ObsoleteFileFormatException(string message)
    255                 : base(message)
    256             {
    257             }
    258         }
    259 
    260         #endregion
    261 
    262         /// <summary>
    263         /// Determines whether the node is a leaf (if data is stored at the node, we assume the node is a leaf)
    264         /// </summary>
    265         public bool IsLeaf
    266         {
    267             get { return (_objList != null); }
    268         }
    269 
    270         ///// <summary>
    271         ///// Gets/sets the list of objects in the node
    272         ///// </summary>
    273         //public List<SharpMap.Geometries.IGeometry> ObjList
    274         //{
    275         //    get { return _objList; }
    276         //    set { _objList = value; }
    277         //}
    278 
    279         /// <summary>
    280         /// Gets/sets the Axis Aligned Bounding Box
    281         /// </summary>
    282         public BoundingBox Box
    283         {
    284             get { return _box; }
    285             set { _box = value; }
    286         }
    287 
    288         /// <summary>
    289         /// Gets/sets the left child node
    290         /// </summary>
    291         public QuadTree Child0
    292         {
    293             get { return _child0; }
    294             set { _child0 = value; }
    295         }
    296 
    297         /// <summary>
    298         /// Gets/sets the right child node
    299         /// </summary>
    300         public QuadTree Child1
    301         {
    302             get { return _child1; }
    303             set { _child1 = value; }
    304         }
    305 
    306         /// <summary>
    307         /// Gets the depth of the current node in the tree
    308         /// </summary>
    309         public uint Depth
    310         {
    311             get { return _Depth; }
    312         }
    313 
    314         #region IDisposable Members
    315 
    316         /// <summary>
    317         /// Disposes the node
    318         /// </summary>
    319         public void Dispose()
    320         {
    321             //this._box = null;
    322             _child0 = null;
    323             _child1 = null;
    324             _objList = null;
    325         }
    326 
    327         #endregion
    328 
    329         /// <summary>
    330         /// Calculate the floating point error metric 
    331         /// </summary>
    332         /// <returns></returns>
    333         public double ErrorMetric(BoundingBox box)
    334         {
    335             Point temp = new Point(1, 1) + (box.Max - box.Min);
    336             return temp.X * temp.Y;
    337         }
    338 
    339         /// <summary>
    340         /// Searches the tree and looks for intersections with the boundingbox 'bbox'
    341         /// </summary>
    342         /// <param name="box">Boundingbox to intersect with</param>
    343         public Collection<uint> Search(BoundingBox box)
    344         {
    345             Collection<uint> objectlist = new Collection<uint>();
    346             IntersectTreeRecursive(box, this, ref objectlist);
    347             return objectlist;
    348         }
    349 
    350         /// <summary>
    351         /// Recursive function that traverses the tree and looks for intersections with a boundingbox
    352         /// </summary>
    353         /// <param name="box">Boundingbox to intersect with</param>
    354         /// <param name="node">Node to search from</param>
    355         /// <param name="list">List of found intersections</param>
    356         private void IntersectTreeRecursive(BoundingBox box, QuadTree node, ref Collection<uint> list)
    357         {
    358             if (node.IsLeaf) //Leaf has been reached
    359             {
    360                 foreach (BoxObjects boxObject in node._objList)
    361                 {
    362                     if (box.Intersects(boxObject.box))
    363                         list.Add(boxObject.ID);
    364 
    365                 }
    366                 /*
    367                 for (int i = 0; i < node._objList.Count; i++)
    368                 {
    369                     list.Add(node._objList[i].ID);
    370                 }
    371                 */
    372             }
    373             else
    374             {
    375                 if (node.Box.Intersects(box))
    376                 {
    377                     IntersectTreeRecursive(box, node.Child0, ref list);
    378                     IntersectTreeRecursive(box, node.Child1, ref list);
    379                 }
    380             }
    381         }
    382 
    383         #region Nested type: BoxObjects
    384 
    385         /// <summary>
    386         /// BoundingBox and Feature ID structure used for storing in the quadtree 
    387         /// 包围盒和要素ID数据结构,用于在四叉树中存储
    388         /// </summary>
    389         public struct BoxObjects
    390         {
    391             /// <summary>
    392             /// Boundingbox
    393             /// 包围盒
    394             /// </summary>
    395             public BoundingBox box;
    396 
    397             /// <summary>
    398             /// Feature ID
    399             /// 要素ID
    400             /// </summary>
    401             public uint ID;
    402         }
    403 
    404         #endregion
    405     }
    406 }
    View Code

    今天看了下DotSpatial中读取Shp的代码,真正实现的四叉树空间索引。

  • 相关阅读:
    正则表达式在NLP中应用
    spring boot中 异常:Error resolving template "xxx", template might not exist or might not be accessible...解决办法
    毕业设计6
    毕业设计5
    毕业设计4
    毕业设计3
    毕业设计2
    毕业设计1
    支付宝架构
    Javaee应用架构
  • 原文地址:https://www.cnblogs.com/yhlx125/p/3661925.html
Copyright © 2011-2022 走看看