LCOV - code coverage report
Current view: top level - frmts/sdts - sdtspolygonreader.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 178 215 82.8 %
Date: 2024-11-21 22:18:42 Functions: 13 15 86.7 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  SDTS Translator
       4             :  * Purpose:  Implementation of SDTSPolygonReader and SDTSRawPolygon classes.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 1999, Frank Warmerdam
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "sdts_al.h"
      14             : 
      15             : #include <cmath>
      16             : 
      17             : /************************************************************************/
      18             : /* ==================================================================== */
      19             : /*                            SDTSRawPolygon                            */
      20             : /*                                                                      */
      21             : /*      This is a simple class for holding the data related with a      */
      22             : /*      polygon feature.                                                */
      23             : /* ==================================================================== */
      24             : /************************************************************************/
      25             : 
      26             : /************************************************************************/
      27             : /*                           SDTSRawPolygon()                           */
      28             : /************************************************************************/
      29             : 
      30          35 : SDTSRawPolygon::SDTSRawPolygon()
      31             :     : nEdges(0), papoEdges(nullptr), nRings(0), nVertices(0),
      32          35 :       panRingStart(nullptr), padfX(nullptr), padfY(nullptr), padfZ(nullptr)
      33             : {
      34          35 :     nAttributes = 0;
      35          35 : }
      36             : 
      37             : /************************************************************************/
      38             : /*                          ~SDTSRawPolygon()                           */
      39             : /************************************************************************/
      40             : 
      41          70 : SDTSRawPolygon::~SDTSRawPolygon()
      42             : 
      43             : {
      44          35 :     CPLFree(papoEdges);
      45          35 :     CPLFree(panRingStart);
      46          35 :     CPLFree(padfX);
      47          35 :     CPLFree(padfY);
      48          35 :     CPLFree(padfZ);
      49          70 : }
      50             : 
      51             : /************************************************************************/
      52             : /*                                Read()                                */
      53             : /*                                                                      */
      54             : /*      Read a record from the passed SDTSPolygonReader, and assign the */
      55             : /*      values from that record to this object.  This is the bulk of    */
      56             : /*      the work in this whole file.                                    */
      57             : /************************************************************************/
      58             : 
      59          35 : int SDTSRawPolygon::Read(DDFRecord *poRecord)
      60             : 
      61             : {
      62             :     /* ==================================================================== */
      63             :     /*      Loop over fields in this record, looking for those we           */
      64             :     /*      recognise, and need.                                            */
      65             :     /* ==================================================================== */
      66         105 :     for (int iField = 0; iField < poRecord->GetFieldCount(); iField++)
      67             :     {
      68          70 :         DDFField *poField = poRecord->GetField(iField);
      69          70 :         if (poField == nullptr)
      70           0 :             return FALSE;
      71          70 :         DDFFieldDefn *poFieldDefn = poField->GetFieldDefn();
      72          70 :         if (poFieldDefn == nullptr)
      73           0 :             return FALSE;
      74             : 
      75          70 :         const char *pszFieldName = poFieldDefn->GetName();
      76             : 
      77          70 :         if (EQUAL(pszFieldName, "POLY"))
      78             :         {
      79          35 :             oModId.Set(poField);
      80             :         }
      81             : 
      82          35 :         else if (EQUAL(pszFieldName, "ATID"))
      83             :         {
      84           0 :             ApplyATID(poField);
      85             :         }
      86             :     }
      87             : 
      88          35 :     return TRUE;
      89             : }
      90             : 
      91             : /************************************************************************/
      92             : /*                              AddEdge()                               */
      93             : /************************************************************************/
      94             : 
      95          50 : void SDTSRawPolygon::AddEdge(SDTSRawLine *poNewLine)
      96             : 
      97             : {
      98          50 :     nEdges++;
      99             : 
     100          50 :     papoEdges = reinterpret_cast<SDTSRawLine **>(
     101          50 :         CPLRealloc(papoEdges, sizeof(void *) * nEdges));
     102          50 :     papoEdges[nEdges - 1] = poNewLine;
     103          50 : }
     104             : 
     105             : /************************************************************************/
     106             : /*                           AddEdgeToRing()                            */
     107             : /************************************************************************/
     108             : 
     109          52 : void SDTSRawPolygon::AddEdgeToRing(int nVertToAdd, double *padfXToAdd,
     110             :                                    double *padfYToAdd, double *padfZToAdd,
     111             :                                    int bReverse, int bDropVertex)
     112             : 
     113             : {
     114          52 :     int iStart = 0;
     115          52 :     int iEnd = nVertToAdd - 1;
     116          52 :     int iStep = 1;
     117             : 
     118          52 :     if (bDropVertex && bReverse)
     119             :     {
     120           4 :         iStart = nVertToAdd - 2;
     121           4 :         iEnd = 0;
     122           4 :         iStep = -1;
     123             :     }
     124          48 :     else if (bDropVertex && !bReverse)
     125             :     {
     126          29 :         iStart = 1;
     127          29 :         iEnd = nVertToAdd - 1;
     128          29 :         iStep = 1;
     129             :     }
     130          19 :     else if (!bDropVertex && !bReverse)
     131             :     {
     132          19 :         iStart = 0;
     133          19 :         iEnd = nVertToAdd - 1;
     134          19 :         iStep = 1;
     135             :     }
     136           0 :     else if (!bDropVertex && bReverse)
     137             :     {
     138           0 :         iStart = nVertToAdd - 1;
     139           0 :         iEnd = 0;
     140           0 :         iStep = -1;
     141             :     }
     142             : 
     143        1211 :     for (int i = iStart; i != (iEnd + iStep); i += iStep)
     144             :     {
     145        1159 :         padfX[nVertices] = padfXToAdd[i];
     146        1159 :         padfY[nVertices] = padfYToAdd[i];
     147        1159 :         padfZ[nVertices] = padfZToAdd[i];
     148             : 
     149        1159 :         nVertices++;
     150             :     }
     151          52 : }
     152             : 
     153             : /************************************************************************/
     154             : /*                           AssembleRings()                            */
     155             : /************************************************************************/
     156             : 
     157             : /**
     158             :  * Form border lines (arcs) into outer and inner rings.
     159             :  *
     160             :  * See SDTSPolygonReader::AssemblePolygons() for a simple one step process
     161             :  * to assembling geometry for all polygons in a transfer.
     162             :  *
     163             :  * This method will assemble the lines attached to a polygon into
     164             :  * an outer ring, and zero or more inner rings.  Before calling it is
     165             :  * necessary that all the lines associated with this polygon have already
     166             :  * been attached.  Normally this is accomplished by calling
     167             :  * SDTSLineReader::AttachToPolygons() on all line layers that might
     168             :  * contain edges related to this layer.
     169             :  *
     170             :  * This method then forms the lines into rings.  Rings are formed by:
     171             :  * <ol>
     172             :  * <li> Take a previously unconsumed line, and start a ring with it.  Mark
     173             :  *      it as consumed, and keep track of its start and end node ids as
     174             :  *      being the start and end node ids of the ring.
     175             :  * <li> If the rings start id is the same as the end node id then this ring
     176             :  *      is completely formed, return to step 1.
     177             :  * <li> Search all unconsumed lines for a line with the same start or end
     178             :  *      node id as the rings current node id.  If none are found then the
     179             :  *      assembly has failed.  Return to step 1 but report failure on
     180             :  *      completion.
     181             :  * <li> Once found, add the line to the current ring, dropping the duplicated
     182             :  *      vertex and reverse order if necessary.  Mark the line as consumed,
     183             :  *      and update the rings end node id accordingly.
     184             :  * <li> go to step 2.
     185             :  * </ol>
     186             :  *
     187             :  * Once ring assembly from lines is complete, another pass is made to
     188             :  * order the rings such that the exterior ring is first, the first ring
     189             :  * has counter-clockwise vertex ordering and the inner rings have clockwise
     190             :  * vertex ordering.  This is accomplished based on the assumption that the
     191             :  * outer ring has the largest area, and using the +/- sign of area to establish
     192             :  * direction of rings.
     193             :  *
     194             :  * @return TRUE if all rings assembled without problems or FALSE if a problem
     195             :  * occurred.  If a problem occurs rings are still formed from all lines, but
     196             :  * some of the rings will not be closed, and rings will have no particular
     197             :  * order or direction.
     198             :  */
     199             : 
     200          35 : int SDTSRawPolygon::AssembleRings()
     201             : 
     202             : {
     203          35 :     if (nRings > 0)
     204           0 :         return TRUE;
     205             : 
     206          35 :     if (nEdges == 0)
     207          22 :         return FALSE;
     208             : 
     209             :     /* -------------------------------------------------------------------- */
     210             :     /*      Setup array of line markers indicating if they have been        */
     211             :     /*      added to a ring yet.                                            */
     212             :     /* -------------------------------------------------------------------- */
     213          13 :     int nRemainingEdges = nEdges;
     214             : 
     215             :     int *panEdgeConsumed =
     216          13 :         reinterpret_cast<int *>(CPLCalloc(sizeof(int), nEdges));
     217             : 
     218             :     /* -------------------------------------------------------------------- */
     219             :     /*      Allocate ring arrays.                                           */
     220             :     /* -------------------------------------------------------------------- */
     221          13 :     panRingStart = reinterpret_cast<int *>(CPLMalloc(sizeof(int) * nEdges));
     222             : 
     223          13 :     nVertices = 0;
     224          63 :     for (int iEdge = 0; iEdge < nEdges; iEdge++)
     225             :     {
     226          50 :         if (papoEdges[iEdge]->nVertices < 2)
     227             :         {
     228           0 :             panEdgeConsumed[iEdge] = TRUE;
     229           0 :             nRemainingEdges--;
     230             :         }
     231             :         else
     232             :         {
     233          50 :             nVertices += papoEdges[iEdge]->nVertices;
     234             :         }
     235             :     }
     236             : 
     237          13 :     padfX = reinterpret_cast<double *>(CPLMalloc(sizeof(double) * nVertices));
     238          13 :     padfY = reinterpret_cast<double *>(CPLMalloc(sizeof(double) * nVertices));
     239          13 :     padfZ = reinterpret_cast<double *>(CPLMalloc(sizeof(double) * nVertices));
     240             : 
     241          13 :     nVertices = 0;
     242             : 
     243             :     /* ==================================================================== */
     244             :     /*      Loop generating rings.                                          */
     245             :     /* ==================================================================== */
     246          13 :     bool bSuccess = true;
     247             : 
     248          30 :     while (nRemainingEdges > 0)
     249             :     {
     250             :         /* --------------------------------------------------------------------
     251             :          */
     252             :         /*      Find the first unconsumed edge. */
     253             :         /* --------------------------------------------------------------------
     254             :          */
     255          17 :         int iEdge = 0;
     256          25 :         for (; panEdgeConsumed[iEdge]; iEdge++)
     257             :         {
     258             :         }
     259             : 
     260          17 :         SDTSRawLine *poEdge = papoEdges[iEdge];
     261             : 
     262             :         /* --------------------------------------------------------------------
     263             :          */
     264             :         /*      Start a new ring, copying in the current line directly */
     265             :         /* --------------------------------------------------------------------
     266             :          */
     267          17 :         panRingStart[nRings++] = nVertices;
     268             : 
     269          17 :         AddEdgeToRing(poEdge->nVertices, poEdge->padfX, poEdge->padfY,
     270             :                       poEdge->padfZ, FALSE, FALSE);
     271             : 
     272          17 :         panEdgeConsumed[iEdge] = TRUE;
     273          17 :         nRemainingEdges--;
     274             : 
     275          17 :         const int nStartNode = poEdge->oStartNode.nRecord;
     276          17 :         int nLinkNode = poEdge->oEndNode.nRecord;
     277             : 
     278             :         /* ====================================================================
     279             :          */
     280             :         /*      Loop adding edges to this ring until we make a whole pass */
     281             :         /*      within finding anything to add. */
     282             :         /* ====================================================================
     283             :          */
     284          17 :         bool bWorkDone = true;
     285             : 
     286          38 :         while (nLinkNode != nStartNode && nRemainingEdges > 0 && bWorkDone)
     287             :         {
     288          21 :             bWorkDone = false;
     289             : 
     290         319 :             for (iEdge = 0; iEdge < nEdges; iEdge++)
     291             :             {
     292         298 :                 if (panEdgeConsumed[iEdge])
     293         182 :                     continue;
     294             : 
     295         116 :                 poEdge = papoEdges[iEdge];
     296         116 :                 if (poEdge->oStartNode.nRecord == nLinkNode)
     297             :                 {
     298          29 :                     AddEdgeToRing(poEdge->nVertices, poEdge->padfX,
     299             :                                   poEdge->padfY, poEdge->padfZ, FALSE, TRUE);
     300          29 :                     nLinkNode = poEdge->oEndNode.nRecord;
     301             :                 }
     302          87 :                 else if (poEdge->oEndNode.nRecord == nLinkNode)
     303             :                 {
     304           4 :                     AddEdgeToRing(poEdge->nVertices, poEdge->padfX,
     305             :                                   poEdge->padfY, poEdge->padfZ, TRUE, TRUE);
     306           4 :                     nLinkNode = poEdge->oStartNode.nRecord;
     307             :                 }
     308             :                 else
     309             :                 {
     310          83 :                     continue;
     311             :                 }
     312             : 
     313          33 :                 panEdgeConsumed[iEdge] = TRUE;
     314          33 :                 nRemainingEdges--;
     315          33 :                 bWorkDone = true;
     316             :             }
     317             :         }
     318             : 
     319             :         /* --------------------------------------------------------------------
     320             :          */
     321             :         /*      Did we fail to complete the ring? */
     322             :         /* --------------------------------------------------------------------
     323             :          */
     324          17 :         if (nLinkNode != nStartNode)
     325          15 :             bSuccess = false;
     326             :     } /* next ring */
     327             : 
     328          13 :     CPLFree(panEdgeConsumed);
     329             : 
     330          13 :     if (!bSuccess)
     331          11 :         return bSuccess;
     332             : 
     333             :     /* ==================================================================== */
     334             :     /*      Compute the area of each ring.  The sign will be positive       */
     335             :     /*      for counter clockwise rings, otherwise negative.                */
     336             :     /*                                                                      */
     337             :     /*      The algorithm used in this function was taken from _Graphics    */
     338             :     /*      Gems II_, James Arvo, 1991, Academic Press, Inc., section 1.1,  */
     339             :     /*      "The Area of a Simple Polygon", Jon Rokne, pp. 5-6.             */
     340             :     /* ==================================================================== */
     341           2 :     double dfMaxArea = 0.0;
     342           2 :     int iBiggestRing = -1;
     343             : 
     344             :     double *padfRingArea =
     345           2 :         reinterpret_cast<double *>(CPLCalloc(sizeof(double), nRings));
     346             : 
     347           4 :     for (int iRing = 0; iRing < nRings; iRing++)
     348             :     {
     349             :         int nRingVertices;
     350           2 :         if (iRing == nRings - 1)
     351           2 :             nRingVertices = nVertices - panRingStart[iRing];
     352             :         else
     353           0 :             nRingVertices = panRingStart[iRing + 1] - panRingStart[iRing];
     354             : 
     355           2 :         double dfSum1 = 0.0;
     356           2 :         double dfSum2 = 0.0;
     357           2 :         for (int i = panRingStart[iRing];
     358         382 :              i < panRingStart[iRing] + nRingVertices - 1; i++)
     359             :         {
     360         380 :             dfSum1 += padfX[i] * padfY[i + 1];
     361         380 :             dfSum2 += padfY[i] * padfX[i + 1];
     362             :         }
     363             : 
     364           2 :         padfRingArea[iRing] = (dfSum1 - dfSum2) / 2;
     365             : 
     366           2 :         if (std::abs(padfRingArea[iRing]) > dfMaxArea)
     367             :         {
     368           2 :             dfMaxArea = std::abs(padfRingArea[iRing]);
     369           2 :             iBiggestRing = iRing;
     370             :         }
     371             :     }
     372             : 
     373           2 :     if (iBiggestRing < 0)
     374             :     {
     375           0 :         CPLFree(padfRingArea);
     376           0 :         return FALSE;
     377             :     }
     378             : 
     379             :     /* ==================================================================== */
     380             :     /*      Make a new set of vertices, and copy the largest ring into      */
     381             :     /*      it, adjusting the direction if necessary to ensure that this    */
     382             :     /*      outer ring is counter clockwise.                                */
     383             :     /* ==================================================================== */
     384           2 :     double *padfXRaw = padfX;
     385           2 :     double *padfYRaw = padfY;
     386           2 :     double *padfZRaw = padfZ;
     387           2 :     int *panRawRingStart = panRingStart;
     388           2 :     int nRawVertices = nVertices;
     389           2 :     int nRawRings = nRings;
     390             : 
     391           2 :     padfX = reinterpret_cast<double *>(CPLMalloc(sizeof(double) * nVertices));
     392           2 :     padfY = reinterpret_cast<double *>(CPLMalloc(sizeof(double) * nVertices));
     393           2 :     padfZ = reinterpret_cast<double *>(CPLMalloc(sizeof(double) * nVertices));
     394           2 :     panRingStart = reinterpret_cast<int *>(CPLMalloc(sizeof(int) * nRawRings));
     395           2 :     nVertices = 0;
     396           2 :     nRings = 0;
     397             : 
     398             :     int nRingVertices;
     399           2 :     if (iBiggestRing == nRawRings - 1)
     400           2 :         nRingVertices = nRawVertices - panRawRingStart[iBiggestRing];
     401             :     else
     402           0 :         nRingVertices =
     403           0 :             panRawRingStart[iBiggestRing + 1] - panRawRingStart[iBiggestRing];
     404             : 
     405           2 :     panRingStart[nRings++] = 0;
     406           2 :     AddEdgeToRing(nRingVertices, padfXRaw + panRawRingStart[iBiggestRing],
     407           2 :                   padfYRaw + panRawRingStart[iBiggestRing],
     408           2 :                   padfZRaw + panRawRingStart[iBiggestRing],
     409           2 :                   padfRingArea[iBiggestRing] < 0.0, FALSE);
     410             : 
     411             :     /* ==================================================================== */
     412             :     /*      Add the rest of the rings, which must be holes, in clockwise    */
     413             :     /*      order.                                                          */
     414             :     /* ==================================================================== */
     415           4 :     for (int iRing = 0; iRing < nRawRings; iRing++)
     416             :     {
     417           2 :         if (iRing == iBiggestRing)
     418           2 :             continue;
     419             : 
     420           0 :         if (iRing == nRawRings - 1)
     421           0 :             nRingVertices = nRawVertices - panRawRingStart[iRing];
     422             :         else
     423           0 :             nRingVertices = panRawRingStart[iRing + 1] - panRawRingStart[iRing];
     424             : 
     425           0 :         panRingStart[nRings++] = nVertices;
     426           0 :         AddEdgeToRing(nRingVertices, padfXRaw + panRawRingStart[iRing],
     427           0 :                       padfYRaw + panRawRingStart[iRing],
     428           0 :                       padfZRaw + panRawRingStart[iRing],
     429           0 :                       padfRingArea[iRing] > 0.0, FALSE);
     430             :     }
     431             : 
     432             :     /* -------------------------------------------------------------------- */
     433             :     /*      Cleanup                                                         */
     434             :     /* -------------------------------------------------------------------- */
     435           2 :     CPLFree(padfXRaw);
     436           2 :     CPLFree(padfYRaw);
     437           2 :     CPLFree(padfZRaw);
     438           2 :     CPLFree(padfRingArea);
     439           2 :     CPLFree(panRawRingStart);
     440             : 
     441           2 :     CPLFree(papoEdges);
     442           2 :     papoEdges = nullptr;
     443           2 :     nEdges = 0;
     444             : 
     445           2 :     return TRUE;
     446             : }
     447             : 
     448             : /************************************************************************/
     449             : /*                                Dump()                                */
     450             : /************************************************************************/
     451             : 
     452           0 : void SDTSRawPolygon::Dump(FILE *fp)
     453             : 
     454             : {
     455           0 :     fprintf(fp, "SDTSRawPolygon %s: ", oModId.GetName());
     456             : 
     457           0 :     for (int i = 0; i < nAttributes; i++)
     458           0 :         fprintf(fp, "  ATID[%d]=%s", i, paoATID[i].GetName());
     459             : 
     460           0 :     fprintf(fp, "\n");
     461           0 : }
     462             : 
     463             : /************************************************************************/
     464             : /* ==================================================================== */
     465             : /*                             SDTSPolygonReader                        */
     466             : /*                                                                      */
     467             : /*      This is the class used to read a Polygon module.                */
     468             : /* ==================================================================== */
     469             : /************************************************************************/
     470             : 
     471             : /************************************************************************/
     472             : /*                           SDTSPolygonReader()                          */
     473             : /************************************************************************/
     474             : 
     475           1 : SDTSPolygonReader::SDTSPolygonReader() : bRingsAssembled(FALSE)
     476             : {
     477           1 : }
     478             : 
     479             : /************************************************************************/
     480             : /*                             ~SDTSPolygonReader()                     */
     481             : /************************************************************************/
     482             : 
     483           2 : SDTSPolygonReader::~SDTSPolygonReader()
     484             : {
     485           2 : }
     486             : 
     487             : /************************************************************************/
     488             : /*                               Close()                                */
     489             : /************************************************************************/
     490             : 
     491           0 : void SDTSPolygonReader::Close()
     492             : 
     493             : {
     494           0 :     oDDFModule.Close();
     495           0 : }
     496             : 
     497             : /************************************************************************/
     498             : /*                                Open()                                */
     499             : /*                                                                      */
     500             : /*      Open the requested line file, and prepare to start reading      */
     501             : /*      data records.                                                   */
     502             : /************************************************************************/
     503             : 
     504           1 : int SDTSPolygonReader::Open(const char *pszFilename)
     505             : 
     506             : {
     507           1 :     return oDDFModule.Open(pszFilename);
     508             : }
     509             : 
     510             : /************************************************************************/
     511             : /*                            GetNextPolygon()                          */
     512             : /*                                                                      */
     513             : /*      Fetch the next feature as an STDSRawPolygon.                    */
     514             : /************************************************************************/
     515             : 
     516          36 : SDTSRawPolygon *SDTSPolygonReader::GetNextPolygon()
     517             : 
     518             : {
     519             :     /* -------------------------------------------------------------------- */
     520             :     /*      Read a record.                                                  */
     521             :     /* -------------------------------------------------------------------- */
     522          36 :     if (oDDFModule.GetFP() == nullptr)
     523           0 :         return nullptr;
     524             : 
     525          36 :     DDFRecord *poRecord = oDDFModule.ReadRecord();
     526             : 
     527          36 :     if (poRecord == nullptr)
     528           1 :         return nullptr;
     529             : 
     530             :     /* -------------------------------------------------------------------- */
     531             :     /*      Transform into a Polygon feature.                                 */
     532             :     /* -------------------------------------------------------------------- */
     533          35 :     SDTSRawPolygon *poRawPolygon = new SDTSRawPolygon();
     534             : 
     535          35 :     if (poRawPolygon->Read(poRecord))
     536             :     {
     537          35 :         return poRawPolygon;
     538             :     }
     539             : 
     540           0 :     delete poRawPolygon;
     541           0 :     return nullptr;
     542             : }
     543             : 
     544             : /************************************************************************/
     545             : /*                           AssembleRings()                            */
     546             : /************************************************************************/
     547             : 
     548             : /**
     549             :  * Assemble geometry for a polygon transfer.
     550             :  *
     551             :  * This method takes care of attaching lines from all the line layers in
     552             :  * this transfer to this polygon layer, assembling the lines into rings on
     553             :  * the polygons, and then cleaning up unnecessary intermediate results.
     554             :  *
     555             :  * Currently this method will leave the line layers rewound to the beginning
     556             :  * but indexed, and the polygon layer rewound but indexed.  In the future
     557             :  * it may restore reading positions, and possibly flush line indexes if they
     558             :  * were not previously indexed.
     559             :  *
     560             :  * This method does nothing if the rings have already been assembled on
     561             :  * this layer using this method.
     562             :  *
     563             :  * See SDTSRawPolygon::AssembleRings() for more information on how the lines
     564             :  * are assembled into rings.
     565             :  *
     566             :  * @param poTransfer the SDTSTransfer that this reader is a part of.  Used
     567             :  * to get a list of line layers that might be needed.
     568             :  * @param iPolyLayer the polygon reader instance number, used to avoid
     569             :  * processing lines for other layers.
     570             :  */
     571             : 
     572          38 : void SDTSPolygonReader::AssembleRings(SDTSTransfer *poTransfer, int iPolyLayer)
     573             : 
     574             : {
     575          38 :     if (bRingsAssembled)
     576          37 :         return;
     577             : 
     578           1 :     bRingsAssembled = TRUE;
     579             : 
     580             :     /* -------------------------------------------------------------------- */
     581             :     /*      To write polygons we need to build them from their related      */
     582             :     /*      arcs.  We don't know off hand which arc (line) layers           */
     583             :     /*      contribute so we process all line layers, attaching them to     */
     584             :     /*      polygons as appropriate.                                        */
     585             :     /* -------------------------------------------------------------------- */
     586           9 :     for (int iLineLayer = 0; iLineLayer < poTransfer->GetLayerCount();
     587             :          iLineLayer++)
     588             :     {
     589           8 :         if (poTransfer->GetLayerType(iLineLayer) != SLTLine)
     590           7 :             continue;
     591             : 
     592             :         SDTSLineReader *poLineReader = reinterpret_cast<SDTSLineReader *>(
     593           1 :             poTransfer->GetLayerIndexedReader(iLineLayer));
     594           1 :         if (poLineReader == nullptr)
     595           0 :             continue;
     596             : 
     597           1 :         poLineReader->AttachToPolygons(poTransfer, iPolyLayer);
     598           1 :         poLineReader->Rewind();
     599             :     }
     600             : 
     601           1 :     if (!IsIndexed())
     602           0 :         return;
     603             : 
     604             :     /* -------------------------------------------------------------------- */
     605             :     /*      Scan all polygons indexed on this reader, and assemble their    */
     606             :     /*      rings.                                                          */
     607             :     /* -------------------------------------------------------------------- */
     608           1 :     Rewind();
     609             : 
     610           1 :     SDTSFeature *poFeature = nullptr;
     611          36 :     while ((poFeature = GetNextFeature()) != nullptr)
     612             :     {
     613          35 :         SDTSRawPolygon *poPoly = reinterpret_cast<SDTSRawPolygon *>(poFeature);
     614             : 
     615          35 :         poPoly->AssembleRings();
     616             :     }
     617             : 
     618           1 :     Rewind();
     619             : }

Generated by: LCOV version 1.14