LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/avc - ogravcbinlayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 130 154 84.4 %
Date: 2024-05-06 22:33:47 Functions: 9 10 90.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OGR
       4             :  * Purpose:  Implements OGRAVCBinLayer class.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com>
       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_avc.h"
      30             : #include "ogr_api.h"
      31             : #include "cpl_conv.h"
      32             : #include "cpl_string.h"
      33             : 
      34             : #include <cstdlib>
      35             : 
      36             : /************************************************************************/
      37             : /*                           OGRAVCBinLayer()                           */
      38             : /************************************************************************/
      39             : 
      40           7 : OGRAVCBinLayer::OGRAVCBinLayer(OGRAVCBinDataSource *poDSIn,
      41           7 :                                AVCE00Section *psSectionIn)
      42             :     : OGRAVCLayer(psSectionIn->eType, poDSIn), m_psSection(psSectionIn),
      43             :       hFile(nullptr), poArcLayer(nullptr), bNeedReset(false), hTable(nullptr),
      44           7 :       nTableBaseField(-1), nTableAttrIndex(-1), nNextFID(1)
      45             : {
      46           7 :     SetupFeatureDefinition(m_psSection->pszName);
      47             : 
      48           7 :     szTableName[0] = '\0';
      49           7 :     if (m_psSection->eType == AVCFilePAL)
      50           1 :         snprintf(szTableName, sizeof(szTableName), "%s.PAT",
      51           1 :                  poDS->GetCoverageName());
      52           6 :     else if (m_psSection->eType == AVCFileRPL)
      53           0 :         snprintf(szTableName, sizeof(szTableName), "%s.PAT%s",
      54           0 :                  poDS->GetCoverageName(), m_psSection->pszName);
      55           6 :     else if (m_psSection->eType == AVCFileARC)
      56           2 :         snprintf(szTableName, sizeof(szTableName), "%s.AAT",
      57           2 :                  poDS->GetCoverageName());
      58           4 :     else if (m_psSection->eType == AVCFileLAB)
      59             :     {
      60             :         AVCE00ReadPtr psInfo =
      61           3 :             static_cast<OGRAVCBinDataSource *>(poDS)->GetInfo();
      62             : 
      63           6 :         snprintf(szTableName, sizeof(szTableName), "%s.PAT",
      64           3 :                  poDS->GetCoverageName());
      65             : 
      66          41 :         for (int iSection = 0; iSection < psInfo->numSections; iSection++)
      67             :         {
      68          38 :             if (psInfo->pasSections[iSection].eType == AVCFilePAL)
      69           1 :                 nTableAttrIndex = poFeatureDefn->GetFieldIndex("PolyId");
      70             :         }
      71             :     }
      72             : 
      73           7 :     CheckSetupTable();
      74           7 : }
      75             : 
      76             : /************************************************************************/
      77             : /*                          ~OGRAVCBinLayer()                           */
      78             : /************************************************************************/
      79             : 
      80          14 : OGRAVCBinLayer::~OGRAVCBinLayer()
      81             : 
      82             : {
      83           7 :     OGRAVCBinLayer::ResetReading();
      84          14 : }
      85             : 
      86             : /************************************************************************/
      87             : /*                            ResetReading()                            */
      88             : /************************************************************************/
      89             : 
      90          14 : void OGRAVCBinLayer::ResetReading()
      91             : 
      92             : {
      93          14 :     if (hFile != nullptr)
      94             :     {
      95           7 :         AVCBinReadClose(hFile);
      96           7 :         hFile = nullptr;
      97             :     }
      98             : 
      99          14 :     bNeedReset = false;
     100          14 :     nNextFID = 1;
     101          14 :     m_bEOF = false;
     102             : 
     103          14 :     if (hTable != nullptr)
     104             :     {
     105           4 :         AVCBinReadClose(hTable);
     106           4 :         hTable = nullptr;
     107             :     }
     108          14 : }
     109             : 
     110             : /************************************************************************/
     111             : /*                             GetFeature()                             */
     112             : /************************************************************************/
     113             : 
     114         209 : OGRFeature *OGRAVCBinLayer::GetFeature(GIntBig nFID)
     115             : 
     116             : {
     117         209 :     if (!CPL_INT64_FITS_ON_INT32(nFID))
     118           0 :         return nullptr;
     119             : 
     120             :     /* -------------------------------------------------------------------- */
     121             :     /*      If we haven't started yet, open the file now.                   */
     122             :     /* -------------------------------------------------------------------- */
     123         209 :     if (hFile == nullptr)
     124             :     {
     125             :         AVCE00ReadPtr psInfo =
     126           7 :             static_cast<OGRAVCBinDataSource *>(poDS)->GetInfo();
     127             : 
     128          14 :         hFile = AVCBinReadOpen(psInfo->pszCoverPath, m_psSection->pszFilename,
     129           7 :                                psInfo->eCoverType, m_psSection->eType,
     130             :                                psInfo->psDBCSInfo);
     131           7 :         if (hFile == nullptr)
     132           0 :             return nullptr;
     133             :     }
     134             : 
     135             :     /* -------------------------------------------------------------------- */
     136             :     /*      Read the raw feature - the SERIAL_ACCESS_FID fid is a special flag
     137             :      */
     138             :     /*      indicating serial access.                                       */
     139             :     /* -------------------------------------------------------------------- */
     140         209 :     void *pFeature = nullptr;
     141             : 
     142         209 :     if (nFID == SERIAL_ACCESS_FID)
     143             :     {
     144         357 :         while ((pFeature = AVCBinReadNextObject(hFile)) != nullptr &&
     145         176 :                !MatchesSpatialFilter(pFeature))
     146             :         {
     147           0 :             nNextFID++;
     148             :         }
     149             :     }
     150             :     else
     151             :     {
     152          28 :         bNeedReset = true;
     153          28 :         pFeature = AVCBinReadObject(hFile, (int)nFID);
     154             :     }
     155             : 
     156         209 :     if (pFeature == nullptr)
     157           5 :         return nullptr;
     158             : 
     159             :     /* -------------------------------------------------------------------- */
     160             :     /*      Translate the feature.                                          */
     161             :     /* -------------------------------------------------------------------- */
     162         204 :     OGRFeature *poFeature = TranslateFeature(pFeature);
     163         204 :     if (poFeature == nullptr)
     164           0 :         return nullptr;
     165             : 
     166             :     /* -------------------------------------------------------------------- */
     167             :     /*      LAB's we have to assign the FID to directly, since it           */
     168             :     /*      doesn't seem to be stored in the file structure.                */
     169             :     /* -------------------------------------------------------------------- */
     170         204 :     if (m_psSection->eType == AVCFileLAB)
     171             :     {
     172         160 :         if (nFID == SERIAL_ACCESS_FID)
     173         160 :             poFeature->SetFID(nNextFID++);
     174             :         else
     175           0 :             poFeature->SetFID(nFID);
     176             :     }
     177             : 
     178             :     /* -------------------------------------------------------------------- */
     179             :     /*      If this is a polygon layer, try to assemble the arcs to form    */
     180             :     /*      the whole polygon geometry.                                     */
     181             :     /* -------------------------------------------------------------------- */
     182         204 :     if (m_psSection->eType == AVCFilePAL || m_psSection->eType == AVCFileRPL)
     183           8 :         FormPolygonGeometry(poFeature, (AVCPal *)pFeature);
     184             : 
     185             :     /* -------------------------------------------------------------------- */
     186             :     /*      If we have an attribute table, append the attributes now.       */
     187             :     /* -------------------------------------------------------------------- */
     188         204 :     AppendTableFields(poFeature);
     189             : 
     190         204 :     return poFeature;
     191             : }
     192             : 
     193             : /************************************************************************/
     194             : /*                           GetNextFeature()                           */
     195             : /************************************************************************/
     196             : 
     197         179 : OGRFeature *OGRAVCBinLayer::GetNextFeature()
     198             : 
     199             : {
     200         179 :     if (m_bEOF)
     201           0 :         return nullptr;
     202             : 
     203         179 :     if (bNeedReset)
     204           0 :         ResetReading();
     205             : 
     206         179 :     OGRFeature *poFeature = GetFeature(SERIAL_ACCESS_FID);
     207             : 
     208             :     // Skip universe polygon.
     209         185 :     if (poFeature != nullptr && poFeature->GetFID() == 1 &&
     210           6 :         m_psSection->eType == AVCFilePAL)
     211             :     {
     212           2 :         OGRFeature::DestroyFeature(poFeature);
     213           2 :         poFeature = GetFeature(SERIAL_ACCESS_FID);
     214             :     }
     215             : 
     216         353 :     while (poFeature != nullptr &&
     217         174 :            ((m_poAttrQuery != nullptr && !m_poAttrQuery->Evaluate(poFeature)) ||
     218         174 :             !FilterGeometry(poFeature->GetGeometryRef())))
     219             :     {
     220           0 :         OGRFeature::DestroyFeature(poFeature);
     221           0 :         poFeature = GetFeature(SERIAL_ACCESS_FID);
     222             :     }
     223             : 
     224         179 :     if (poFeature == nullptr)
     225           5 :         m_bEOF = true;
     226             : 
     227         179 :     return poFeature;
     228             : }
     229             : 
     230             : /************************************************************************/
     231             : /*                           TestCapability()                           */
     232             : /************************************************************************/
     233             : 
     234           0 : int OGRAVCBinLayer::TestCapability(const char *pszCap)
     235             : 
     236             : {
     237           0 :     if (eSectionType == AVCFileARC && EQUAL(pszCap, OLCRandomRead))
     238           0 :         return TRUE;
     239             : 
     240           0 :     return OGRAVCLayer::TestCapability(pszCap);
     241             : }
     242             : 
     243             : /************************************************************************/
     244             : /*                        FormPolygonGeometry()                         */
     245             : /*                                                                      */
     246             : /*      Collect all the arcs forming edges to this polygon and form     */
     247             : /*      them into the appropriate OGR geometry on the target feature.   */
     248             : /************************************************************************/
     249             : 
     250           8 : bool OGRAVCBinLayer::FormPolygonGeometry(OGRFeature *poFeature, AVCPal *psPAL)
     251             : 
     252             : {
     253             :     /* -------------------------------------------------------------------- */
     254             :     /*      Try to find the corresponding ARC layer if not already          */
     255             :     /*      recorded.                                                       */
     256             :     /* -------------------------------------------------------------------- */
     257           8 :     if (poArcLayer == nullptr)
     258             :     {
     259           5 :         for (int i = 0; i < poDS->GetLayerCount(); i++)
     260             :         {
     261             :             OGRAVCBinLayer *poLayer =
     262           4 :                 static_cast<OGRAVCBinLayer *>(poDS->GetLayer(i));
     263             : 
     264           4 :             if (poLayer->eSectionType == AVCFileARC)
     265           1 :                 poArcLayer = poLayer;
     266             :         }
     267             : 
     268           1 :         if (poArcLayer == nullptr)
     269           0 :             return false;
     270             :     }
     271             : 
     272             :     /* -------------------------------------------------------------------- */
     273             :     /*      Read all the arcs related to this polygon, making a working     */
     274             :     /*      copy of them since the one returned by AVC is temporary.        */
     275             :     /* -------------------------------------------------------------------- */
     276          16 :     OGRGeometryCollection oArcs;
     277             : 
     278          38 :     for (int iArc = 0; iArc < psPAL->numArcs; iArc++)
     279             :     {
     280          30 :         if (psPAL->pasArcs[iArc].nArcId == 0)
     281           2 :             continue;
     282             : 
     283             :         // If the other side of the line is the same polygon then this
     284             :         // arc is a "bridge" arc and can be discarded.  If we don't discard
     285             :         // it, then we should double it as bridge arcs seem to only appear
     286             :         // once.  But by discarding it we ensure a multi-ring polygon will be
     287             :         // properly formed.
     288          28 :         if (psPAL->pasArcs[iArc].nAdjPoly == psPAL->nPolyId)
     289           0 :             continue;
     290             : 
     291             :         OGRFeature *poArc =
     292          28 :             poArcLayer->GetFeature(std::abs(psPAL->pasArcs[iArc].nArcId));
     293             : 
     294          28 :         if (poArc == nullptr)
     295           0 :             return false;
     296             : 
     297          28 :         if (poArc->GetGeometryRef() == nullptr)
     298           0 :             return false;
     299             : 
     300          28 :         oArcs.addGeometry(poArc->GetGeometryRef());
     301          28 :         OGRFeature::DestroyFeature(poArc);
     302             :     }
     303             : 
     304             :     OGRErr eErr;
     305           8 :     OGRGeometry *poPolygon = OGRGeometry::FromHandle(OGRBuildPolygonFromEdges(
     306             :         (OGRGeometryH)&oArcs, TRUE, FALSE, 0.0, &eErr));
     307           8 :     if (poPolygon != nullptr)
     308             :     {
     309           8 :         poPolygon->assignSpatialReference(GetSpatialRef());
     310           8 :         poFeature->SetGeometryDirectly(poPolygon);
     311             :     }
     312             : 
     313           8 :     return eErr == OGRERR_NONE;
     314             : }
     315             : 
     316             : /************************************************************************/
     317             : /*                          CheckSetupTable()                           */
     318             : /*                                                                      */
     319             : /*      Check if the named table exists, and if so, setup access to     */
     320             : /*      it (open it), and add its fields to the feature class           */
     321             : /*      definition.                                                     */
     322             : /************************************************************************/
     323             : 
     324           7 : bool OGRAVCBinLayer::CheckSetupTable()
     325             : 
     326             : {
     327           7 :     if (szTableName[0] == '\0')
     328           1 :         return false;
     329             : 
     330             :     /* -------------------------------------------------------------------- */
     331             :     /*      Scan for the indicated section.                                 */
     332             :     /* -------------------------------------------------------------------- */
     333           6 :     AVCE00ReadPtr psInfo = static_cast<OGRAVCBinDataSource *>(poDS)->GetInfo();
     334             : 
     335           6 :     AVCE00Section *l_psSection = nullptr;
     336          86 :     for (int iSection = 0; iSection < psInfo->numSections; iSection++)
     337             :     {
     338         160 :         if (EQUAL(szTableName,
     339         163 :                   CPLString(psInfo->pasSections[iSection].pszName).Trim()) &&
     340           3 :             psInfo->pasSections[iSection].eType == AVCFileTABLE)
     341           3 :             l_psSection = psInfo->pasSections + iSection;
     342             :     }
     343             : 
     344           6 :     if (l_psSection == nullptr)
     345             :     {
     346           3 :         szTableName[0] = '\0';
     347           3 :         return false;
     348             :     }
     349             : 
     350             :     /* -------------------------------------------------------------------- */
     351             :     /*      Try opening the table.                                          */
     352             :     /* -------------------------------------------------------------------- */
     353           3 :     hTable =
     354           3 :         AVCBinReadOpen(psInfo->pszInfoPath, szTableName, psInfo->eCoverType,
     355             :                        AVCFileTABLE, psInfo->psDBCSInfo);
     356             : 
     357           3 :     if (hTable == nullptr)
     358             :     {
     359           0 :         szTableName[0] = '\0';
     360           0 :         return false;
     361             :     }
     362             : 
     363             :     /* -------------------------------------------------------------------- */
     364             :     /*      Setup attributes.                                               */
     365             :     /* -------------------------------------------------------------------- */
     366           3 :     nTableBaseField = poFeatureDefn->GetFieldCount();
     367             : 
     368           3 :     AppendTableDefinition(hTable->hdr.psTableDef);
     369             : 
     370             :     /* -------------------------------------------------------------------- */
     371             :     /*      Close table so we don't have to many files open at once.        */
     372             :     /* -------------------------------------------------------------------- */
     373           3 :     AVCBinReadClose(hTable);
     374             : 
     375           3 :     hTable = nullptr;
     376             : 
     377           3 :     return true;
     378             : }
     379             : 
     380             : /************************************************************************/
     381             : /*                         AppendTableFields()                          */
     382             : /************************************************************************/
     383             : 
     384         204 : bool OGRAVCBinLayer::AppendTableFields(OGRFeature *poFeature)
     385             : 
     386             : {
     387         204 :     AVCE00ReadPtr psInfo = static_cast<OGRAVCBinDataSource *>(poDS)->GetInfo();
     388             : 
     389         204 :     if (szTableName[0] == '\0')
     390          36 :         return false;
     391             : 
     392             :     /* -------------------------------------------------------------------- */
     393             :     /*      Open the table if it is currently closed.                       */
     394             :     /* -------------------------------------------------------------------- */
     395         168 :     if (hTable == nullptr)
     396             :     {
     397           4 :         hTable =
     398           4 :             AVCBinReadOpen(psInfo->pszInfoPath, szTableName, psInfo->eCoverType,
     399             :                            AVCFileTABLE, psInfo->psDBCSInfo);
     400             :     }
     401             : 
     402         168 :     if (hTable == nullptr)
     403           0 :         return false;
     404             : 
     405             :     /* -------------------------------------------------------------------- */
     406             :     /*      Read the info record.                                           */
     407             :     /*                                                                      */
     408             :     /*      We usually assume the FID of the feature is the key but in a    */
     409             :     /*      polygon coverage we need to use the PolyId attribute of LAB     */
     410             :     /*      features to lookup the related attributes.  In this case        */
     411             :     /*      nTableAttrIndex will already be setup to refer to the           */
     412             :     /*      PolyId field.                                                   */
     413             :     /* -------------------------------------------------------------------- */
     414         168 :     const int nRecordId = nTableAttrIndex == -1
     415         168 :                               ? static_cast<int>(poFeature->GetFID())
     416           0 :                               : poFeature->GetFieldAsInteger(nTableAttrIndex);
     417             : 
     418         168 :     void *hRecord = AVCBinReadObject(hTable, nRecordId);
     419         168 :     if (hRecord == nullptr)
     420           0 :         return false;
     421             : 
     422             :     /* -------------------------------------------------------------------- */
     423             :     /*      Translate it.                                                   */
     424             :     /* -------------------------------------------------------------------- */
     425         336 :     return TranslateTableFields(poFeature, nTableBaseField,
     426         168 :                                 hTable->hdr.psTableDef, (AVCField *)hRecord);
     427             : }

Generated by: LCOV version 1.14