LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/dxf - ogr_dxf.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 158 174 90.8 %
Date: 2024-11-21 22:18:42 Functions: 47 55 85.5 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  * $Id$
       3             :  *
       4             :  * Project:  DXF Translator
       5             :  * Purpose:  Definition of classes for OGR .dxf driver.
       6             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2009,  Frank Warmerdam
      10             :  * Copyright (c) 2010-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             : #ifndef OGR_DXF_H_INCLUDED
      17             : #define OGR_DXF_H_INCLUDED
      18             : 
      19             : #include "ogrsf_frmts.h"
      20             : #include "ogr_autocad_services.h"
      21             : #include "cpl_conv.h"
      22             : #include <vector>
      23             : #include <map>
      24             : #include <set>
      25             : #include <queue>
      26             : #include <memory>
      27             : 
      28             : class OGRDXFDataSource;
      29             : class OGRDXFFeature;
      30             : 
      31             : /************************************************************************/
      32             : /*                          DXFBlockDefinition                          */
      33             : /*                                                                      */
      34             : /*      Container for info about a block.                               */
      35             : /************************************************************************/
      36             : 
      37             : class DXFBlockDefinition
      38             : {
      39             :   public:
      40          75 :     DXFBlockDefinition()
      41          75 :     {
      42          75 :     }
      43             : 
      44             :     ~DXFBlockDefinition();
      45             : 
      46             :     std::vector<OGRDXFFeature *> apoFeatures;
      47             : };
      48             : 
      49             : /************************************************************************/
      50             : /*                         OGRDXFFeatureQueue                           */
      51             : /************************************************************************/
      52             : 
      53             : class OGRDXFFeatureQueue
      54             : {
      55             :     std::queue<OGRDXFFeature *> apoFeatures;
      56             : 
      57             :   public:
      58         537 :     OGRDXFFeatureQueue()
      59         537 :     {
      60         537 :     }
      61             : 
      62             :     void push(OGRDXFFeature *poFeature);
      63             : 
      64        1736 :     OGRDXFFeature *front() const
      65             :     {
      66        1736 :         return apoFeatures.front();
      67             :     }
      68             : 
      69             :     void pop();
      70             : 
      71        5921 :     bool empty() const
      72             :     {
      73        5921 :         return apoFeatures.empty();
      74             :     }
      75             : 
      76             :     size_t size() const
      77             :     {
      78             :         return apoFeatures.size();
      79             :     }
      80             : };
      81             : 
      82             : /************************************************************************/
      83             : /*                          OGRDXFBlocksLayer                           */
      84             : /************************************************************************/
      85             : 
      86             : class OGRDXFBlocksLayer final : public OGRLayer
      87             : {
      88             :     OGRDXFDataSource *poDS;
      89             : 
      90             :     OGRFeatureDefn *poFeatureDefn;
      91             : 
      92             :     GIntBig iNextFID;
      93             : 
      94             :     std::map<CPLString, DXFBlockDefinition>::iterator oIt;
      95             :     CPLString osBlockName;
      96             : 
      97             :     OGRDXFFeatureQueue apoPendingFeatures;
      98             : 
      99             :   public:
     100             :     explicit OGRDXFBlocksLayer(OGRDXFDataSource *poDS);
     101             :     ~OGRDXFBlocksLayer();
     102             : 
     103             :     void ResetReading() override;
     104             :     OGRFeature *GetNextFeature() override;
     105             : 
     106          14 :     OGRFeatureDefn *GetLayerDefn() override
     107             :     {
     108          14 :         return poFeatureDefn;
     109             :     }
     110             : 
     111             :     int TestCapability(const char *) override;
     112             : 
     113             :     OGRDXFFeature *GetNextUnfilteredFeature();
     114             : };
     115             : 
     116             : /************************************************************************/
     117             : /*                       OGRDXFInsertTransformer                        */
     118             : /*                                                                      */
     119             : /*      Stores the transformation needed to insert a block reference.   */
     120             : /************************************************************************/
     121             : 
     122             : class OGRDXFInsertTransformer final : public OGRCoordinateTransformation
     123             : {
     124             :   public:
     125         336 :     OGRDXFInsertTransformer() = default;
     126             : 
     127             :     double dfXOffset = 0.0;
     128             :     double dfYOffset = 0.0;
     129             :     double dfZOffset = 0.0;
     130             :     double dfXScale = 1.0;
     131             :     double dfYScale = 1.0;
     132             :     double dfZScale = 1.0;
     133             :     double dfAngle = 0.0;
     134             : 
     135         696 :     OGRDXFInsertTransformer GetOffsetTransformer()
     136             :     {
     137         696 :         OGRDXFInsertTransformer oResult;
     138         696 :         oResult.dfXOffset = this->dfXOffset;
     139         696 :         oResult.dfYOffset = this->dfYOffset;
     140         696 :         oResult.dfZOffset = this->dfZOffset;
     141         696 :         return oResult;
     142             :     }
     143             : 
     144         696 :     OGRDXFInsertTransformer GetRotateScaleTransformer()
     145             :     {
     146         696 :         OGRDXFInsertTransformer oResult;
     147         696 :         oResult.dfXScale = this->dfXScale;
     148         696 :         oResult.dfYScale = this->dfYScale;
     149         696 :         oResult.dfZScale = this->dfZScale;
     150         696 :         oResult.dfAngle = this->dfAngle;
     151         696 :         return oResult;
     152             :     }
     153             : 
     154           0 :     OGRCoordinateTransformation *Clone() const override
     155             :     {
     156           0 :         return new OGRDXFInsertTransformer(*this);
     157             :     }
     158             : 
     159           0 :     const OGRSpatialReference *GetSourceCS() const override
     160             :     {
     161           0 :         return nullptr;
     162             :     }
     163             : 
     164        3410 :     const OGRSpatialReference *GetTargetCS() const override
     165             :     {
     166        3410 :         return nullptr;
     167             :     }
     168             : 
     169        3275 :     int Transform(size_t nCount, double *x, double *y, double *z,
     170             :                   double * /* t */, int *pabSuccess) override
     171             :     {
     172       16649 :         for (size_t i = 0; i < nCount; i++)
     173             :         {
     174       13374 :             x[i] *= dfXScale;
     175       13374 :             y[i] *= dfYScale;
     176       13374 :             if (z)
     177       13374 :                 z[i] *= dfZScale;
     178             : 
     179       13374 :             const double dfXNew = x[i] * cos(dfAngle) - y[i] * sin(dfAngle);
     180       13374 :             const double dfYNew = x[i] * sin(dfAngle) + y[i] * cos(dfAngle);
     181             : 
     182       13374 :             x[i] = dfXNew;
     183       13374 :             y[i] = dfYNew;
     184             : 
     185       13374 :             x[i] += dfXOffset;
     186       13374 :             y[i] += dfYOffset;
     187       13374 :             if (z)
     188       13374 :                 z[i] += dfZOffset;
     189             : 
     190       13374 :             if (pabSuccess)
     191       13374 :                 pabSuccess[i] = TRUE;
     192             :         }
     193        3275 :         return TRUE;
     194             :     }
     195             : 
     196           0 :     OGRCoordinateTransformation *GetInverse() const override
     197             :     {
     198           0 :         return nullptr;
     199             :     }
     200             : };
     201             : 
     202             : /************************************************************************/
     203             : /*                         OGRDXFAffineTransform                        */
     204             : /*                                                                      */
     205             : /*    A simple 3D affine transform used to keep track of the            */
     206             : /*    transformation to be applied to an ASM entity.                    */
     207             : /************************************************************************/
     208             : 
     209             : class OGRDXFAffineTransform
     210             : {
     211             :   public:
     212           2 :     OGRDXFAffineTransform()
     213           2 :         : adfData{1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0}
     214             :     {
     215           2 :     }
     216             : 
     217             :     double adfData[12];  // Column-major: adfMatrix[5] is column 2, row 3
     218             :                          // Last 3 elements are translation
     219             : 
     220             :     // Left composition (composes oOther o this), modifying this
     221           6 :     void ComposeWith(const OGRDXFInsertTransformer &oCT)
     222             :     {
     223             :         double adfNew[12];
     224             : 
     225           6 :         adfNew[0] = oCT.dfXScale * cos(oCT.dfAngle) * adfData[0] -
     226           6 :                     oCT.dfYScale * sin(oCT.dfAngle) * adfData[1];
     227           6 :         adfNew[1] = oCT.dfXScale * sin(oCT.dfAngle) * adfData[0] +
     228           6 :                     oCT.dfYScale * cos(oCT.dfAngle) * adfData[1];
     229           6 :         adfNew[2] = oCT.dfZScale * adfData[2];
     230             : 
     231           6 :         adfNew[3] = oCT.dfXScale * cos(oCT.dfAngle) * adfData[3] -
     232           6 :                     oCT.dfYScale * sin(oCT.dfAngle) * adfData[4];
     233           6 :         adfNew[4] = oCT.dfXScale * sin(oCT.dfAngle) * adfData[3] +
     234           6 :                     oCT.dfYScale * cos(oCT.dfAngle) * adfData[4];
     235           6 :         adfNew[5] = oCT.dfZScale * adfData[5];
     236             : 
     237           6 :         adfNew[6] = oCT.dfXScale * cos(oCT.dfAngle) * adfData[6] -
     238           6 :                     oCT.dfYScale * sin(oCT.dfAngle) * adfData[7];
     239           6 :         adfNew[7] = oCT.dfXScale * sin(oCT.dfAngle) * adfData[6] +
     240           6 :                     oCT.dfYScale * cos(oCT.dfAngle) * adfData[7];
     241           6 :         adfNew[8] = oCT.dfZScale * adfData[8];
     242             : 
     243           6 :         adfNew[9] = oCT.dfXScale * cos(oCT.dfAngle) * adfData[9] -
     244           6 :                     oCT.dfYScale * sin(oCT.dfAngle) * adfData[10] +
     245           6 :                     oCT.dfXOffset;
     246           6 :         adfNew[10] = oCT.dfXScale * sin(oCT.dfAngle) * adfData[9] +
     247           6 :                      oCT.dfYScale * cos(oCT.dfAngle) * adfData[10] +
     248           6 :                      oCT.dfYOffset;
     249           6 :         adfNew[11] = oCT.dfZScale * adfData[11] + oCT.dfZOffset;
     250             : 
     251           6 :         memcpy(adfData, adfNew, sizeof(adfNew));
     252           6 :     }
     253             : 
     254           5 :     void SetField(OGRFeature *poFeature, const char *pszFieldName) const
     255             :     {
     256           5 :         poFeature->SetField(pszFieldName, 12, adfData);
     257           5 :     }
     258             : };
     259             : 
     260             : /************************************************************************/
     261             : /*                         OGRDXFOCSTransformer                         */
     262             : /************************************************************************/
     263             : 
     264             : class OGRDXFOCSTransformer final : public OGRCoordinateTransformation
     265             : {
     266             :   private:
     267             :     double adfN[3];
     268             :     double adfAX[3];
     269             :     double adfAY[3];
     270             : 
     271             :     double dfDeterminant;
     272             :     double aadfInverse[4][4];
     273             : 
     274             :   public:
     275             :     explicit OGRDXFOCSTransformer(double adfNIn[3], bool bInverse = false);
     276             : 
     277           0 :     const OGRSpatialReference *GetSourceCS() const override
     278             :     {
     279           0 :         return nullptr;
     280             :     }
     281             : 
     282        2078 :     const OGRSpatialReference *GetTargetCS() const override
     283             :     {
     284        2078 :         return nullptr;
     285             :     }
     286             : 
     287             :     int Transform(size_t nCount, double *adfX, double *adfY, double *adfZ,
     288             :                   double *adfT, int *pabSuccess) override;
     289             : 
     290             :     int InverseTransform(size_t nCount, double *adfX, double *adfY,
     291             :                          double *adfZ);
     292             : 
     293             :     void ComposeOnto(OGRDXFAffineTransform &poCT) const;
     294             : 
     295           0 :     OGRCoordinateTransformation *Clone() const override
     296             :     {
     297           0 :         return new OGRDXFOCSTransformer(*this);
     298             :     }
     299             : 
     300           0 :     OGRCoordinateTransformation *GetInverse() const override
     301             :     {
     302           0 :         return nullptr;
     303             :     }
     304             : };
     305             : 
     306             : /************************************************************************/
     307             : /*                              DXFTriple                               */
     308             : /*                                                                      */
     309             : /*     Represents a triple (X, Y, Z) used for various purposes in       */
     310             : /*     DXF files.  We do not use OGRPoint for this purpose, as the      */
     311             : /*     triple does not always represent a point as such (for            */
     312             : /*     example, it could contain a scale factor for each dimension).    */
     313             : /************************************************************************/
     314             : struct DXFTriple
     315             : {
     316             :     double dfX, dfY, dfZ;
     317             : 
     318          27 :     DXFTriple() : dfX(0.0), dfY(0.0), dfZ(0.0)
     319             :     {
     320          27 :     }
     321             : 
     322       12587 :     DXFTriple(double x, double y, double z) : dfX(x), dfY(y), dfZ(z)
     323             :     {
     324       12587 :     }
     325             : 
     326        1956 :     void ToArray(double adfOut[3]) const
     327             :     {
     328        1956 :         adfOut[0] = dfX;
     329        1956 :         adfOut[1] = dfY;
     330        1956 :         adfOut[2] = dfZ;
     331        1956 :     }
     332             : 
     333          18 :     DXFTriple &operator*=(const double dfValue)
     334             :     {
     335          18 :         dfX *= dfValue;
     336          18 :         dfY *= dfValue;
     337          18 :         dfZ *= dfValue;
     338          18 :         return *this;
     339             :     }
     340             : 
     341           2 :     DXFTriple &operator/=(const double dfValue)
     342             :     {
     343           2 :         dfX /= dfValue;
     344           2 :         dfY /= dfValue;
     345           2 :         dfZ /= dfValue;
     346           2 :         return *this;
     347             :     }
     348             : 
     349             :     bool operator==(const DXFTriple &oOther) const
     350             :     {
     351             :         return dfX == oOther.dfX && dfY == oOther.dfY && dfZ == oOther.dfZ;
     352             :     }
     353             : };
     354             : 
     355             : /************************************************************************/
     356             : /*                            OGRDXFFeature                             */
     357             : /*                                                                      */
     358             : /*     Extends OGRFeature with some DXF-specific members.               */
     359             : /************************************************************************/
     360             : class OGRDXFFeature final : public OGRFeature
     361             : {
     362             :     friend class OGRDXFLayer;
     363             : 
     364             :   protected:
     365             :     // The feature's Object Coordinate System (OCS) unit normal vector
     366             :     DXFTriple oOCS;
     367             : 
     368             :     // A list of properties that are used to construct the style string
     369             :     std::map<CPLString, CPLString> oStyleProperties;
     370             : 
     371             :     // Additional data for INSERT entities
     372             :     bool bIsBlockReference;
     373             :     CPLString osBlockName;
     374             :     double dfBlockAngle;
     375             :     DXFTriple oBlockScale;
     376             : 
     377             :     // Used for INSERT entities when DXF_INLINE_BLOCKS is false, to store
     378             :     // the OCS insertion point
     379             :     DXFTriple oOriginalCoords;
     380             : 
     381             :     // Used in 3D mode to store transformation parameters for ASM entities
     382             :     std::unique_ptr<OGRDXFAffineTransform> poASMTransform;
     383             : 
     384             :     // Additional data for ATTRIB and ATTDEF entities
     385             :     CPLString osAttributeTag;
     386             : 
     387             :     // Store ATTRIB entities associated with an INSERT, for use when
     388             :     // DXF_INLINE_BLOCKS is true and a block with attributes is INSERTed
     389             :     // in another block
     390             :     std::vector<std::unique_ptr<OGRDXFFeature>> apoAttribFeatures;
     391             : 
     392             :   public:
     393             :     explicit OGRDXFFeature(OGRFeatureDefn *poFeatureDefn);
     394             : 
     395             :     OGRDXFFeature *CloneDXFFeature();
     396             : 
     397             :     DXFTriple GetOCS() const
     398             :     {
     399             :         return oOCS;
     400             :     }
     401             : 
     402        2695 :     bool IsBlockReference() const
     403             :     {
     404        2695 :         return bIsBlockReference;
     405             :     }
     406             : 
     407             :     CPLString GetBlockName() const
     408             :     {
     409             :         return osBlockName;
     410             :     }
     411             : 
     412             :     double GetBlockAngle() const
     413             :     {
     414             :         return dfBlockAngle;
     415             :     }
     416             : 
     417             :     DXFTriple GetBlockScale() const
     418             :     {
     419             :         return oBlockScale;
     420             :     }
     421             : 
     422         793 :     DXFTriple GetInsertOCSCoords() const
     423             :     {
     424         793 :         return oOriginalCoords;
     425             :     }
     426             : 
     427          44 :     CPLString GetAttributeTag() const
     428             :     {
     429          44 :         return osAttributeTag;
     430             :     }
     431             : 
     432             :     const std::vector<std::unique_ptr<OGRDXFFeature>> &GetAttribFeatures() const
     433             :     {
     434             :         return apoAttribFeatures;
     435             :     }
     436             : 
     437         793 :     void SetInsertOCSCoords(const DXFTriple &oTriple)
     438             :     {
     439         793 :         oOriginalCoords = oTriple;
     440         793 :     }
     441             : 
     442             :     void ApplyOCSTransformer(OGRGeometry *const poGeometry) const;
     443             :     void ApplyOCSTransformer(OGRDXFAffineTransform *const poCT) const;
     444             :     const CPLString GetColor(OGRDXFDataSource *const poDS,
     445             :                              OGRDXFFeature *const poBlockFeature = nullptr);
     446             : };
     447             : 
     448             : /************************************************************************/
     449             : /*                             OGRDXFLayer                              */
     450             : /************************************************************************/
     451             : class OGRDXFLayer final : public OGRLayer
     452             : {
     453             :     friend class OGRDXFBlocksLayer;
     454             : 
     455             :     OGRDXFDataSource *poDS;
     456             : 
     457             :     OGRFeatureDefn *poFeatureDefn;
     458             :     GIntBig iNextFID;
     459             : 
     460             :     std::set<CPLString> oIgnoredEntities;
     461             : 
     462             :     OGRDXFFeatureQueue apoPendingFeatures;
     463             : 
     464             :     struct InsertState
     465             :     {
     466             :         OGRDXFInsertTransformer m_oTransformer{};
     467             :         CPLString m_osBlockName{};
     468             :         CPLStringList m_aosAttribs{};
     469             :         int m_nColumnCount = 0;
     470             :         int m_nRowCount = 0;
     471             :         int m_iCurCol = 0;
     472             :         int m_iCurRow = 0;
     473             :         double m_dfColumnSpacing = 0.0;
     474             :         double m_dfRowSpacing = 0.0;
     475             :         std::vector<std::unique_ptr<OGRDXFFeature>> m_apoAttribs{};
     476             :         std::unique_ptr<OGRDXFFeature> m_poTemplateFeature{};
     477             :     };
     478             : 
     479             :     InsertState m_oInsertState{};
     480             : 
     481             :     void ClearPendingFeatures();
     482             : 
     483             :     void TranslateGenericProperty(OGRDXFFeature *poFeature, int nCode,
     484             :                                   char *pszValue);
     485             : 
     486             :     void PrepareFeatureStyle(OGRDXFFeature *const poFeature,
     487             :                              OGRDXFFeature *const poBlockFeature = nullptr);
     488             :     void PrepareBrushStyle(OGRDXFFeature *const poFeature,
     489             :                            OGRDXFFeature *const poBlockFeature = nullptr);
     490             :     void PrepareLineStyle(OGRDXFFeature *const poFeature,
     491             :                           OGRDXFFeature *const poBlockFeature = nullptr);
     492             : 
     493             :     OGRDXFFeature *TranslatePOINT();
     494             :     OGRDXFFeature *TranslateLINE();
     495             :     OGRDXFFeature *TranslatePOLYLINE();
     496             :     OGRDXFFeature *TranslateLWPOLYLINE();
     497             :     OGRDXFFeature *TranslateMLINE();
     498             :     OGRDXFFeature *TranslateCIRCLE();
     499             :     OGRDXFFeature *TranslateELLIPSE();
     500             :     OGRDXFFeature *TranslateARC();
     501             :     OGRDXFFeature *TranslateSPLINE();
     502             :     OGRDXFFeature *Translate3DFACE();
     503             :     bool TranslateINSERT();
     504             :     OGRDXFFeature *TranslateMTEXT();
     505             :     OGRDXFFeature *TranslateTEXT(const bool bIsAttribOrAttdef);
     506             :     OGRDXFFeature *TranslateDIMENSION();
     507             :     OGRDXFFeature *TranslateHATCH();
     508             :     OGRDXFFeature *TranslateSOLID();
     509             :     OGRDXFFeature *TranslateLEADER();
     510             :     OGRDXFFeature *TranslateMLEADER();
     511             :     OGRDXFFeature *TranslateASMEntity();
     512             : 
     513             :     static constexpr int FORTRAN_INDEXING = 1;
     514             : 
     515             :     bool GenerateINSERTFeatures();
     516             :     std::unique_ptr<OGRLineString>
     517             :     InsertSplineWithChecks(const int nDegree,
     518             :                            std::vector<double> &adfControlPoints, bool bHasZ,
     519             :                            int nControlPoints, std::vector<double> &adfKnots,
     520             :                            int nKnots, std::vector<double> &adfWeights);
     521             :     static OGRGeometry *SimplifyBlockGeometry(OGRGeometryCollection *);
     522             :     OGRDXFFeature *InsertBlockInline(GUInt32 nInitialErrorCounter,
     523             :                                      const CPLString &osBlockName,
     524             :                                      OGRDXFInsertTransformer oTransformer,
     525             :                                      OGRDXFFeature *const poFeature,
     526             :                                      OGRDXFFeatureQueue &apoExtraFeatures,
     527             :                                      const bool bInlineNestedBlocks,
     528             :                                      const bool bMergeGeometry);
     529             :     static OGRDXFFeature *
     530             :     InsertBlockReference(const CPLString &osBlockName,
     531             :                          const OGRDXFInsertTransformer &oTransformer,
     532             :                          OGRDXFFeature *const poFeature);
     533             :     static void FormatDimension(CPLString &osText, const double dfValue,
     534             :                                 int nPrecision);
     535             :     void InsertArrowhead(OGRDXFFeature *const poFeature,
     536             :                          const CPLString &osBlockName,
     537             :                          OGRLineString *const poLine,
     538             :                          const double dfArrowheadSize,
     539             :                          const bool bReverse = false);
     540             :     OGRErr CollectBoundaryPath(OGRGeometryCollection *poGC,
     541             :                                const double dfElevation);
     542             :     OGRErr CollectPolylinePath(OGRGeometryCollection *poGC,
     543             :                                const double dfElevation);
     544             : 
     545             :     CPLString TextRecode(const char *);
     546             :     CPLString TextUnescape(const char *, bool);
     547             : 
     548             :   public:
     549             :     explicit OGRDXFLayer(OGRDXFDataSource *poDS);
     550             :     ~OGRDXFLayer();
     551             : 
     552             :     void ResetReading() override;
     553             :     OGRFeature *GetNextFeature() override;
     554             : 
     555         255 :     OGRFeatureDefn *GetLayerDefn() override
     556             :     {
     557         255 :         return poFeatureDefn;
     558             :     }
     559             : 
     560             :     int TestCapability(const char *) override;
     561             : 
     562             :     GDALDataset *GetDataset() override;
     563             : 
     564             :     OGRDXFFeature *GetNextUnfilteredFeature();
     565             : };
     566             : 
     567             : /************************************************************************/
     568             : /*                             OGRDXFReader                             */
     569             : /*                                                                      */
     570             : /*      A class for very low level DXF reading without interpretation.  */
     571             : /************************************************************************/
     572             : 
     573             : #define DXF_READER_ERROR()                                                     \
     574             :     do                                                                         \
     575             :     {                                                                          \
     576             :         CPLError(CE_Failure, CPLE_AppDefined,                                  \
     577             :                  "%s, %d: error at line %d of %s", __FILE__, __LINE__,         \
     578             :                  GetLineNumber(), GetDescription());                           \
     579             :     } while (0)
     580             : #define DXF_LAYER_READER_ERROR()                                               \
     581             :     do                                                                         \
     582             :     {                                                                          \
     583             :         CPLError(CE_Failure, CPLE_AppDefined,                                  \
     584             :                  "%s, %d: error at line %d of %s", __FILE__, __LINE__,         \
     585             :                  poDS->GetLineNumber(), poDS->GetDescription());               \
     586             :     } while (0)
     587             : 
     588             : class OGRDXFReader
     589             : {
     590             :     int ReadValueRaw(char *pszValueBuffer, int nValueBufferSize);
     591             : 
     592             :   public:
     593             :     OGRDXFReader();
     594             :     ~OGRDXFReader();
     595             : 
     596             :     void Initialize(VSILFILE *fp);
     597             : 
     598             :     VSILFILE *fp;
     599             : 
     600             :     unsigned int iSrcBufferOffset;
     601             :     unsigned int nSrcBufferBytes;
     602             :     unsigned int iSrcBufferFileOffset;
     603             :     char achSrcBuffer[1025];
     604             : 
     605             :     unsigned int nLastValueSize;
     606             :     int nLineNumber;
     607             : 
     608             :     int ReadValue(char *pszValueBuffer, int nValueBufferSize = 81);
     609             :     void UnreadValue();
     610             :     void LoadDiskChunk();
     611             :     void ResetReadPointer(unsigned int iNewOffset, int nNewLineNumber = 0);
     612             : };
     613             : 
     614             : /************************************************************************/
     615             : /*                           OGRDXFFieldModes                           */
     616             : /*                                                                      */
     617             : /*    Represents which fields should be included in the data source.    */
     618             : /************************************************************************/
     619             : 
     620             : enum OGRDXFFieldModes
     621             : {
     622             :     ODFM_None = 0,
     623             :     ODFM_IncludeRawCodeValues = 0x1,
     624             :     ODFM_IncludeBlockFields = 0x2,
     625             :     ODFM_Include3DModeFields = 0x4
     626             : };
     627             : 
     628             : /************************************************************************/
     629             : /*                           OGRDXFDataSource                           */
     630             : /************************************************************************/
     631             : 
     632             : class OGRDXFDataSource final : public GDALDataset
     633             : {
     634             :     VSILFILE *fp;
     635             : 
     636             :     std::vector<OGRLayer *> apoLayers;
     637             : 
     638             :     unsigned int iEntitiesOffset;
     639             :     int iEntitiesLineNumber;
     640             : 
     641             :     std::map<CPLString, DXFBlockDefinition> oBlockMap;
     642             :     std::map<CPLString, CPLString> oBlockRecordHandles;
     643             :     std::map<CPLString, CPLString> oHeaderVariables;
     644             : 
     645             :     CPLString osEncoding;
     646             : 
     647             :     // indexed by layer name, then by property name.
     648             :     std::map<CPLString, std::map<CPLString, CPLString>> oLayerTable;
     649             : 
     650             :     // indexed by style name, then by property name.
     651             :     std::map<CPLString, std::map<CPLString, CPLString>> oTextStyleTable;
     652             :     std::map<CPLString, CPLString> oTextStyleHandles;
     653             : 
     654             :     // indexed by dimstyle name, then by DIM... variable name
     655             :     std::map<CPLString, std::map<CPLString, CPLString>> oDimStyleTable;
     656             : 
     657             :     std::map<CPLString, std::vector<double>> oLineTypeTable;
     658             : 
     659             :     bool bInlineBlocks;
     660             :     bool bMergeBlockGeometries;
     661             :     bool bTranslateEscapeSequences;
     662             :     bool bIncludeRawCodeValues;
     663             :     bool m_bClosedLineAsPolygon = false;
     664             :     double m_dfHatchTolerance = -1.0;
     665             : 
     666             :     bool b3DExtensibleMode;
     667             :     bool bHaveReadSolidData;
     668             :     std::map<CPLString, std::vector<GByte>> oSolidBinaryData;
     669             : 
     670             :     OGRDXFReader oReader;
     671             : 
     672             :     std::vector<CPLString> aosBlockInsertionStack;
     673             : 
     674             :   public:
     675             :     OGRDXFDataSource();
     676             :     ~OGRDXFDataSource();
     677             : 
     678             :     int Open(const char *pszFilename, bool bHeaderOnly,
     679             :              CSLConstList papszOptionsIn);
     680             : 
     681         392 :     int GetLayerCount() override
     682             :     {
     683         392 :         return static_cast<int>(apoLayers.size());
     684             :     }
     685             : 
     686             :     OGRLayer *GetLayer(int) override;
     687             : 
     688             :     int TestCapability(const char *) override;
     689             : 
     690             :     // The following is only used by OGRDXFLayer
     691             : 
     692        1366 :     bool InlineBlocks() const
     693             :     {
     694        1366 :         return bInlineBlocks;
     695             :     }
     696             : 
     697         122 :     bool ShouldMergeBlockGeometries() const
     698             :     {
     699         122 :         return bMergeBlockGeometries;
     700             :     }
     701             : 
     702         148 :     bool ShouldTranslateEscapes() const
     703             :     {
     704         148 :         return bTranslateEscapeSequences;
     705             :     }
     706             : 
     707        2766 :     bool ShouldIncludeRawCodeValues() const
     708             :     {
     709        2766 :         return bIncludeRawCodeValues;
     710             :     }
     711             : 
     712         173 :     bool In3DExtensibleMode() const
     713             :     {
     714         173 :         return b3DExtensibleMode;
     715             :     }
     716             : 
     717          25 :     bool ClosedLineAsPolygon() const
     718             :     {
     719          25 :         return m_bClosedLineAsPolygon;
     720             :     }
     721             : 
     722          28 :     double HatchTolerance() const
     723             :     {
     724          28 :         return m_dfHatchTolerance;
     725             :     }
     726             : 
     727             :     static void AddStandardFields(OGRFeatureDefn *poDef, const int nFieldModes);
     728             : 
     729             :     // Implemented in ogrdxf_blockmap.cpp
     730             :     bool ReadBlocksSection();
     731             :     DXFBlockDefinition *LookupBlock(const char *pszName);
     732             :     CPLString GetBlockNameByRecordHandle(const char *pszID);
     733             : 
     734          42 :     std::map<CPLString, DXFBlockDefinition> &GetBlockMap()
     735             :     {
     736          42 :         return oBlockMap;
     737             :     }
     738             : 
     739             :     bool PushBlockInsertion(const CPLString &osBlockName);
     740             : 
     741         296 :     void PopBlockInsertion()
     742             :     {
     743         296 :         aosBlockInsertionStack.pop_back();
     744         296 :     }
     745             : 
     746             :     // Layer and other Table Handling (ogrdatasource.cpp)
     747             :     bool ReadTablesSection();
     748             :     bool ReadLayerDefinition();
     749             :     bool ReadLineTypeDefinition();
     750             :     bool ReadTextStyleDefinition();
     751             :     bool ReadDimStyleDefinition();
     752             :     const char *LookupLayerProperty(const char *pszLayer,
     753             :                                     const char *pszProperty);
     754             :     const char *LookupTextStyleProperty(const char *pszTextStyle,
     755             :                                         const char *pszProperty,
     756             :                                         const char *pszDefault);
     757             :     bool LookupDimStyle(const char *pszDimstyle,
     758             :                         std::map<CPLString, CPLString> &oDimStyleProperties);
     759             : 
     760           4 :     const std::map<CPLString, std::vector<double>> &GetLineTypeTable() const
     761             :     {
     762           4 :         return oLineTypeTable;
     763             :     }
     764             : 
     765             :     std::vector<double> LookupLineType(const char *pszName);
     766             :     bool TextStyleExists(const char *pszTextStyle);
     767             :     CPLString GetTextStyleNameByHandle(const char *pszID);
     768             :     static void PopulateDefaultDimStyleProperties(
     769             :         std::map<CPLString, CPLString> &oDimStyleProperties);
     770             :     size_t GetEntryFromAcDsDataSection(const char *pszEntityHandle,
     771             :                                        const GByte **pabyBuffer);
     772             : 
     773             :     // Header variables.
     774             :     bool ReadHeaderSection();
     775             :     const char *GetVariable(const char *pszName,
     776             :                             const char *pszDefault = nullptr);
     777             : 
     778        2680 :     const char *GetEncoding()
     779             :     {
     780        2680 :         return osEncoding;
     781             :     }
     782             : 
     783             :     // reader related.
     784           6 :     int GetLineNumber()
     785             :     {
     786           6 :         return oReader.nLineNumber;
     787             :     }
     788             : 
     789      108194 :     int ReadValue(char *pszValueBuffer, int nValueBufferSize = 81)
     790             :     {
     791      108194 :         return oReader.ReadValue(pszValueBuffer, nValueBufferSize);
     792             :     }
     793             : 
     794         157 :     void RestartEntities()
     795             :     {
     796         157 :         oReader.ResetReadPointer(iEntitiesOffset, iEntitiesLineNumber);
     797         157 :     }
     798             : 
     799        1958 :     void UnreadValue()
     800             :     {
     801        1958 :         oReader.UnreadValue();
     802        1958 :     }
     803             : 
     804          44 :     void ResetReadPointer(int iNewOffset)
     805             :     {
     806          44 :         oReader.ResetReadPointer(iNewOffset);
     807          44 :     }
     808             : };
     809             : 
     810             : /************************************************************************/
     811             : /*                          OGRDXFWriterLayer                           */
     812             : /************************************************************************/
     813             : 
     814             : class OGRDXFWriterDS;
     815             : 
     816             : class OGRDXFWriterLayer final : public OGRLayer
     817             : {
     818             :     VSILFILE *fp;
     819             :     OGRFeatureDefn *poFeatureDefn;
     820             : 
     821             :     OGRDXFWriterDS *poDS;
     822             : 
     823             :     int WriteValue(int nCode, const char *pszValue);
     824             :     int WriteValue(int nCode, int nValue);
     825             :     int WriteValue(int nCode, double dfValue);
     826             : 
     827             :     OGRErr WriteCore(OGRFeature *);
     828             :     OGRErr WritePOINT(OGRFeature *);
     829             :     OGRErr WriteTEXT(OGRFeature *);
     830             :     OGRErr WritePOLYLINE(OGRFeature *, const OGRGeometry * = nullptr);
     831             :     OGRErr WriteHATCH(OGRFeature *, OGRGeometry * = nullptr);
     832             :     OGRErr WriteINSERT(OGRFeature *);
     833             : 
     834             :     static CPLString TextEscape(const char *);
     835             :     static int ColorStringToDXFColor(const char *);
     836             :     static std::vector<double> PrepareLineTypeDefinition(OGRStylePen *);
     837             :     static std::map<CPLString, CPLString>
     838             :     PrepareTextStyleDefinition(OGRStyleLabel *);
     839             : 
     840             :     std::map<CPLString, std::vector<double>> oNewLineTypes;
     841             :     std::map<CPLString, std::map<CPLString, CPLString>> oNewTextStyles;
     842             :     int nNextAutoID;
     843             :     int bWriteHatch;
     844             : 
     845             :   public:
     846             :     OGRDXFWriterLayer(OGRDXFWriterDS *poDS, VSILFILE *fp);
     847             :     ~OGRDXFWriterLayer();
     848             : 
     849          16 :     void ResetReading() override
     850             :     {
     851          16 :     }
     852             : 
     853          16 :     OGRFeature *GetNextFeature() override
     854             :     {
     855          16 :         return nullptr;
     856             :     }
     857             : 
     858         489 :     OGRFeatureDefn *GetLayerDefn() override
     859             :     {
     860         489 :         return poFeatureDefn;
     861             :     }
     862             : 
     863             :     int TestCapability(const char *) override;
     864             :     OGRErr ICreateFeature(OGRFeature *poFeature) override;
     865             :     OGRErr CreateField(const OGRFieldDefn *poField,
     866             :                        int bApproxOK = TRUE) override;
     867             : 
     868             :     GDALDataset *GetDataset() override;
     869             : 
     870             :     void ResetFP(VSILFILE *);
     871             : 
     872          43 :     std::map<CPLString, std::vector<double>> &GetNewLineTypeMap()
     873             :     {
     874          43 :         return oNewLineTypes;
     875             :     }
     876             : 
     877          43 :     std::map<CPLString, std::map<CPLString, CPLString>> &GetNewTextStyleMap()
     878             :     {
     879          43 :         return oNewTextStyles;
     880             :     }
     881             : };
     882             : 
     883             : /************************************************************************/
     884             : /*                       OGRDXFBlocksWriterLayer                        */
     885             : /************************************************************************/
     886             : 
     887             : class OGRDXFBlocksWriterLayer final : public OGRLayer
     888             : {
     889             :     OGRFeatureDefn *poFeatureDefn;
     890             : 
     891             :   public:
     892             :     explicit OGRDXFBlocksWriterLayer(OGRDXFWriterDS *poDS);
     893             :     ~OGRDXFBlocksWriterLayer();
     894             : 
     895           0 :     void ResetReading() override
     896             :     {
     897           0 :     }
     898             : 
     899           0 :     OGRFeature *GetNextFeature() override
     900             :     {
     901           0 :         return nullptr;
     902             :     }
     903             : 
     904          10 :     OGRFeatureDefn *GetLayerDefn() override
     905             :     {
     906          10 :         return poFeatureDefn;
     907             :     }
     908             : 
     909             :     int TestCapability(const char *) override;
     910             :     OGRErr ICreateFeature(OGRFeature *poFeature) override;
     911             :     OGRErr CreateField(const OGRFieldDefn *poField,
     912             :                        int bApproxOK = TRUE) override;
     913             : 
     914             :     std::vector<OGRFeature *> apoBlocks;
     915             :     OGRFeature *FindBlock(const char *);
     916             : };
     917             : 
     918             : /************************************************************************/
     919             : /*                           OGRDXFWriterDS                             */
     920             : /************************************************************************/
     921             : 
     922             : class OGRDXFWriterDS final : public GDALDataset
     923             : {
     924             :     friend class OGRDXFWriterLayer;
     925             : 
     926             :     int nNextFID;
     927             : 
     928             :     OGRDXFWriterLayer *poLayer;
     929             :     OGRDXFBlocksWriterLayer *poBlocksLayer;
     930             :     VSILFILE *fp;
     931             :     CPLString osTrailerFile;
     932             : 
     933             :     CPLString osTempFilename;
     934             :     VSILFILE *fpTemp;
     935             : 
     936             :     CPLString osHeaderFile;
     937             :     OGRDXFDataSource oHeaderDS;
     938             :     char **papszLayersToCreate;
     939             : 
     940             :     vsi_l_offset nHANDSEEDOffset;
     941             : 
     942             :     std::vector<int> anDefaultLayerCode;
     943             :     std::vector<CPLString> aosDefaultLayerText;
     944             : 
     945             :     std::set<CPLString> aosUsedEntities;
     946             :     void ScanForEntities(const char *pszFilename, const char *pszTarget);
     947             : 
     948             :     bool WriteNewLineTypeRecords(VSILFILE *fp);
     949             :     bool WriteNewTextStyleRecords(VSILFILE *fp);
     950             :     bool WriteNewBlockRecords(VSILFILE *);
     951             :     bool WriteNewBlockDefinitions(VSILFILE *);
     952             :     bool WriteNewLayerDefinitions(VSILFILE *);
     953             :     bool TransferUpdateHeader(VSILFILE *);
     954             :     bool TransferUpdateTrailer(VSILFILE *);
     955             :     bool FixupHANDSEED(VSILFILE *);
     956             : 
     957             :     OGREnvelope oGlobalEnvelope;
     958             : 
     959             :     bool m_bHeaderFileIsTemp = false;
     960             :     bool m_bTrailerFileIsTemp = false;
     961             : 
     962             :   public:
     963             :     OGRDXFWriterDS();
     964             :     ~OGRDXFWriterDS();
     965             : 
     966             :     int Open(const char *pszFilename, char **papszOptions);
     967             : 
     968             :     int GetLayerCount() override;
     969             :     OGRLayer *GetLayer(int) override;
     970             : 
     971             :     int TestCapability(const char *) override;
     972             : 
     973             :     OGRLayer *ICreateLayer(const char *pszName,
     974             :                            const OGRGeomFieldDefn *poGeomFieldDefn,
     975             :                            CSLConstList papszOptions) override;
     976             : 
     977             :     bool CheckEntityID(const char *pszEntityID);
     978             :     bool WriteEntityID(VSILFILE *fp, unsigned int &nAssignedFID,
     979             :                        GIntBig nPreferredFID = OGRNullFID);
     980             : 
     981             :     void UpdateExtent(OGREnvelope *psEnvelope);
     982             : };
     983             : 
     984             : #endif /* ndef OGR_DXF_H_INCLUDED */

Generated by: LCOV version 1.14