LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/nas - ogrnaslayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 78 152 51.3 %
Date: 2024-11-21 22:18:42 Functions: 6 8 75.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OGR
       4             :  * Purpose:  Implements OGRNASLayer class.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com>
       9             :  * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_conv.h"
      15             : #include "cpl_port.h"
      16             : #include "cpl_string.h"
      17             : #include "ogr_nas.h"
      18             : 
      19             : /************************************************************************/
      20             : /*                           OGRNASLayer()                              */
      21             : /************************************************************************/
      22             : 
      23           5 : OGRNASLayer::OGRNASLayer(const char *pszName, OGRNASDataSource *poDSIn)
      24             :     : poFeatureDefn(new OGRFeatureDefn(
      25           5 :           pszName + (STARTS_WITH_CI(pszName, "ogr:") ? 4 : 0))),
      26             :       iNextNASId(0), poDS(poDSIn),
      27             :       // Readers should get the corresponding GMLFeatureClass and cache it.
      28          10 :       poFClass(poDS->GetReader()->GetClass(pszName))
      29             : {
      30           5 :     SetDescription(poFeatureDefn->GetName());
      31           5 :     poFeatureDefn->Reference();
      32           5 :     poFeatureDefn->SetGeomType(wkbNone);
      33           5 : }
      34             : 
      35             : /************************************************************************/
      36             : /*                           ~OGRNASLayer()                           */
      37             : /************************************************************************/
      38             : 
      39          10 : OGRNASLayer::~OGRNASLayer()
      40             : 
      41             : {
      42           5 :     if (poFeatureDefn)
      43           5 :         poFeatureDefn->Release();
      44          10 : }
      45             : 
      46             : /************************************************************************/
      47             : /*                            ResetReading()                            */
      48             : /************************************************************************/
      49             : 
      50           6 : void OGRNASLayer::ResetReading()
      51             : 
      52             : {
      53           6 :     iNextNASId = 0;
      54           6 :     poDS->GetReader()->ResetReading();
      55           6 :     if (poFClass)
      56           6 :         poDS->GetReader()->SetFilteredClassName(poFClass->GetElementName());
      57           6 : }
      58             : 
      59             : /************************************************************************/
      60             : /*                           GetNextFeature()                           */
      61             : /************************************************************************/
      62             : 
      63           3 : OGRFeature *OGRNASLayer::GetNextFeature()
      64             : 
      65             : {
      66           3 :     GMLFeature *poNASFeature = nullptr;
      67             : 
      68           3 :     if (iNextNASId == 0)
      69           3 :         ResetReading();
      70             : 
      71             :     /* ==================================================================== */
      72             :     /*      Loop till we find and translate a feature meeting all our       */
      73             :     /*      requirements.                                                   */
      74             :     /* ==================================================================== */
      75             :     while (true)
      76             :     {
      77             :         /* --------------------------------------------------------------------
      78             :          */
      79             :         /*      Cleanup last feature, and get a new raw nas feature. */
      80             :         /* --------------------------------------------------------------------
      81             :          */
      82           3 :         delete poNASFeature;
      83           3 :         poNASFeature = poDS->GetReader()->NextFeature();
      84           3 :         if (poNASFeature == nullptr)
      85           3 :             return nullptr;
      86             : 
      87             :         /* --------------------------------------------------------------------
      88             :          */
      89             :         /*      Is it of the proper feature class? */
      90             :         /* --------------------------------------------------------------------
      91             :          */
      92             : 
      93             :         // We count reading low level NAS features as a feature read for
      94             :         // work checking purposes, though at least we didn't necessary
      95             :         // have to turn it into an OGRFeature.
      96           3 :         m_nFeaturesRead++;
      97             : 
      98           3 :         if (poNASFeature->GetClass() != poFClass)
      99           0 :             continue;
     100             : 
     101           3 :         iNextNASId++;
     102             : 
     103             :         /* --------------------------------------------------------------------
     104             :          */
     105             :         /*      Does it satisfy the spatial query, if there is one? */
     106             :         /* --------------------------------------------------------------------
     107             :          */
     108           3 :         const CPLXMLNode *const *papsGeometry = poNASFeature->GetGeometryList();
     109             : 
     110           3 :         std::vector<OGRGeometry *> poGeom(poNASFeature->GetGeometryCount());
     111             : 
     112           3 :         bool bErrored = false, bFiltered = false;
     113           3 :         CPLString osLastErrorMsg;
     114           4 :         for (int iGeom = 0; iGeom < poNASFeature->GetGeometryCount(); ++iGeom)
     115             :         {
     116           1 :             if (papsGeometry[iGeom] == nullptr)
     117             :             {
     118           0 :                 poGeom[iGeom] = nullptr;
     119             :             }
     120             :             else
     121             :             {
     122           1 :                 CPLPushErrorHandler(CPLQuietErrorHandler);
     123             : 
     124           2 :                 poGeom[iGeom] =
     125           1 :                     (OGRGeometry *)OGR_G_CreateFromGMLTree(papsGeometry[iGeom]);
     126           1 :                 CPLPopErrorHandler();
     127           1 :                 if (poGeom[iGeom] == nullptr)
     128           0 :                     osLastErrorMsg = CPLGetLastErrorMsg();
     129           1 :                 poGeom[iGeom] = NASReader::ConvertGeometry(poGeom[iGeom]);
     130           2 :                 poGeom[iGeom] =
     131           1 :                     OGRGeometryFactory::forceTo(poGeom[iGeom], GetGeomType());
     132             :                 // poGeom->dumpReadable( 0, "NAS: " );
     133             : 
     134           1 :                 if (poGeom[iGeom] == nullptr)
     135           0 :                     bErrored = true;
     136             :             }
     137             : 
     138           1 :             bFiltered =
     139           1 :                 m_poFilterGeom != nullptr && !FilterGeometry(poGeom[iGeom]);
     140           1 :             if (bErrored || bFiltered)
     141             :             {
     142           0 :                 while (iGeom > 0)
     143           0 :                     delete poGeom[--iGeom];
     144           0 :                 poGeom.clear();
     145             : 
     146           0 :                 break;
     147             :             }
     148             :         }
     149             : 
     150           3 :         if (bErrored)
     151             :         {
     152             : 
     153           0 :             CPLString osGMLId;
     154           0 :             if (poFClass->GetPropertyIndex("gml_id") == 0)
     155             :             {
     156           0 :                 const GMLProperty *psGMLProperty = poNASFeature->GetProperty(0);
     157           0 :                 if (psGMLProperty && psGMLProperty->nSubProperties == 1)
     158             :                 {
     159             :                     osGMLId.Printf("(gml_id=%s) ",
     160           0 :                                    psGMLProperty->papszSubProperties[0]);
     161             :                 }
     162             :             }
     163             : 
     164           0 :             delete poNASFeature;
     165           0 :             poNASFeature = nullptr;
     166             : 
     167           0 :             const bool bGoOn = CPLTestBool(
     168             :                 CPLGetConfigOption("NAS_SKIP_CORRUPTED_FEATURES", "NO"));
     169           0 :             CPLError(bGoOn ? CE_Warning : CE_Failure, CPLE_AppDefined,
     170             :                      "Geometry of feature %d %scannot be parsed: %s%s",
     171             :                      iNextNASId, osGMLId.c_str(), osLastErrorMsg.c_str(),
     172             :                      bGoOn ? ". Skipping to next feature."
     173             :                            : ". You may set the NAS_SKIP_CORRUPTED_FEATURES "
     174             :                              "configuration option to YES to skip to the next "
     175             :                              "feature");
     176           0 :             if (bGoOn)
     177           0 :                 continue;
     178             : 
     179           0 :             return nullptr;
     180             :         }
     181             : 
     182           3 :         if (bFiltered)
     183           0 :             continue;
     184             : 
     185             :         /* --------------------------------------------------------------------
     186             :          */
     187             :         /*      Convert the whole feature into an OGRFeature. */
     188             :         /* --------------------------------------------------------------------
     189             :          */
     190           3 :         OGRFeature *poOGRFeature = new OGRFeature(GetLayerDefn());
     191             : 
     192           3 :         poOGRFeature->SetFID(iNextNASId);
     193             : 
     194          45 :         for (int iField = 0; iField < poFClass->GetPropertyCount(); iField++)
     195             :         {
     196             :             const GMLProperty *psGMLProperty =
     197          42 :                 poNASFeature->GetProperty(iField);
     198          42 :             if (psGMLProperty == nullptr || psGMLProperty->nSubProperties == 0)
     199           8 :                 continue;
     200             : 
     201          34 :             switch (poFClass->GetProperty(iField)->GetType())
     202             :             {
     203           1 :                 case GMLPT_Real:
     204             :                 {
     205           1 :                     poOGRFeature->SetField(
     206           1 :                         iField, CPLAtof(psGMLProperty->papszSubProperties[0]));
     207             :                 }
     208           1 :                 break;
     209             : 
     210           0 :                 case GMLPT_IntegerList:
     211             :                 {
     212           0 :                     int nCount = psGMLProperty->nSubProperties;
     213             :                     int *panIntList =
     214           0 :                         static_cast<int *>(CPLMalloc(sizeof(int) * nCount));
     215             : 
     216           0 :                     for (int i = 0; i < nCount; i++)
     217           0 :                         panIntList[i] =
     218           0 :                             atoi(psGMLProperty->papszSubProperties[i]);
     219             : 
     220           0 :                     poOGRFeature->SetField(iField, nCount, panIntList);
     221           0 :                     CPLFree(panIntList);
     222             :                 }
     223           0 :                 break;
     224             : 
     225           0 :                 case GMLPT_RealList:
     226             :                 {
     227           0 :                     int nCount = psGMLProperty->nSubProperties;
     228             :                     double *padfList = static_cast<double *>(
     229           0 :                         CPLMalloc(sizeof(double) * nCount));
     230             : 
     231           0 :                     for (int i = 0; i < nCount; i++)
     232           0 :                         padfList[i] =
     233           0 :                             CPLAtof(psGMLProperty->papszSubProperties[i]);
     234             : 
     235           0 :                     poOGRFeature->SetField(iField, nCount, padfList);
     236           0 :                     CPLFree(padfList);
     237             :                 }
     238           0 :                 break;
     239             : 
     240           2 :                 case GMLPT_StringList:
     241             :                 {
     242           2 :                     poOGRFeature->SetField(iField,
     243           2 :                                            psGMLProperty->papszSubProperties);
     244             :                 }
     245           2 :                 break;
     246             : 
     247          31 :                 default:
     248          31 :                     poOGRFeature->SetField(
     249          31 :                         iField, psGMLProperty->papszSubProperties[0]);
     250          31 :                     break;
     251             :             }
     252             :         }
     253             : 
     254           4 :         for (int iGeom = 0; iGeom < poNASFeature->GetGeometryCount(); ++iGeom)
     255             :         {
     256           1 :             poOGRFeature->SetGeomFieldDirectly(iGeom, poGeom[iGeom]);
     257           1 :             poGeom[iGeom] = nullptr;
     258             :         }
     259           3 :         poGeom.clear();
     260             : 
     261             :         /* --------------------------------------------------------------------
     262             :          */
     263             :         /*      Test against the attribute query. */
     264             :         /* --------------------------------------------------------------------
     265             :          */
     266           3 :         if (m_poAttrQuery != nullptr && !m_poAttrQuery->Evaluate(poOGRFeature))
     267             :         {
     268           0 :             delete poOGRFeature;
     269           0 :             continue;
     270             :         }
     271             : 
     272             :         /* --------------------------------------------------------------------
     273             :          */
     274             :         /*      Wow, we got our desired feature. Return it. */
     275             :         /* --------------------------------------------------------------------
     276             :          */
     277           3 :         delete poNASFeature;
     278             : 
     279           3 :         return poOGRFeature;
     280           0 :     }
     281             : 
     282             :     return nullptr;
     283             : }
     284             : 
     285             : /************************************************************************/
     286             : /*                          GetFeatureCount()                           */
     287             : /************************************************************************/
     288             : 
     289           3 : GIntBig OGRNASLayer::GetFeatureCount(int bForce)
     290             : 
     291             : {
     292           3 :     if (poFClass == nullptr)
     293           0 :         return 0;
     294             : 
     295           3 :     if (m_poFilterGeom != nullptr || m_poAttrQuery != nullptr)
     296           0 :         return OGRLayer::GetFeatureCount(bForce);
     297             : 
     298           3 :     return poFClass->GetFeatureCount();
     299             : }
     300             : 
     301             : /************************************************************************/
     302             : /*                             GetExtent()                              */
     303             : /************************************************************************/
     304             : 
     305           0 : OGRErr OGRNASLayer::GetExtent(OGREnvelope *psExtent, int bForce)
     306             : 
     307             : {
     308           0 :     double dfXMin = 0.0;
     309           0 :     double dfXMax = 0.0;
     310           0 :     double dfYMin = 0.0;
     311           0 :     double dfYMax = 0.0;
     312             : 
     313           0 :     if (poFClass != nullptr &&
     314           0 :         poFClass->GetExtents(&dfXMin, &dfXMax, &dfYMin, &dfYMax))
     315             :     {
     316           0 :         psExtent->MinX = dfXMin;
     317           0 :         psExtent->MaxX = dfXMax;
     318           0 :         psExtent->MinY = dfYMin;
     319           0 :         psExtent->MaxY = dfYMax;
     320             : 
     321           0 :         return OGRERR_NONE;
     322             :     }
     323             : 
     324           0 :     return OGRLayer::GetExtent(psExtent, bForce);
     325             : }
     326             : 
     327             : /************************************************************************/
     328             : /*                           TestCapability()                           */
     329             : /************************************************************************/
     330             : 
     331           0 : int OGRNASLayer::TestCapability(const char *pszCap)
     332             : 
     333             : {
     334           0 :     if (EQUAL(pszCap, OLCFastGetExtent))
     335             :     {
     336           0 :         if (poFClass == nullptr)
     337           0 :             return FALSE;
     338             : 
     339           0 :         double dfXMin = 0.0;
     340           0 :         double dfXMax = 0.0;
     341           0 :         double dfYMin = 0.0;
     342           0 :         double dfYMax = 0.0;
     343             : 
     344           0 :         return poFClass->GetExtents(&dfXMin, &dfXMax, &dfYMin, &dfYMax);
     345             :     }
     346             : 
     347           0 :     if (EQUAL(pszCap, OLCFastFeatureCount))
     348             :     {
     349           0 :         if (poFClass == nullptr || m_poFilterGeom != nullptr ||
     350           0 :             m_poAttrQuery != nullptr)
     351           0 :             return FALSE;
     352             : 
     353           0 :         return poFClass->GetFeatureCount() != -1;
     354             :     }
     355             : 
     356           0 :     if (EQUAL(pszCap, OLCStringsAsUTF8))
     357           0 :         return TRUE;
     358             : 
     359           0 :     return FALSE;
     360             : }

Generated by: LCOV version 1.14