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

Generated by: LCOV version 1.14