?? ogrshapelayer.cpp
字號:
/****************************************************************************** * $Id: ogrshapelayer.cpp 10682 2007-01-23 21:53:38Z warmerdam $ * * Project: OpenGIS Simple Features Reference Implementation * Purpose: Implements OGRShapeLayer class. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 1999, Les Technologies SoftMap Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/#include "ogrshape.h"#include "cpl_conv.h"#include "cpl_string.h"#if defined(_WIN32_WCE)# include <wce_errno.h>#endifCPL_CVSID("$Id: ogrshapelayer.cpp 10682 2007-01-23 21:53:38Z warmerdam $");/************************************************************************//* OGRShapeLayer() *//************************************************************************/OGRShapeLayer::OGRShapeLayer( const char * pszName, SHPHandle hSHPIn, DBFHandle hDBFIn, OGRSpatialReference *poSRSIn, int bUpdate, OGRwkbGeometryType eReqType ){ poSRS = poSRSIn; pszFullName = CPLStrdup(pszName); hSHP = hSHPIn; hDBF = hDBFIn; bUpdateAccess = bUpdate; iNextShapeId = 0; panMatchingFIDs = NULL; bCheckedForQIX = FALSE; fpQIX = NULL; bHeaderDirty = FALSE; if( hSHP != NULL ) nTotalShapeCount = hSHP->nRecords; else nTotalShapeCount = hDBF->nRecords; poFeatureDefn = SHPReadOGRFeatureDefn( CPLGetBasename(pszName), hSHP, hDBF ); eRequestedGeomType = eReqType;}/************************************************************************//* ~OGRShapeLayer() *//************************************************************************/OGRShapeLayer::~OGRShapeLayer(){ if( m_nFeaturesRead > 0 && poFeatureDefn != NULL ) { CPLDebug( "Shape", "%d features read on layer '%s'.", (int) m_nFeaturesRead, poFeatureDefn->GetName() ); } CPLFree( panMatchingFIDs ); panMatchingFIDs = NULL; CPLFree( pszFullName ); poFeatureDefn->Release(); poSRS->Release(); if( hDBF != NULL ) DBFClose( hDBF ); if( hSHP != NULL ) SHPClose( hSHP ); if( fpQIX != NULL ) VSIFClose( fpQIX );}/************************************************************************//* CheckForQIX() *//************************************************************************/int OGRShapeLayer::CheckForQIX(){ const char *pszQIXFilename; if( bCheckedForQIX ) return fpQIX != NULL; pszQIXFilename = CPLResetExtension( pszFullName, "qix" ); fpQIX = VSIFOpen( pszQIXFilename, "rb" ); bCheckedForQIX = TRUE; return fpQIX != NULL;}/************************************************************************//* ScanIndices() *//* *//* Utilize optional spatial and attribute indices if they are *//* available. *//************************************************************************/int OGRShapeLayer::ScanIndices(){ iMatchingFID = 0;/* -------------------------------------------------------------------- *//* Utilize attribute index if appropriate. *//* -------------------------------------------------------------------- */ if( m_poAttrQuery != NULL ) { CPLAssert( panMatchingFIDs == NULL ); panMatchingFIDs = m_poAttrQuery->EvaluateAgainstIndices( this, NULL ); }/* -------------------------------------------------------------------- *//* Check for spatial index if we have a spatial query. *//* -------------------------------------------------------------------- */ if( m_poFilterGeom != NULL && !bCheckedForQIX ) CheckForQIX();/* -------------------------------------------------------------------- *//* Utilize spatial index if appropriate. *//* -------------------------------------------------------------------- */ if( m_poFilterGeom && fpQIX ) { int nSpatialFIDCount, *panSpatialFIDs; double adfBoundsMin[4], adfBoundsMax[4]; OGREnvelope oEnvelope; m_poFilterGeom->getEnvelope( &oEnvelope ); adfBoundsMin[0] = oEnvelope.MinX; adfBoundsMin[1] = oEnvelope.MinY; adfBoundsMin[2] = 0.0; adfBoundsMin[3] = 0.0; adfBoundsMax[0] = oEnvelope.MaxX; adfBoundsMax[1] = oEnvelope.MaxY; adfBoundsMax[2] = 0.0; adfBoundsMax[3] = 0.0; panSpatialFIDs = SHPSearchDiskTree( fpQIX, adfBoundsMin, adfBoundsMax, &nSpatialFIDCount ); CPLDebug( "SHAPE", "Used spatial index, got %d matches.", nSpatialFIDCount ); // Use resulting list as matching FID list (but reallocate and // terminate with OGRNullFID). if( panMatchingFIDs == NULL ) { int i; panMatchingFIDs = (long *) CPLMalloc(sizeof(long) * (nSpatialFIDCount+1) ); for( i = 0; i < nSpatialFIDCount; i++ ) panMatchingFIDs[i] = (long) panSpatialFIDs[i]; panMatchingFIDs[nSpatialFIDCount] = OGRNullFID; free( panSpatialFIDs ); } // Cull attribute index matches based on those in the spatial index // result set. We assume that the attribute results are in sorted // order. else { int iRead, iWrite=0, iSpatial=0; for( iRead = 0; panMatchingFIDs[iRead] != OGRNullFID; iRead++ ) { while( iSpatial < nSpatialFIDCount && panSpatialFIDs[iSpatial] < panMatchingFIDs[iRead] ) iSpatial++; if( iSpatial == nSpatialFIDCount ) continue; if( panSpatialFIDs[iSpatial] == panMatchingFIDs[iRead] ) panMatchingFIDs[iWrite++] = panMatchingFIDs[iRead]; } panMatchingFIDs[iWrite] = OGRNullFID; } } return TRUE;}/************************************************************************//* ResetReading() *//************************************************************************/void OGRShapeLayer::ResetReading(){/* -------------------------------------------------------------------- *//* Clear previous index search result, if any. *//* -------------------------------------------------------------------- */ CPLFree( panMatchingFIDs ); panMatchingFIDs = NULL; iMatchingFID = 0; iNextShapeId = 0; if( bHeaderDirty ) SyncToDisk();}/************************************************************************//* SetNextByIndex() *//* *//* If we already have an FID list, we can easily resposition *//* ourselves in it. *//************************************************************************/OGRErr OGRShapeLayer::SetNextByIndex( long nIndex ){ // Eventually we should try to use panMatchingFIDs list // if available and appropriate. if( m_poFilterGeom != NULL || m_poAttrQuery != NULL ) return OGRLayer::SetNextByIndex( nIndex ); iNextShapeId = nIndex; return OGRERR_NONE;}/************************************************************************//* GetNextFeature() *//************************************************************************/OGRFeature *OGRShapeLayer::GetNextFeature(){ OGRFeature *poFeature = NULL;/* -------------------------------------------------------------------- *//* Collect a matching list if we have attribute or spatial *//* indices. Only do this on the first request for a given pass *//* of course. *//* -------------------------------------------------------------------- */ if( (m_poAttrQuery != NULL || m_poFilterGeom != NULL) && iNextShapeId == 0 && panMatchingFIDs == NULL ) { ScanIndices(); } /* -------------------------------------------------------------------- *//* Loop till we find a feature matching our criteria. *//* -------------------------------------------------------------------- */ while( TRUE ) { if( panMatchingFIDs != NULL ) { if( panMatchingFIDs[iMatchingFID] == OGRNullFID ) { return NULL; } poFeature = SHPReadOGRFeature( hSHP, hDBF, poFeatureDefn, panMatchingFIDs[iMatchingFID++] ); } else { if( iNextShapeId >= nTotalShapeCount ) { return NULL; } if( hDBF && DBFIsRecordDeleted( hDBF, iNextShapeId ) ) poFeature = NULL; else poFeature = SHPReadOGRFeature( hSHP, hDBF, poFeatureDefn, iNextShapeId ); iNextShapeId++; } if( poFeature != NULL ) { if( poFeature->GetGeometryRef() != NULL ) { poFeature->GetGeometryRef()->assignSpatialReference( poSRS ); } m_nFeaturesRead++; if( (m_poFilterGeom == NULL || FilterGeometry( poFeature->GetGeometryRef() ) ) && (m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeature )) ) { return poFeature; } delete poFeature; } } /* * NEVER SHOULD GET HERE */ CPLAssert(!"OGRShapeLayer::GetNextFeature(): Execution never should get here!");}/************************************************************************//* GetFeature() *//************************************************************************/OGRFeature *OGRShapeLayer::GetFeature( long nFeatureId ){ OGRFeature *poFeature = NULL; poFeature = SHPReadOGRFeature( hSHP, hDBF, poFeatureDefn, nFeatureId ); if( poFeature != NULL ) { if( poFeature->GetGeometryRef() != NULL ) poFeature->GetGeometryRef()->assignSpatialReference( poSRS ); m_nFeaturesRead++; return poFeature; }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -