LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/dxf - ogrdxf_hatch.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 254 336 75.6 %
Date: 2024-11-21 22:18:42 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  DXF Translator
       4             :  * Purpose:  Implements translation support for HATCH elements as part
       5             :  *           of the OGRDXFLayer class.
       6             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2010, Frank Warmerdam <warmerdam@pobox.com>
      10             :  * Copyright (c) 2011-2013, Even Rouault <even dot rouault at spatialys.com>
      11             :  * Copyright (c) 2017, Alan Thomas <alant@outlook.com.au>
      12             :  *
      13             :  * SPDX-License-Identifier: MIT
      14             :  ****************************************************************************/
      15             : 
      16             : #include "ogr_dxf.h"
      17             : #include "cpl_conv.h"
      18             : #include "ogr_api.h"
      19             : 
      20             : #include <algorithm>
      21             : #include <cmath>
      22             : #include "ogrdxf_polyline_smooth.h"
      23             : 
      24             : /************************************************************************/
      25             : /*                           TranslateHATCH()                           */
      26             : /*                                                                      */
      27             : /*      We mostly just try to convert hatch objects as polygons or      */
      28             : /*      multipolygons representing the hatched area.  It is hard to     */
      29             : /*      preserve the actual details of the hatching.                    */
      30             : /************************************************************************/
      31             : 
      32          28 : OGRDXFFeature *OGRDXFLayer::TranslateHATCH()
      33             : 
      34             : {
      35             :     char szLineBuf[257];
      36          28 :     int nCode = 0;
      37          28 :     OGRDXFFeature *poFeature = new OGRDXFFeature(poFeatureDefn);
      38             : 
      39          56 :     CPLString osHatchPattern;
      40          28 :     double dfElevation = 0.0;  // Z value to be used for EVERY point
      41             :     /* int nFillFlag = 0; */
      42          56 :     OGRGeometryCollection oGC;
      43             : 
      44         880 :     while ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) > 0)
      45             :     {
      46         852 :         switch (nCode)
      47             :         {
      48          28 :             case 30:
      49             :                 // Constant elevation.
      50          28 :                 dfElevation = CPLAtof(szLineBuf);
      51          28 :                 break;
      52             : 
      53          28 :             case 70:
      54             :                 /* nFillFlag = atoi(szLineBuf); */
      55          28 :                 break;
      56             : 
      57          26 :             case 2:
      58          26 :                 osHatchPattern = szLineBuf;
      59          26 :                 poFeature->SetField("Text", osHatchPattern.c_str());
      60          26 :                 break;
      61             : 
      62          28 :             case 91:
      63             :             {
      64          28 :                 int nBoundaryPathCount = atoi(szLineBuf);
      65             : 
      66          65 :                 for (int iBoundary = 0; iBoundary < nBoundaryPathCount;
      67             :                      iBoundary++)
      68             :                 {
      69          37 :                     if (CollectBoundaryPath(&oGC, dfElevation) != OGRERR_NONE)
      70           0 :                         break;
      71             :                 }
      72             :             }
      73          28 :             break;
      74             : 
      75         742 :             default:
      76         742 :                 TranslateGenericProperty(poFeature, nCode, szLineBuf);
      77         742 :                 break;
      78             :         }
      79             :     }
      80          28 :     if (nCode < 0)
      81             :     {
      82           0 :         DXF_LAYER_READER_ERROR();
      83           0 :         delete poFeature;
      84           0 :         return nullptr;
      85             :     }
      86             : 
      87          28 :     if (nCode == 0)
      88          28 :         poDS->UnreadValue();
      89             : 
      90             :     /* -------------------------------------------------------------------- */
      91             :     /*      Obtain a tolerance value used when building the polygon.        */
      92             :     /* -------------------------------------------------------------------- */
      93          28 :     double dfTolerance = poDS->HatchTolerance();
      94          28 :     if (dfTolerance < 0)
      95             :     {
      96             :         // If the configuration variable isn't set, compute the bounding box
      97             :         // and work out a tolerance from that
      98          28 :         OGREnvelope oEnvelope;
      99          28 :         oGC.getEnvelope(&oEnvelope);
     100          56 :         dfTolerance = std::max(oEnvelope.MaxX - oEnvelope.MinX,
     101          28 :                                oEnvelope.MaxY - oEnvelope.MinY) *
     102             :                       1e-7;
     103             :     }
     104             : 
     105             :     /* -------------------------------------------------------------------- */
     106             :     /*      Try to turn the set of lines into something useful.             */
     107             :     /* -------------------------------------------------------------------- */
     108             :     OGRErr eErr;
     109             : 
     110          28 :     OGRGeometry *poFinalGeom = (OGRGeometry *)OGRBuildPolygonFromEdges(
     111             :         (OGRGeometryH)&oGC, TRUE, TRUE, dfTolerance, &eErr);
     112          28 :     if (eErr != OGRERR_NONE)
     113             :     {
     114           0 :         delete poFinalGeom;
     115           0 :         OGRMultiLineString *poMLS = new OGRMultiLineString();
     116           0 :         for (int i = 0; i < oGC.getNumGeometries(); i++)
     117           0 :             poMLS->addGeometry(oGC.getGeometryRef(i));
     118           0 :         poFinalGeom = poMLS;
     119             :     }
     120             : 
     121          28 :     poFeature->ApplyOCSTransformer(poFinalGeom);
     122          28 :     poFeature->SetGeometryDirectly(poFinalGeom);
     123             : 
     124          28 :     PrepareBrushStyle(poFeature);
     125             : 
     126          28 :     return poFeature;
     127             : }
     128             : 
     129             : /************************************************************************/
     130             : /*                        CollectBoundaryPath()                         */
     131             : /************************************************************************/
     132             : 
     133          37 : OGRErr OGRDXFLayer::CollectBoundaryPath(OGRGeometryCollection *poGC,
     134             :                                         const double dfElevation)
     135             : 
     136             : {
     137             :     char szLineBuf[257];
     138             : 
     139             :     /* -------------------------------------------------------------------- */
     140             :     /*      Read the boundary path type.                                    */
     141             :     /* -------------------------------------------------------------------- */
     142          37 :     int nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf));
     143          37 :     if (nCode != 92)
     144             :     {
     145           0 :         DXF_LAYER_READER_ERROR();
     146           0 :         return OGRERR_FAILURE;
     147             :     }
     148             : 
     149          37 :     const int nBoundaryPathType = atoi(szLineBuf);
     150             : 
     151             :     /* ==================================================================== */
     152             :     /*      Handle polyline loops.                                          */
     153             :     /* ==================================================================== */
     154          37 :     if (nBoundaryPathType & 0x02)
     155          18 :         return CollectPolylinePath(poGC, dfElevation);
     156             : 
     157             :     /* ==================================================================== */
     158             :     /*      Handle non-polyline loops.                                      */
     159             :     /* ==================================================================== */
     160             : 
     161             :     /* -------------------------------------------------------------------- */
     162             :     /*      Read number of edges.                                           */
     163             :     /* -------------------------------------------------------------------- */
     164          19 :     nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf));
     165          19 :     if (nCode != 93)
     166             :     {
     167           0 :         DXF_LAYER_READER_ERROR();
     168           0 :         return OGRERR_FAILURE;
     169             :     }
     170             : 
     171          19 :     const int nEdgeCount = atoi(szLineBuf);
     172             : 
     173             :     /* -------------------------------------------------------------------- */
     174             :     /*      Loop reading edges.                                             */
     175             :     /* -------------------------------------------------------------------- */
     176          84 :     for (int iEdge = 0; iEdge < nEdgeCount; iEdge++)
     177             :     {
     178             :         /* --------------------------------------------------------------------
     179             :          */
     180             :         /*      Read the edge type. */
     181             :         /* --------------------------------------------------------------------
     182             :          */
     183          65 :         const int ET_LINE = 1;
     184          65 :         const int ET_CIRCULAR_ARC = 2;
     185          65 :         const int ET_ELLIPTIC_ARC = 3;
     186          65 :         const int ET_SPLINE = 4;
     187             : 
     188          65 :         nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf));
     189          65 :         if (nCode != 72)
     190             :         {
     191           0 :             DXF_LAYER_READER_ERROR();
     192           0 :             return OGRERR_FAILURE;
     193             :         }
     194             : 
     195          65 :         int nEdgeType = atoi(szLineBuf);
     196             : 
     197             :         /* --------------------------------------------------------------------
     198             :          */
     199             :         /*      Process a line edge. */
     200             :         /* --------------------------------------------------------------------
     201             :          */
     202          65 :         if (nEdgeType == ET_LINE)
     203             :         {
     204          45 :             double dfStartX = 0.0;
     205             : 
     206          45 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 10)
     207          45 :                 dfStartX = CPLAtof(szLineBuf);
     208             :             else
     209           0 :                 break;
     210             : 
     211          45 :             double dfStartY = 0.0;
     212             : 
     213          45 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 20)
     214          45 :                 dfStartY = CPLAtof(szLineBuf);
     215             :             else
     216           0 :                 break;
     217             : 
     218          45 :             double dfEndX = 0.0;
     219             : 
     220          45 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 11)
     221          45 :                 dfEndX = CPLAtof(szLineBuf);
     222             :             else
     223           0 :                 break;
     224             : 
     225          45 :             double dfEndY = 0.0;
     226             : 
     227          45 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 21)
     228          45 :                 dfEndY = CPLAtof(szLineBuf);
     229             :             else
     230           0 :                 break;
     231             : 
     232          45 :             OGRLineString *poLS = new OGRLineString();
     233             : 
     234          45 :             poLS->addPoint(dfStartX, dfStartY, dfElevation);
     235          45 :             poLS->addPoint(dfEndX, dfEndY, dfElevation);
     236             : 
     237          45 :             poGC->addGeometryDirectly(poLS);
     238             :         }
     239             :         /* --------------------------------------------------------------------
     240             :          */
     241             :         /*      Process a circular arc. */
     242             :         /* --------------------------------------------------------------------
     243             :          */
     244          20 :         else if (nEdgeType == ET_CIRCULAR_ARC)
     245             :         {
     246          12 :             double dfCenterX = 0.0;
     247             : 
     248          12 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 10)
     249          12 :                 dfCenterX = CPLAtof(szLineBuf);
     250             :             else
     251           0 :                 break;
     252             : 
     253          12 :             double dfCenterY = 0.0;
     254             : 
     255          12 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 20)
     256          12 :                 dfCenterY = CPLAtof(szLineBuf);
     257             :             else
     258           0 :                 break;
     259             : 
     260          12 :             double dfRadius = 0.0;
     261             : 
     262          12 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 40)
     263          12 :                 dfRadius = CPLAtof(szLineBuf);
     264             :             else
     265           0 :                 break;
     266             : 
     267          12 :             double dfStartAngle = 0.0;
     268             : 
     269          12 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 50)
     270          12 :                 dfStartAngle = CPLAtof(szLineBuf);
     271             :             else
     272           0 :                 break;
     273             : 
     274          12 :             double dfEndAngle = 0.0;
     275             : 
     276          12 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 51)
     277          12 :                 dfEndAngle = CPLAtof(szLineBuf);
     278             :             else
     279           0 :                 break;
     280             : 
     281          12 :             bool bCounterClockwise = false;
     282             : 
     283          12 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 73)
     284          12 :                 bCounterClockwise = atoi(szLineBuf) != 0;
     285           0 :             else if (nCode >= 0)
     286           0 :                 poDS->UnreadValue();
     287             :             else
     288           0 :                 break;
     289             : 
     290          12 :             if (dfStartAngle > dfEndAngle)
     291           4 :                 dfEndAngle += 360.0;
     292          12 :             if (bCounterClockwise)
     293             :             {
     294           8 :                 dfStartAngle *= -1;
     295           8 :                 dfEndAngle *= -1;
     296             :             }
     297             : 
     298          12 :             if (fabs(dfEndAngle - dfStartAngle) <= 361.0)
     299             :             {
     300          12 :                 OGRGeometry *poArc = OGRGeometryFactory::approximateArcAngles(
     301             :                     dfCenterX, dfCenterY, dfElevation, dfRadius, dfRadius, 0.0,
     302          12 :                     dfStartAngle, dfEndAngle, 0.0, poDS->InlineBlocks());
     303             : 
     304             :                 // If the input was 2D, we assume we want to keep it that way
     305          12 :                 if (dfElevation == 0.0)
     306           8 :                     poArc->flattenTo2D();
     307             : 
     308          12 :                 poGC->addGeometryDirectly(poArc);
     309             :             }
     310             :             else
     311             :             {
     312             :                 // TODO: emit error ?
     313             :             }
     314             :         }
     315             : 
     316             :         /* --------------------------------------------------------------------
     317             :          */
     318             :         /*      Process an elliptical arc. */
     319             :         /* --------------------------------------------------------------------
     320             :          */
     321           8 :         else if (nEdgeType == ET_ELLIPTIC_ARC)
     322             :         {
     323           6 :             double dfCenterX = 0.0;
     324             : 
     325           6 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 10)
     326           6 :                 dfCenterX = CPLAtof(szLineBuf);
     327             :             else
     328           0 :                 break;
     329             : 
     330           6 :             double dfCenterY = 0.0;
     331             : 
     332           6 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 20)
     333           6 :                 dfCenterY = CPLAtof(szLineBuf);
     334             :             else
     335           0 :                 break;
     336             : 
     337           6 :             double dfMajorX = 0.0;
     338             : 
     339           6 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 11)
     340           6 :                 dfMajorX = CPLAtof(szLineBuf);
     341             :             else
     342           0 :                 break;
     343             : 
     344           6 :             double dfMajorY = 0.0;
     345             : 
     346           6 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 21)
     347           6 :                 dfMajorY = CPLAtof(szLineBuf);
     348             :             else
     349           0 :                 break;
     350             : 
     351           6 :             double dfRatio = 0.0;
     352             : 
     353           6 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 40)
     354           6 :                 dfRatio = CPLAtof(szLineBuf);
     355           6 :             if (dfRatio == 0.0)
     356           0 :                 break;
     357             : 
     358           6 :             double dfStartAngle = 0.0;
     359             : 
     360           6 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 50)
     361           6 :                 dfStartAngle = CPLAtof(szLineBuf);
     362             :             else
     363           0 :                 break;
     364             : 
     365           6 :             double dfEndAngle = 0.0;
     366             : 
     367           6 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 51)
     368           6 :                 dfEndAngle = CPLAtof(szLineBuf);
     369             :             else
     370           0 :                 break;
     371             : 
     372           6 :             bool bCounterClockwise = false;
     373             : 
     374           6 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 73)
     375           6 :                 bCounterClockwise = atoi(szLineBuf) != 0;
     376           0 :             else if (nCode >= 0)
     377           0 :                 poDS->UnreadValue();
     378             :             else
     379           0 :                 break;
     380             : 
     381           6 :             if (dfStartAngle > dfEndAngle)
     382           0 :                 dfEndAngle += 360.0;
     383           6 :             if (bCounterClockwise)
     384             :             {
     385           5 :                 dfStartAngle *= -1;
     386           5 :                 dfEndAngle *= -1;
     387             :             }
     388             : 
     389             :             const double dfMajorRadius =
     390           6 :                 sqrt(dfMajorX * dfMajorX + dfMajorY * dfMajorY);
     391           6 :             const double dfMinorRadius = dfMajorRadius * dfRatio;
     392             : 
     393             :             const double dfRotation =
     394           6 :                 -1 * atan2(dfMajorY, dfMajorX) * 180 / M_PI;
     395             : 
     396             :             // The start and end angles are stored as circular angles. However,
     397             :             // approximateArcAngles is expecting elliptical angles (what AutoCAD
     398             :             // calls "parameters"), so let's transform them.
     399           6 :             dfStartAngle =
     400           6 :                 180.0 * round(dfStartAngle / 180) +
     401           6 :                 (fabs(fmod(dfStartAngle, 180)) == 90
     402           4 :                      ? (std::signbit(dfStartAngle) ? 180 : -180)
     403             :                      : 0) +
     404           6 :                 atan((1.0 / dfRatio) * tan(dfStartAngle * M_PI / 180)) * 180 /
     405             :                     M_PI;
     406           6 :             dfEndAngle = 180.0 * round(dfEndAngle / 180) +
     407           6 :                          (fabs(fmod(dfEndAngle, 180)) == 90
     408           1 :                               ? (std::signbit(dfEndAngle) ? 180 : -180)
     409             :                               : 0) +
     410           6 :                          atan((1.0 / dfRatio) * tan(dfEndAngle * M_PI / 180)) *
     411           6 :                              180 / M_PI;
     412             : 
     413           6 :             if (fabs(dfEndAngle - dfStartAngle) <= 361.0)
     414             :             {
     415           6 :                 OGRGeometry *poArc = OGRGeometryFactory::approximateArcAngles(
     416             :                     dfCenterX, dfCenterY, dfElevation, dfMajorRadius,
     417             :                     dfMinorRadius, dfRotation, dfStartAngle, dfEndAngle, 0.0,
     418           6 :                     poDS->InlineBlocks());
     419             : 
     420             :                 // If the input was 2D, we assume we want to keep it that way
     421           6 :                 if (dfElevation == 0.0)
     422           2 :                     poArc->flattenTo2D();
     423             : 
     424           6 :                 poGC->addGeometryDirectly(poArc);
     425             :             }
     426             :             else
     427             :             {
     428             :                 // TODO: emit error ?
     429             :             }
     430             :         }
     431             : 
     432             :         /* --------------------------------------------------------------------
     433             :          */
     434             :         /*      Process an elliptical arc. */
     435             :         /* --------------------------------------------------------------------
     436             :          */
     437           2 :         else if (nEdgeType == ET_SPLINE)
     438             :         {
     439           2 :             int nDegree = 3;
     440             : 
     441           2 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 94)
     442           2 :                 nDegree = atoi(szLineBuf);
     443             :             else
     444           0 :                 break;
     445             : 
     446             :             // Skip a few things we don't care about
     447           2 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) != 73)
     448           0 :                 break;
     449           2 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) != 74)
     450           0 :                 break;
     451             : 
     452           2 :             int nKnots = 0;
     453             : 
     454           2 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 95)
     455           2 :                 nKnots = atoi(szLineBuf);
     456             :             else
     457           0 :                 break;
     458             : 
     459           2 :             int nControlPoints = 0;
     460             : 
     461           2 :             if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 96)
     462           2 :                 nControlPoints = atoi(szLineBuf);
     463             :             else
     464           0 :                 break;
     465             : 
     466           2 :             std::vector<double> adfKnots(FORTRAN_INDEXING, 0.0);
     467             : 
     468           2 :             nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf));
     469           2 :             if (nCode != 40)
     470           0 :                 break;
     471             : 
     472          23 :             while (nCode == 40)
     473             :             {
     474          21 :                 adfKnots.push_back(CPLAtof(szLineBuf));
     475          21 :                 nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf));
     476             :             }
     477             : 
     478           2 :             std::vector<double> adfControlPoints(FORTRAN_INDEXING, 0.0);
     479           2 :             std::vector<double> adfWeights(FORTRAN_INDEXING, 0.0);
     480             : 
     481           2 :             if (nCode != 10)
     482           0 :                 break;
     483             : 
     484          15 :             while (nCode == 10)
     485             :             {
     486          13 :                 adfControlPoints.push_back(CPLAtof(szLineBuf));
     487             : 
     488          13 :                 if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) ==
     489             :                     20)
     490             :                 {
     491          13 :                     adfControlPoints.push_back(CPLAtof(szLineBuf));
     492             :                 }
     493             :                 else
     494           0 :                     break;
     495             : 
     496          13 :                 adfControlPoints.push_back(0.0);  // Z coordinate
     497             : 
     498             :                 // 42 (weights) are optional
     499          13 :                 if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) ==
     500             :                     42)
     501             :                 {
     502           7 :                     adfWeights.push_back(CPLAtof(szLineBuf));
     503           7 :                     nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf));
     504             :                 }
     505             :             }
     506             : 
     507             :             // Skip past the number of fit points
     508           2 :             if (nCode != 97)
     509           0 :                 break;
     510             : 
     511             :             // Eat the rest of this section, if present, until the next
     512             :             // boundary segment (72) or the conclusion of the boundary data (97)
     513           2 :             nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf));
     514          14 :             while (nCode > 0 && nCode != 72 && nCode != 97)
     515          12 :                 nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf));
     516           2 :             if (nCode > 0)
     517           2 :                 poDS->UnreadValue();
     518             : 
     519             :             auto poLS =
     520             :                 InsertSplineWithChecks(nDegree, adfControlPoints,
     521             :                                        /* bHaZ = */ false, nControlPoints,
     522           2 :                                        adfKnots, nKnots, adfWeights);
     523             : 
     524           2 :             if (!poLS)
     525             :             {
     526           0 :                 DXF_LAYER_READER_ERROR();
     527           0 :                 return OGRERR_FAILURE;
     528             :             }
     529             : 
     530           2 :             poGC->addGeometryDirectly(poLS.release());
     531             :         }
     532             : 
     533             :         else
     534             :         {
     535           0 :             CPLDebug("DXF", "Unsupported HATCH boundary line type:%d",
     536             :                      nEdgeType);
     537           0 :             return OGRERR_UNSUPPORTED_OPERATION;
     538             :         }
     539             :     }
     540             : 
     541          19 :     if (nCode < 0)
     542             :     {
     543           0 :         DXF_LAYER_READER_ERROR();
     544           0 :         return OGRERR_FAILURE;
     545             :     }
     546             : 
     547             :     /* -------------------------------------------------------------------- */
     548             :     /*      Skip through source boundary objects if present.                */
     549             :     /* -------------------------------------------------------------------- */
     550          19 :     nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf));
     551          19 :     if (nCode != 97)
     552             :     {
     553           0 :         if (nCode < 0)
     554           0 :             return OGRERR_FAILURE;
     555           0 :         poDS->UnreadValue();
     556             :     }
     557             :     else
     558             :     {
     559          19 :         int iObj, nObjCount = atoi(szLineBuf);
     560             : 
     561          21 :         for (iObj = 0; iObj < nObjCount; iObj++)
     562             :         {
     563           2 :             if (poDS->ReadValue(szLineBuf, sizeof(szLineBuf)) < 0)
     564           0 :                 return OGRERR_FAILURE;
     565             :         }
     566             :     }
     567             : 
     568          19 :     return OGRERR_NONE;
     569             : }
     570             : 
     571             : /************************************************************************/
     572             : /*                        CollectPolylinePath()                         */
     573             : /************************************************************************/
     574             : 
     575          18 : OGRErr OGRDXFLayer::CollectPolylinePath(OGRGeometryCollection *poGC,
     576             :                                         const double dfElevation)
     577             : 
     578             : {
     579          18 :     int nCode = 0;
     580             :     char szLineBuf[257];
     581          36 :     DXFSmoothPolyline oSmoothPolyline;
     582          18 :     double dfBulge = 0.0;
     583          18 :     double dfX = 0.0;
     584          18 :     double dfY = 0.0;
     585          18 :     bool bHaveX = false;
     586          18 :     bool bHaveY = false;
     587          18 :     bool bIsClosed = false;
     588          18 :     int nVertexCount = -1;
     589          18 :     bool bHaveBulges = false;
     590             : 
     591          18 :     if (dfElevation != 0)
     592           1 :         oSmoothPolyline.setCoordinateDimension(3);
     593             : 
     594             :     /* -------------------------------------------------------------------- */
     595             :     /*      Read the boundary path type.                                    */
     596             :     /* -------------------------------------------------------------------- */
     597         224 :     while ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) > 0)
     598             :     {
     599         224 :         if (nVertexCount > 0 && (int)oSmoothPolyline.size() == nVertexCount)
     600          18 :             break;
     601             : 
     602         206 :         switch (nCode)
     603             :         {
     604          18 :             case 93:
     605          18 :                 nVertexCount = atoi(szLineBuf);
     606          18 :                 break;
     607             : 
     608          18 :             case 72:
     609          18 :                 bHaveBulges = CPL_TO_BOOL(atoi(szLineBuf));
     610          18 :                 break;
     611             : 
     612          18 :             case 73:
     613          18 :                 bIsClosed = CPL_TO_BOOL(atoi(szLineBuf));
     614          18 :                 break;
     615             : 
     616          76 :             case 10:
     617          76 :                 if (bHaveX && bHaveY)
     618             :                 {
     619           0 :                     oSmoothPolyline.AddPoint(dfX, dfY, dfElevation, dfBulge);
     620           0 :                     dfBulge = 0.0;
     621           0 :                     bHaveY = false;
     622             :                 }
     623          76 :                 dfX = CPLAtof(szLineBuf);
     624          76 :                 bHaveX = true;
     625          76 :                 break;
     626             : 
     627          76 :             case 20:
     628          76 :                 if (bHaveX && bHaveY)
     629             :                 {
     630           0 :                     oSmoothPolyline.AddPoint(dfX, dfY, dfElevation, dfBulge);
     631           0 :                     dfBulge = 0.0;
     632           0 :                     bHaveX = false;
     633             :                 }
     634          76 :                 dfY = CPLAtof(szLineBuf);
     635          76 :                 bHaveY = true;
     636          76 :                 if (bHaveX /* && bHaveY */ && !bHaveBulges)
     637             :                 {
     638          76 :                     oSmoothPolyline.AddPoint(dfX, dfY, dfElevation, dfBulge);
     639          76 :                     dfBulge = 0.0;
     640          76 :                     bHaveX = false;
     641          76 :                     bHaveY = false;
     642             :                 }
     643          76 :                 break;
     644             : 
     645           0 :             case 42:
     646           0 :                 dfBulge = CPLAtof(szLineBuf);
     647           0 :                 if (bHaveX && bHaveY)
     648             :                 {
     649           0 :                     oSmoothPolyline.AddPoint(dfX, dfY, dfElevation, dfBulge);
     650           0 :                     dfBulge = 0.0;
     651           0 :                     bHaveX = false;
     652           0 :                     bHaveY = false;
     653             :                 }
     654           0 :                 break;
     655             : 
     656           0 :             default:
     657           0 :                 break;
     658             :         }
     659             :     }
     660          18 :     if (nCode < 0)
     661             :     {
     662           0 :         DXF_LAYER_READER_ERROR();
     663           0 :         return OGRERR_FAILURE;
     664             :     }
     665             : 
     666          18 :     if (nCode != 10 && nCode != 20 && nCode != 42)
     667          18 :         poDS->UnreadValue();
     668             : 
     669          18 :     if (bHaveX && bHaveY)
     670           0 :         oSmoothPolyline.AddPoint(dfX, dfY, dfElevation, dfBulge);
     671             : 
     672          18 :     if (bIsClosed)
     673          18 :         oSmoothPolyline.Close();
     674             : 
     675          18 :     if (oSmoothPolyline.IsEmpty())
     676             :     {
     677           0 :         return OGRERR_FAILURE;
     678             :     }
     679             : 
     680             :     // Only process polylines with at least 2 vertices
     681          18 :     if (nVertexCount >= 2)
     682             :     {
     683          18 :         oSmoothPolyline.SetUseMaxGapWhenTessellatingArcs(poDS->InlineBlocks());
     684          18 :         poGC->addGeometryDirectly(oSmoothPolyline.Tessellate(false));
     685             :     }
     686             : 
     687             :     /* -------------------------------------------------------------------- */
     688             :     /*      Skip through source boundary objects if present.                */
     689             :     /* -------------------------------------------------------------------- */
     690          18 :     nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf));
     691          18 :     if (nCode != 97)
     692             :     {
     693           0 :         if (nCode < 0)
     694           0 :             return OGRERR_FAILURE;
     695           0 :         poDS->UnreadValue();
     696             :     }
     697             :     else
     698             :     {
     699          18 :         int iObj, nObjCount = atoi(szLineBuf);
     700             : 
     701          18 :         for (iObj = 0; iObj < nObjCount; iObj++)
     702             :         {
     703           0 :             if (poDS->ReadValue(szLineBuf, sizeof(szLineBuf)) < 0)
     704           0 :                 return OGRERR_FAILURE;
     705             :         }
     706             :     }
     707          18 :     return OGRERR_NONE;
     708             : }

Generated by: LCOV version 1.14