天天看点

空间数据的空间索引

首先说一下spatial index grid

其实它就是索引的一种——格网索引,将空间数据的区域分成一块块格网来维护,目的是为了加快空间查询、检索的速度(先判断某个要素落在哪个格网内,再根据格网索引直接去该格网里去找具体的要素)。

spatial index grid一般是地理数据库自动维护的,它会根据数据的范围去计算出合适的格网大小,当用ArcCatalog将数据导入地理数据库后计算出来的grid是一个定值。

所以这里grid的大小其实对数据本身并没影响,不设置都行。只是设置合适的格网可以增加执行效率,过大或者过小都会影响效率。但在ArcGIS里面很多时候都会去检查数据是否有空间索引,没有的话可能会出错。

可能导致的错误

地理数据库有个检查落在每个grid内的feature数量的机制,如果这个数量过大,超过容限,就被认为会减慢空间查询的效率,这时候就会出现grid is too small的错误。

有时候我们在ArcCatalog建好数据后,再用程序往里面添加Feature的时候会出现Spatial index grid error,这也是grid size不当导致的。

解决办法

当然可以在导入的时候将grid值改大,能满足后续的添加数据要求即可,没太大影响,不过具体改多大不好把握;

还可以在添加数据之前将spatial index删掉,修改完后再重新生成,这些都可以通过调用GP工具数据管理工具——indexes下的工具来轻易完成。

那当我们自己去指定grid size的时候到底指定多少呢?这就需要自己设计算法去计算了,总之能加快空间检索的速度就行。计算最终数据合适的spatial index grid可以参考Engine for VB帮助文档里frmSpatialIdxCalc.frm那个例子,它就提供了一种计算合适的grid size的方法。

除了调用ArcToolbox里的GP工具来管理索引外,其实Engine也提供了方法,下面就是具体的测试代码,无论空间索引还是属性索引都可以通过这种方式来管理。

示例代码

Public Sub ChangeSpatialIndex()
Dim pMxDoc As IMxDocument
Dim pFeatLyr As IFeatureLayer
Dim pFeatCls As IFeatureClass

Set pMxDoc = ThisDocument
Set pFeatLyr = pMxDoc.FocusMap.Layer(0)
Set pFeatCls = pFeatLyr.FeatureClass

Dim pIndexes As IIndexes
Set pIndexes = pFeatCls.Indexes
MsgBox pIndexes.IndexCount

Dim pField As IField
Set pField =
pFeatCls.Fields.Field(pFeatCls.Fields.FindField(pFeatCls.ShapeFieldName))
Dim pEnumIndex As IEnumIndex
Set pEnumIndex =
pFeatCls.Indexes.FindIndexesByFieldName(pFeatCls.ShapeFieldName)

Debug.Print pFeatCls.Indexes.index(0).Name 'FDO_OBJECTID
Debug.Print pFeatCls.Indexes.index(1).Name 'Shape_Index

'Dim pIndex As IIndex
'Set pIndex = pEnumIndex.Next
'If Not pIndex Is Nothing Then
' MsgBox pIndex.Name
'End If
'pFeatCls.DeleteIndex pIndex '**删除已经存在的空间索引**

Dim pgeoDef As IGeometryDef
Dim pGeoDefEdit As IGeometryDefEdit
Set pgeoDef = pField.GeometryDef

'**如果只是在这里改了gridsize后,size确实变了,但数据在catalog里显示spatialindex还**
'**是原来的**
'**而且在catalog下修改gridsize,再执行recalculate的话spatial Index还是原先默认的**
Set pGeoDefEdit = pgeoDef '**设置每一级grid size**
With pGeoDefEdit
.AvgNumPoints = 5
.GridCount = 2
.GridSize(0) = 0.2
.GridSize(1) = 1.33
.GridSize(2) = 5
End With

'**以下测试通过IIndexEdit来重新添加空间索引,先将原来的空间索引删除,然后更改**
'**geometry字段的grid size,'然后再添加新的index,这样修改的grid size才会生效**
Dim pIndex As IIndex
Set pIndex = New index '**定义新的空间索引**
Dim pIdxEdit As IIndexEdit
Set pIdxEdit = pIndex

Dim pFields As IFields
Dim pFEdit As IFieldsEdit
Set pFields = New Fields
Set pFEdit = pFields
pFEdit.FieldCount = 1
Set pFEdit.Field(0) = pField

Set pIdxEdit.Fields = pFields '**将索引与geometry字段关联**
pIdxEdit.Name = “myIndex”
pFeatCls.AddIndex pIndex
End Sub
           

想要了解更多知识,获得干货,关注微信公众号:GIS点滴

继续阅读