Beispiel #1
0
///////////////////////////////////////////////////////////////////////////////
// ein neues Objekt zum Baum hinzufügen
bool CSpatialTreeNode::AddObject(CObjectWithRect &rObject, int nMaxDepth)
{
// If there are subnodes, then consider wether this object
// will fit in them.
	if (nMaxDepth > 1 && m_nSubNodes > 0) {
		for (int i = 0; i < m_nSubNodes; ++i) {
			_ASSERTE(NULL != m_apsSubNode[i]);
			if (m_apsSubNode[i] -> CheckObjectContained(rObject)) 
				return m_apsSubNode[i] -> AddObject(rObject, nMaxDepth - 1);
		}
	}
	else if (nMaxDepth > 1 && 0 == m_nSubNodes)	{
	// Otherwise, consider creating four subnodes if could fit into	
	// them, and adding to the appropriate subnode.
	double adfBoundsMinH1[SPATIALTREE_DIMENSION], adfBoundsMaxH1[SPATIALTREE_DIMENSION];
	double adfBoundsMinH2[SPATIALTREE_DIMENSION], adfBoundsMaxH2[SPATIALTREE_DIMENSION];
	double adfBoundsMin1[SPATIALTREE_DIMENSION], adfBoundsMax1[SPATIALTREE_DIMENSION];
	double adfBoundsMin2[SPATIALTREE_DIMENSION], adfBoundsMax2[SPATIALTREE_DIMENSION];
	double adfBoundsMin3[SPATIALTREE_DIMENSION], adfBoundsMax3[SPATIALTREE_DIMENSION];
	double adfBoundsMin4[SPATIALTREE_DIMENSION], adfBoundsMax4[SPATIALTREE_DIMENSION];

		SplitBounds(m_dBoundsMin, m_dBoundsMax, adfBoundsMinH1, adfBoundsMaxH1, adfBoundsMinH2, adfBoundsMaxH2);
		SplitBounds(adfBoundsMinH1, adfBoundsMaxH1, adfBoundsMin1, adfBoundsMax1, adfBoundsMin2, adfBoundsMax2);
		SplitBounds(adfBoundsMinH2, adfBoundsMaxH2, adfBoundsMin3, adfBoundsMax3, adfBoundsMin4, adfBoundsMax4);

		if (CheckObjectContained(rObject, adfBoundsMin1, adfBoundsMax1) ||
			CheckObjectContained(rObject, adfBoundsMin2, adfBoundsMax2) ||
			CheckObjectContained(rObject, adfBoundsMin3, adfBoundsMax3) ||
			CheckObjectContained(rObject, adfBoundsMin4, adfBoundsMax4))
		{
			m_nSubNodes = 4;
			ATLTRY((
				m_apsSubNode[0] = new CSpatialTreeNode(adfBoundsMin1, adfBoundsMax1),
				m_apsSubNode[1] = new CSpatialTreeNode(adfBoundsMin2, adfBoundsMax2),
				m_apsSubNode[2] = new CSpatialTreeNode(adfBoundsMin3, adfBoundsMax3),
				m_apsSubNode[3] = new CSpatialTreeNode(adfBoundsMin4, adfBoundsMax4)
			));

		// recurse back on this node now that it has subnodes
			return AddObject(rObject, nMaxDepth);
		}
	}

// If none of that worked, just add it to this nodes list.
	++m_nFeatureCount;

IUnknown * *pFeatureIds = SfRealloc(m_pFeatureIds, sizeof(IUnknown *) * m_nFeatureCount);

	if (NULL != pFeatureIds) {
		m_pFeatureIds =	pFeatureIds;
		m_pFeatureIds[m_nFeatureCount - 1] = rObject.GetUnknown();
		if (NULL != m_pFeatureIds[m_nFeatureCount - 1])
			m_pFeatureIds[m_nFeatureCount - 1] -> AddRef();
		return true;
	}
	return false;
}
Beispiel #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 );
    }
}
Beispiel #3
0
// Work function implementing CSpatialTreeFindLikelyShapes() on a
// tree node by tree node basis.
bool CSpatialTree::CollectFeatureIds(
	CSpatialTreeNode *psTreeNode, double *padfBoundsMin, double * padfBoundsMax,
	int *pnFeatureCount, int *pnMaxFeatures, _DGMGeometry * **ppanFeatureList)
{
// Does this node overlap the area of interest at all?  If not,	
// return without adding to the list at all.
	if (!psTreeNode->CheckBoundsOverlap(padfBoundsMin, padfBoundsMax))
		return true;

// Grow the list to hold the shapes on this node.
	if (*pnFeatureCount + psTreeNode->m_nFeatureCount > *pnMaxFeatures)
	{
		*pnMaxFeatures = (*pnFeatureCount + psTreeNode->m_nFeatureCount) * 2 + 20;

	_DGMGeometry **panFeatureList = SfRealloc (*ppanFeatureList, 
		sizeof(_DGMGeometry *) * *pnMaxFeatures);

		if (NULL != panFeatureList)
			*ppanFeatureList = panFeatureList;
		else
			return false;
	}

// Add the local nodes shapeids to the list.
	for (int i = 0; i < psTreeNode->m_nFeatureCount; ++i)
		(*ppanFeatureList)[(*pnFeatureCount)++] = psTreeNode->m_pFeatureIds[i];
	
// Recurse to subnodes if they exist.
	for (int j = 0; j < psTreeNode->m_nSubNodes; ++j)
	{
		if (NULL != psTreeNode->m_apsSubNode[j]) {
			if (!CollectFeatureIds(psTreeNode->m_apsSubNode[j], padfBoundsMin, 
				padfBoundsMax, pnFeatureCount, pnMaxFeatures, ppanFeatureList))
			{
				return false;		// Fehler, daher abbrechen
			}
		}
	}
	return true;
}
Beispiel #4
0
DBFReadTuple(DBFHandle psDBF, int hEntity )

