LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/s57 - ogrs57layer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 109 117 93.2 %
Date: 2025-09-10 17:48:50 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  S-57 Translator
       4             :  * Purpose:  Implements OGRS57Layer class.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 1999, Frank Warmerdam
       9             :  * Copyright (c) 2009-2014, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_conv.h"
      15             : #include "cpl_string.h"
      16             : #include "ogr_s57.h"
      17             : 
      18             : /************************************************************************/
      19             : /*                            OGRS57Layer()                             */
      20             : /*                                                                      */
      21             : /*      Note that the OGRS57Layer assumes ownership of the passed       */
      22             : /*      OGRFeatureDefn object.                                          */
      23             : /************************************************************************/
      24             : 
      25        5402 : OGRS57Layer::OGRS57Layer(OGRS57DataSource *poDSIn, OGRFeatureDefn *poDefnIn,
      26        5402 :                          int nFeatureCountIn, int nOBJLIn)
      27             :     : poDS(poDSIn), poFeatureDefn(poDefnIn), nCurrentModule(-1),
      28             :       nRCNM(100),  // Default to feature.
      29        5402 :       nOBJL(nOBJLIn), nNextFEIndex(0), nFeatureCount(nFeatureCountIn)
      30             : {
      31        5402 :     SetDescription(poFeatureDefn->GetName());
      32        5402 :     if (poFeatureDefn->GetGeomFieldCount() > 0)
      33       10442 :         poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(
      34        5221 :             poDS->DSGetSpatialRef());
      35             : 
      36        5402 :     if (EQUAL(poDefnIn->GetName(), OGRN_VI))
      37          21 :         nRCNM = RCNM_VI;
      38        5381 :     else if (EQUAL(poDefnIn->GetName(), OGRN_VC))
      39          21 :         nRCNM = RCNM_VC;
      40        5360 :     else if (EQUAL(poDefnIn->GetName(), OGRN_VE))
      41          21 :         nRCNM = RCNM_VE;
      42        5339 :     else if (EQUAL(poDefnIn->GetName(), OGRN_VF))
      43          21 :         nRCNM = RCNM_VF;
      44        5318 :     else if (EQUAL(poDefnIn->GetName(), "DSID"))
      45          37 :         nRCNM = RCNM_DSID;
      46             :     // Leave as feature.
      47        5402 : }
      48             : 
      49             : /************************************************************************/
      50             : /*                           ~OGRS57Layer()                           */
      51             : /************************************************************************/
      52             : 
      53       10804 : OGRS57Layer::~OGRS57Layer()
      54             : 
      55             : {
      56        5402 :     if (m_nFeaturesRead > 0)
      57             :     {
      58          98 :         CPLDebug("S57", "%d features read on layer '%s'.",
      59          49 :                  static_cast<int>(m_nFeaturesRead), poFeatureDefn->GetName());
      60             :     }
      61             : 
      62        5402 :     poFeatureDefn->Release();
      63       10804 : }
      64             : 
      65             : /************************************************************************/
      66             : /*                            ResetReading()                            */
      67             : /************************************************************************/
      68             : 
      69        1119 : void OGRS57Layer::ResetReading()
      70             : 
      71             : {
      72        1119 :     nNextFEIndex = 0;
      73        1119 :     nCurrentModule = -1;
      74        1119 : }
      75             : 
      76             : /************************************************************************/
      77             : /*                      GetNextUnfilteredFeature()                      */
      78             : /************************************************************************/
      79             : 
      80        2123 : OGRFeature *OGRS57Layer::GetNextUnfilteredFeature()
      81             : 
      82             : {
      83             :     /* -------------------------------------------------------------------- */
      84             :     /*      Are we out of modules to request features from?                 */
      85             :     /* -------------------------------------------------------------------- */
      86        2123 :     if (nCurrentModule >= poDS->GetModuleCount())
      87         400 :         return nullptr;
      88             : 
      89             :     /* -------------------------------------------------------------------- */
      90             :     /*      Set the current position on the current module and fetch a      */
      91             :     /*      feature.                                                        */
      92             :     /* -------------------------------------------------------------------- */
      93        1723 :     S57Reader *poReader = poDS->GetModule(nCurrentModule);
      94        1723 :     OGRFeature *poFeature = nullptr;
      95             : 
      96        1723 :     if (poReader != nullptr)
      97             :     {
      98        1207 :         poReader->SetNextFEIndex(nNextFEIndex, nRCNM);
      99        1207 :         poFeature = poReader->ReadNextFeature(poFeatureDefn);
     100        1207 :         nNextFEIndex = poReader->GetNextFEIndex(nRCNM);
     101             :     }
     102             : 
     103             :     /* -------------------------------------------------------------------- */
     104             :     /*      If we didn't get a feature we need to move onto the next file.  */
     105             :     /* -------------------------------------------------------------------- */
     106        1723 :     if (poFeature == nullptr)
     107             :     {
     108         877 :         nCurrentModule++;
     109         877 :         poReader = poDS->GetModule(nCurrentModule);
     110             : 
     111         877 :         if (poReader != nullptr && poReader->GetModule() == nullptr)
     112             :         {
     113           0 :             if (!poReader->Open(FALSE))
     114           0 :                 return nullptr;
     115             :         }
     116             : 
     117         877 :         return GetNextUnfilteredFeature();
     118             :     }
     119             :     else
     120             :     {
     121         846 :         m_nFeaturesRead++;
     122         846 :         if (poFeature->GetGeometryRef() != nullptr)
     123        1610 :             poFeature->GetGeometryRef()->assignSpatialReference(
     124         805 :                 GetSpatialRef());
     125             :     }
     126             : 
     127         846 :     return poFeature;
     128             : }
     129             : 
     130             : /************************************************************************/
     131             : /*                           GetNextFeature()                           */
     132             : /************************************************************************/
     133             : 
     134        1019 : OGRFeature *OGRS57Layer::GetNextFeature()
     135             : 
     136             : {
     137        1019 :     OGRFeature *poFeature = nullptr;
     138             : 
     139             :     /* -------------------------------------------------------------------- */
     140             :     /*      Read features till we find one that satisfies our current       */
     141             :     /*      spatial criteria.                                               */
     142             :     /* -------------------------------------------------------------------- */
     143             :     while (true)
     144             :     {
     145        1246 :         poFeature = GetNextUnfilteredFeature();
     146        1246 :         if (poFeature == nullptr)
     147         400 :             break;
     148             : 
     149        1923 :         if ((m_poFilterGeom == nullptr ||
     150        1598 :              FilterGeometry(poFeature->GetGeometryRef())) &&
     151         752 :             (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature)))
     152         619 :             break;
     153             : 
     154         227 :         delete poFeature;
     155             :     }
     156             : 
     157        1019 :     return poFeature;
     158             : }
     159             : 
     160             : /************************************************************************/
     161             : /*                           TestCapability()                           */
     162             : /************************************************************************/
     163             : 
     164         772 : int OGRS57Layer::TestCapability(const char *pszCap) const
     165             : 
     166             : {
     167         772 :     if (EQUAL(pszCap, OLCRandomRead))
     168           0 :         return false;
     169             : 
     170         772 :     if (EQUAL(pszCap, OLCSequentialWrite))
     171          13 :         return true;
     172             : 
     173         759 :     if (EQUAL(pszCap, OLCRandomWrite))
     174          13 :         return false;
     175             : 
     176         746 :     if (EQUAL(pszCap, OLCFastFeatureCount))
     177         231 :         return !(
     178         231 :             m_poFilterGeom != nullptr || m_poAttrQuery != nullptr ||
     179         157 :             nFeatureCount == -1 ||
     180         144 :             (EQUAL(poFeatureDefn->GetName(), "SOUNDG") &&
     181          12 :              poDS->GetModule(0) != nullptr &&
     182         243 :              (poDS->GetModule(0)->GetOptionFlags() & S57M_SPLIT_MULTIPOINT)));
     183             : 
     184         515 :     if (EQUAL(pszCap, OLCFastGetExtent))
     185             :     {
     186          24 :         OGREnvelope oEnvelope;
     187             : 
     188          24 :         return const_cast<OGRS57Layer *>(this)->GetExtent(&oEnvelope, FALSE) ==
     189          24 :                OGRERR_NONE;
     190             :     }
     191             : 
     192         491 :     if (EQUAL(pszCap, OLCFastSpatialFilter))
     193           0 :         return false;
     194             : 
     195         491 :     if (EQUAL(pszCap, OLCStringsAsUTF8))
     196             :     {
     197         306 :         return poDS->GetModule(0) != nullptr &&
     198         306 :                (poDS->GetModule(0)->GetOptionFlags() & S57M_RECODE_BY_DSSI);
     199             :     }
     200             : 
     201         338 :     if (EQUAL(pszCap, OLCZGeometries))
     202          39 :         return true;
     203             : 
     204         299 :     return false;
     205             : }
     206             : 
     207             : /************************************************************************/
     208             : /*                            IGetExtent()                              */
     209             : /************************************************************************/
     210             : 
     211          72 : OGRErr OGRS57Layer::IGetExtent(int /*iGeomField*/, OGREnvelope *psExtent,
     212             :                                bool bForce)
     213             : 
     214             : {
     215          72 :     if (GetGeomType() == wkbNone)
     216           0 :         return OGRERR_FAILURE;
     217             : 
     218          72 :     return poDS->GetDSExtent(psExtent, bForce);
     219             : }
     220             : 
     221             : /************************************************************************/
     222             : /*                          GetFeatureCount()                           */
     223             : /************************************************************************/
     224         231 : GIntBig OGRS57Layer::GetFeatureCount(int bForce)
     225             : {
     226             : 
     227         231 :     if (!TestCapability(OLCFastFeatureCount))
     228          87 :         return OGRLayer::GetFeatureCount(bForce);
     229             : 
     230         144 :     return nFeatureCount;
     231             : }
     232             : 
     233             : /************************************************************************/
     234             : /*                             GetFeature()                             */
     235             : /************************************************************************/
     236             : 
     237          64 : OGRFeature *OGRS57Layer::GetFeature(GIntBig nFeatureId)
     238             : 
     239             : {
     240          64 :     S57Reader *poReader = poDS->GetModule(0);  // not multi-reader aware
     241             : 
     242          64 :     if (poReader != nullptr && nFeatureId <= INT_MAX)
     243             :     {
     244             :         OGRFeature *poFeature =
     245          51 :             poReader->ReadFeature(static_cast<int>(nFeatureId), poFeatureDefn);
     246             : 
     247          51 :         if (poFeature != nullptr && poFeature->GetGeometryRef() != nullptr)
     248          48 :             poFeature->GetGeometryRef()->assignSpatialReference(
     249          24 :                 GetSpatialRef());
     250          51 :         return poFeature;
     251             :     }
     252             : 
     253          13 :     return nullptr;
     254             : }
     255             : 
     256             : /************************************************************************/
     257             : /*                           ICreateFeature()                            */
     258             : /************************************************************************/
     259             : 
     260         118 : OGRErr OGRS57Layer::ICreateFeature(OGRFeature *poFeature)
     261             : 
     262             : {
     263             :     /* -------------------------------------------------------------------- */
     264             :     /*      Set RCNM if not already set.                                    */
     265             :     /* -------------------------------------------------------------------- */
     266         118 :     const int iRCNMFld = poFeature->GetFieldIndex("RCNM");
     267             : 
     268         118 :     if (iRCNMFld != -1)
     269             :     {
     270          94 :         if (!poFeature->IsFieldSetAndNotNull(iRCNMFld))
     271           0 :             poFeature->SetField(iRCNMFld, nRCNM);
     272             :         else
     273             :         {
     274          94 :             CPLAssert(poFeature->GetFieldAsInteger(iRCNMFld) == nRCNM);
     275             :         }
     276             :     }
     277             : 
     278             :     /* -------------------------------------------------------------------- */
     279             :     /*      Set OBJL if not already set.                                    */
     280             :     /* -------------------------------------------------------------------- */
     281         118 :     if (nOBJL != -1)
     282             :     {
     283          24 :         const int iOBJLFld = poFeature->GetFieldIndex("OBJL");
     284             : 
     285          24 :         if (!poFeature->IsFieldSetAndNotNull(iOBJLFld))
     286           0 :             poFeature->SetField(iOBJLFld, nOBJL);
     287             :         else
     288             :         {
     289          24 :             CPLAssert(poFeature->GetFieldAsInteger(iOBJLFld) == nOBJL);
     290             :         }
     291             :     }
     292             : 
     293             :     /* -------------------------------------------------------------------- */
     294             :     /*      Create the isolated node feature.                               */
     295             :     /* -------------------------------------------------------------------- */
     296         118 :     if (poDS->GetWriter()->WriteCompleteFeature(poFeature))
     297         118 :         return OGRERR_NONE;
     298             : 
     299           0 :     return OGRERR_FAILURE;
     300             : }

Generated by: LCOV version 1.14