LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/sdts - ogrsdtslayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 164 176 93.2 %
Date: 2024-11-21 22:18:42 Functions: 7 8 87.5 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  SDTSReader
       4             :  * Purpose:  Implements OGRSDTSLayer class.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 1999, Frank Warmerdam
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "ogr_sdts.h"
      14             : #include "cpl_conv.h"
      15             : #include "cpl_string.h"
      16             : 
      17             : /************************************************************************/
      18             : /*                            OGRSDTSLayer()                            */
      19             : /*                                                                      */
      20             : /*      Note that the OGRSDTSLayer assumes ownership of the passed      */
      21             : /*      OGRFeatureDefn object.                                          */
      22             : /************************************************************************/
      23             : 
      24           8 : OGRSDTSLayer::OGRSDTSLayer(SDTSTransfer *poTransferIn, int iLayerIn,
      25           8 :                            OGRSDTSDataSource *poDSIn)
      26             :     : poFeatureDefn(nullptr), poTransfer(poTransferIn), iLayer(iLayerIn),
      27           8 :       poReader(poTransferIn->GetLayerIndexedReader(iLayerIn)), poDS(poDSIn)
      28             : {
      29             :     /* -------------------------------------------------------------------- */
      30             :     /*      Define the feature.                                             */
      31             :     /* -------------------------------------------------------------------- */
      32           8 :     const int iCATDEntry = poTransfer->GetLayerCATDEntry(iLayer);
      33             : 
      34           8 :     poFeatureDefn =
      35           8 :         new OGRFeatureDefn(poTransfer->GetCATD()->GetEntryModule(iCATDEntry));
      36           8 :     SetDescription(poFeatureDefn->GetName());
      37           8 :     poFeatureDefn->Reference();
      38           8 :     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poDS->GetSpatialRef());
      39             : 
      40          16 :     OGRFieldDefn oRecId("RCID", OFTInteger);
      41           8 :     poFeatureDefn->AddFieldDefn(&oRecId);
      42             : 
      43           8 :     if (poTransfer->GetLayerType(iLayer) == SLTPoint)
      44             :     {
      45           3 :         poFeatureDefn->SetGeomType(wkbPoint);
      46             :     }
      47           5 :     else if (poTransfer->GetLayerType(iLayer) == SLTLine)
      48             :     {
      49           1 :         poFeatureDefn->SetGeomType(wkbLineString);
      50             : 
      51           1 :         oRecId.SetName("SNID");
      52           1 :         poFeatureDefn->AddFieldDefn(&oRecId);
      53             : 
      54           1 :         oRecId.SetName("ENID");
      55           1 :         poFeatureDefn->AddFieldDefn(&oRecId);
      56             :     }
      57           4 :     else if (poTransfer->GetLayerType(iLayer) == SLTPoly)
      58             :     {
      59           1 :         poFeatureDefn->SetGeomType(wkbPolygon);
      60             :     }
      61           3 :     else if (poTransfer->GetLayerType(iLayer) == SLTAttr)
      62             :     {
      63           3 :         poFeatureDefn->SetGeomType(wkbNone);
      64             :     }
      65             : 
      66             :     /* -------------------------------------------------------------------- */
      67             :     /*      Add schema from referenced attribute records.                   */
      68             :     /* -------------------------------------------------------------------- */
      69           8 :     char **papszATIDRefs = nullptr;
      70             : 
      71           8 :     if (poTransfer->GetLayerType(iLayer) != SLTAttr)
      72           5 :         papszATIDRefs = poReader->ScanModuleReferences();
      73             :     else
      74           3 :         papszATIDRefs = CSLAddString(
      75           3 :             papszATIDRefs, poTransfer->GetCATD()->GetEntryModule(iCATDEntry));
      76             : 
      77          12 :     for (int iTable = 0;
      78          12 :          papszATIDRefs != nullptr && papszATIDRefs[iTable] != nullptr; iTable++)
      79             :     {
      80             :         /* --------------------------------------------------------------------
      81             :          */
      82             :         /*      Get the attribute table reader, and the associated user */
      83             :         /*      attribute field. */
      84             :         /* --------------------------------------------------------------------
      85             :          */
      86           4 :         const int nLayerIdx = poTransfer->FindLayer(papszATIDRefs[iTable]);
      87           4 :         if (nLayerIdx < 0)
      88           0 :             continue;
      89           0 :         SDTSAttrReader *poAttrReader = dynamic_cast<SDTSAttrReader *>(
      90           4 :             poTransfer->GetLayerIndexedReader(nLayerIdx));
      91             : 
      92           4 :         if (poAttrReader == nullptr)
      93           0 :             continue;
      94             : 
      95             :         DDFFieldDefn *poFDefn =
      96           4 :             poAttrReader->GetModule()->FindFieldDefn("ATTP");
      97           4 :         if (poFDefn == nullptr)
      98           0 :             poFDefn = poAttrReader->GetModule()->FindFieldDefn("ATTS");
      99           4 :         if (poFDefn == nullptr)
     100           0 :             continue;
     101             : 
     102             :         /* --------------------------------------------------------------------
     103             :          */
     104             :         /*      Process each user subfield on the attribute table into an */
     105             :         /*      OGR field definition. */
     106             :         /* --------------------------------------------------------------------
     107             :          */
     108          64 :         for (int iSF = 0; iSF < poFDefn->GetSubfieldCount(); iSF++)
     109             :         {
     110          60 :             DDFSubfieldDefn *poSFDefn = poFDefn->GetSubfield(iSF);
     111          60 :             const int nWidth = poSFDefn->GetWidth();
     112             : 
     113             :             char *pszFieldName =
     114          60 :                 poFeatureDefn->GetFieldIndex(poSFDefn->GetName()) != -1
     115          60 :                     ? CPLStrdup(CPLSPrintf("%s_%s", papszATIDRefs[iTable],
     116             :                                            poSFDefn->GetName()))
     117          60 :                     : CPLStrdup(poSFDefn->GetName());
     118             : 
     119          60 :             switch (poSFDefn->GetType())
     120             :             {
     121          44 :                 case DDFString:
     122             :                 {
     123          88 :                     OGRFieldDefn oStrField(pszFieldName, OFTString);
     124             : 
     125          44 :                     if (nWidth != 0)
     126          44 :                         oStrField.SetWidth(nWidth);
     127             : 
     128          44 :                     poFeatureDefn->AddFieldDefn(&oStrField);
     129             :                 }
     130          44 :                 break;
     131             : 
     132           4 :                 case DDFInt:
     133             :                 {
     134           8 :                     OGRFieldDefn oIntField(pszFieldName, OFTInteger);
     135             : 
     136           4 :                     if (nWidth != 0)
     137           4 :                         oIntField.SetWidth(nWidth);
     138             : 
     139           4 :                     poFeatureDefn->AddFieldDefn(&oIntField);
     140             :                 }
     141           4 :                 break;
     142             : 
     143          12 :                 case DDFFloat:
     144             :                 {
     145          24 :                     OGRFieldDefn oRealField(pszFieldName, OFTReal);
     146             : 
     147             :                     // We don't have a precision in DDF files, so we never even
     148             :                     // use the width.  Otherwise with a precision of zero the
     149             :                     // result would look like an integer.
     150             : 
     151          12 :                     poFeatureDefn->AddFieldDefn(&oRealField);
     152             :                 }
     153          12 :                 break;
     154             : 
     155           0 :                 default:
     156           0 :                     break;
     157             :             }
     158             : 
     159          60 :             CPLFree(pszFieldName);
     160             :         } /* next iSF (subfield) */
     161             :     }     /* next iTable */
     162           8 :     CSLDestroy(papszATIDRefs);
     163           8 : }
     164             : 
     165             : /************************************************************************/
     166             : /*                           ~OGRSDTSLayer()                           */
     167             : /************************************************************************/
     168             : 
     169          16 : OGRSDTSLayer::~OGRSDTSLayer()
     170             : 
     171             : {
     172           8 :     if (m_nFeaturesRead > 0 && poFeatureDefn != nullptr)
     173             :     {
     174          16 :         CPLDebug("SDTS", "%d features read on layer '%s'.",
     175           8 :                  static_cast<int>(m_nFeaturesRead), poFeatureDefn->GetName());
     176             :     }
     177             : 
     178           8 :     if (poFeatureDefn)
     179           8 :         poFeatureDefn->Release();
     180          16 : }
     181             : 
     182             : /************************************************************************/
     183             : /*                            ResetReading()                            */
     184             : /************************************************************************/
     185             : 
     186          16 : void OGRSDTSLayer::ResetReading()
     187             : 
     188             : {
     189          16 :     poReader->Rewind();
     190          16 : }
     191             : 
     192             : /************************************************************************/
     193             : /*                     AssignAttrRecordToFeature()                      */
     194             : /************************************************************************/
     195             : 
     196         195 : static void AssignAttrRecordToFeature(OGRFeature *poFeature,
     197             :                                       CPL_UNUSED SDTSTransfer *poTransfer,
     198             :                                       DDFField *poSR)
     199             : {
     200             :     /* -------------------------------------------------------------------- */
     201             :     /*      Process each subfield in the record.                            */
     202             :     /* -------------------------------------------------------------------- */
     203         195 :     DDFFieldDefn *poFDefn = poSR->GetFieldDefn();
     204             : 
     205        3027 :     for (int iSF = 0; iSF < poFDefn->GetSubfieldCount(); iSF++)
     206             :     {
     207        2832 :         DDFSubfieldDefn *poSFDefn = poFDefn->GetSubfield(iSF);
     208        2832 :         int nMaxBytes = 0;
     209        2832 :         const char *pachData = poSR->GetSubfieldData(poSFDefn, &nMaxBytes);
     210             :         /* --------------------------------------------------------------------
     211             :          */
     212             :         /*      Identify this field on the feature. */
     213             :         /* --------------------------------------------------------------------
     214             :          */
     215        2832 :         const int iField = poFeature->GetFieldIndex(poSFDefn->GetName());
     216             : 
     217             :         /* --------------------------------------------------------------------
     218             :          */
     219             :         /*      Handle each of the types. */
     220             :         /* --------------------------------------------------------------------
     221             :          */
     222        2832 :         switch (poSFDefn->GetType())
     223             :         {
     224        2466 :             case DDFString:
     225             :             {
     226             :                 const char *pszValue =
     227        2466 :                     poSFDefn->ExtractStringData(pachData, nMaxBytes, nullptr);
     228             : 
     229        2466 :                 if (iField != -1)
     230        2466 :                     poFeature->SetField(iField, pszValue);
     231        2466 :                 break;
     232             :             }
     233          24 :             case DDFFloat:
     234             :             {
     235             :                 double dfValue =
     236          24 :                     poSFDefn->ExtractFloatData(pachData, nMaxBytes, nullptr);
     237             : 
     238          24 :                 if (iField != -1)
     239          24 :                     poFeature->SetField(iField, dfValue);
     240          24 :                 break;
     241             :             }
     242         342 :             case DDFInt:
     243             :             {
     244             :                 int nValue =
     245         342 :                     poSFDefn->ExtractIntData(pachData, nMaxBytes, nullptr);
     246             : 
     247         342 :                 if (iField != -1)
     248         342 :                     poFeature->SetField(iField, nValue);
     249         342 :                 break;
     250             :             }
     251           0 :             default:
     252           0 :                 break;
     253             :         }
     254             :     } /* next subfield */
     255         195 : }
     256             : 
     257             : /************************************************************************/
     258             : /*                      GetNextUnfilteredFeature()                      */
     259             : /************************************************************************/
     260             : 
     261         391 : OGRFeature *OGRSDTSLayer::GetNextUnfilteredFeature()
     262             : 
     263             : {
     264             :     /* -------------------------------------------------------------------- */
     265             :     /*      If not done before we need to assemble the geometry for a       */
     266             :     /*      polygon layer.                                                  */
     267             :     /* -------------------------------------------------------------------- */
     268         391 :     if (poTransfer->GetLayerType(iLayer) == SLTPoly)
     269             :     {
     270          38 :         ((SDTSPolygonReader *)poReader)->AssembleRings(poTransfer, iLayer);
     271             :     }
     272             : 
     273             :     /* -------------------------------------------------------------------- */
     274             :     /*      Fetch the next sdts style feature object from the reader.       */
     275             :     /* -------------------------------------------------------------------- */
     276         391 :     SDTSFeature *poSDTSFeature = poReader->GetNextFeature();
     277             :     // Retain now the IsIndexed state to determine if we must delete or
     278             :     // not poSDTSFeature when done with it, because later calls might cause
     279             :     // indexing.
     280         391 :     const bool bIsIndexed = CPL_TO_BOOL(poReader->IsIndexed());
     281             : 
     282         391 :     if (poSDTSFeature == nullptr)
     283           8 :         return nullptr;
     284             : 
     285             :     /* -------------------------------------------------------------------- */
     286             :     /*      Create the OGR feature.                                         */
     287             :     /* -------------------------------------------------------------------- */
     288         383 :     OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
     289             : 
     290         383 :     m_nFeaturesRead++;
     291             : 
     292         383 :     switch (poTransfer->GetLayerType(iLayer))
     293             :     {
     294             :             /* --------------------------------------------------------------------
     295             :              */
     296             :             /*      Translate point feature specific information and geometry.
     297             :              */
     298             :             /* --------------------------------------------------------------------
     299             :              */
     300         129 :         case SLTPoint:
     301             :         {
     302         129 :             SDTSRawPoint *poPoint = (SDTSRawPoint *)poSDTSFeature;
     303             : 
     304         129 :             poFeature->SetGeometryDirectly(
     305         129 :                 new OGRPoint(poPoint->dfX, poPoint->dfY, poPoint->dfZ));
     306             :         }
     307         129 :         break;
     308             : 
     309             :             /* --------------------------------------------------------------------
     310             :              */
     311             :             /*      Translate line feature specific information and geometry. */
     312             :             /* --------------------------------------------------------------------
     313             :              */
     314          28 :         case SLTLine:
     315             :         {
     316          28 :             SDTSRawLine *poLine = (SDTSRawLine *)poSDTSFeature;
     317          28 :             OGRLineString *poOGRLine = new OGRLineString();
     318             : 
     319          28 :             poOGRLine->setPoints(poLine->nVertices, poLine->padfX,
     320          28 :                                  poLine->padfY, poLine->padfZ);
     321          28 :             poFeature->SetGeometryDirectly(poOGRLine);
     322          28 :             poFeature->SetField("SNID", (int)poLine->oStartNode.nRecord);
     323          28 :             poFeature->SetField("ENID", (int)poLine->oEndNode.nRecord);
     324             :         }
     325          28 :         break;
     326             : 
     327             :             /* --------------------------------------------------------------------
     328             :              */
     329             :             /*      Translate polygon feature specific information and geometry.
     330             :              */
     331             :             /* --------------------------------------------------------------------
     332             :              */
     333          37 :         case SLTPoly:
     334             :         {
     335          37 :             SDTSRawPolygon *poPoly = (SDTSRawPolygon *)poSDTSFeature;
     336          37 :             OGRPolygon *poOGRPoly = new OGRPolygon();
     337             : 
     338          58 :             for (int iRing = 0; iRing < poPoly->nRings; iRing++)
     339             :             {
     340          21 :                 OGRLinearRing *poRing = new OGRLinearRing();
     341          21 :                 const int nVertices =
     342          21 :                     iRing == poPoly->nRings - 1
     343          21 :                         ? poPoly->nVertices - poPoly->panRingStart[iRing]
     344           6 :                         : (poPoly->panRingStart[iRing + 1] -
     345           6 :                            poPoly->panRingStart[iRing]);
     346             : 
     347          21 :                 poRing->setPoints(nVertices,
     348          21 :                                   poPoly->padfX + poPoly->panRingStart[iRing],
     349          21 :                                   poPoly->padfY + poPoly->panRingStart[iRing],
     350          21 :                                   poPoly->padfZ + poPoly->panRingStart[iRing]);
     351             : 
     352          21 :                 poOGRPoly->addRingDirectly(poRing);
     353             :             }
     354             : 
     355          37 :             poFeature->SetGeometryDirectly(poOGRPoly);
     356             :         }
     357          37 :         break;
     358             : 
     359         189 :         default:
     360         189 :             break;
     361             :     }
     362             : 
     363             :     /* -------------------------------------------------------------------- */
     364             :     /*      Set attributes for any indicated attribute records.             */
     365             :     /* -------------------------------------------------------------------- */
     366         389 :     for (int iAttrRecord = 0; iAttrRecord < poSDTSFeature->nAttributes;
     367             :          iAttrRecord++)
     368             :     {
     369             :         DDFField *poSR =
     370           6 :             poTransfer->GetAttr(poSDTSFeature->paoATID + iAttrRecord);
     371           6 :         if (poSR != nullptr)
     372           6 :             AssignAttrRecordToFeature(poFeature, poTransfer, poSR);
     373             :     }
     374             : 
     375             :     /* -------------------------------------------------------------------- */
     376             :     /*      If this record is an attribute record, attach the local         */
     377             :     /*      attributes.                                                     */
     378             :     /* -------------------------------------------------------------------- */
     379         383 :     if (poTransfer->GetLayerType(iLayer) == SLTAttr)
     380             :     {
     381         189 :         AssignAttrRecordToFeature(poFeature, poTransfer,
     382             :                                   ((SDTSAttrRecord *)poSDTSFeature)->poATTR);
     383             :     }
     384             : 
     385             :     /* -------------------------------------------------------------------- */
     386             :     /*      Translate the record id.                                        */
     387             :     /* -------------------------------------------------------------------- */
     388         383 :     poFeature->SetFID(poSDTSFeature->oModId.nRecord);
     389         383 :     poFeature->SetField(0, (int)poSDTSFeature->oModId.nRecord);
     390         383 :     if (poFeature->GetGeometryRef() != nullptr)
     391         388 :         poFeature->GetGeometryRef()->assignSpatialReference(
     392         194 :             poDS->GetSpatialRef());
     393             : 
     394         383 :     if (!bIsIndexed)
     395         346 :         delete poSDTSFeature;
     396             : 
     397         383 :     return poFeature;
     398             : }
     399             : 
     400             : /************************************************************************/
     401             : /*                           GetNextFeature()                           */
     402             : /************************************************************************/
     403             : 
     404         391 : OGRFeature *OGRSDTSLayer::GetNextFeature()
     405             : 
     406             : {
     407         391 :     OGRFeature *poFeature = nullptr;
     408             : 
     409             :     /* -------------------------------------------------------------------- */
     410             :     /*      Read features till we find one that satisfies our current       */
     411             :     /*      spatial criteria.                                               */
     412             :     /* -------------------------------------------------------------------- */
     413             :     while (true)
     414             :     {
     415         391 :         poFeature = GetNextUnfilteredFeature();
     416         391 :         if (poFeature == nullptr)
     417           8 :             break;
     418             : 
     419         766 :         if ((m_poFilterGeom == nullptr ||
     420         766 :              FilterGeometry(poFeature->GetGeometryRef())) &&
     421         383 :             (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature)))
     422         383 :             break;
     423             : 
     424           0 :         delete poFeature;
     425             :     }
     426             : 
     427         391 :     return poFeature;
     428             : }
     429             : 
     430             : /************************************************************************/
     431             : /*                           TestCapability()                           */
     432             : /************************************************************************/
     433             : 
     434           0 : int OGRSDTSLayer::TestCapability(const char * /* pszCap */)
     435             : 
     436             : {
     437           0 :     return FALSE;
     438             : }

Generated by: LCOV version 1.14