{
    int		nRecordOffset;
    unsigned char	*pabyRec;
    static char	*pReturnTuple = NULL;

    static int	nTupleLen = 0;

/* -------------------------------------------------------------------- */
/*	Have we read the record?					*/
/* -------------------------------------------------------------------- */
    if( hEntity < 0 || hEntity >= psDBF->nRecords )
	return( NULL );

    if( psDBF->nCurrentRecord != hEntity )
    {
	DBFFlushRecord( psDBF );

	nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;

	fseek( psDBF->fp, nRecordOffset, 0 );
	if (fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 
		   1, psDBF->fp ) != 1) error("binary read error");

	psDBF->nCurrentRecord = hEntity;
    }

    pabyRec = (unsigned char *) psDBF->pszCurrentRecord;

    if ( nTupleLen < psDBF->nRecordLength) {
      nTupleLen = psDBF->nRecordLength;
      pReturnTuple = (char *) SfRealloc(pReturnTuple, psDBF->nRecordLength);
    }

    memcpy ( pReturnTuple, pabyRec, psDBF->nRecordLength );

    return( pReturnTuple );
}
Beispiel #5
0
static int SBNAddShapeId( SearchStruct* psSearch,
                          int nShapeId )
{
    if (psSearch->nShapeCount == psSearch->nShapeAlloc)
    {
        int* pNewPtr;

        psSearch->nShapeAlloc =
            (int) (((psSearch->nShapeCount + 100) * 5) / 4);
        pNewPtr =
            (int *) SfRealloc( psSearch->panShapeId,
                               psSearch->nShapeAlloc * sizeof(int) );
        if( pNewPtr == NULL )
        {
            psSearch->hSBN->sHooks.Error( "Out of memory error" );
            return FALSE;
        }
        psSearch->panShapeId = pNewPtr;
    }

    psSearch->panShapeId[psSearch->nShapeCount] = nShapeId;
    psSearch->nShapeCount ++;
    return TRUE;
}
Beispiel #6
0
static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
                              char chReqType )

{
    int	       	nRecordOffset;
    uchar	*pabyRec;
    void	*pReturnField = NULL;

    static double dDoubleField;

/* -------------------------------------------------------------------- */
/*	Have we read the record?					*/
/* -------------------------------------------------------------------- */
    if( hEntity < 0 || hEntity >= psDBF->nRecords )
        return( NULL );

    if( psDBF->nCurrentRecord != hEntity )
    {
	DBFFlushRecord( psDBF );

	nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;

	fseek( psDBF->fp, nRecordOffset, 0 );
	fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );

	psDBF->nCurrentRecord = hEntity;
    }

    pabyRec = (uchar *) psDBF->pszCurrentRecord;

/* -------------------------------------------------------------------- */
/*	Ensure our field buffer is large enough to hold this buffer.	*/
/* -------------------------------------------------------------------- */
    if( psDBF->panFieldSize[iField]+1 > nStringFieldLen )
    {
	nStringFieldLen = psDBF->panFieldSize[iField]*2 + 10;
	pszStringField = (char *) SfRealloc(pszStringField,nStringFieldLen);
    }

/* -------------------------------------------------------------------- */
/*	Extract the requested field.					*/
/* -------------------------------------------------------------------- */
    strncpy( pszStringField, (const char *)pabyRec+psDBF->panFieldOffset[iField],
	     psDBF->panFieldSize[iField] );
    pszStringField[psDBF->panFieldSize[iField]] = '\0';

    pReturnField = pszStringField;

/* -------------------------------------------------------------------- */
/*      Decode the field.                                               */
/* -------------------------------------------------------------------- */
    if( chReqType == 'N' )
    {
        sscanf( pszStringField, "%lf", &dDoubleField );

	pReturnField = &dDoubleField;
    }

/* -------------------------------------------------------------------- */
/*      Should we trim white space off the string attribute value?      */
/* -------------------------------------------------------------------- */
#ifdef TRIM_DBF_WHITESPACE
    else
    {
        char	*pchSrc, *pchDst;

        pchDst = pchSrc = pszStringField;
        while( *pchSrc == ' ' )
            pchSrc++;

        while( *pchSrc != '\0' )
            *(pchDst++) = *(pchSrc++);
        *pchDst = '\0';

        while( *(--pchDst) == ' ' && pchDst != pszStringField )
            *pchDst = '\0';

    }
#endif
    
    return( pReturnField );
}
Beispiel #7
0
int	DBFAddField(DBFHandle psDBF, const char * pszFieldName, 
		    DBFFieldType eType, int nWidth, int nDecimals )

