网格索引在ARX开发中的使用
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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
2.1创建索引
#define GRID_XCOUNT 100 //横向划分100个网格
#define GRID_YCOUNT 100 //纵向划分100个网格
void CreateSpatialIndex(const AcDbVoidPtrArray& lines,
AcArray
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 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 {