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: 2026-04-19 18:43: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        5514 : OGRS57Layer::OGRS57Layer(OGRS57DataSource *poDSIn, OGRFeatureDefn *poDefnIn,
      26        5514 :                          int nFeatureCountIn, int nOBJLIn)
      27             :     : poDS(poDSIn), poFeatureDefn(poDefnIn), nCurrentModule(-1),
      28             :       nRCNM(100),  // Default to feature.
      29        5514 :       nOBJL(nOBJLIn), nNextFEIndex(0), nFeatureCount(nFeatureCountIn)
      30             : {
      31        5514 :     SetDescription(poFeatureDefn->GetName());
      32        5514 :     if (poFeatureDefn->GetGeomFieldCount() > 0)
      33       10658 :         poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(
      34        5329 :             poDS->DSGetSpatialRef());
      35             : 
      36        5514 :     if (EQUAL(poDefnIn->GetName(), OGRN_VI))
      37          21 :         nRCNM = RCNM_VI;
      38        5493 :     else if (EQUAL(poDefnIn->GetName(), OGRN_VC))
      39          21 :         nRCNM = RCNM_VC;
      40        5472 :     else if (EQUAL(poDefnIn->GetName(), OGRN_VE))
      41          21 :         nRCNM = RCNM_VE;
      42        5451 :     else if (EQUAL(poDefnIn->GetName(), OGRN_VF))
      43          21 :         nRCNM = RCNM_VF;
      44        5430 :     else if (EQUAL(poDefnIn->GetName(), "DSID"))
      45          39 :         nRCNM = RCNM_DSID;
      46             :     // Leave as feature.
      47        5514 : }
      48             : 
      49             : /************************************************************************/
      50             : /*                            ~OGRS57Layer()                            */
      51             : /************************************************************************/
      52             : 
      53       11028 : OGRS57Layer::~OGRS57Layer()
      54             : 
      55             : {
      56        5514 :     if (m_nFeaturesRead > 0)
      57             :     {
      58         192 :         CPLDebug("S57", "%d features read on layer '%s'.",
      59          96 :                  static_cast<int>(m_nFeaturesRead), poFeatureDefn->GetName());
      60             :     }
      61             : 
      62        5514 :     poFeatureDefn->Release();
      63       11028 : }
      64             : 
      65             : /************************************************************************/
      66             : /*                            ResetReading()                            */
      67             : /************************************************************************/
      68             : 
      69        1166 : void OGRS57Layer::ResetReading()
      70             : 
      71             : {
      72        1166 :     nNextFEIndex = 0;
      73        1166 :     nCurrentModule = -1;
      74        1166 : }
      75             : 
      76             : /************************************************************************/
      77             : /*                      GetNextUnfilteredFeature()                      */
      78             : /************************************************************************/
      79             : 
      80        9127 : OGRFeature *OGRS57Layer::GetNextUnfilteredFeature()
      81             : 
      82             : {
      83             :     /* -------------------------------------------------------------------- */
      84             :     /*      Are we out of modules to request features from?                 */
      85             :     /* -------------------------------------------------------------------- */
      86        9127 :     if (nCurrentModule >= poDS->GetModuleCount())
      87         447 :         return nullptr;
      88             : 
      89             :     /* -------------------------------------------------------------------- */
      90             :     /*      Set the current position on the current module and fetch a      */
      91             :     /*      feature.                                                        */
      92             :     /* -------------------------------------------------------------------- */
      93        8680 :     S57Reader *poReader = poDS->GetModule(nCurrentModule);
      94        8680 :     OGRFeature *poFeature = nullptr;
      95             : 
      96        8680 :     if (poReader != nullptr)
      97             :     {
      98        8117 :         poReader->SetNextFEIndex(nNextFEIndex, nRCNM);
      99        8117 :         poFeature = poReader->ReadNextFeature(poFeatureDefn);
     100        8117 :         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        8680 :     if (poFeature == nullptr)
     107             :     {
     108         971 :         nCurrentModule++;
     109         971 :         poReader = poDS->GetModule(nCurrentModule);
     110             : 
     111         971 :         if (poReader != nullptr && poReader->GetModule() == nullptr)
     112             :         {
     113           0 :             if (!poReader->Open(FALSE))
     114           0 :                 return nullptr;
     115             :         }
     116             : 
     117         971 :         return GetNextUnfilteredFeature();
     118             :     }
     119             :     else
     120             :     {
     121        7709 :         m_nFeaturesRead++;
     122        7709 :         if (poFeature->GetGeometryRef() != nullptr)
     123       15330 :             poFeature->GetGeometryRef()->assignSpatialReference(
     124        7665 :                 GetSpatialRef());
     125             :     }
     126             : 
     127        7709 :     return poFeature;
     128             : }
     129             : 
     130             : /************************************************************************/
     131             : /*                           GetNextFeature()                           */
     132             : /************************************************************************/
     133             : 
     134        7929 : OGRFeature *OGRS57Layer::GetNextFeature()
     135             : 
     136             : {
     137        7929 :     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        8156 :         poFeature = GetNextUnfilteredFeature();
     146        8156 :         if (poFeature == nullptr)
     147         447 :             break;
     148             : 
     149       15649 :         if ((m_poFilterGeom == nullptr ||
     150       15324 :              FilterGeometry(poFeature->GetGeometryRef())) &&
     151        7615 :             (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature)))
     152        7482 :             break;
     153             : 
     154         227 :         delete poFeature;
     155             :     }
     156             : 
     157        7929 :     return poFeature;
     158             : }
     159             : 
     160             : /************************************************************************/
     161             : /*                           TestCapability()                           */
     162             : /************************************************************************/
     163             : 
     164         784 : int OGRS57Layer::TestCapability(const char *pszCap) const
     165             : 
     166             : {
     167         784 :     if (EQUAL(pszCap, OLCRandomRead))
     168           0 :         return false;
     169             : 
     170         784 :     if (EQUAL(pszCap, OLCSequentialWrite))
     171          13 :         return true;
     172             : 
     173         771 :     if (EQUAL(pszCap, OLCRandomWrite))
     174          13 :         return false;
     175             : 
     176         758 :     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         527 :     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         503 :     if (EQUAL(pszCap, OLCFastSpatialFilter))
     193           0 :         return false;
     194             : 
     195         503 :     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         350 :     if (EQUAL(pszCap, OLCZGeometries))
     202          45 :         return true;
     203             : 
     204         305 :     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          65 : OGRFeature *OGRS57Layer::GetFeature(GIntBig nFeatureId)
     238             : 
     239             : {
     240          65 :     S57Reader *poReader = poDS->GetModule(0);  // not multi-reader aware
     241             : 
     242          65 :     if (poReader != nullptr && nFeatureId <= INT_MAX)
     243             :     {
     244             :         OGRFeature *poFeature =
     245          52 :             poReader->ReadFeature(static_cast<int>(nFeatureId), poFeatureDefn);
     246             : 
     247          52 :         if (poFeature != nullptr && poFeature->GetGeometryRef() != nullptr)
     248          50 :             poFeature->GetGeometryRef()->assignSpatialReference(
     249          25 :                 GetSpatialRef());
     250          52 :         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