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

Generated by: LCOV version 1.14