OGRFeature *OGRGMLLayer::GetNextFeature() { GMLFeature *poGMLFeature = NULL; OGRGeometry *poGeom = NULL; if (bWriter) { CPLError(CE_Failure, CPLE_NotSupported, "Cannot read features when writing a GML file"); return NULL; } if( iNextGMLId == 0 ) ResetReading(); /* ==================================================================== */ /* Loop till we find and translate a feature meeting all our */ /* requirements. */ /* ==================================================================== */ while( TRUE ) { /* -------------------------------------------------------------------- */ /* Cleanup last feature, and get a new raw gml feature. */ /* -------------------------------------------------------------------- */ if( poGMLFeature != NULL ) delete poGMLFeature; if( poGeom != NULL ) { delete poGeom; poGeom = NULL; } poGMLFeature = poDS->GetReader()->NextFeature(); if( poGMLFeature == NULL ) return NULL; /* -------------------------------------------------------------------- */ /* Is it of the proper feature class? */ /* -------------------------------------------------------------------- */ // We count reading low level GML features as a feature read for // work checking purposes, though at least we didn't necessary // have to turn it into an OGRFeature. m_nFeaturesRead++; if( poGMLFeature->GetClass() != poFClass ) continue; /* -------------------------------------------------------------------- */ /* Extract the fid: */ /* -Assumes the fids are non-negative integers with an optional */ /* prefix */ /* -If a prefix differs from the prefix of the first feature from */ /* the poDS then the fids from the poDS are ignored and are */ /* assigned serially thereafter */ /* -------------------------------------------------------------------- */ int nFID = -1; const char * pszGML_FID = poGMLFeature->GetFID(); if( bInvalidFIDFound ) { nFID = iNextGMLId++; } else if( pszGML_FID == NULL ) { bInvalidFIDFound = TRUE; nFID = iNextGMLId++; } else if( iNextGMLId == 0 ) { int i = strlen( pszGML_FID )-1, j = 0; while( i >= 0 && pszGML_FID[i] >= '0' && pszGML_FID[i] <= '9' && j<8) i--, j++; /* i points the last character of the fid */ if( i >= 0 && j < 8 && pszFIDPrefix == NULL) { pszFIDPrefix = (char *) CPLMalloc(i+2); pszFIDPrefix[i+1] = '\0'; strncpy(pszFIDPrefix, pszGML_FID, i+1); } /* pszFIDPrefix now contains the prefix or NULL if no prefix is found */ if( j < 8 && sscanf(pszGML_FID+i+1, "%d", &nFID)==1) { if( iNextGMLId <= nFID ) iNextGMLId = nFID + 1; } else { bInvalidFIDFound = TRUE; nFID = iNextGMLId++; } } else if( iNextGMLId != 0 ) { const char* pszFIDPrefix_notnull = pszFIDPrefix; if (pszFIDPrefix_notnull == NULL) pszFIDPrefix_notnull = ""; int nLenPrefix = strlen(pszFIDPrefix_notnull); if( strncmp(pszGML_FID, pszFIDPrefix_notnull, nLenPrefix) == 0 && strlen(pszGML_FID+nLenPrefix) <= 9 && sscanf(pszGML_FID+nLenPrefix, "%d", &nFID) == 1 ) { /* fid with the prefix. Using its numerical part */ if( iNextGMLId < nFID ) iNextGMLId = nFID + 1; } else { /* fid without the aforementioned prefix or a valid numerical part */ bInvalidFIDFound = TRUE; nFID = iNextGMLId++; } } /* -------------------------------------------------------------------- */ /* Does it satisfy the spatial query, if there is one? */ /* -------------------------------------------------------------------- */ char** papszGeometryList = poGMLFeature->GetGeometryList(); if( papszGeometryList != NULL ) { const char* pszSRSName = poDS->GetGlobalSRSName(); poGeom = GML_BuildOGRGeometryFromList(papszGeometryList, TRUE, m_bInvertAxisOrderIfLatLong, pszSRSName); if (poGeom != NULL && poSRS != NULL) poGeom->assignSpatialReference(poSRS); // We assume the createFromGML() function would have already // reported the error. if( poGeom == NULL ) { delete poGMLFeature; return NULL; } if( m_poFilterGeom != NULL && !FilterGeometry( poGeom ) ) continue; } /* -------------------------------------------------------------------- */ /* Convert the whole feature into an OGRFeature. */ /* -------------------------------------------------------------------- */ int iField; int iDstField = 0; OGRFeature *poOGRFeature = new OGRFeature( GetLayerDefn() ); poOGRFeature->SetFID( nFID ); if (poDS->ExposeGMLId()) { if (pszGML_FID) poOGRFeature->SetField( iDstField, pszGML_FID ); iDstField ++; } for( iField = 0; iField < poFClass->GetPropertyCount(); iField++, iDstField ++ ) { const GMLProperty *psGMLProperty = poGMLFeature->GetProperty( iField ); if( psGMLProperty == NULL || psGMLProperty->nSubProperties == 0 ) continue; switch( poFClass->GetProperty(iField)->GetType() ) { case GMLPT_Real: { poOGRFeature->SetField( iDstField, CPLAtof(psGMLProperty->papszSubProperties[0]) ); } break; case GMLPT_IntegerList: { int nCount = psGMLProperty->nSubProperties; int *panIntList = (int *) CPLMalloc(sizeof(int) * nCount ); int i; for( i = 0; i < nCount; i++ ) panIntList[i] = atoi(psGMLProperty->papszSubProperties[i]); poOGRFeature->SetField( iDstField, nCount, panIntList ); CPLFree( panIntList ); } break; case GMLPT_RealList: { int nCount = psGMLProperty->nSubProperties; double *padfList = (double *)CPLMalloc(sizeof(double)*nCount); int i; for( i = 0; i < nCount; i++ ) padfList[i] = CPLAtof(psGMLProperty->papszSubProperties[i]); poOGRFeature->SetField( iDstField, nCount, padfList ); CPLFree( padfList ); } break; case GMLPT_StringList: { poOGRFeature->SetField( iDstField, psGMLProperty->papszSubProperties ); } break; default: poOGRFeature->SetField( iDstField, psGMLProperty->papszSubProperties[0] ); break; } } /* -------------------------------------------------------------------- */ /* Test against the attribute query. */ /* -------------------------------------------------------------------- */ if( m_poAttrQuery != NULL && !m_poAttrQuery->Evaluate( poOGRFeature ) ) { delete poOGRFeature; continue; } /* -------------------------------------------------------------------- */ /* Wow, we got our desired feature. Return it. */ /* -------------------------------------------------------------------- */ delete poGMLFeature; poOGRFeature->SetGeometryDirectly( poGeom ); return poOGRFeature; } return NULL; }
OGRFeature *OGRGMLLayer::GetNextFeature() { if (bWriter) { CPLError(CE_Failure, CPLE_NotSupported, "Cannot read features when writing a GML file"); return NULL; } if( poDS->GetLastReadLayer() != this ) { if( poDS->GetReadMode() != INTERLEAVED_LAYERS ) ResetReading(); poDS->SetLastReadLayer(this); } /* ==================================================================== */ /* Loop till we find and translate a feature meeting all our */ /* requirements. */ /* ==================================================================== */ while( true ) { GMLFeature *poGMLFeature = NULL; OGRGeometry *poGeom = NULL; poGMLFeature = poDS->PeekStoredGMLFeature(); if (poGMLFeature != NULL) poDS->SetStoredGMLFeature(NULL); else { poGMLFeature = poDS->GetReader()->NextFeature(); if( poGMLFeature == NULL ) return NULL; // We count reading low level GML features as a feature read for // work checking purposes, though at least we didn't necessary // have to turn it into an OGRFeature. m_nFeaturesRead++; } /* -------------------------------------------------------------------- */ /* Is it of the proper feature class? */ /* -------------------------------------------------------------------- */ if( poGMLFeature->GetClass() != poFClass ) { if( poDS->GetReadMode() == INTERLEAVED_LAYERS || (poDS->GetReadMode() == SEQUENTIAL_LAYERS && iNextGMLId != 0) ) { CPLAssert(poDS->PeekStoredGMLFeature() == NULL); poDS->SetStoredGMLFeature(poGMLFeature); return NULL; } else { delete poGMLFeature; continue; } } /* -------------------------------------------------------------------- */ /* Extract the fid: */ /* -Assumes the fids are non-negative integers with an optional */ /* prefix */ /* -If a prefix differs from the prefix of the first feature from */ /* the poDS then the fids from the poDS are ignored and are */ /* assigned serially thereafter */ /* -------------------------------------------------------------------- */ GIntBig nFID = -1; const char * pszGML_FID = poGMLFeature->GetFID(); if( bInvalidFIDFound ) { nFID = iNextGMLId++; } else if( pszGML_FID == NULL ) { bInvalidFIDFound = true; nFID = iNextGMLId++; } else if( iNextGMLId == 0 ) { int j = 0; int i = static_cast<int>(strlen( pszGML_FID ))-1; while( i >= 0 && pszGML_FID[i] >= '0' && pszGML_FID[i] <= '9' && j<20) i--, j++; /* i points the last character of the fid */ if( i >= 0 && j < 20 && pszFIDPrefix == NULL) { pszFIDPrefix = (char *) CPLMalloc(i+2); pszFIDPrefix[i+1] = '\0'; strncpy(pszFIDPrefix, pszGML_FID, i+1); } /* pszFIDPrefix now contains the prefix or NULL if no prefix is found */ if( j < 20 && sscanf(pszGML_FID+i+1, CPL_FRMT_GIB, &nFID)==1) { if( iNextGMLId <= nFID ) iNextGMLId = nFID + 1; } else { bInvalidFIDFound = true; nFID = iNextGMLId++; } } else if( iNextGMLId != 0 ) { const char* pszFIDPrefix_notnull = pszFIDPrefix; if (pszFIDPrefix_notnull == NULL) pszFIDPrefix_notnull = ""; int nLenPrefix = static_cast<int>(strlen(pszFIDPrefix_notnull)); if( strncmp(pszGML_FID, pszFIDPrefix_notnull, nLenPrefix) == 0 && strlen(pszGML_FID+nLenPrefix) < 20 && sscanf(pszGML_FID+nLenPrefix, CPL_FRMT_GIB, &nFID) == 1 ) { /* fid with the prefix. Using its numerical part */ if( iNextGMLId < nFID ) iNextGMLId = nFID + 1; } else { /* fid without the aforementioned prefix or a valid numerical part */ bInvalidFIDFound = true; nFID = iNextGMLId++; } } /* -------------------------------------------------------------------- */ /* Does it satisfy the spatial query, if there is one? */ /* -------------------------------------------------------------------- */ OGRGeometry** papoGeometries = NULL; const CPLXMLNode* const * papsGeometry = poGMLFeature->GetGeometryList(); if( poFeatureDefn->GetGeomFieldCount() > 1 ) { papoGeometries = (OGRGeometry**) CPLCalloc( poFeatureDefn->GetGeomFieldCount(), sizeof(OGRGeometry*) ); const char* pszSRSName = poDS->GetGlobalSRSName(); for( int i=0; i < poFeatureDefn->GetGeomFieldCount(); i++ ) { const CPLXMLNode* psGeom = poGMLFeature->GetGeometryRef(i); if( psGeom != NULL ) { const CPLXMLNode* myGeometryList[2]; myGeometryList[0] = psGeom; myGeometryList[1] = NULL; poGeom = GML_BuildOGRGeometryFromList(myGeometryList, true, poDS->GetInvertAxisOrderIfLatLong(), pszSRSName, poDS->GetConsiderEPSGAsURN(), poDS->GetSecondaryGeometryOption(), hCacheSRS, bFaceHoleNegative ); /* Do geometry type changes if needed to match layer geometry type */ if (poGeom != NULL) { papoGeometries[i] = OGRGeometryFactory::forceTo(poGeom, poFeatureDefn->GetGeomFieldDefn(i)->GetType()); poGeom = NULL; } else // We assume the createFromGML() function would have already // reported the error. { for( i=0; i < poFeatureDefn->GetGeomFieldCount(); i++) { delete papoGeometries[i]; } CPLFree(papoGeometries); delete poGMLFeature; return NULL; } } } if( m_poFilterGeom != NULL && m_iGeomFieldFilter >= 0 && m_iGeomFieldFilter < poFeatureDefn->GetGeomFieldCount() && papoGeometries[m_iGeomFieldFilter] && !FilterGeometry( papoGeometries[m_iGeomFieldFilter] ) ) { for( int i=0; i < poFeatureDefn->GetGeomFieldCount(); i++ ) { delete papoGeometries[i]; } CPLFree(papoGeometries); delete poGMLFeature; continue; } } else if (papsGeometry[0] != NULL) { const char* pszSRSName = poDS->GetGlobalSRSName(); poGeom = GML_BuildOGRGeometryFromList(papsGeometry, true, poDS->GetInvertAxisOrderIfLatLong(), pszSRSName, poDS->GetConsiderEPSGAsURN(), poDS->GetSecondaryGeometryOption(), hCacheSRS, bFaceHoleNegative ); /* Do geometry type changes if needed to match layer geometry type */ if (poGeom != NULL) { poGeom = OGRGeometryFactory::forceTo(poGeom, GetGeomType()); } else // We assume the createFromGML() function would have already // reported the error. { delete poGMLFeature; return NULL; } if( m_poFilterGeom != NULL && !FilterGeometry( poGeom ) ) { delete poGMLFeature; delete poGeom; continue; } } /* -------------------------------------------------------------------- */ /* Convert the whole feature into an OGRFeature. */ /* -------------------------------------------------------------------- */ int iField; int iDstField = 0; OGRFeature *poOGRFeature = new OGRFeature( poFeatureDefn ); poOGRFeature->SetFID( nFID ); if (poDS->ExposeId()) { if (pszGML_FID) poOGRFeature->SetField( iDstField, pszGML_FID ); iDstField ++; } int nPropertyCount = poFClass->GetPropertyCount(); for( iField = 0; iField < nPropertyCount; iField++, iDstField ++ ) { const GMLProperty *psGMLProperty = poGMLFeature->GetProperty( iField ); if( psGMLProperty == NULL || psGMLProperty->nSubProperties == 0 ) continue; switch( poFClass->GetProperty(iField)->GetType() ) { case GMLPT_Real: { poOGRFeature->SetField( iDstField, CPLAtof(psGMLProperty->papszSubProperties[0]) ); } break; case GMLPT_IntegerList: { int nCount = psGMLProperty->nSubProperties; int *panIntList = (int *) CPLMalloc(sizeof(int) * nCount ); for( int i = 0; i < nCount; i++ ) panIntList[i] = atoi(psGMLProperty->papszSubProperties[i]); poOGRFeature->SetField( iDstField, nCount, panIntList ); CPLFree( panIntList ); } break; case GMLPT_Integer64List: { int nCount = psGMLProperty->nSubProperties; GIntBig *panIntList = (GIntBig *) CPLMalloc(sizeof(GIntBig) * nCount ); for( int i = 0; i < nCount; i++ ) panIntList[i] = CPLAtoGIntBig(psGMLProperty->papszSubProperties[i]); poOGRFeature->SetField( iDstField, nCount, panIntList ); CPLFree( panIntList ); } break; case GMLPT_RealList: { int nCount = psGMLProperty->nSubProperties; double *padfList = (double *)CPLMalloc(sizeof(double)*nCount); for( int i = 0; i < nCount; i++ ) padfList[i] = CPLAtof(psGMLProperty->papszSubProperties[i]); poOGRFeature->SetField( iDstField, nCount, padfList ); CPLFree( padfList ); } break; case GMLPT_StringList: case GMLPT_FeaturePropertyList: { poOGRFeature->SetField( iDstField, psGMLProperty->papszSubProperties ); } break; case GMLPT_Boolean: { if( strcmp(psGMLProperty->papszSubProperties[0], "true") == 0 || strcmp(psGMLProperty->papszSubProperties[0], "1") == 0 ) { poOGRFeature->SetField( iDstField, 1); } else if( strcmp(psGMLProperty->papszSubProperties[0], "false") == 0 || strcmp(psGMLProperty->papszSubProperties[0], "0") == 0 ) { poOGRFeature->SetField( iDstField, 0); } else poOGRFeature->SetField( iDstField, psGMLProperty->papszSubProperties[0] ); break; } case GMLPT_BooleanList: { int nCount = psGMLProperty->nSubProperties; int *panIntList = (int *) CPLMalloc(sizeof(int) * nCount ); for( int i = 0; i < nCount; i++ ) { panIntList[i] = ( strcmp(psGMLProperty->papszSubProperties[i], "true") == 0 || strcmp(psGMLProperty->papszSubProperties[i], "1") == 0 ); } poOGRFeature->SetField( iDstField, nCount, panIntList ); CPLFree( panIntList ); break; } default: poOGRFeature->SetField( iDstField, psGMLProperty->papszSubProperties[0] ); break; } } delete poGMLFeature; poGMLFeature = NULL; /* Assign the geometry before the attribute filter because */ /* the attribute filter may use a special field like OGR_GEOMETRY */ if( papoGeometries != NULL ) { for( int i=0; i < poFeatureDefn->GetGeomFieldCount(); i++ ) { poOGRFeature->SetGeomFieldDirectly( i, papoGeometries[i] ); } CPLFree(papoGeometries); papoGeometries = NULL; } else poOGRFeature->SetGeometryDirectly( poGeom ); /* Assign SRS */ for( int i=0; i < poFeatureDefn->GetGeomFieldCount(); i++ ) { poGeom = poOGRFeature->GetGeomFieldRef(i); if( poGeom != NULL ) { OGRSpatialReference* poSRS = poFeatureDefn->GetGeomFieldDefn(i)->GetSpatialRef(); if (poSRS != NULL) poGeom->assignSpatialReference(poSRS); } } /* -------------------------------------------------------------------- */ /* Test against the attribute query. */ /* -------------------------------------------------------------------- */ if( m_poAttrQuery != NULL && !m_poAttrQuery->Evaluate( poOGRFeature ) ) { delete poOGRFeature; continue; } /* -------------------------------------------------------------------- */ /* Wow, we got our desired feature. Return it. */ /* -------------------------------------------------------------------- */ return poOGRFeature; } return NULL; }