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-05-03 15:49:35 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             :  * Permission is hereby granted, free of charge, to any person obtaining a
      12             :  * copy of this software and associated documentation files (the "Software"),
      13             :  * to deal in the Software without restriction, including without limitation
      14             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15             :  * and/or sell copies of the Software, and to permit persons to whom the
      16             :  * Software is furnished to do so, subject to the following conditions:
      17             :  *
      18             :  * The above copyright notice and this permission notice shall be included
      19             :  * in all copies or substantial portions of the Software.
      20             :  *
      21             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27             :  * DEALINGS IN THE SOFTWARE.
      28             :  ****************************************************************************/
      29             : 
      30             : #include "cpl_conv.h"
      31             : #include "cpl_port.h"
      32             : #include "cpl_string.h"
      33             : #include "ogr_nas.h"
      34             : 
      35             : /************************************************************************/
      36             : /*                           OGRNASLayer()                              */
      37             : /************************************************************************/
      38             : 
      39           3 : OGRNASLayer::OGRNASLayer(const char *pszName, OGRNASDataSource *poDSIn)
      40             :     : poFeatureDefn(new OGRFeatureDefn(
      41           3 :           pszName + (STARTS_WITH_CI(pszName, "ogr:") ? 4 : 0))),
      42             :       iNextNASId(0), poDS(poDSIn),
      43             :       // Readers should get the corresponding GMLFeatureClass and cache it.
      44           6 :       poFClass(poDS->GetReader()->GetClass(pszName))
      45             : {
      46           3 :     SetDescription(poFeatureDefn->GetName());
      47           3 :     poFeatureDefn->Reference();
      48           3 :     poFeatureDefn->SetGeomType(wkbNone);
      49           3 : }
      50             : 
      51             : /************************************************************************/
      52             : /*                           ~OGRNASLayer()                           */
      53             : /************************************************************************/
      54             : 
      55           6 : OGRNASLayer::~OGRNASLayer()
      56             : 
      57             : {
      58           3 :     if (poFeatureDefn)
      59           3 :         poFeatureDefn->Release();
      60           6 : }
      61             : 
      62             : /************************************************************************/
      63             : /*                            ResetReading()                            */
      64             : /************************************************************************/
      65             : 
      66           6 : void OGRNASLayer::ResetReading()
      67             : 
      68             : {
      69           6 :     iNextNASId = 0;
      70           6 :     poDS->GetReader()->ResetReading();
      71           6 :     if (poFClass)
      72           6 :         poDS->GetReader()->SetFilteredClassName(poFClass->GetElementName());
      73           6 : }
      74             : 
      75             : /************************************************************************/
      76             : /*                           GetNextFeature()                           */
      77             : /************************************************************************/
      78             : 
      79           3 : OGRFeature *OGRNASLayer::GetNextFeature()
      80             : 
      81             : {
      82           3 :     GMLFeature *poNASFeature = nullptr;
      83             : 
      84           3 :     if (iNextNASId == 0)
      85           3 :         ResetReading();
      86             : 
      87             :     /* ==================================================================== */
      88             :     /*      Loop till we find and translate a feature meeting all our       */
      89             :     /*      requirements.                                                   */
      90             :     /* ==================================================================== */
      91             :     while (true)
      92             :     {
      93             :         /* --------------------------------------------------------------------
      94             :          */
      95             :         /*      Cleanup last feature, and get a new raw nas feature. */
      96             :         /* --------------------------------------------------------------------
      97             :          */
      98           3 :         delete poNASFeature;
      99           3 :         poNASFeature = poDS->GetReader()->NextFeature();
     100           3 :         if (poNASFeature == nullptr)
     101           3 :             return nullptr;
     102             : 
     103             :         /* --------------------------------------------------------------------
     104             :          */
     105             :         /*      Is it of the proper feature class? */
     106             :         /* --------------------------------------------------------------------
     107             :          */
     108             : 
     109             :         // We count reading low level NAS features as a feature read for
     110             :         // work checking purposes, though at least we didn't necessary
     111             :         // have to turn it into an OGRFeature.
     112           3 :         m_nFeaturesRead++;
     113             : 
     114           3 :         if (poNASFeature->GetClass() != poFClass)
     115           0 :             continue;
     116             : 
     117           3 :         iNextNASId++;
     118             : 
     119             :         /* --------------------------------------------------------------------
     120             :          */
     121             :         /*      Does it satisfy the spatial query, if there is one? */
     122             :         /* --------------------------------------------------------------------
     123             :          */
     124           3 :         const CPLXMLNode *const *papsGeometry = poNASFeature->GetGeometryList();
     125             : 
     126           3 :         std::vector<OGRGeometry *> poGeom(poNASFeature->GetGeometryCount());
     127             : 
     128           3 :         bool bErrored = false, bFiltered = false;
     129           3 :         CPLString osLastErrorMsg;
     130           4 :         for (int iGeom = 0; iGeom < poNASFeature->GetGeometryCount(); ++iGeom)
     131             :         {
     132           1 :             if (papsGeometry[iGeom] == nullptr)
     133             :             {
     134           0 :                 poGeom[iGeom] = nullptr;
     135             :             }
     136             :             else
     137             :             {
     138           1 :                 CPLPushErrorHandler(CPLQuietErrorHandler);
     139             : 
     140           2 :                 poGeom[iGeom] =
     141           1 :                     (OGRGeometry *)OGR_G_CreateFromGMLTree(papsGeometry[iGeom]);
     142           1 :                 CPLPopErrorHandler();
     143           1 :                 if (poGeom[iGeom] == nullptr)
     144           0 :                     osLastErrorMsg = CPLGetLastErrorMsg();
     145           1 :                 poGeom[iGeom] = NASReader::ConvertGeometry(poGeom[iGeom]);
     146           2 :                 poGeom[iGeom] =
     147           1 :                     OGRGeometryFactory::forceTo(poGeom[iGeom], GetGeomType());
     148             :                 // poGeom->dumpReadable( 0, "NAS: " );
     149             : 
     150           1 :                 if (poGeom[iGeom] == nullptr)
     151           0 :                     bErrored = true;
     152             :             }
     153             : 
     154           1 :             bFiltered =
     155           1 :                 m_poFilterGeom != nullptr && !FilterGeometry(poGeom[iGeom]);
     156           1 :             if (bErrored || bFiltered)
     157             :             {
     158           0 :                 while (iGeom > 0)
     159           0 :                     delete poGeom[--iGeom];
     160           0 :                 poGeom.clear();
     161             : 
     162           0 :                 break;
     163             :             }
     164             :         }
     165             : 
     166           3 :         if (bErrored)
     167             :         {
     168             : 
     169           0 :             CPLString osGMLId;
     170           0 :             if (poFClass->GetPropertyIndex("gml_id") == 0)
     171             :             {
     172           0 :                 const GMLProperty *psGMLProperty = poNASFeature->GetProperty(0);
     173           0 :                 if (psGMLProperty && psGMLProperty->nSubProperties == 1)
     174             :                 {
     175             :                     osGMLId.Printf("(gml_id=%s) ",
     176           0 :                                    psGMLProperty->papszSubProperties[0]);
     177             :                 }
     178             :             }
     179             : 
     180           0 :             delete poNASFeature;
     181           0 :             poNASFeature = nullptr;
     182             : 
     183           0 :             const bool bGoOn = CPLTestBool(
     184             :                 CPLGetConfigOption("NAS_SKIP_CORRUPTED_FEATURES", "NO"));
     185           0 :             CPLError(bGoOn ? CE_Warning : CE_Failure, CPLE_AppDefined,
     186             :                      "Geometry of feature %d %scannot be parsed: %s%s",
     187             :                      iNextNASId, osGMLId.c_str(), osLastErrorMsg.c_str(),
     188             :                      bGoOn ? ". Skipping to next feature."
     189             :                            : ". You may set the NAS_SKIP_CORRUPTED_FEATURES "
     190             :                              "configuration option to YES to skip to the next "
     191             :                              "feature");
     192           0 :             if (bGoOn)
     193           0 :                 continue;
     194             : 
     195           0 :             return nullptr;
     196             :         }
     197             : 
     198           3 :         if (bFiltered)
     199           0 :             continue;
     200             : 
     201             :         /* --------------------------------------------------------------------
     202             :          */
     203             :         /*      Convert the whole feature into an OGRFeature. */
     204             :         /* --------------------------------------------------------------------
     205             :          */
     206           3 :         OGRFeature *poOGRFeature = new OGRFeature(GetLayerDefn());
     207             : 
     208           3 :         poOGRFeature->SetFID(iNextNASId);
     209             : 
     210          45 :         for (int iField = 0; iField < poFClass->GetPropertyCount(); iField++)
     211             :         {
     212             :             const GMLProperty *psGMLProperty =
     213          42 :                 poNASFeature->GetProperty(iField);
     214          42 :             if (psGMLProperty == nullptr || psGMLProperty->nSubProperties == 0)
     215           8 :                 continue;
     216             : 
     217          34 :             switch (poFClass->GetProperty(iField)->GetType())
     218             :             {
     219           1 :                 case GMLPT_Real:
     220             :                 {
     221           1 :                     poOGRFeature->SetField(
     222           1 :                         iField, CPLAtof(psGMLProperty->papszSubProperties[0]));
     223             :                 }
     224           1 :                 break;
     225             : 
     226           0 :                 case GMLPT_IntegerList:
     227             :                 {
     228           0 :                     int nCount = psGMLProperty->nSubProperties;
     229             :                     int *panIntList =
     230           0 :                         static_cast<int *>(CPLMalloc(sizeof(int) * nCount));
     231             : 
     232           0 :                     for (int i = 0; i < nCount; i++)
     233           0 :                         panIntList[i] =
     234           0 :                             atoi(psGMLProperty->papszSubProperties[i]);
     235             : 
     236           0 :                     poOGRFeature->SetField(iField, nCount, panIntList);
     237           0 :                     CPLFree(panIntList);
     238             :                 }
     239           0 :                 break;
     240             : 
     241           0 :                 case GMLPT_RealList:
     242             :                 {
     243           0 :                     int nCount = psGMLProperty->nSubProperties;
     244             :                     double *padfList = static_cast<double *>(
     245           0 :                         CPLMalloc(sizeof(double) * nCount));
     246             : 
     247           0 :                     for (int i = 0; i < nCount; i++)
     248           0 :                         padfList[i] =
     249           0 :                             CPLAtof(psGMLProperty->papszSubProperties[i]);
     250             : 
     251           0 :                     poOGRFeature->SetField(iField, nCount, padfList);
     252           0 :                     CPLFree(padfList);
     253             :                 }
     254           0 :                 break;
     255             : 
     256           2 :                 case GMLPT_StringList:
     257             :                 {
     258           2 :                     poOGRFeature->SetField(iField,
     259           2 :                                            psGMLProperty->papszSubProperties);
     260             :                 }
     261           2 :                 break;
     262             : 
     263          31 :                 default:
     264          31 :                     poOGRFeature->SetField(
     265          31 :                         iField, psGMLProperty->papszSubProperties[0]);
     266          31 :                     break;
     267             :             }
     268             :         }
     269             : 
     270           4 :         for (int iGeom = 0; iGeom < poNASFeature->GetGeometryCount(); ++iGeom)
     271             :         {
     272           1 :             poOGRFeature->SetGeomFieldDirectly(iGeom, poGeom[iGeom]);
     273           1 :             poGeom[iGeom] = nullptr;
     274             :         }
     275           3 :         poGeom.clear();
     276             : 
     277             :         /* --------------------------------------------------------------------
     278             :          */
     279             :         /*      Test against the attribute query. */
     280             :         /* --------------------------------------------------------------------
     281             :          */
     282           3 :         if (m_poAttrQuery != nullptr && !m_poAttrQuery->Evaluate(poOGRFeature))
     283             :         {
     284           0 :             delete poOGRFeature;
     285           0 :             continue;
     286             :         }
     287             : 
     288             :         /* --------------------------------------------------------------------
     289             :          */
     290             :         /*      Wow, we got our desired feature. Return it. */
     291             :         /* --------------------------------------------------------------------
     292             :          */
     293           3 :         delete poNASFeature;
     294             : 
     295           3 :         return poOGRFeature;
     296           0 :     }
     297             : 
     298             :     return nullptr;
     299             : }
     300             : 
     301             : /************************************************************************/
     302             : /*                          GetFeatureCount()                           */
     303             : /************************************************************************/
     304             : 
     305           3 : GIntBig OGRNASLayer::GetFeatureCount(int bForce)
     306             : 
     307             : {
     308           3 :     if (poFClass == nullptr)
     309           0 :         return 0;
     310             : 
     311           3 :     if (m_poFilterGeom != nullptr || m_poAttrQuery != nullptr)
     312           0 :         return OGRLayer::GetFeatureCount(bForce);
     313             : 
     314           3 :     return poFClass->GetFeatureCount();
     315             : }
     316             : 
     317             : /************************************************************************/
     318             : /*                             GetExtent()                              */
     319             : /************************************************************************/
     320             : 
     321           0 : OGRErr OGRNASLayer::GetExtent(OGREnvelope *psExtent, int bForce)
     322             : 
     323             : {
     324           0 :     double dfXMin = 0.0;
     325           0 :     double dfXMax = 0.0;
     326           0 :     double dfYMin = 0.0;
     327           0 :     double dfYMax = 0.0;
     328             : 
     329           0 :     if (poFClass != nullptr &&
     330           0 :         poFClass->GetExtents(&dfXMin, &dfXMax, &dfYMin, &dfYMax))
     331             :     {
     332           0 :         psExtent->MinX = dfXMin;
     333           0 :         psExtent->MaxX = dfXMax;
     334           0 :         psExtent->MinY = dfYMin;
     335           0 :         psExtent->MaxY = dfYMax;
     336             : 
     337           0 :         return OGRERR_NONE;
     338             :     }
     339             : 
     340           0 :     return OGRLayer::GetExtent(psExtent, bForce);
     341             : }
     342             : 
     343             : /************************************************************************/
     344             : /*                           TestCapability()                           */
     345             : /************************************************************************/
     346             : 
     347           0 : int OGRNASLayer::TestCapability(const char *pszCap)
     348             : 
     349             : {
     350           0 :     if (EQUAL(pszCap, OLCFastGetExtent))
     351             :     {
     352           0 :         if (poFClass == nullptr)
     353           0 :             return FALSE;
     354             : 
     355           0 :         double dfXMin = 0.0;
     356           0 :         double dfXMax = 0.0;
     357           0 :         double dfYMin = 0.0;
     358           0 :         double dfYMax = 0.0;
     359             : 
     360           0 :         return poFClass->GetExtents(&dfXMin, &dfXMax, &dfYMin, &dfYMax);
     361             :     }
     362             : 
     363           0 :     if (EQUAL(pszCap, OLCFastFeatureCount))
     364             :     {
     365           0 :         if (poFClass == nullptr || m_poFilterGeom != nullptr ||
     366           0 :             m_poAttrQuery != nullptr)
     367           0 :             return FALSE;
     368             : 
     369           0 :         return poFClass->GetFeatureCount() != -1;
     370             :     }
     371             : 
     372           0 :     if (EQUAL(pszCap, OLCStringsAsUTF8))
     373           0 :         return TRUE;
     374             : 
     375           0 :     return FALSE;
     376             : }

Generated by: LCOV version 1.14