LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/avc - ogravce00layer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 156 188 83.0 %
Date: 2024-11-21 22:18:42 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OGR
       4             :  * Purpose:  Implements OGRAVCE00Layer class.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *           James Flemer <jflemer@alum.rpi.edu>
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com>
      10             :  * Copyright (c) 2006, James Flemer <jflemer@alum.rpi.edu>
      11             :  *
      12             :  * SPDX-License-Identifier: MIT
      13             :  ****************************************************************************/
      14             : 
      15             : #include "ogr_avc.h"
      16             : #include "ogr_api.h"
      17             : #include "cpl_conv.h"
      18             : #include "cpl_string.h"
      19             : 
      20             : #include <cstdlib>
      21             : 
      22             : /************************************************************************/
      23             : /*                           OGRAVCE00Layer()                           */
      24             : /************************************************************************/
      25             : 
      26           7 : OGRAVCE00Layer::OGRAVCE00Layer(OGRAVCDataSource *poDSIn,
      27           7 :                                AVCE00Section *psSectionIn)
      28             :     : OGRAVCLayer(psSectionIn->eType, poDSIn), psSection(psSectionIn),
      29             :       psRead(nullptr), poArcLayer(nullptr), nFeatureCount(-1),
      30             :       bNeedReset(false), nNextFID(1), psTableSection(nullptr),
      31             :       psTableRead(nullptr), pszTableFilename(nullptr), nTablePos(0),
      32           7 :       nTableBaseField(0), nTableAttrIndex(-1)
      33             : {
      34           7 :     SetupFeatureDefinition(psSection->pszName);
      35             :     /* psRead = AVCE00ReadOpenE00(psSection->pszFilename); */
      36             : 
      37             : #if 0
      38             :     szTableName[0] = '\0';
      39             :     if( psSection->eType == AVCFilePAL )
      40             :         sprintf( szTableName, "%s.PAT", poDS->GetCoverageName() );
      41             :     else if( psSection->eType == AVCFileRPL )
      42             :         sprintf( szTableName, "%s.PAT%s", poDS->GetCoverageName(),
      43             :                  psSectionIn->pszName );
      44             :     else if( psSection->eType == AVCFileARC )
      45             :         sprintf( szTableName, "%s.AAT", poDS->GetCoverageName() );
      46             :     else if( psSection->eType == AVCFileLAB )
      47             :     {
      48             :         AVCE00ReadPtr psInfo = ((OGRAVCE00DataSource *) poDS)->GetInfo();
      49             : 
      50             :         sprintf( szTableName, "%s.PAT", poDS->GetCoverageName() );
      51             : 
      52             :         for( int iSection = 0; iSection < psInfo->numSections; iSection++ )
      53             :         {
      54             :             if( psInfo->pasSections[iSection].eType == AVCFilePAL )
      55             :                 nTableAttrIndex = poFeatureDefn->GetFieldIndex( "PolyId" );
      56             :         }
      57             :     }
      58             : 
      59             : #endif
      60           7 : }
      61             : 
      62             : /************************************************************************/
      63             : /*                          ~OGRAVCE00Layer()                           */
      64             : /************************************************************************/
      65             : 
      66          14 : OGRAVCE00Layer::~OGRAVCE00Layer()
      67             : 
      68             : {
      69           7 :     if (psRead)
      70             :     {
      71           4 :         AVCE00ReadCloseE00(psRead);
      72           4 :         psRead = nullptr;
      73             :     }
      74             : 
      75           7 :     if (psTableRead)
      76             :     {
      77           3 :         AVCE00ReadCloseE00(psTableRead);
      78           3 :         psTableRead = nullptr;
      79             :     }
      80             : 
      81           7 :     if (pszTableFilename)
      82             :     {
      83           3 :         CPLFree(pszTableFilename);
      84           3 :         pszTableFilename = nullptr;
      85             :     }
      86          14 : }
      87             : 
      88             : /************************************************************************/
      89             : /*                            ResetReading()                            */
      90             : /************************************************************************/
      91             : 
      92           3 : void OGRAVCE00Layer::ResetReading()
      93             : 
      94             : {
      95           3 :     if (psRead)
      96             :     {
      97           1 :         AVCE00ReadGotoSectionE00(psRead, psSection, 0);
      98             :     }
      99             : 
     100           3 :     if (psTableRead)
     101             :     {
     102           2 :         AVCE00ReadGotoSectionE00(psTableRead, psTableSection, 0);
     103             :     }
     104             : 
     105           3 :     m_bEOF = false;
     106           3 :     bNeedReset = false;
     107           3 :     nNextFID = 1;
     108           3 : }
     109             : 
     110             : /************************************************************************/
     111             : /*                             GetFeature()                             */
     112             : /************************************************************************/
     113             : 
     114         109 : OGRFeature *OGRAVCE00Layer::GetFeature(GIntBig nFID)
     115             : 
     116             : {
     117         109 :     if (nFID < 0 && nFID != SERIAL_ACCESS_FID)
     118           0 :         return nullptr;
     119             : 
     120             :     /* -------------------------------------------------------------------- */
     121             :     /*      If we haven't started yet, open the file now.                   */
     122             :     /* -------------------------------------------------------------------- */
     123         109 :     if (psRead == nullptr)
     124             :     {
     125           4 :         psRead = AVCE00ReadOpenE00(psSection->pszFilename);
     126           4 :         if (psRead == nullptr)
     127           0 :             return nullptr;
     128             :         /* advance to the specified line number */
     129           4 :         if (AVCE00ReadGotoSectionE00(psRead, psSection, 0) != 0)
     130           0 :             return nullptr;
     131           4 :         nNextFID = 1;
     132             :     }
     133             : 
     134             :     /* -------------------------------------------------------------------- */
     135             :     /*      Read the raw feature - the SERIAL_ACCESS_FID fid is a special flag
     136             :      */
     137             :     /*      indicating serial access.                                       */
     138             :     /* -------------------------------------------------------------------- */
     139         109 :     void *pFeature = nullptr;
     140             : 
     141         109 :     if (nFID == SERIAL_ACCESS_FID)
     142             :     {
     143          95 :         bLastWasSequential = true;
     144             : 
     145          95 :         while ((pFeature = AVCE00ReadNextObjectE00(psRead)) != nullptr &&
     146         187 :                psRead->hParseInfo->eFileType != AVCFileUnknown &&
     147          92 :                !MatchesSpatialFilter(pFeature))
     148             :         {
     149           0 :             nNextFID++;
     150             :         }
     151             :     }
     152             :     else
     153             :     {
     154          14 :         bNeedReset = true;
     155             : 
     156          14 :         if (nNextFID > nFID || bLastWasSequential)
     157             :         {
     158           6 :             bLastWasSequential = false;
     159             :             /* advance to the specified line number */
     160           6 :             if (AVCE00ReadGotoSectionE00(psRead, psSection, 0) != 0)
     161           0 :                 return nullptr;
     162           6 :             nNextFID = 1;
     163             :         }
     164             : 
     165          20 :         do
     166             :         {
     167          34 :             pFeature = AVCE00ReadNextObjectE00(psRead);
     168          34 :             ++nNextFID;
     169          34 :         } while (nullptr != pFeature && nNextFID <= nFID);
     170             :     }
     171             : 
     172         109 :     if (pFeature == nullptr)
     173           3 :         return nullptr;
     174         106 :     if (eSectionType != psRead->hParseInfo->eFileType)
     175           0 :         return nullptr;
     176             : 
     177             :     /* -------------------------------------------------------------------- */
     178             :     /*      Translate the feature.                                          */
     179             :     /* -------------------------------------------------------------------- */
     180         106 :     OGRFeature *poFeature = TranslateFeature(pFeature);
     181         106 :     if (poFeature == nullptr)
     182           0 :         return nullptr;
     183             : 
     184             :     /* -------------------------------------------------------------------- */
     185             :     /*      LAB's we have to assign the FID to directly, since it           */
     186             :     /*      doesn't seem to be stored in the file structure.                */
     187             :     /* -------------------------------------------------------------------- */
     188         106 :     if (psSection->eType == AVCFileLAB)
     189             :     {
     190          80 :         if (nFID == SERIAL_ACCESS_FID)
     191          80 :             poFeature->SetFID(nNextFID++);
     192             :         else
     193           0 :             poFeature->SetFID(nFID);
     194             :     }
     195             : 
     196             :     /* -------------------------------------------------------------------- */
     197             :     /*      If this is a polygon layer, try to assemble the arcs to form    */
     198             :     /*      the whole polygon geometry.                                     */
     199             :     /* -------------------------------------------------------------------- */
     200         106 :     if (psSection->eType == AVCFilePAL || psSection->eType == AVCFileRPL)
     201             :     {
     202           4 :         FormPolygonGeometry(poFeature, static_cast<AVCPal *>(pFeature));
     203             :     }
     204             : 
     205             :     /* -------------------------------------------------------------------- */
     206             :     /*      If we have an attribute table, append the attributes now.       */
     207             :     /* -------------------------------------------------------------------- */
     208         106 :     AppendTableFields(poFeature);
     209             : 
     210         106 :     return poFeature;
     211             : }
     212             : 
     213             : /************************************************************************/
     214             : /*                           GetNextFeature()                           */
     215             : /************************************************************************/
     216             : 
     217          94 : OGRFeature *OGRAVCE00Layer::GetNextFeature()
     218             : 
     219             : {
     220          94 :     if (m_bEOF)
     221           0 :         return nullptr;
     222             : 
     223          94 :     if (bNeedReset)
     224           0 :         ResetReading();
     225             : 
     226          94 :     OGRFeature *poFeature = GetFeature(SERIAL_ACCESS_FID);
     227             : 
     228             :     // Skip universe polygon.
     229          98 :     if (poFeature != nullptr && poFeature->GetFID() == 1 &&
     230           4 :         psSection->eType == AVCFilePAL)
     231             :     {
     232           1 :         OGRFeature::DestroyFeature(poFeature);
     233           1 :         poFeature = GetFeature(SERIAL_ACCESS_FID);
     234             :     }
     235             : 
     236         185 :     while (poFeature != nullptr &&
     237          91 :            ((m_poAttrQuery != nullptr && !m_poAttrQuery->Evaluate(poFeature)) ||
     238          91 :             !FilterGeometry(poFeature->GetGeometryRef())))
     239             :     {
     240           0 :         OGRFeature::DestroyFeature(poFeature);
     241           0 :         poFeature = GetFeature(SERIAL_ACCESS_FID);
     242             :     }
     243             : 
     244          94 :     if (poFeature == nullptr)
     245           3 :         m_bEOF = true;
     246             : 
     247          94 :     return poFeature;
     248             : }
     249             : 
     250             : /************************************************************************/
     251             : /*                           TestCapability()                           */
     252             : /************************************************************************/
     253             : 
     254             : #if 0
     255             : int OGRAVCE00Layer::TestCapability( const char * pszCap )
     256             : 
     257             : {
     258             :     if( eSectionType == AVCFileARC && EQUAL(pszCap,OLCRandomRead) )
     259             :         return TRUE;
     260             : 
     261             :     return OGRAVCLayer::TestCapability( pszCap );
     262             : }
     263             : #endif
     264             : 
     265             : /************************************************************************/
     266             : /*                        FormPolygonGeometry()                         */
     267             : /*                                                                      */
     268             : /*      Collect all the arcs forming edges to this polygon and form     */
     269             : /*      them into the appropriate OGR geometry on the target feature.   */
     270             : /************************************************************************/
     271             : 
     272           4 : bool OGRAVCE00Layer::FormPolygonGeometry(OGRFeature *poFeature, AVCPal *psPAL)
     273             : {
     274             :     /* -------------------------------------------------------------------- */
     275             :     /*      Try to find the corresponding ARC layer if not already          */
     276             :     /*      recorded.                                                       */
     277             :     /* -------------------------------------------------------------------- */
     278           4 :     if (poArcLayer == nullptr)
     279             :     {
     280           5 :         for (int i = 0; i < poDS->GetLayerCount(); i++)
     281             :         {
     282             :             OGRAVCE00Layer *poLayer =
     283           4 :                 static_cast<OGRAVCE00Layer *>(poDS->GetLayer(i));
     284             : 
     285           4 :             if (poLayer->eSectionType == AVCFileARC)
     286           1 :                 poArcLayer = poLayer;
     287             :         }
     288             : 
     289           1 :         if (poArcLayer == nullptr)
     290           0 :             return false;
     291             :     }
     292             : 
     293             :     /* -------------------------------------------------------------------- */
     294             :     /*  Read all the arcs related to this polygon, making a working         */
     295             :     /*  copy of them since the one returned by AVC is temporary.            */
     296             :     /* -------------------------------------------------------------------- */
     297           8 :     OGRGeometryCollection oArcs;
     298             : 
     299          19 :     for (int iArc = 0; iArc < psPAL->numArcs; iArc++)
     300             :     {
     301          15 :         if (psPAL->pasArcs[iArc].nArcId == 0 ||
     302          14 :             psPAL->pasArcs[iArc].nArcId == INT_MIN)
     303             :         {
     304           1 :             continue;
     305             :         }
     306             : 
     307             :         // If the other side of the line is the same polygon then this
     308             :         // arc is a "bridge" arc and can be discarded.  If we don't discard
     309             :         // it, then we should double it as bridge arcs seem to only appear
     310             :         // once.  But by discarding it we ensure a multi-ring polygon will be
     311             :         // properly formed.
     312          14 :         if (psPAL->pasArcs[iArc].nAdjPoly == psPAL->nPolyId)
     313           0 :             continue;
     314             : 
     315             :         auto poArc = std::unique_ptr<OGRFeature>(
     316          14 :             poArcLayer->GetFeature(std::abs(psPAL->pasArcs[iArc].nArcId)));
     317             : 
     318          14 :         if (poArc == nullptr)
     319           0 :             return false;
     320             : 
     321          14 :         if (poArc->GetGeometryRef() == nullptr)
     322           0 :             return false;
     323             : 
     324          14 :         oArcs.addGeometryDirectly(poArc->StealGeometry());
     325             :     }
     326             : 
     327             :     OGRErr eErr;
     328           4 :     OGRGeometry *poPolygon = OGRGeometry::FromHandle(OGRBuildPolygonFromEdges(
     329             :         OGRGeometry::ToHandle(&oArcs), TRUE, FALSE, 0.0, &eErr));
     330           4 :     if (poPolygon != nullptr)
     331             :     {
     332           4 :         poPolygon->assignSpatialReference(GetSpatialRef());
     333           4 :         poFeature->SetGeometryDirectly(poPolygon);
     334             :     }
     335             : 
     336           4 :     return eErr == OGRERR_NONE;
     337             : }
     338             : 
     339             : /************************************************************************/
     340             : /*                          CheckSetupTable()                           */
     341             : /*                                                                      */
     342             : /*      Check if the named table exists, and if so, setup access to     */
     343             : /*      it (open it), and add its fields to the feature class           */
     344             : /*      definition.                                                     */
     345             : /************************************************************************/
     346             : 
     347          31 : bool OGRAVCE00Layer::CheckSetupTable(AVCE00Section *psTblSectionIn)
     348             : {
     349          31 :     if (psTableRead)
     350           5 :         return false;
     351             : 
     352          26 :     const char *pszTableType = nullptr;
     353          26 :     switch (eSectionType)
     354             :     {
     355           9 :         case AVCFileARC:
     356           9 :             pszTableType = ".AAT";
     357           9 :             break;
     358             : 
     359          12 :         case AVCFilePAL:
     360             :         case AVCFileLAB:
     361          12 :             pszTableType = ".PAT";
     362          12 :             break;
     363             : 
     364           5 :         default:
     365           5 :             break;
     366             :     }
     367             : 
     368             :     /* -------------------------------------------------------------------- */
     369             :     /*      Is the table type found anywhere in the section pszName?  Do    */
     370             :     /*      a case insensitive check.                                       */
     371             :     /* -------------------------------------------------------------------- */
     372          26 :     if (pszTableType == nullptr)
     373           5 :         return false;
     374             : 
     375          21 :     int iCheckOff = 0;
     376         618 :     for (; psTblSectionIn->pszName[iCheckOff] != '\0'; iCheckOff++)
     377             :     {
     378         600 :         if (EQUALN(psTblSectionIn->pszName + iCheckOff, pszTableType,
     379             :                    strlen(pszTableType)))
     380           3 :             break;
     381             :     }
     382             : 
     383          21 :     if (psTblSectionIn->pszName[iCheckOff] == '\0')
     384          18 :         return false;
     385             : 
     386           3 :     psTableSection = psTblSectionIn;
     387             : 
     388             :     /* -------------------------------------------------------------------- */
     389             :     /*      Try opening the table.                                          */
     390             :     /* -------------------------------------------------------------------- */
     391           3 :     psTableRead = AVCE00ReadOpenE00(psTblSectionIn->pszFilename);
     392           3 :     if (psTableRead == nullptr)
     393           0 :         return false;
     394             : 
     395             :     /* advance to the specified line number */
     396           3 :     if (AVCE00ReadGotoSectionE00(psTableRead, psTableSection, 0) != 0)
     397             :     {
     398           0 :         AVCE00ReadCloseE00(psTableRead);
     399           0 :         psTableRead = nullptr;
     400           0 :         return false;
     401             :     }
     402             : 
     403           3 :     AVCE00ReadNextObjectE00(psTableRead);
     404           3 :     bNeedReset = true;
     405             : 
     406           3 :     CPLFree(pszTableFilename);
     407           3 :     pszTableFilename = CPLStrdup(psTblSectionIn->pszFilename);
     408           3 :     nTableBaseField = poFeatureDefn->GetFieldCount();
     409             : 
     410           3 :     if (eSectionType == AVCFileLAB)
     411             :     {
     412             :         AVCE00ReadE00Ptr psInfo =
     413           2 :             static_cast<OGRAVCE00DataSource *>(poDS)->GetInfo();
     414          16 :         for (int iSection = 0; iSection < psInfo->numSections; iSection++)
     415             :         {
     416          14 :             if (psInfo->pasSections[iSection].eType == AVCFilePAL)
     417           1 :                 nTableAttrIndex = poFeatureDefn->GetFieldIndex("PolyId");
     418             :         }
     419             :     }
     420             : 
     421             :     /* -------------------------------------------------------------------- */
     422             :     /*      Setup attributes.                                               */
     423             :     /* -------------------------------------------------------------------- */
     424           3 :     if (psTableRead->hParseInfo->hdr.psTableDef == nullptr)
     425             :     {
     426           0 :         AVCE00ReadCloseE00(psTableRead);
     427           0 :         psTableRead = nullptr;
     428           0 :         return false;
     429             :     }
     430             : 
     431           3 :     AppendTableDefinition(psTableRead->hParseInfo->hdr.psTableDef);
     432             : 
     433             :     /* -------------------------------------------------------------------- */
     434             :     /*      Close table so we don't have to many files open at once.        */
     435             :     /* -------------------------------------------------------------------- */
     436             :     /* AVCE00ReadCloseE00( psTableRead ); */
     437             : 
     438           3 :     return true;
     439             : }
     440             : 
     441             : /************************************************************************/
     442             : /*                         AppendTableFields()                          */
     443             : /************************************************************************/
     444             : 
     445         106 : bool OGRAVCE00Layer::AppendTableFields(OGRFeature *poFeature)
     446             : 
     447             : {
     448         106 :     if (psTableRead == nullptr)
     449          22 :         return false;
     450             : #ifdef deadcode
     451             :     /* -------------------------------------------------------------------- */
     452             :     /*      Open the table if it is currently closed.                       */
     453             :     /* -------------------------------------------------------------------- */
     454             :     if (psTableRead == nullptr)
     455             :     {
     456             :         psTableRead = AVCE00ReadOpenE00(pszTableFilename);
     457             :         if (psTableRead == nullptr)
     458             :             return false;
     459             : 
     460             :         /* Advance to the specified line number */
     461             :         if (AVCE00ReadGotoSectionE00(psTableRead, psTableSection, 0) != 0)
     462             :         {
     463             :             AVCE00ReadCloseE00(psTableRead);
     464             :             psTableRead = nullptr;
     465             :             return false;
     466             :         }
     467             :         nTablePos = 0;
     468             :     }
     469             : #endif
     470             :     /* -------------------------------------------------------------------- */
     471             :     /*      Read the info record.                                           */
     472             :     /*                                                                      */
     473             :     /*      We usually assume the FID of the feature is the key but in a    */
     474             :     /*      polygon coverage we need to use the PolyId attribute of LAB     */
     475             :     /*      features to lookup the related attributes.  In this case        */
     476             :     /*      nTableAttrIndex will already be setup to refer to the           */
     477             :     /*      PolyId field.                                                   */
     478             :     /* -------------------------------------------------------------------- */
     479          84 :     const int nRecordId = nTableAttrIndex == -1
     480          84 :                               ? static_cast<int>(poFeature->GetFID())
     481           0 :                               : poFeature->GetFieldAsInteger(nTableAttrIndex);
     482             : 
     483          84 :     if (nRecordId <= nTablePos)
     484             :     {
     485           0 :         if (AVCE00ReadGotoSectionE00(psTableRead, psTableSection, 0) != 0)
     486           0 :             return false;
     487           0 :         nTablePos = 0;
     488             :     }
     489             : 
     490          84 :     void *hRecord = nullptr;
     491           0 :     do
     492             :     {
     493          84 :         hRecord = AVCE00ReadNextObjectE00(psTableRead);
     494          84 :         ++nTablePos;
     495          84 :     } while (nullptr != hRecord && nTablePos < nRecordId);
     496             : 
     497          84 :     if (hRecord == nullptr)
     498           0 :         return false;
     499          84 :     if (psTableRead->hParseInfo->hdr.psTableDef == nullptr)
     500           0 :         return false;
     501             : 
     502             :     /* -------------------------------------------------------------------- */
     503             :     /*      Translate it.                                                   */
     504             :     /* -------------------------------------------------------------------- */
     505         168 :     return TranslateTableFields(poFeature, nTableBaseField,
     506          84 :                                 psTableRead->hParseInfo->hdr.psTableDef,
     507          84 :                                 static_cast<AVCField *>(hRecord));
     508             : }
     509             : 
     510           2 : GIntBig OGRAVCE00Layer::GetFeatureCount(int bForce)
     511             : {
     512           2 :     if (m_poAttrQuery != nullptr || m_poFilterGeom != nullptr)
     513           0 :         return OGRAVCLayer::GetFeatureCount(bForce);
     514             : 
     515           2 :     if (bForce && nFeatureCount < 0)
     516             :     {
     517           2 :         if (psSection->nFeatureCount < 0)
     518             :         {
     519           0 :             nFeatureCount = (int)OGRLayer::GetFeatureCount(bForce);
     520             :         }
     521             :         else
     522             :         {
     523           2 :             nFeatureCount = psSection->nFeatureCount;
     524           2 :             if (psSection->eType == AVCFilePAL)
     525           1 :                 --nFeatureCount;
     526             :         }
     527             :     }
     528           2 :     return nFeatureCount;
     529             : }

Generated by: LCOV version 1.14