{
    char	*pszFInfo;
    int		i;

/* -------------------------------------------------------------------- */
/*      Do some checking to ensure we can add records to this file.     */
/* -------------------------------------------------------------------- */
    if( psDBF->nRecords > 0 )
        return( -1 );

    if( !psDBF->bNoHeader )
        return( -1 );

    if( eType != FTDouble && nDecimals != 0 )
        return( -1 );

/* -------------------------------------------------------------------- */
/*      SfRealloc all the arrays larger to hold the additional field      */
/*      information.                                                    */
/* -------------------------------------------------------------------- */
    psDBF->nFields++;

    psDBF->panFieldOffset = (int *) 
      SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );

    psDBF->panFieldSize = (int *) 
      SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields );

    psDBF->panFieldDecimals = (int *) 
      SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );

    psDBF->pachFieldType = (char *) 
      SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields );

/* -------------------------------------------------------------------- */
/*      Assign the new field information fields.                        */
/* -------------------------------------------------------------------- */
    psDBF->panFieldOffset[psDBF->nFields-1] = psDBF->nRecordLength;
    psDBF->nRecordLength += nWidth;
    psDBF->panFieldSize[psDBF->nFields-1] = nWidth;
    psDBF->panFieldDecimals[psDBF->nFields-1] = nDecimals;

    if( eType == FTString )
        psDBF->pachFieldType[psDBF->nFields-1] = 'C';
    else
        psDBF->pachFieldType[psDBF->nFields-1] = 'N';

/* -------------------------------------------------------------------- */
/*      Extend the required header information.                         */
/* -------------------------------------------------------------------- */
    psDBF->nHeaderLength += 32;
    psDBF->bUpdated = FALSE;

    psDBF->pszHeader = (char *) SfRealloc(psDBF->pszHeader,psDBF->nFields*32);

    pszFInfo = psDBF->pszHeader + 32 * (psDBF->nFields-1);

    for( i = 0; i < 32; i++ )
        pszFInfo[i] = '\0';

    if( strlen(pszFieldName) < 10 )
        strncpy( pszFInfo, pszFieldName, strlen(pszFieldName));
    else
        strncpy( pszFInfo, pszFieldName, 10);

    pszFInfo[11] = psDBF->pachFieldType[psDBF->nFields-1];

    if( eType == FTString )
    {
        pszFInfo[16] = nWidth % 256;
        pszFInfo[17] = nWidth / 256;
    }
    else
    {
        pszFInfo[16] = nWidth;
        pszFInfo[17] = nDecimals;
    }
    
/* -------------------------------------------------------------------- */
/*      Make the current record buffer appropriately larger.            */
/* -------------------------------------------------------------------- */
    psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
					       psDBF->nRecordLength);

    return( psDBF->nFields-1 );
}
Beispiel #8
0
DBFHandle DBFOpen( const char * pszFilename, const char * pszAccess )

