Пример #1
0
static void SHPTreeNodeSearchAndDump( SHPTree * hTree,
                                      double *padfBoundsMin,
                                      double *padfBoundsMax )

{
    int		*panHits, nShapeCount, i;

/* -------------------------------------------------------------------- */
/*      Perform the search for likely candidates.  These are shapes     */
/*      that fall into a tree node whose bounding box intersects our    */
/*      area of interest.                                               */
/* -------------------------------------------------------------------- */
    panHits = SHPTreeFindLikelyShapes( hTree, padfBoundsMin, padfBoundsMax,
                                       &nShapeCount );

/* -------------------------------------------------------------------- */
/*      Read all of these shapes, and establish whether the shape's     */
/*      bounding box actually intersects the area of interest.  Note    */
/*      that the bounding box could intersect the area of interest,     */
/*      and the shape itself still not cross it but we don't try to     */
/*      address that here.                                              */
/* -------------------------------------------------------------------- */
    for( i = 0; i < nShapeCount; i++ )
    {
        SHPObject	*psObject;

        psObject = SHPReadObject( hTree->hSHP, panHits[i] );
        if( psObject == NULL )
            continue;
        
        if( !SHPCheckBoundsOverlap( padfBoundsMin, padfBoundsMax,
                                    &(psObject->dfXMin),
                                    &(psObject->dfXMax),
                                    hTree->nDimension ) )
        {
            printf( "Shape %d: not in area of interest, but fetched.\n",
                    panHits[i] );
        }
        else
        {
            printf( "Shape %d: appears to be in area of interest.\n",
                    panHits[i] );
        }

        SHPDestroyObject( psObject );
    }

    if( nShapeCount == 0 )
        printf( "No shapes found in search.\n" );
}
Пример #2
0
void SHPAPI_CALL
SHPTreeCollectShapeIds( SHPTree *hTree, SHPTreeNode * psTreeNode,
                        double * padfBoundsMin, double * padfBoundsMax,
                        int * pnShapeCount, int * pnMaxShapes,
                        int ** ppanShapeList )

{
    int		i;
    
/* -------------------------------------------------------------------- */
/*      Does this node overlap the area of interest at all?  If not,    */
/*      return without adding to the list at all.                       */
/* -------------------------------------------------------------------- */
    if( !SHPCheckBoundsOverlap( psTreeNode->adfBoundsMin,
                                psTreeNode->adfBoundsMax,
                                padfBoundsMin,
                                padfBoundsMax,
                                hTree->nDimension ) )
        return;

/* -------------------------------------------------------------------- */
/*      Grow the list to hold the shapes on this node.                  */
/* -------------------------------------------------------------------- */
    if( *pnShapeCount + psTreeNode->nShapeCount > *pnMaxShapes )
    {
        *pnMaxShapes = (*pnShapeCount + psTreeNode->nShapeCount) * 2 + 20;
        *ppanShapeList = (int *)
            SfRealloc(*ppanShapeList,sizeof(int) * *pnMaxShapes);
    }

/* -------------------------------------------------------------------- */
/*      Add the local nodes shapeids to the list.                       */
/* -------------------------------------------------------------------- */
    for( i = 0; i < psTreeNode->nShapeCount; i++ )
    {
        (*ppanShapeList)[(*pnShapeCount)++] = psTreeNode->panShapeIds[i];
    }
    
/* -------------------------------------------------------------------- */
/*      Recurse to subnodes if they exist.                              */
/* -------------------------------------------------------------------- */
    for( i = 0; i < psTreeNode->nSubNodes; i++ )
    {
        if( psTreeNode->apsSubNode[i] != NULL )
            SHPTreeCollectShapeIds( hTree, psTreeNode->apsSubNode[i],
                                    padfBoundsMin, padfBoundsMax,
                                    pnShapeCount, pnMaxShapes,
                                    ppanShapeList );
    }
}
Пример #3
0
static int
SHPSearchDiskTreeNode( FILE *fp, double *padfBoundsMin, double *padfBoundsMax,
                       int **ppanResultBuffer, int *pnBufferMax, 
                       int *pnResultCount, int bNeedSwap )

