前面初略分析了SharpMap的渲染机制,下面再来分析下它的数据访问机制,SharpMap的数据访问机制有两个关键:Provider模式和空间索引。
1 运行机制分析
SharpMap中矢量图层类(SharpMap.Layers.VectorLayer)和注记层(SharpMap.Layers.LabelLayer)的数据源属性(DataSource)其实就是一个IProvider接口(SharpMap.Data.Providers.IProvider):
///
/// Gets or sets the datasource
///
public SharpMap.Data.Providers.IProvider DataSource
{
get { return _DataSource; }
set { _DataSource = value; }
}
因此,SharpMap的所有数据操作都是在IProvider上进行。
下面来看看数据的初始化。
1.1 数据源的初始化
我们再来看看MapHelper.cs文件中的InitializeMap函数,其中图层数据初始化如下:
//Set the datasource to a shapefile in the App_data folder
layCountries.DataSource = new
SharpMap.Data.Providers.ShapeFile(HttpContext.Current.Server.MapPath(@"~/App_data/countries.shp"), true);
即生成一个ShapeFile类来初始化DataSource。初始化代码在ShapeFile.cs中,分为三步:
(1)初始化DBF文件
//Initialize DBF
string dbffile = _Filename.Substring(0, _Filename.LastIndexOf(".")) + ".dbf";
if (File.Exists(dbffile))
dbaseFile = new DbaseReader(dbffile);
(2)解析shape文件头
//Parse shape header
ParseHeader();
(3)读取投影文件
//Read projection file
ParseProjection();
1.2 数据源的打开
数据源的打开使用DataSource的Open函数。
///
/// Opens the datasource
///
public void Open()
ShapeFile的Open函数分为两步:
(1)初始化Shape文件
主要是InitializeShape函数,其主要功能是装载空间索引:
LoadSpatialIndex(FileBasedIndex); //Load spatial index
以后将对空间索引进行介绍。
(2)打开DBF文件
if (dbaseFile != null)
dbaseFile.Open();
1.3 相交查询
执行相交查询的是IProvider接口的ExecuteIntersectionQuery函数。
///
/// Returns all objects whose boundingbox intersects bbox.
///
///
///
/// Please note that this method doesn't guarantee that the geometries returned actually intersect 'bbox', but only
/// that their boundingbox intersects 'bbox'.
///
///
///
///
///
public void ExecuteIntersectionQuery(SharpMap.Geometries.BoundingBox bbox, SharpMap.Data.FeatureDataSet ds)
它分为以下几步:
(1)得到bbox范围框中的所有对象ID
//Use the spatial index to get a list of features whose boundingbox intersects bbox
List
objectlist = GetObjectIDsInView(bbox);
这个函数的实现如下:
//Use the spatial index to get a list of features whose boundingbox intersects bbox
return tree.Search(bbox);
所以,它实际使用四叉树的搜索功能。以后将在空间索引中予以介绍。
(2)根据ID得到属性信息并加入空间数据集
SharpMap.Data.FeatureDataTable dt = dbaseFile.NewTable;
for (int i = 0; i < objectlist.Count; i++)
{
SharpMap.Data.FeatureDataRow fdr = dbaseFile.GetFeature(objectlist[i], dt);
fdr.Geometry = ReadGeometry(objectlist[i]);
if (fdr.Geometry != null)
if (fdr.Geometry.GetBoundingBox().Intersects(bbox))
if (FilterDelegate == null || FilterDelegate(fdr))
dt.AddRow(fdr);
}
ds.Tables.Add(dt);
2 IProvider接口的其它函数
(1)关闭函数
///
/// Closes the datasource
///
void Close();
(2)得到范围框
///
///
of dataset
///
///
boundingbox
SharpMap.Geometries.BoundingBox GetExtents();
3 总结
从以上分析可知,SharpMap通过IProvider接口对数据源进行抽象,只要能实现IProvider接口的数据源就可以支持。IProvider接口的相交查询通过空间索引实现,空间索引及四叉树将在以后专门介绍。