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

Generated by: LCOV version 1.14