网格索引在ARX开发中的使用

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

网格索引在ARX开发中的使用

1.简介

网格索引是GIS软件中经常使用的一种简单、高效的空间索引技术,例如著名的ESRI 公司的ArcSDE空间数据库系统就是采用了这种索引技术。其原理非常简单,如“图1”所示,有6条直线段,被划分成了16(4x4)个网格,

线段1到6分别占用了5(包括A3和B2)、2、

1、3、

2、2个网格。其中B2网格同时被线段1、

2、3占用,B3网格同时被线段线段1、2占用。

现在假设要对这6条线段两两求交,对于线段

1来说,只有线段2、3和它有共用网格现象,

所以只需和线段2、3进行计算,同理线段2

只需和线段3计算即可,总共计算3次。而如

果不采用索引技术,需要计算5+4+3+2=14次。图1

而这仅仅是只有6条线段时的情况,其中的差别可想而知。

2.在ARX中使用网格索引

分析网格索引技术,核心思想是把整个图形区域划分成MxN个矩形网格,每个网格都是一个数组,记录所有从中穿过的图形。针对“图1”的情况,需要定义4X4=16个数组D[4][4],保存数据后,D[1][C]、D[1][D]中都保存了线段6,D[2][A]中保存了线段1,D[2][B]中保存了线段1、2、3,D[2][C]中保存了线段5,D[2][D]中保存了线段4,等等。那么,在具体实现上,只需定义一个AcArray >数组的数组即可,大小初始化为MXN。下面用一个实例进行说明(假设图形都是直线段)。

2.1创建索引

#define GRID_XCOUNT 100 //横向划分100个网格

#define GRID_YCOUNT 100 //纵向划分100个网格

void CreateSpatialIndex(const AcDbVoidPtrArray& lines,

AcArray > &gridT oGeo, //返回空间索引

AcGePoint2dArray &ptLBs, //返回每个图形的左下角

AcGePoint2dArray &ptRTs, //返回每个图形的右上角

AcGePoint2d &ptBase, //返回所有图形的左下角

AcGeVector2d &gridSize //返回网格横、纵向尺寸

)

{

const AcDbLine* pLine;

AcGePoint2d ptLB,ptRT;

int i,nCount = lines.length();

//计算每个图形的左下角、右上角坐标和全部图形的左下角、右上角坐标

GetExtents(lines, ptLBs, ptRTs, ptBase, ptRT);

//每个网格的横向和纵向尺寸(加1是处理精度问题)

gridSize.x = (ptRT.x - ptBase.x)/GRID_XCOUNT + 1;

gridSize.y = (ptRT.y - ptBase.y)/GRID_YCOUNT + 1;

//初始化空间索引数组的内存

gridToGeo.setLogicalLength(GRID_XCOUNT*GRID_YCOUNT);

//创建索引

int nGridXMin, nGridXMax, nGridYMin, nGridYMax;

for(i=0; i

{

//计算每个图形占用的网格(根据外包矩形简化处理)

nGridXMin = (ptLBs.at(i).x - ptBase.x)/gridSize.x;

nGridYMin = (ptLBs.at(i).y - ptBase.y)/gridSize.y;

nGridXMax = (ptRTs.at(i).x - ptBase.x)/gridSize.x;

nGridYMax = (ptRTs.at(i).y - ptBase.y)/gridSize.y;

//在计算出的每个网格数组中添加当前图形的索引

for(int j=nGridYMin; j<=nGridYMax; j++)

{

for(int k=nGridXMin; k<=nGridXMax; k++)

{

gridToGeo[j*GRID_XCOUNT+k].append(i);

}

}

}

}

2.2使用索引

void TestWithSpatialIndex(const AcDbVoidPtrArray& lines)

{

AcArray > gridToGeo; //索引

AcGePoint2d ptBase; //图形范围左下角

AcGeVector2d gridSize; //网格尺寸

AcGePoint2dArray ptLBs, ptRTs; //每个图形的左下角,右上角坐标

//创建空间索引

CreateSpatialIndex(lines, gridToGeo, ptLBs, ptRTs, ptBase, gridSize);

AcGePoint3dArray results;

const AcDbLine *pLine1, *pLine2;

int nGridXMin, nGridXMax, nGridYMin, nGridYMax, nIndex, nMaskBufferSize;

//创建一个映射区标记计算过的图形(因为一个图形可能会被添加到多个网格中),每个图形占用1位。

nMaskBufferSize = (lines.length()+7)/8;

BYTE *pMask = new BYTE[nMaskBufferSize];

//两两求交

for(int i=0; i

{

pLine1 = (const AcDbLine*)lines.at(i);

memset(pMask, 0, nMaskBufferSize); //映射区清零

//计算当前图形占用的网格(根据外包矩形简化处理)

nGridXMin = (ptLBs.at(i).x - ptBase.x)/gridSize.x;

nGridYMin = (ptLBs.at(i).y - ptBase.y)/gridSize.y;

nGridXMax = (ptRTs.at(i).x - ptBase.x)/gridSize.x;

nGridYMax = (ptRTs.at(i).y - ptBase.y)/gridSize.y;

//遍历占用的所有网格,和其中的图形求交

for(int j=nGridYMin; j<=nGridYMax; j++)

{

for(int k=nGridXMin; k<=nGridXMax; k++)

{

//遍历一个网格中的所有图形

for(int m=0; m

{

相关文档
最新文档