{
    DBFHandle		psDBF;
    uchar		*pabyBuf;
    int			nFields, nRecords, nHeadLen, nRecLen, iField, i;
    char		*pszBasename, *pszFullname;

/* -------------------------------------------------------------------- */
/*      We only allow the access strings "rb" and "r+".                  */
/* -------------------------------------------------------------------- */
    if( strcmp(pszAccess,"r") != 0 && strcmp(pszAccess,"r+") != 0 
        && strcmp(pszAccess,"rb") != 0 && strcmp(pszAccess,"rb+") != 0
        && strcmp(pszAccess,"r+b") != 0 )
        return( NULL );

/* -------------------------------------------------------------------- */
/*	Compute the base (layer) name.  If there is any extension	*/
/*	on the passed in filename we will strip it off.			*/
/* -------------------------------------------------------------------- */
    pszBasename = (char *) malloc(strlen(pszFilename)+5);
    strcpy( pszBasename, pszFilename );
    for( i = strlen(pszBasename)-1; 
	 i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
	       && pszBasename[i] != '\\';
	 i-- ) {}

    if( pszBasename[i] == '.' )
        pszBasename[i] = '\0';

    pszFullname = (char *) malloc(strlen(pszBasename) + 5);
    sprintf( pszFullname, "%s.dbf", pszBasename );
    free( pszBasename );
        
    psDBF = (DBFHandle) calloc( 1, sizeof(DBFInfo) );
    psDBF->fp = fopen( pszFullname, pszAccess );
    free( pszFullname );
    if( psDBF->fp == NULL )
        return( NULL );

    psDBF->bNoHeader = FALSE;
    psDBF->nCurrentRecord = -1;
    psDBF->bCurrentRecordModified = FALSE;

/* -------------------------------------------------------------------- */
/*  Read Table Header info                                              */
/* -------------------------------------------------------------------- */
    pabyBuf = (uchar *) malloc(500);
    fread( pabyBuf, 32, 1, psDBF->fp );

    psDBF->nRecords = nRecords = 
     pabyBuf[4] + pabyBuf[5]*256 + pabyBuf[6]*256*256 + pabyBuf[7]*256*256*256;

    psDBF->nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256;
    psDBF->nRecordLength = nRecLen = pabyBuf[10] + pabyBuf[11]*256;
    
    psDBF->nFields = nFields = (nHeadLen - 32) / 32;

    psDBF->pszCurrentRecord = (char *) malloc(nRecLen);

/* -------------------------------------------------------------------- */
/*  Read in Field Definitions                                           */
/* -------------------------------------------------------------------- */
    
    pabyBuf = (uchar *) SfRealloc(pabyBuf,nHeadLen);
    psDBF->pszHeader = (char *) pabyBuf;

    fseek( psDBF->fp, 32, 0 );
    fread( pabyBuf, nHeadLen, 1, psDBF->fp );

    psDBF->panFieldOffset = (int *) malloc(sizeof(int) * nFields);
    psDBF->panFieldSize = (int *) malloc(sizeof(int) * nFields);
    psDBF->panFieldDecimals = (int *) malloc(sizeof(int) * nFields);
    psDBF->pachFieldType = (char *) malloc(sizeof(char) * nFields);

    for( iField = 0; iField < nFields; iField++ )
    {
	uchar		*pabyFInfo;

	pabyFInfo = pabyBuf+iField*32;

	if( pabyFInfo[11] == 'N' || pabyFInfo[11] == 'F' )
	{
	    psDBF->panFieldSize[iField] = pabyFInfo[16];
	    psDBF->panFieldDecimals[iField] = pabyFInfo[17];
	}
	else
	{
	    psDBF->panFieldSize[iField] = pabyFInfo[16] + pabyFInfo[17]*256;
	    psDBF->panFieldDecimals[iField] = 0;
	}

	psDBF->pachFieldType[iField] = (char) pabyFInfo[11];
	if( iField == 0 )
	    psDBF->panFieldOffset[iField] = 1;
	else
	    psDBF->panFieldOffset[iField] = 
	      psDBF->panFieldOffset[iField-1] + psDBF->panFieldSize[iField-1];
    }

    return( psDBF );
}
Beispiel #9
0
static int treeNodeAddShapeId( treeNodeObj *node, int id, rectObj rect, int maxdepth)
{
  int i;

  /* -------------------------------------------------------------------- */
  /*      If there are subnodes, then consider whether this object        */
  /*      will fit in them.                                               */
  /* -------------------------------------------------------------------- */
  if( maxdepth > 1 && node->numsubnodes > 0 ) {
    for(i=0; i<node->numsubnodes; i++ ) {
      if( msRectContained(&rect, &node->subnode[i]->rect)) {
        return treeNodeAddShapeId( node->subnode[i], id, rect, maxdepth-1);
      }
    }
  }

  /* -------------------------------------------------------------------- */
  /*      Otherwise, consider creating four subnodes if could fit into    */
  /*      them, and adding to the appropriate subnode.                    */
  /* -------------------------------------------------------------------- */
#if MAX_SUBNODES == 4
  else if( maxdepth > 1 && node->numsubnodes == 0 ) {
    rectObj half1, half2, quad1, quad2, quad3, quad4;

    treeSplitBounds(&node->rect, &half1, &half2);
    treeSplitBounds(&half1, &quad1, &quad2);
    treeSplitBounds(&half2, &quad3, &quad4);

    if(msRectContained(&rect, &quad1) || msRectContained(&rect, &quad2) ||  msRectContained(&rect, &quad3) || msRectContained(&rect, &quad4)) {
      node->numsubnodes = 4;
      node->subnode[0] = treeNodeCreate(quad1);
      node->subnode[1] = treeNodeCreate(quad2);
      node->subnode[2] = treeNodeCreate(quad3);
      node->subnode[3] = treeNodeCreate(quad4);

      /* recurse back on this node now that it has subnodes */
      return(treeNodeAddShapeId(node, id, rect, maxdepth));
    }
  }
#endif

  /* -------------------------------------------------------------------- */
  /*      Otherwise, consider creating two subnodes if could fit into     */
  /*      them, and adding to the appropriate subnode.                    */
  /* -------------------------------------------------------------------- */
#if MAX_SUBNODE == 2
  else if( maxdepth > 1 && node->numsubnodes == 0 ) {
    rectObj half1, half2;

    treeSplitBounds(&node->rect, &half1, &half2);

    if( msRectContained(&rect, &half1)) {
      node->numsubnodes = 2;
      node->subnode[0] = treeNodeCreate(half1);
      node->subnode[1] = treeNodeCreate(half2);

      return(treeNodeAddShapeId(node->subnode[0], id, rect, maxdepth-1));
    } else if(msRectContained(&rect, &half2)) {
      node->numsubnodes = 2;
      node->subnode[0] = treeNodeCreate(&half1);
      node->subnode[1] = treeNodeCreate(&half2);

      return(treeNodeAddShapeId(node->subnode[1], id, rect, maxdepth-1));
    }
  }
#endif /* MAX_SUBNODE == 2 */

  /* -------------------------------------------------------------------- */
  /*      If none of that worked, just add it to this nodes list.         */
  /* -------------------------------------------------------------------- */
  node->numshapes++;

  node->ids = SfRealloc( node->ids, sizeof(ms_int32) * node->numshapes );
  node->ids[node->numshapes-1] = id;

  return MS_TRUE;
}
Beispiel #10
0
static int
SHPTreeNodeAddShapeId( SHPTreeNode * psTreeNode, SHPObject * psObject,
                       int nMaxDepth, int nDimension )

