Exemple #1
0
OGRGeometry* GML_BuildOGRGeometryFromList(const CPLXMLNode* const * papsGeometry,
                                          int bTryToMakeMultipolygons,
                                          int bInvertAxisOrderIfLatLong,
                                          const char* pszDefaultSRSName,
                                          int bConsiderEPSGAsURN,
                                          int bGetSecondaryGeometryOption,
                                          void* hCacheSRS,
                                          int bFaceHoleNegative)
{
    OGRGeometry* poGeom = NULL;
    int i;
    OGRGeometryCollection* poCollection = NULL;
    for(i=0;papsGeometry[i] != NULL;i++)
    {
        OGRGeometry* poSubGeom = GML2OGRGeometry_XMLNode( papsGeometry[i],
                                                          bGetSecondaryGeometryOption,
                                                          0, 0, FALSE, TRUE,
                                                          bFaceHoleNegative );
        if (poSubGeom)
        {
            if (poGeom == NULL)
                poGeom = poSubGeom;
            else
            {
                if (poCollection == NULL)
                {
                    if (bTryToMakeMultipolygons &&
                        wkbFlatten(poGeom->getGeometryType()) == wkbPolygon &&
                        wkbFlatten(poSubGeom->getGeometryType()) == wkbPolygon)
                    {
                        OGRGeometryCollection* poGeomColl = new OGRMultiPolygon();
                        poGeomColl->addGeometryDirectly(poGeom);
                        poGeomColl->addGeometryDirectly(poSubGeom);
                        poGeom = poGeomColl;
                    }
                    else if (bTryToMakeMultipolygons &&
                                wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon &&
                                wkbFlatten(poSubGeom->getGeometryType()) == wkbPolygon)
                    {
                        OGRGeometryCollection* poGeomColl = (OGRGeometryCollection* )poGeom;
                        poGeomColl->addGeometryDirectly(poSubGeom);
                    }
                    else if (bTryToMakeMultipolygons &&
                                wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon &&
                                wkbFlatten(poSubGeom->getGeometryType()) == wkbMultiPolygon)
                    {
                        OGRGeometryCollection* poGeomColl = (OGRGeometryCollection* )poGeom;
                        OGRGeometryCollection* poGeomColl2 = (OGRGeometryCollection* )poSubGeom;
                        int nCount = poGeomColl2->getNumGeometries();
                        int i;
                        for(i=0;i<nCount;i++)
                        {
                            poGeomColl->addGeometry(poGeomColl2->getGeometryRef(i));
                        }
                        delete poSubGeom;
                    }
                    else if (bTryToMakeMultipolygons &&
                                wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon)
                    {
                        delete poGeom;
                        delete poSubGeom;
                        return GML_BuildOGRGeometryFromList(papsGeometry, FALSE,
                                                            bInvertAxisOrderIfLatLong,
                                                            pszDefaultSRSName,
                                                            bConsiderEPSGAsURN,
                                                            bGetSecondaryGeometryOption,
                                                            hCacheSRS);
                    }
                    else
                    {
                        poCollection = new OGRGeometryCollection();
                        poCollection->addGeometryDirectly(poGeom);
                        poGeom = poCollection;
                    }
                }
                if (poCollection != NULL)
                {
                    poCollection->addGeometryDirectly(poSubGeom);
                }
            }
        }
    }
    
    if( poGeom == NULL )
        return NULL;

    std::string osWork;
    const char* pszSRSName = GML_ExtractSrsNameFromGeometry(papsGeometry, osWork,
                                                            bConsiderEPSGAsURN);
    const char* pszNameLookup = pszSRSName;
    if( pszNameLookup == NULL )
        pszNameLookup = pszDefaultSRSName;

    if (pszNameLookup != NULL)
    {
        SRSCache* poSRSCache = (SRSCache*)hCacheSRS;
        SRSDesc& oSRSDesc = poSRSCache->Get(pszNameLookup);
        poGeom->assignSpatialReference(oSRSDesc.poSRS);
        if (oSRSDesc.bAxisInvert && bInvertAxisOrderIfLatLong)
            poGeom->swapXY();
    }

    return poGeom;
}
Exemple #2
0
OGRGeometry* GML_BuildOGRGeometryFromList(const CPLXMLNode* const * papsGeometry,
                                          int bTryToMakeMultipolygons,
                                          int bInvertAxisOrderIfLatLong,
                                          const char* pszDefaultSRSName,
                                          int bConsiderEPSGAsURN,
                                          int bGetSecondaryGeometryOption,
                                          void* hCacheSRS)
{
    OGRGeometry* poGeom = NULL;
    int i;
    OGRGeometryCollection* poCollection = NULL;
    for(i=0;papsGeometry[i] != NULL;i++)
    {
        OGRGeometry* poSubGeom = GML2OGRGeometry_XMLNode( papsGeometry[i],
                                                          bGetSecondaryGeometryOption );
        if (poSubGeom)
        {
            if (poGeom == NULL)
                poGeom = poSubGeom;
            else
            {
                if (poCollection == NULL)
                {
                    if (bTryToMakeMultipolygons &&
                        wkbFlatten(poGeom->getGeometryType()) == wkbPolygon &&
                        wkbFlatten(poSubGeom->getGeometryType()) == wkbPolygon)
                    {
                        OGRGeometryCollection* poGeomColl = new OGRMultiPolygon();
                        poGeomColl->addGeometryDirectly(poGeom);
                        poGeomColl->addGeometryDirectly(poSubGeom);
                        poGeom = poGeomColl;
                    }
                    else if (bTryToMakeMultipolygons &&
                                wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon &&
                                wkbFlatten(poSubGeom->getGeometryType()) == wkbPolygon)
                    {
                        OGRGeometryCollection* poGeomColl = (OGRGeometryCollection* )poGeom;
                        poGeomColl->addGeometryDirectly(poSubGeom);
                    }
                    else if (bTryToMakeMultipolygons &&
                                wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon &&
                                wkbFlatten(poSubGeom->getGeometryType()) == wkbMultiPolygon)
                    {
                        OGRGeometryCollection* poGeomColl = (OGRGeometryCollection* )poGeom;
                        OGRGeometryCollection* poGeomColl2 = (OGRGeometryCollection* )poSubGeom;
                        int nCount = poGeomColl2->getNumGeometries();
                        int i;
                        for(i=0;i<nCount;i++)
                        {
                            poGeomColl->addGeometry(poGeomColl2->getGeometryRef(i));
                        }
                        delete poSubGeom;
                    }
                    else if (bTryToMakeMultipolygons &&
                                wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon)
                    {
                        delete poGeom;
                        delete poSubGeom;
                        return GML_BuildOGRGeometryFromList(papsGeometry, FALSE,
                                                            bInvertAxisOrderIfLatLong,
                                                            pszDefaultSRSName,
                                                            bConsiderEPSGAsURN,
                                                            bGetSecondaryGeometryOption,
                                                            hCacheSRS);
                    }
                    else
                    {
                        poCollection = new OGRGeometryCollection();
                        poCollection->addGeometryDirectly(poGeom);
                        poGeom = poCollection;
                    }
                }
                if (poCollection != NULL)
                {
                    poCollection->addGeometryDirectly(poSubGeom);
                }
            }
        }
    }

    if ( poGeom != NULL && bInvertAxisOrderIfLatLong )
    {
        std::string osWork;
        const char* pszSRSName = GML_ExtractSrsNameFromGeometry(papsGeometry, osWork,
                                                          bConsiderEPSGAsURN);
        const char* pszNameLookup = pszSRSName ? pszSRSName : pszDefaultSRSName;
        if (pszNameLookup != NULL)
        {
            SRSCache* poSRSCache = (SRSCache*)hCacheSRS;
            int bSwap;
            if (strcmp(poSRSCache->osLastSRSName.c_str(), pszNameLookup) == 0)
            {
                bSwap = poSRSCache->bAxisInvertLastSRSName;
            }
            else
            {
                bSwap = GML_IsSRSLatLongOrder(pszNameLookup);
                poSRSCache->osLastSRSName = pszNameLookup;
                poSRSCache->bAxisInvertLastSRSName= bSwap;
            }
            if (bSwap)
                poGeom->swapXY();
        }
    }

    return poGeom;
}
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;
}
Exemple #4
0
OGRGeometry* GML_BuildOGRGeometryFromList(char** papszGeometryList,
                                          int bTryToMakeMultipolygons,
                                          int bInvertAxisOrderIfLatLong,
                                          const char* pszDefaultSRSName)
{
    OGRGeometry* poGeom = NULL;
    if( papszGeometryList != NULL )
    {
        char** papszIter = papszGeometryList;
        OGRGeometryCollection* poCollection = NULL;
        while(*papszIter)
        {
            OGRGeometry* poSubGeom = OGRGeometryFactory::createFromGML( *papszIter );
            if (poSubGeom)
            {
                if (poGeom == NULL)
                    poGeom = poSubGeom;
                else
                {
                    if (poCollection == NULL)
                    {
                        if (bTryToMakeMultipolygons &&
                            wkbFlatten(poGeom->getGeometryType()) == wkbPolygon &&
                            wkbFlatten(poSubGeom->getGeometryType()) == wkbPolygon)
                        {
                            OGRGeometryCollection* poGeomColl = new OGRMultiPolygon();
                            poGeomColl->addGeometryDirectly(poGeom);
                            poGeomColl->addGeometryDirectly(poSubGeom);
                            poGeom = poGeomColl;
                        }
                        else if (bTryToMakeMultipolygons &&
                                  wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon &&
                                 wkbFlatten(poSubGeom->getGeometryType()) == wkbPolygon)
                        {
                            OGRGeometryCollection* poGeomColl = (OGRGeometryCollection* )poGeom;
                            poGeomColl->addGeometryDirectly(poSubGeom);
                        }
                        else if (bTryToMakeMultipolygons &&
                                 wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon &&
                                 wkbFlatten(poSubGeom->getGeometryType()) == wkbMultiPolygon)
                        {
                            OGRGeometryCollection* poGeomColl = (OGRGeometryCollection* )poGeom;
                            OGRGeometryCollection* poGeomColl2 = (OGRGeometryCollection* )poSubGeom;
                            int nCount = poGeomColl2->getNumGeometries();
                            int i;
                            for(i=0;i<nCount;i++)
                            {
                                poGeomColl->addGeometry(poGeomColl2->getGeometryRef(i));
                            }
                            delete poSubGeom;
                        }
                        else if (bTryToMakeMultipolygons &&
                                 wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon)
                        {
                            delete poGeom;
                            delete poSubGeom;
                            return GML_BuildOGRGeometryFromList(papszGeometryList, FALSE,
                                                                bInvertAxisOrderIfLatLong,
                                                                pszDefaultSRSName);
                        }
                        else
                        {
                            poCollection = new OGRGeometryCollection();
                            poCollection->addGeometryDirectly(poGeom);
                            poGeom = poCollection;
                        }
                    }
                    if (poCollection != NULL)
                    {
                        poCollection->addGeometryDirectly(poSubGeom);
                    }
                }
            }
            papszIter ++;
        }
    }

    if (bInvertAxisOrderIfLatLong)
    {
        char* pszSRSName = GML_ExtractSrsNameFromGeometry(papszGeometryList);
        if (GML_IsSRSLatLongOrder(pszSRSName ? pszSRSName : pszDefaultSRSName))
            poGeom->swapXY();
        CPLFree(pszSRSName);
    }
    
    return poGeom;
}
Exemple #5
0
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;
}