{
    int i;
    int offset;
    int numshapes, numsubnodes;
    double adfNodeBoundsMin[2], adfNodeBoundsMax[2];

/* -------------------------------------------------------------------- */
/*      Read and unswap first part of node info.                        */
/* -------------------------------------------------------------------- */
    fread( &offset, 4, 1, fp );
    if ( bNeedSwap ) SwapWord ( 4, &offset );

    fread( adfNodeBoundsMin, sizeof(double), 2, fp );
    fread( adfNodeBoundsMax, sizeof(double), 2, fp );
    if ( bNeedSwap )
    {
        SwapWord( 8, adfNodeBoundsMin + 0 );
        SwapWord( 8, adfNodeBoundsMin + 1 );
        SwapWord( 8, adfNodeBoundsMax + 0 );
        SwapWord( 8, adfNodeBoundsMax + 1 );
    }
      
    fread( &numshapes, 4, 1, fp );
    if ( bNeedSwap ) SwapWord ( 4, &numshapes );

/* -------------------------------------------------------------------- */
/*      If we don't overlap this node at all, we can just fseek()       */
/*      pass this node info and all subnodes.                           */
/* -------------------------------------------------------------------- */
    if( !SHPCheckBoundsOverlap( adfNodeBoundsMin, adfNodeBoundsMax, 
                                padfBoundsMin, padfBoundsMax, 2 ) )
    {
        offset += numshapes*sizeof(int) + sizeof(int);
        fseek(fp, offset, SEEK_CUR);
        return TRUE;
    }

/* -------------------------------------------------------------------- */
/*      Add all the shapeids at this node to our list.                  */
/* -------------------------------------------------------------------- */
    if(numshapes > 0) 
    {
        if( *pnResultCount + numshapes > *pnBufferMax )
        {
            *pnBufferMax = (int) ((*pnResultCount + numshapes + 100) * 1.25);
            *ppanResultBuffer = (int *) 
                SfRealloc( *ppanResultBuffer, *pnBufferMax * sizeof(int) );
        }

        fread( *ppanResultBuffer + *pnResultCount, 
               sizeof(int), numshapes, fp );

        if (bNeedSwap )
        {
            for( i=0; i<numshapes; i++ )
                SwapWord( 4, *ppanResultBuffer + *pnResultCount + i );
        }

        *pnResultCount += numshapes; 
    } 

/* -------------------------------------------------------------------- */
/*      Process the subnodes.                                           */
/* -------------------------------------------------------------------- */
    fread( &numsubnodes, 4, 1, fp );
    if ( bNeedSwap  ) SwapWord ( 4, &numsubnodes );

    for(i=0; i<numsubnodes; i++)
    {
        if( !SHPSearchDiskTreeNode( fp, padfBoundsMin, padfBoundsMax, 
                                    ppanResultBuffer, pnBufferMax, 
                                    pnResultCount, bNeedSwap ) )
            return FALSE;
    }

    return TRUE;
}
Пример #4
0
static int
SHPSearchDiskTreeNode( SHPTreeDiskHandle hDiskTree, double *padfBoundsMin, double *padfBoundsMax,
                       int **ppanResultBuffer, int *pnBufferMax, 
                       int *pnResultCount, int bNeedSwap, int nRecLevel )