{
    int		i;
    
/* -------------------------------------------------------------------- */
/*      If there are subnodes, then consider wiether this object        */
/*      will fit in them.                                               */
/* -------------------------------------------------------------------- */
    if( nMaxDepth > 1 && psTreeNode->nSubNodes > 0 )
    {
        for( i = 0; i < psTreeNode->nSubNodes; i++ )
        {
            if( SHPCheckObjectContained(psObject, nDimension,
                                      psTreeNode->apsSubNode[i]->adfBoundsMin,
                                      psTreeNode->apsSubNode[i]->adfBoundsMax))
            {
                return SHPTreeNodeAddShapeId( psTreeNode->apsSubNode[i],
                                              psObject, nMaxDepth-1,
                                              nDimension );
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Otherwise, consider creating four subnodes if could fit into    */
/*      them, and adding to the appropriate subnode.                    */
/* -------------------------------------------------------------------- */
#if MAX_SUBNODE == 4
    else if( nMaxDepth > 1 && psTreeNode->nSubNodes == 0 )
    {
        double	adfBoundsMinH1[4], adfBoundsMaxH1[4];
        double	adfBoundsMinH2[4], adfBoundsMaxH2[4];
        double	adfBoundsMin1[4], adfBoundsMax1[4];
        double	adfBoundsMin2[4], adfBoundsMax2[4];
        double	adfBoundsMin3[4], adfBoundsMax3[4];
        double	adfBoundsMin4[4], adfBoundsMax4[4];

        SHPTreeSplitBounds( psTreeNode->adfBoundsMin,
                            psTreeNode->adfBoundsMax,
                            adfBoundsMinH1, adfBoundsMaxH1,
                            adfBoundsMinH2, adfBoundsMaxH2 );

        SHPTreeSplitBounds( adfBoundsMinH1, adfBoundsMaxH1,
                            adfBoundsMin1, adfBoundsMax1,
                            adfBoundsMin2, adfBoundsMax2 );

        SHPTreeSplitBounds( adfBoundsMinH2, adfBoundsMaxH2,
                            adfBoundsMin3, adfBoundsMax3,
                            adfBoundsMin4, adfBoundsMax4 );

        if( SHPCheckObjectContained(psObject, nDimension,
                                    adfBoundsMin1, adfBoundsMax1)
            || SHPCheckObjectContained(psObject, nDimension,
                                    adfBoundsMin2, adfBoundsMax2)
            || SHPCheckObjectContained(psObject, nDimension,
                                    adfBoundsMin3, adfBoundsMax3)
            || SHPCheckObjectContained(psObject, nDimension,
                                    adfBoundsMin4, adfBoundsMax4) )
        {
            psTreeNode->nSubNodes = 4;
            psTreeNode->apsSubNode[0] = SHPTreeNodeCreate( adfBoundsMin1,
                                                           adfBoundsMax1 );
            psTreeNode->apsSubNode[1] = SHPTreeNodeCreate( adfBoundsMin2,
                                                           adfBoundsMax2 );
            psTreeNode->apsSubNode[2] = SHPTreeNodeCreate( adfBoundsMin3,
                                                           adfBoundsMax3 );
            psTreeNode->apsSubNode[3] = SHPTreeNodeCreate( adfBoundsMin4,
                                                           adfBoundsMax4 );

            /* recurse back on this node now that it has subnodes */
            return( SHPTreeNodeAddShapeId( psTreeNode, psObject,
                                           nMaxDepth, nDimension ) );
        }
    }
#endif /* MAX_SUBNODE == 4 */

/* -------------------------------------------------------------------- */
/*      Otherwise, consider creating two subnodes if could fit into     */
/*      them, and adding to the appropriate subnode.                    */
/* -------------------------------------------------------------------- */
#if MAX_SUBNODE == 2
    else if( nMaxDepth > 1 && psTreeNode->nSubNodes == 0 )
    {
        double	adfBoundsMin1[4], adfBoundsMax1[4];
        double	adfBoundsMin2[4], adfBoundsMax2[4];

        SHPTreeSplitBounds( psTreeNode->adfBoundsMin, psTreeNode->adfBoundsMax,
                            adfBoundsMin1, adfBoundsMax1,
                            adfBoundsMin2, adfBoundsMax2 );

        if( SHPCheckObjectContained(psObject, nDimension,
                                 adfBoundsMin1, adfBoundsMax1))
        {
            psTreeNode->nSubNodes = 2;
            psTreeNode->apsSubNode[0] = SHPTreeNodeCreate( adfBoundsMin1,
                                                           adfBoundsMax1 );
            psTreeNode->apsSubNode[1] = SHPTreeNodeCreate( adfBoundsMin2,
                                                           adfBoundsMax2 );

            return( SHPTreeNodeAddShapeId( psTreeNode->apsSubNode[0], psObject,
                                           nMaxDepth - 1, nDimension ) );
        }
        else if( SHPCheckObjectContained(psObject, nDimension,
                                         adfBoundsMin2, adfBoundsMax2) )
        {
            psTreeNode->nSubNodes = 2;
            psTreeNode->apsSubNode[0] = SHPTreeNodeCreate( adfBoundsMin1,
                                                           adfBoundsMax1 );
            psTreeNode->apsSubNode[1] = SHPTreeNodeCreate( adfBoundsMin2,
                                                           adfBoundsMax2 );

            return( SHPTreeNodeAddShapeId( psTreeNode->apsSubNode[1], psObject,
                                           nMaxDepth - 1, nDimension ) );
        }
    }
#endif /* MAX_SUBNODE == 2 */

/* -------------------------------------------------------------------- */
/*      If none of that worked, just add it to this nodes list.         */
/* -------------------------------------------------------------------- */
    psTreeNode->nShapeCount++;

    psTreeNode->panShapeIds =
        SfRealloc( psTreeNode->panShapeIds,
                   sizeof(int) * psTreeNode->nShapeCount );
    psTreeNode->panShapeIds[psTreeNode->nShapeCount-1] = psObject->nShapeId;

    if( psTreeNode->papsShapeObj != NULL )
    {
        psTreeNode->papsShapeObj =
            SfRealloc( psTreeNode->papsShapeObj,
                       sizeof(void *) * psTreeNode->nShapeCount );
        psTreeNode->papsShapeObj[psTreeNode->nShapeCount-1] = NULL;
    }

    return TRUE;
}
Beispiel #11
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;
}
Beispiel #12
0
static char *msDBFReadAttribute(DBFHandle psDBF, int hEntity, int iField )

{
  int         i;
  unsigned int nRecordOffset;
  uchar *pabyRec;
  char  *pReturnField = NULL;

  /* -------------------------------------------------------------------- */
  /*  Is the request valid?                             */
  /* -------------------------------------------------------------------- */
  if( iField < 0 || iField >= psDBF->nFields ) {
    msSetError(MS_DBFERR, "Invalid field index %d.", "msDBFReadAttribute()",iField );
    return( NULL );
  }

  if( hEntity < 0 || hEntity >= psDBF->nRecords ) {
    msSetError(MS_DBFERR, "Invalid record number %d.", "msDBFReadAttribute()",hEntity );
    return( NULL );
  }

  /* -------------------------------------------------------------------- */
  /*  Have we read the record?              */
  /* -------------------------------------------------------------------- */
  if( psDBF->nCurrentRecord != hEntity ) {
    flushRecord( psDBF );

    nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;

    safe_fseek( psDBF->fp, nRecordOffset, 0 );
    fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );

    psDBF->nCurrentRecord = hEntity;
  }

  pabyRec = (uchar *) psDBF->pszCurrentRecord;
  /* DEBUG */
  /* printf("CurrentRecord(%c):%s\n", psDBF->pachFieldType[iField], pabyRec); */

  /* -------------------------------------------------------------------- */
  /*  Ensure our field buffer is large enough to hold this buffer.      */
  /* -------------------------------------------------------------------- */
  if( psDBF->panFieldSize[iField]+1 > psDBF->nStringFieldLen ) {
    psDBF->nStringFieldLen = psDBF->panFieldSize[iField]*2 + 10;
    psDBF->pszStringField = (char *) SfRealloc(psDBF->pszStringField,psDBF->nStringFieldLen);
  }

  /* -------------------------------------------------------------------- */
  /*  Extract the requested field.              */
  /* -------------------------------------------------------------------- */
  strncpy( psDBF->pszStringField,(char *) pabyRec+psDBF->panFieldOffset[iField], psDBF->panFieldSize[iField] );
  psDBF->pszStringField[psDBF->panFieldSize[iField]] = '\0';

  /*
  ** Trim trailing blanks (SDL Modification)
  */
  for(i=strlen(psDBF->pszStringField)-1; i>=0; i--) {
    if(psDBF->pszStringField[i] != ' ') {
      psDBF->pszStringField[i+1] = '\0';
      break;
    }
  }

  if(i == -1) psDBF->pszStringField[0] = '\0'; /* whole string is blank (SDL fix)       */

  /*
  ** Trim/skip leading blanks (SDL/DM Modification - only on numeric types)
  */
  if( psDBF->pachFieldType[iField] == 'N' || psDBF->pachFieldType[iField] == 'F' || psDBF->pachFieldType[iField] == 'D' ) {
    for(i=0; psDBF->pszStringField[i] != '\0' ; i++) {
      if(psDBF->pszStringField[i] != ' ')
        break;
    }
    pReturnField = psDBF->pszStringField+i;
  } else
    pReturnField = psDBF->pszStringField;

  /*  detect null values */
  if ( DBFIsValueNULL( pReturnField, psDBF->pachFieldType[iField] )  ) {
    if (psDBF->pachFieldType[iField] == 'N' || psDBF->pachFieldType[iField] == 'F' || psDBF->pachFieldType[iField] == 'D')
      pReturnField="0";
  }
  return( pReturnField );
}
Beispiel #13
0
DBFHandle msDBFOpen( const char * pszFilename, const char * pszAccess )

{
  DBFHandle   psDBF;
  uchar   *pabyBuf;
  int     nFields, nRecords, nHeadLen, nRecLen, iField;
  char          *pszDBFFilename;

  /* -------------------------------------------------------------------- */
  /*      We only allow the access strings "rb" and "r+".                 */
  /* -------------------------------------------------------------------- */
  if( strcmp(pszAccess,"r") != 0 && strcmp(pszAccess,"r+") != 0
      && strcmp(pszAccess,"rb") != 0 && strcmp(pszAccess,"r+b") != 0 )
    return( NULL );

  /* -------------------------------------------------------------------- */
  /*  Ensure the extension is converted to dbf or DBF if it is      */
  /*  currently .shp or .shx.               */
  /* -------------------------------------------------------------------- */
  pszDBFFilename = (char *) msSmallMalloc(strlen(pszFilename)+1);
  strcpy( pszDBFFilename, pszFilename );

  if( strcmp(pszFilename+strlen(pszFilename)-4,".shp")
      || strcmp(pszFilename+strlen(pszFilename)-4,".shx") ) {
    strcpy( pszDBFFilename+strlen(pszDBFFilename)-4, ".dbf");
  } else if( strcmp(pszFilename+strlen(pszFilename)-4,".SHP")
             || strcmp(pszFilename+strlen(pszFilename)-4,".SHX") ) {
    strcpy( pszDBFFilename+strlen(pszDBFFilename)-4, ".DBF");
  }

  /* -------------------------------------------------------------------- */
  /*      Open the file.                                                  */
  /* -------------------------------------------------------------------- */
  psDBF = (DBFHandle) calloc( 1, sizeof(DBFInfo) );
  MS_CHECK_ALLOC(psDBF, sizeof(DBFInfo), NULL);
  psDBF->fp = fopen( pszDBFFilename, pszAccess );
  if( psDBF->fp == NULL )
    return( NULL );

  psDBF->bNoHeader = MS_FALSE;
  psDBF->nCurrentRecord = -1;
  psDBF->bCurrentRecordModified = MS_FALSE;

  psDBF->pszStringField = NULL;
  psDBF->nStringFieldLen = 0;

  free( pszDBFFilename );

  /* -------------------------------------------------------------------- */
  /*  Read Table Header info                                              */
  /* -------------------------------------------------------------------- */
  pabyBuf = (uchar *) msSmallMalloc(500);
  fread( pabyBuf, 32, 1, psDBF->fp );

  psDBF->nRecords = nRecords =
                      pabyBuf[4] + pabyBuf[5]*256 + pabyBuf[6]*256*256 + pabyBuf[7]*256*256*256;

  psDBF->nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256;
  psDBF->nRecordLength = nRecLen = pabyBuf[10] + pabyBuf[11]*256;

  psDBF->nFields = nFields = (nHeadLen - 32) / 32;

  psDBF->pszCurrentRecord = (char *) msSmallMalloc(nRecLen);

  /* -------------------------------------------------------------------- */
  /*  Read in Field Definitions                                           */
  /* -------------------------------------------------------------------- */
  pabyBuf = (uchar *) SfRealloc(pabyBuf,nHeadLen);
  psDBF->pszHeader = (char *) pabyBuf;

  fseek( psDBF->fp, 32, 0 );
  fread( pabyBuf, nHeadLen, 1, psDBF->fp );

  psDBF->panFieldOffset = (int *) msSmallMalloc(sizeof(int) * nFields);
  psDBF->panFieldSize = (int *) msSmallMalloc(sizeof(int) * nFields);
  psDBF->panFieldDecimals = (int *) msSmallMalloc(sizeof(int) * nFields);
  psDBF->pachFieldType = (char *) msSmallMalloc(sizeof(char) * nFields);

  for( iField = 0; iField < nFields; iField++ ) {
    uchar   *pabyFInfo;

    pabyFInfo = pabyBuf+iField*32;

    if( pabyFInfo[11] == 'N' || pabyFInfo[11] == 'F' ) {
      psDBF->panFieldSize[iField] = pabyFInfo[16];
      psDBF->panFieldDecimals[iField] = pabyFInfo[17];
    } else {
      psDBF->panFieldSize[iField] = pabyFInfo[16] + pabyFInfo[17]*256;
      psDBF->panFieldDecimals[iField] = 0;
    }

    psDBF->pachFieldType[iField] = (char) pabyFInfo[11];
    if( iField == 0 )
      psDBF->panFieldOffset[iField] = 1;
    else
      psDBF->panFieldOffset[iField] =
        psDBF->panFieldOffset[iField-1] + psDBF->panFieldSize[iField-1];
  }

  return( psDBF );
}
Beispiel #14
0
DBFHandle SHPAPI_CALL
DBFOpen( const char * pszFilename, const char * pszAccess )

{
    DBFHandle		psDBF;
    unsigned char		*pabyBuf;
    int			nFields, nHeadLen, nRecLen, iField;

/* -------------------------------------------------------------------- */
/*      We only allow the access strings "rb" and "r+".                  */
/* -------------------------------------------------------------------- */
    if( strcmp(pszAccess,"r") != 0 && strcmp(pszAccess,"r+") != 0
	&& strcmp(pszAccess,"rb") != 0 && strcmp(pszAccess,"rb+") != 0
	&& strcmp(pszAccess,"r+b") != 0 )
	return( NULL );

    if( strcmp(pszAccess,"r") == 0 )
	pszAccess = "rb";

    if( strcmp(pszAccess,"r+") == 0 )
	pszAccess = "rb+";

/* Changed in 0.8-40 to use name as supplied */
    psDBF = (DBFHandle) calloc( 1, sizeof(DBFInfo) );
    psDBF->fp = fopen( pszFilename, pszAccess );

    if( psDBF->fp == NULL )
    {
	free( psDBF );
	return( NULL );
    }

    psDBF->bNoHeader = FALSE;
    psDBF->nCurrentRecord = -1;
    psDBF->bCurrentRecordModified = FALSE;

/* -------------------------------------------------------------------- */
/*  Read Table Header info                                              */
/* -------------------------------------------------------------------- */
    pabyBuf = (unsigned char *) malloc(500);
    if( fread( pabyBuf, 32, 1, psDBF->fp ) != 1 )
    {
	fclose( psDBF->fp );
	free( pabyBuf );
	free( psDBF );
	return NULL;
    }

    psDBF->nRecords =
     pabyBuf[4] + pabyBuf[5]*256 + pabyBuf[6]*256*256 + pabyBuf[7]*256*256*256;

    psDBF->nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256;
    psDBF->nRecordLength = nRecLen = pabyBuf[10] + pabyBuf[11]*256;

    psDBF->nFields = nFields = (nHeadLen - 32) / 32;

    psDBF->pszCurrentRecord = (char *) malloc(nRecLen);

/* -------------------------------------------------------------------- */
/*  Read in Field Definitions                                           */
/* -------------------------------------------------------------------- */

    pabyBuf = (unsigned char *) SfRealloc(pabyBuf,nHeadLen);
    psDBF->pszHeader = (char *) pabyBuf;

    fseek( psDBF->fp, 32, 0 );
    if( fread( pabyBuf, nHeadLen-32, 1, psDBF->fp ) != 1 )
    {
	fclose( psDBF->fp );
	free( pabyBuf );
	free( psDBF );
	return NULL;
    }

    psDBF->panFieldOffset = (int *) malloc(sizeof(int) * nFields);
    psDBF->panFieldSize = (int *) malloc(sizeof(int) * nFields);
    psDBF->panFieldDecimals = (int *) malloc(sizeof(int) * nFields);
    psDBF->pachFieldType = (char *) malloc(sizeof(char) * nFields);

    for( iField = 0; iField < nFields; iField++ )
    {
	unsigned char		*pabyFInfo;

	pabyFInfo = pabyBuf+iField*32;

	if( pabyFInfo[11] == 'N' || pabyFInfo[11] == 'F' )
	{
	    psDBF->panFieldSize[iField] = pabyFInfo[16];
	    psDBF->panFieldDecimals[iField] = pabyFInfo[17];
	}
	else
	{
	    psDBF->panFieldSize[iField] = pabyFInfo[16] + pabyFInfo[17]*256;
	    psDBF->panFieldDecimals[iField] = 0;
	}

	psDBF->pachFieldType[iField] = (char) pabyFInfo[11];
	if( iField == 0 )
	    psDBF->panFieldOffset[iField] = 1;
	else
	    psDBF->panFieldOffset[iField] =
	      psDBF->panFieldOffset[iField-1] + psDBF->panFieldSize[iField-1];
    }

    return( psDBF );
}
Beispiel #15
0
static char *msDBFReadAttribute(DBFHandle psDBF, int hEntity, int iField )

{
    int	       	nRecordOffset, i;
    const uchar *pabyRec;
    char	*pReturnField = NULL;

    /* -------------------------------------------------------------------- */
    /*	Is the request valid?                  				    */
    /* -------------------------------------------------------------------- */
    if( iField < 0 || iField >= psDBF->nFields ) 
    {
        msSetError(MS_DBFERR, "Invalid field index %d.", "msDBFGetItemIndex()",iField );
        return( NULL );
    }

    if( hEntity < 0 || hEntity >= psDBF->nRecords )
    {
        msSetError(MS_DBFERR, "Invalid record number %d.", "msDBFGetItemIndex()",hEntity );
        return( NULL );
    }

    /* -------------------------------------------------------------------- */
    /*	Have we read the record?					    */
    /* -------------------------------------------------------------------- */
    if( psDBF->nCurrentRecord != hEntity )
    {
#ifdef SHAPELIB_DISABLED
	flushRecord( psDBF );
#endif /* SHAPELIB_DISABLED */

	nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;

	zzip_seek( psDBF->zfp, nRecordOffset, 0 );
	zzip_fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->zfp );

	psDBF->nCurrentRecord = hEntity;
    }

    pabyRec = (const uchar *) psDBF->pszCurrentRecord;

    /* -------------------------------------------------------------------- */
    /*	Ensure our field buffer is large enough to hold this buffer.	    */
    /* -------------------------------------------------------------------- */
    if( psDBF->panFieldSize[iField]+1 > psDBF->nStringFieldLen )
    {
	psDBF->nStringFieldLen = psDBF->panFieldSize[iField]*2 + 10;
	psDBF->pszStringField = (char *) SfRealloc(psDBF->pszStringField,psDBF->nStringFieldLen);
    }

    /* -------------------------------------------------------------------- */
    /*	Extract the requested field.					    */
    /* -------------------------------------------------------------------- */
    strncpy( psDBF->pszStringField,(const char *) pabyRec+psDBF->panFieldOffset[iField], psDBF->panFieldSize[iField] );
    psDBF->pszStringField[psDBF->panFieldSize[iField]] = '\0';

    /*
    ** Trim trailing blanks (SDL Modification)
    */ 
    for(i=strlen(psDBF->pszStringField)-1;i>=0;i--) {
      if(psDBF->pszStringField[i] != ' ') { 
	psDBF->pszStringField[i+1] = '\0'; 
	break;
      }
    }

    if(i == -1) psDBF->pszStringField[0] = '\0'; /* whole string is blank (SDL fix)       */

    /*
    ** Trim/skip leading blanks (SDL/DM Modification - only on numeric types)
    */ 
    if( psDBF->pachFieldType[iField] == 'N' || psDBF->pachFieldType[iField] == 'F' || psDBF->pachFieldType[iField] == 'D' ) {
        for(i=0; psDBF->pszStringField[i] != '\0' ;i++) {
            if(psDBF->pszStringField[i] != ' ')
                break;	
        }
        pReturnField = psDBF->pszStringField+i;
    }
    else
        pReturnField = psDBF->pszStringField;

    return( pReturnField );
}
Beispiel #16
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;
}