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

Generated by: LCOV version 1.14