{
    unsigned int i;
    unsigned int offset;
    unsigned int numshapes, numsubnodes;
    double adfNodeBoundsMin[2], adfNodeBoundsMax[2];
    int nFReadAcc;

/* -------------------------------------------------------------------- */
/*      Read and unswap first part of node info.                        */
/* -------------------------------------------------------------------- */
    nFReadAcc = (int)hDiskTree->sHooks.FRead( &offset, 4, 1, hDiskTree->fpQIX );
    if ( bNeedSwap ) SwapWord ( 4, &offset );

    nFReadAcc += (int)hDiskTree->sHooks.FRead( adfNodeBoundsMin, sizeof(double), 2, hDiskTree->fpQIX );
    nFReadAcc += (int)hDiskTree->sHooks.FRead( adfNodeBoundsMax, sizeof(double), 2, hDiskTree->fpQIX );
    if ( bNeedSwap )
    {
        SwapWord( 8, adfNodeBoundsMin + 0 );
        SwapWord( 8, adfNodeBoundsMin + 1 );
        SwapWord( 8, adfNodeBoundsMax + 0 );
        SwapWord( 8, adfNodeBoundsMax + 1 );
    }
      
    nFReadAcc += (int)hDiskTree->sHooks.FRead( &numshapes, 4, 1, hDiskTree->fpQIX );
    if ( bNeedSwap ) SwapWord ( 4, &numshapes );

    /* Check that we could read all previous values */
    if( nFReadAcc != 1 + 2 + 2 + 1 )
    {
        hDiskTree->sHooks.Error("I/O error");
        return FALSE;
    }

    /* Sanity checks to avoid int overflows in later computation */
    if( offset > INT_MAX - sizeof(int) )
    {
        hDiskTree->sHooks.Error("Invalid value for offset");
        return FALSE;
    }

    if( numshapes > (INT_MAX - offset - sizeof(int)) / sizeof(int) ||
        numshapes > INT_MAX / sizeof(int) - *pnResultCount )
    {
        hDiskTree->sHooks.Error("Invalid value for numshapes");
        return FALSE;
    }

/* -------------------------------------------------------------------- */
/*      If we don't overlap this node at all, we can just fseek()       */
/*      pass this node info and all subnodes.                           */
/* -------------------------------------------------------------------- */
    if( !SHPCheckBoundsOverlap( adfNodeBoundsMin, adfNodeBoundsMax, 
                                padfBoundsMin, padfBoundsMax, 2 ) )
    {
        offset += numshapes*sizeof(int) + sizeof(int);
        hDiskTree->sHooks.FSeek(hDiskTree->fpQIX, offset, SEEK_CUR);
        return TRUE;
    }

/* -------------------------------------------------------------------- */
/*      Add all the shapeids at this node to our list.                  */
/* -------------------------------------------------------------------- */
    if(numshapes > 0) 
    {
        if( *pnResultCount + numshapes > *pnBufferMax )
        {
            int* pNewBuffer;

            *pnBufferMax = (*pnResultCount + numshapes + 100) * 5 / 4;

            if( *pnBufferMax > INT_MAX / sizeof(int) )
                *pnBufferMax = *pnResultCount + numshapes;

            pNewBuffer = (int *)
                SfRealloc( *ppanResultBuffer, *pnBufferMax * sizeof(int) );

            if( pNewBuffer == NULL )
            {
                hDiskTree->sHooks.Error("Out of memory error");
                return FALSE;
            }

            *ppanResultBuffer = pNewBuffer;
        }

        if( hDiskTree->sHooks.FRead( *ppanResultBuffer + *pnResultCount,
                    sizeof(int), numshapes, hDiskTree->fpQIX ) != numshapes )
        {
            hDiskTree->sHooks.Error("I/O error");
            return FALSE;
        }

        if (bNeedSwap )
        {
            for( i=0; i<numshapes; i++ )
                SwapWord( 4, *ppanResultBuffer + *pnResultCount + i );
        }

        *pnResultCount += numshapes; 
    } 

/* -------------------------------------------------------------------- */
/*      Process the subnodes.                                           */
/* -------------------------------------------------------------------- */
    if( hDiskTree->sHooks.FRead( &numsubnodes, 4, 1, hDiskTree->fpQIX ) != 1 )
    {
        hDiskTree->sHooks.Error("I/O error");
        return FALSE;
    }
    if ( bNeedSwap  ) SwapWord ( 4, &numsubnodes );
    if( numsubnodes > 0 && nRecLevel == 32 )
    {
        hDiskTree->sHooks.Error("Shape tree is too deep");
        return FALSE;
    }

    for(i=0; i<numsubnodes; i++)
    {
        if( !SHPSearchDiskTreeNode( hDiskTree, padfBoundsMin, padfBoundsMax, 
                                    ppanResultBuffer, pnBufferMax, 
                                    pnResultCount, bNeedSwap, nRecLevel + 1 ) )
            return FALSE;
    }

    return TRUE;
}