⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtree.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    float x4 = x2;    int jj;    int iCellLeft = 0;    int iCellRight = 0;    for(jj=1; jj<nCell; jj++){      float left = aCell[jj].aCoord[i*2];      float right = aCell[jj].aCoord[i*2+1];      if( left<x1 ) x1 = left;      if( right>x4 ) x4 = right;      if( left>x3 ){        x3 = left;        iCellRight = jj;      }      if( right<x2 ){        x2 = right;        iCellLeft = jj;      }    }    if( x4!=x1 ){      float normalwidth = (x3 - x2) / (x4 - x1);      if( normalwidth>maxNormalInnerWidth ){        iLeftSeed = iCellLeft;        iRightSeed = iCellRight;      }    }  }  *piLeftSeed = iLeftSeed;  *piRightSeed = iRightSeed;}#endif /* VARIANT_GUTTMAN_LINEAR_SPLIT */#if VARIANT_GUTTMAN_QUADRATIC_SPLIT/*** Implementation of the quadratic variant of the PickNext() function from** Guttman[84].*/static RtreeCell *QuadraticPickNext(  Rtree *pRtree,  RtreeCell *aCell,   int nCell,   RtreeCell *pLeftBox,   RtreeCell *pRightBox,  int *aiUsed){  #define FABS(a) ((a)<0.0?-1.0*(a):(a))  int iSelect = -1;  float fDiff;  int ii;  for(ii=0; ii<nCell; ii++){    if( aiUsed[ii]==0 ){      float left = cellGrowth(pRtree, pLeftBox, &aCell[ii]);      float right = cellGrowth(pRtree, pLeftBox, &aCell[ii]);      float diff = FABS(right-left);      if( iSelect<0 || diff>fDiff ){        fDiff = diff;        iSelect = ii;      }    }  }  aiUsed[iSelect] = 1;  return &aCell[iSelect];}/*** Implementation of the quadratic variant of the PickSeeds() function from** Guttman[84].*/static void QuadraticPickSeeds(  Rtree *pRtree,  RtreeCell *aCell,   int nCell,   int *piLeftSeed,   int *piRightSeed){  int ii;  int jj;  int iLeftSeed = 0;  int iRightSeed = 1;  float fWaste = 0.0;  for(ii=0; ii<nCell; ii++){    for(jj=ii+1; jj<nCell; jj++){      float right = cellArea(pRtree, &aCell[jj]);      float growth = cellGrowth(pRtree, &aCell[ii], &aCell[jj]);      float waste = growth - right;      if( waste>fWaste ){        iLeftSeed = ii;        iRightSeed = jj;        fWaste = waste;      }    }  }  *piLeftSeed = iLeftSeed;  *piRightSeed = iRightSeed;}#endif /* VARIANT_GUTTMAN_QUADRATIC_SPLIT *//*** Arguments aIdx, aDistance and aSpare all point to arrays of size** nIdx. The aIdx array contains the set of integers from 0 to ** (nIdx-1) in no particular order. This function sorts the values** in aIdx according to the indexed values in aDistance. For** example, assuming the inputs:****   aIdx      = { 0,   1,   2,   3 }**   aDistance = { 5.0, 2.0, 7.0, 6.0 }**** this function sets the aIdx array to contain:****   aIdx      = { 0,   1,   2,   3 }**** The aSpare array is used as temporary working space by the** sorting algorithm.*/static void SortByDistance(  int *aIdx,   int nIdx,   float *aDistance,   int *aSpare){  if( nIdx>1 ){    int iLeft = 0;    int iRight = 0;    int nLeft = nIdx/2;    int nRight = nIdx-nLeft;    int *aLeft = aIdx;    int *aRight = &aIdx[nLeft];    SortByDistance(aLeft, nLeft, aDistance, aSpare);    SortByDistance(aRight, nRight, aDistance, aSpare);    memcpy(aSpare, aLeft, sizeof(int)*nLeft);    aLeft = aSpare;    while( iLeft<nLeft || iRight<nRight ){      if( iLeft==nLeft ){        aIdx[iLeft+iRight] = aRight[iRight];        iRight++;      }else if( iRight==nRight ){        aIdx[iLeft+iRight] = aLeft[iLeft];        iLeft++;      }else{        float fLeft = aDistance[aLeft[iLeft]];        float fRight = aDistance[aRight[iRight]];        if( fLeft<fRight ){          aIdx[iLeft+iRight] = aLeft[iLeft];          iLeft++;        }else{          aIdx[iLeft+iRight] = aRight[iRight];          iRight++;        }      }    }#if 0    /* Check that the sort worked */    {      int jj;      for(jj=1; jj<nIdx; jj++){        float left = aDistance[aIdx[jj-1]];        float right = aDistance[aIdx[jj]];        assert( left<=right );      }    }#endif  }}/*** Arguments aIdx, aCell and aSpare all point to arrays of size** nIdx. The aIdx array contains the set of integers from 0 to ** (nIdx-1) in no particular order. This function sorts the values** in aIdx according to dimension iDim of the cells in aCell. The** minimum value of dimension iDim is considered first, the** maximum used to break ties.**** The aSpare array is used as temporary working space by the** sorting algorithm.*/static void SortByDimension(  Rtree *pRtree,  int *aIdx,   int nIdx,   int iDim,   RtreeCell *aCell,   int *aSpare){  if( nIdx>1 ){    int iLeft = 0;    int iRight = 0;    int nLeft = nIdx/2;    int nRight = nIdx-nLeft;    int *aLeft = aIdx;    int *aRight = &aIdx[nLeft];    SortByDimension(pRtree, aLeft, nLeft, iDim, aCell, aSpare);    SortByDimension(pRtree, aRight, nRight, iDim, aCell, aSpare);    memcpy(aSpare, aLeft, sizeof(int)*nLeft);    aLeft = aSpare;    while( iLeft<nLeft || iRight<nRight ){      double xleft1 = DCOORD(aCell[aLeft[iLeft]].aCoord[iDim*2]);      double xleft2 = DCOORD(aCell[aLeft[iLeft]].aCoord[iDim*2+1]);      double xright1 = DCOORD(aCell[aRight[iRight]].aCoord[iDim*2]);      double xright2 = DCOORD(aCell[aRight[iRight]].aCoord[iDim*2+1]);      if( (iLeft!=nLeft) && ((iRight==nRight)       || (xleft1<xright1)       || (xleft1==xright1 && xleft2<xright2)      )){        aIdx[iLeft+iRight] = aLeft[iLeft];        iLeft++;      }else{        aIdx[iLeft+iRight] = aRight[iRight];        iRight++;      }    }#if 0    /* Check that the sort worked */    {      int jj;      for(jj=1; jj<nIdx; jj++){        float xleft1 = aCell[aIdx[jj-1]].aCoord[iDim*2];        float xleft2 = aCell[aIdx[jj-1]].aCoord[iDim*2+1];        float xright1 = aCell[aIdx[jj]].aCoord[iDim*2];        float xright2 = aCell[aIdx[jj]].aCoord[iDim*2+1];        assert( xleft1<=xright1 && (xleft1<xright1 || xleft2<=xright2) );      }    }#endif  }}#if VARIANT_RSTARTREE_SPLIT/*** Implementation of the R*-tree variant of SplitNode from Beckman[1990].*/static int splitNodeStartree(  Rtree *pRtree,  RtreeCell *aCell,  int nCell,  RtreeNode *pLeft,  RtreeNode *pRight,  RtreeCell *pBboxLeft,  RtreeCell *pBboxRight){  int **aaSorted;  int *aSpare;  int ii;  int iBestDim;  int iBestSplit;  float fBestMargin;  int nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int));  aaSorted = (int **)sqlite3_malloc(nByte);  if( !aaSorted ){    return SQLITE_NOMEM;  }  aSpare = &((int *)&aaSorted[pRtree->nDim])[pRtree->nDim*nCell];  memset(aaSorted, 0, nByte);  for(ii=0; ii<pRtree->nDim; ii++){    int jj;    aaSorted[ii] = &((int *)&aaSorted[pRtree->nDim])[ii*nCell];    for(jj=0; jj<nCell; jj++){      aaSorted[ii][jj] = jj;    }    SortByDimension(pRtree, aaSorted[ii], nCell, ii, aCell, aSpare);  }  for(ii=0; ii<pRtree->nDim; ii++){    float margin = 0.0;    float fBestOverlap;    float fBestArea;    int iBestLeft;    int nLeft;    for(      nLeft=RTREE_MINCELLS(pRtree);       nLeft<=(nCell-RTREE_MINCELLS(pRtree));       nLeft++    ){      RtreeCell left;      RtreeCell right;      int kk;      float overlap;      float area;      memcpy(&left, &aCell[aaSorted[ii][0]], sizeof(RtreeCell));      memcpy(&right, &aCell[aaSorted[ii][nCell-1]], sizeof(RtreeCell));      for(kk=1; kk<(nCell-1); kk++){        if( kk<nLeft ){          cellUnion(pRtree, &left, &aCell[aaSorted[ii][kk]]);        }else{          cellUnion(pRtree, &right, &aCell[aaSorted[ii][kk]]);        }      }      margin += cellMargin(pRtree, &left);      margin += cellMargin(pRtree, &right);      overlap = cellOverlap(pRtree, &left, &right, 1, -1);      area = cellArea(pRtree, &left) + cellArea(pRtree, &right);      if( (nLeft==RTREE_MINCELLS(pRtree))       || (overlap<fBestOverlap)       || (overlap==fBestOverlap && area<fBestArea)      ){        iBestLeft = nLeft;        fBestOverlap = overlap;        fBestArea = area;      }    }    if( ii==0 || margin<fBestMargin ){      iBestDim = ii;      fBestMargin = margin;      iBestSplit = iBestLeft;    }  }  memcpy(pBboxLeft, &aCell[aaSorted[iBestDim][0]], sizeof(RtreeCell));  memcpy(pBboxRight, &aCell[aaSorted[iBestDim][iBestSplit]], sizeof(RtreeCell));  for(ii=0; ii<nCell; ii++){    RtreeNode *pTarget = (ii<iBestSplit)?pLeft:pRight;    RtreeCell *pBbox = (ii<iBestSplit)?pBboxLeft:pBboxRight;    RtreeCell *pCell = &aCell[aaSorted[iBestDim][ii]];    nodeInsertCell(pRtree, pTarget, pCell);    cellUnion(pRtree, pBbox, pCell);  }  sqlite3_free(aaSorted);  return SQLITE_OK;}#endif#if VARIANT_GUTTMAN_SPLIT/*** Implementation of the regular R-tree SplitNode from Guttman[1984].*/static int splitNodeGuttman(  Rtree *pRtree,  RtreeCell *aCell,  int nCell,  RtreeNode *pLeft,  RtreeNode *pRight,  RtreeCell *pBboxLeft,  RtreeCell *pBboxRight){  int iLeftSeed = 0;  int iRightSeed = 1;  int *aiUsed;  int i;  aiUsed = sqlite3_malloc(sizeof(int)*nCell);  memset(aiUsed, 0, sizeof(int)*nCell);  PickSeeds(pRtree, aCell, nCell, &iLeftSeed, &iRightSeed);  memcpy(pBboxLeft, &aCell[iLeftSeed], sizeof(RtreeCell));  memcpy(pBboxRight, &aCell[iRightSeed], sizeof(RtreeCell));  nodeInsertCell(pRtree, pLeft, &aCell[iLeftSeed]);  nodeInsertCell(pRtree, pRight, &aCell[iRightSeed]);  aiUsed[iLeftSeed] = 1;  aiUsed[iRightSeed] = 1;  for(i=nCell-2; i>0; i--){    RtreeCell *pNext;    pNext = PickNext(pRtree, aCell, nCell, pBboxLeft, pBboxRight, aiUsed);    float diff =        cellGrowth(pRtree, pBboxLeft, pNext) -       cellGrowth(pRtree, pBboxRight, pNext)    ;    if( (RTREE_MINCELLS(pRtree)-NCELL(pRight)==i)     || (diff>0.0 && (RTREE_MINCELLS(pRtree)-NCELL(pLeft)!=i))    ){      nodeInsertCell(pRtree, pRight, pNext);      cellUnion(pRtree, pBboxRight, pNext);    }else{      nodeInsertCell(pRtree, pLeft, pNext);      cellUnion(pRtree, pBboxLeft, pNext);    }  }  sqlite3_free(aiUsed);  return SQLITE_OK;}#endifstatic int updateMapping(  Rtree *pRtree,   i64 iRowid,   RtreeNode *pNode,   int iHeight){  int (*xSetMapping)(Rtree *, sqlite3_int64, sqlite3_int64);  xSetMapping = ((iHeight==0)?rowidWrite:parentWrite);  if( iHeight>0 ){    RtreeNode *pChild = nodeHashLookup(pRtree, iRowid);    if( pChild ){      nodeRelease(pRtree, pChild->pParent);      nodeReference(pNode);      pChild->pParent = pNode;    }  }  return xSetMapping(pRtree, iRowid, pNode->iNode);}static int SplitNode(  Rtree *pRtree,  RtreeNode *pNode,  RtreeCell *pCell,  int iHeight){  int i;  int newCellIsRight = 0;  int rc = SQLITE_OK;  int nCell = NCELL(pNode);  RtreeCell *aCell;  int *aiUsed;  RtreeNode *pLeft = 0;  RtreeNode *pRight = 0;  RtreeCell leftbbox;  RtreeCell rightbbox;  /* Allocate an array and populate it with a copy of pCell and   ** all cells from node pLeft. Then zero the original node.  */  aCell = sqlite3_malloc((sizeof(RtreeCell)+sizeof(int))*(nCell+1));  if( !aCell ){    rc = SQLITE_NOMEM;    goto splitnode_out;  }  aiUsed = (int *)&aCell[nCell+1];  memset(aiUsed, 0, sizeof(int)*(nCell+1));  for(i=0; i<nCell; i++){    nodeGetCell(pRtree, pNode, i, &aCell[i]);  }  nodeZero(pRtree, pNode);  memcpy(&aCell[nCell], pCell, sizeof(RtreeCell));  nCell++;  if( pNode->iNode==1 ){    pRight = nodeNew(pRtree, pNode, 1);    pLeft = nodeNew(pRtree, pNode, 1);    pRtree->iDepth++;    pNode->isDirty = 1;    writeInt16(pNode->zData, pRtree->iDepth);  }else{    pLeft = pNode;    pRight = nodeNew(pRtree, pLeft->pParent, 1);    nodeReference(pLeft);  }  if( !pLeft || !pRight ){    rc = SQLITE_NOMEM;    goto splitnode_out;  }  memset(pLeft->zData, 0, pRtree->iNodeSize);  memset(pRight->zData, 0, pRtree->iNodeSize);  rc = AssignCells(pRtree, aCell, nCell, pLeft, pRight, &leftbbox, &rightbbox);  if( rc!=SQLITE_OK ){    goto splitnode_out;  }  /* Ensure both child nodes have node numbers assigned to them. */  if( (0==pRight->iNode && SQLITE_OK!=(rc = nodeWrite(pRtree, pRight)))   || (0==pLeft->iNode && SQLITE_OK!=(rc = nodeWrite(pRtree, pLeft)))  ){    goto splitnode_out;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -