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: 156 174 89.7 %
Date: 2024-05-04 12:52:34 Functions: 46 55 83.6 %

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

Generated by: LCOV version 1.14