LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/dxf - ogrdxf_feature.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 112 124 90.3 %
Date: 2024-11-21 22:18:42 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  DXF Translator
       4             :  * Purpose:  Provides additional functionality for DXF features
       5             :  * Author:   Alan Thomas, alant@outlook.com.au
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2017, Alan Thomas <alant@outlook.com.au>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "ogr_dxf.h"
      14             : #include "cpl_string.h"
      15             : 
      16             : /************************************************************************/
      17             : /*                            OGRDXFFeature()                           */
      18             : /************************************************************************/
      19             : 
      20        3369 : OGRDXFFeature::OGRDXFFeature(OGRFeatureDefn *poFeatureDefn)
      21             :     : OGRFeature(poFeatureDefn), oOCS(0.0, 0.0, 1.0), bIsBlockReference(false),
      22             :       dfBlockAngle(0.0), oBlockScale(1.0, 1.0, 1.0),
      23        3369 :       oOriginalCoords(0.0, 0.0, 0.0)
      24             : {
      25        3369 : }
      26             : 
      27             : /************************************************************************/
      28             : /*                          CloneDXFFeature()                           */
      29             : /*                                                                      */
      30             : /*      Replacement for OGRFeature::Clone() for DXF features.           */
      31             : /************************************************************************/
      32             : 
      33        2644 : OGRDXFFeature *OGRDXFFeature::CloneDXFFeature()
      34             : {
      35        2644 :     OGRDXFFeature *poNew = new OGRDXFFeature(GetDefnRef());
      36        2644 :     if (poNew == nullptr)
      37           0 :         return nullptr;
      38             : 
      39        2644 :     if (!CopySelfTo(poNew))
      40             :     {
      41           0 :         delete poNew;
      42           0 :         return nullptr;
      43             :     }
      44             : 
      45        2644 :     poNew->oOCS = oOCS;
      46        2644 :     poNew->bIsBlockReference = bIsBlockReference;
      47        2644 :     poNew->osBlockName = osBlockName;
      48        2644 :     poNew->dfBlockAngle = dfBlockAngle;
      49        2644 :     poNew->oBlockScale = oBlockScale;
      50        2644 :     poNew->oOriginalCoords = oOriginalCoords;
      51        2644 :     poNew->osAttributeTag = osAttributeTag;
      52        2644 :     poNew->oStyleProperties = oStyleProperties;
      53             : 
      54        2644 :     if (poASMTransform)
      55             :     {
      56           2 :         poNew->poASMTransform = std::unique_ptr<OGRDXFAffineTransform>(
      57           2 :             new OGRDXFAffineTransform(*poASMTransform));
      58             :     }
      59             : 
      60           2 :     for (const std::unique_ptr<OGRDXFFeature> &poAttribFeature :
      61        2646 :          apoAttribFeatures)
      62             :     {
      63             :         poNew->apoAttribFeatures.emplace_back(
      64           2 :             poAttribFeature->CloneDXFFeature());
      65             :     }
      66             : 
      67        2644 :     return poNew;
      68             : }
      69             : 
      70             : /************************************************************************/
      71             : /*                        ApplyOCSTransformer()                         */
      72             : /*                                                                      */
      73             : /*      Applies the OCS transformation stored in this feature to        */
      74             : /*      the specified geometry.                                         */
      75             : /************************************************************************/
      76             : 
      77        1924 : void OGRDXFFeature::ApplyOCSTransformer(OGRGeometry *const poGeometry) const
      78             : {
      79        1924 :     if (poGeometry == nullptr)
      80           0 :         return;
      81             : 
      82             :     double adfN[3];
      83        1924 :     oOCS.ToArray(adfN);
      84             : 
      85        3848 :     OGRDXFOCSTransformer oTransformer(adfN);
      86             : 
      87             :     // Promote to 3D, in case the OCS transformation introduces a
      88             :     // third dimension to the geometry.
      89        1924 :     const bool bInitially2D = !poGeometry->Is3D();
      90        1924 :     if (bInitially2D)
      91         187 :         poGeometry->set3D(TRUE);
      92             : 
      93        1924 :     poGeometry->transform(&oTransformer);
      94             : 
      95             :     // If the geometry was 2D to begin with, and is still 2D after the
      96             :     // OCS transformation, flatten it back to 2D.
      97        1924 :     if (bInitially2D)
      98             :     {
      99         187 :         OGREnvelope3D oEnvelope;
     100         187 :         poGeometry->getEnvelope(&oEnvelope);
     101         187 :         if (oEnvelope.MaxZ == 0.0 && oEnvelope.MinZ == 0.0)
     102         170 :             poGeometry->flattenTo2D();
     103             :     }
     104             : }
     105             : 
     106             : /************************************************************************/
     107             : /*                        ApplyOCSTransformer()                         */
     108             : /************************************************************************/
     109             : 
     110           3 : void OGRDXFFeature::ApplyOCSTransformer(OGRDXFAffineTransform *const poCT) const
     111             : {
     112           3 :     if (!poCT)
     113           0 :         return;
     114             : 
     115             :     double adfN[3];
     116           3 :     oOCS.ToArray(adfN);
     117             : 
     118           6 :     OGRDXFOCSTransformer oTransformer(adfN);
     119             : 
     120           3 :     oTransformer.ComposeOnto(*poCT);
     121             : }
     122             : 
     123             : /************************************************************************/
     124             : /*                              GetColor()                              */
     125             : /*                                                                      */
     126             : /*      Gets the hex color string for this feature, using the given     */
     127             : /*      data source to fetch layer properties.                          */
     128             : /*                                                                      */
     129             : /*      For usage info about poBlockFeature, see                        */
     130             : /*      OGRDXFLayer::PrepareFeatureStyle.                               */
     131             : /************************************************************************/
     132             : 
     133             : const CPLString
     134        1268 : OGRDXFFeature::GetColor(OGRDXFDataSource *const poDS,
     135             :                         OGRDXFFeature *const poBlockFeature /* = NULL */)
     136             : {
     137        2536 :     CPLString osLayer = GetFieldAsString("Layer");
     138             : 
     139             :     /* -------------------------------------------------------------------- */
     140             :     /*      Is the layer or object hidden/off (1) or frozen (2)?            */
     141             :     /* -------------------------------------------------------------------- */
     142             : 
     143        1268 :     int iHidden = 0;
     144             : 
     145        3024 :     if (oStyleProperties.count("Hidden") > 0 ||
     146         976 :         (poBlockFeature &&
     147        1756 :          poBlockFeature->oStyleProperties.count("Hidden") > 0))
     148             :     {
     149             :         // Hidden objects should never be shown no matter what happens,
     150             :         // so they can be treated as if they are on a frozen layer
     151         119 :         iHidden = 2;
     152             :     }
     153             :     else
     154             :     {
     155        1149 :         const char *pszHidden = poDS->LookupLayerProperty(osLayer, "Hidden");
     156        1149 :         if (pszHidden)
     157        1149 :             iHidden = atoi(pszHidden);
     158             : 
     159             :         // Is the block feature on a frozen layer? If so, hide this feature
     160        1149 :         if (!iHidden && poBlockFeature)
     161             :         {
     162             :             const CPLString osBlockLayer =
     163         858 :                 poBlockFeature->GetFieldAsString("Layer");
     164             :             const char *pszBlockHidden =
     165         429 :                 poDS->LookupLayerProperty(osBlockLayer, "Hidden");
     166         429 :             if (pszBlockHidden && atoi(pszBlockHidden) == 2)
     167          16 :                 iHidden = 2;
     168             :         }
     169             :     }
     170             : 
     171             :     // If this feature is on a frozen layer, make the object totally
     172             :     // hidden so it won't reappear if we regenerate the style string again
     173             :     // during block insertion
     174        1268 :     if (iHidden == 2)
     175         151 :         oStyleProperties["Hidden"] = "1";
     176             : 
     177             :     // Helpful constants
     178        1268 :     const int C_BYLAYER = 256;
     179        1268 :     const int C_BYBLOCK = 0;
     180        1268 :     const int C_TRUECOLOR = -100;  // not used in DXF - for our purposes only
     181             : 
     182             :     /* -------------------------------------------------------------------- */
     183             :     /*      MULTILEADER entities store colors by directly outputting        */
     184             :     /*      the AcCmEntityColor struct as a 32-bit integer.                 */
     185             :     /* -------------------------------------------------------------------- */
     186             : 
     187        1268 :     int nColor = C_BYLAYER;
     188        1268 :     unsigned int nTrueColor = 0;
     189             : 
     190        1268 :     if (oStyleProperties.count("TrueColor") > 0)
     191             :     {
     192          11 :         nTrueColor = atoi(oStyleProperties["TrueColor"]);
     193          11 :         nColor = C_TRUECOLOR;
     194             :     }
     195        1257 :     else if (oStyleProperties.count("Color") > 0)
     196             :     {
     197         786 :         nColor = atoi(oStyleProperties["Color"]);
     198             :     }
     199             : 
     200        1268 :     const unsigned char byColorMethod = (nColor & 0xFF000000) >> 24;
     201        1268 :     switch (byColorMethod)
     202             :     {
     203             :         // ByLayer
     204           0 :         case 0xC0:
     205           0 :             nColor = C_BYLAYER;
     206           0 :             break;
     207             : 
     208             :         // ByBlock
     209          16 :         case 0xC1:
     210          16 :             nColor = C_BYBLOCK;
     211          16 :             break;
     212             : 
     213             :         // RGB true color
     214           0 :         case 0xC2:
     215           0 :             nTrueColor = nColor & 0xFFFFFF;
     216           0 :             nColor = C_TRUECOLOR;
     217           0 :             break;
     218             : 
     219             :         // Indexed color
     220           2 :         case 0xC3:
     221           2 :             nColor &= 0xFF;
     222           2 :             break;
     223             :     }
     224             : 
     225             :     /* -------------------------------------------------------------------- */
     226             :     /*      Work out the indexed color for this feature.                    */
     227             :     /* -------------------------------------------------------------------- */
     228             : 
     229             :     // Use ByBlock color?
     230        1268 :     if (nColor == C_BYBLOCK && poBlockFeature)
     231             :     {
     232         208 :         if (poBlockFeature->oStyleProperties.count("TrueColor") > 0)
     233             :         {
     234             :             // Inherit true color from the owning block
     235           3 :             nTrueColor = atoi(poBlockFeature->oStyleProperties["TrueColor"]);
     236           3 :             nColor = C_TRUECOLOR;
     237             : 
     238             :             // Use the inherited color if we regenerate the style string
     239             :             // again during block insertion
     240           6 :             oStyleProperties["TrueColor"] =
     241           9 :                 poBlockFeature->oStyleProperties["TrueColor"];
     242             :         }
     243         205 :         else if (poBlockFeature->oStyleProperties.count("Color") > 0)
     244             :         {
     245             :             // Inherit color from the owning block
     246         153 :             nColor = atoi(poBlockFeature->oStyleProperties["Color"]);
     247             : 
     248             :             // Use the inherited color if we regenerate the style string
     249             :             // again during block insertion
     250         306 :             oStyleProperties["Color"] =
     251         459 :                 poBlockFeature->oStyleProperties["Color"];
     252             :         }
     253             :         else
     254             :         {
     255             :             // If the owning block has no explicit color, assume ByLayer
     256          52 :             nColor = C_BYLAYER;
     257             :         }
     258             :     }
     259             : 
     260             :     // Use layer color?
     261        1268 :     if (nColor == C_BYLAYER)
     262             :     {
     263         726 :         if (poBlockFeature)
     264             :         {
     265             :             // Use the block feature's layer instead
     266         179 :             osLayer = poBlockFeature->GetFieldAsString("Layer");
     267             :         }
     268             : 
     269             :         const char *pszTrueColor =
     270         726 :             poDS->LookupLayerProperty(osLayer, "TrueColor");
     271         726 :         if (pszTrueColor != nullptr && *pszTrueColor)
     272             :         {
     273           1 :             nTrueColor = atoi(pszTrueColor);
     274           1 :             nColor = C_TRUECOLOR;
     275             : 
     276           1 :             if (poBlockFeature)
     277             :             {
     278             :                 // Use the inherited color if we regenerate the style string
     279             :                 // again during block insertion
     280           1 :                 oStyleProperties["TrueColor"] = pszTrueColor;
     281             :             }
     282             :         }
     283             :         else
     284             :         {
     285         725 :             const char *pszColor = poDS->LookupLayerProperty(osLayer, "Color");
     286         725 :             if (pszColor != nullptr)
     287             :             {
     288         725 :                 nColor = atoi(pszColor);
     289             : 
     290         725 :                 if (poBlockFeature)
     291             :                 {
     292             :                     // Use the inherited color if we regenerate the style string
     293             :                     // again during block insertion
     294         178 :                     oStyleProperties["Color"] = pszColor;
     295             :                 }
     296             :             }
     297             :         }
     298             :     }
     299             : 
     300             :     // If no color is available, use the default black/white color
     301        1268 :     if (nColor != C_TRUECOLOR && (nColor < 1 || nColor > 255))
     302         230 :         nColor = 7;
     303             : 
     304             :     /* -------------------------------------------------------------------- */
     305             :     /*      Translate the DWG/DXF color index to a hex color string.        */
     306             :     /* -------------------------------------------------------------------- */
     307             : 
     308        1268 :     CPLString osResult;
     309             : 
     310        1268 :     if (nColor == C_TRUECOLOR)
     311             :     {
     312          15 :         osResult.Printf("#%06x", nTrueColor);
     313             :     }
     314             :     else
     315             :     {
     316        1253 :         const unsigned char *pabyDXFColors = ACGetColorTable();
     317             : 
     318        1253 :         osResult.Printf("#%02x%02x%02x", pabyDXFColors[nColor * 3 + 0],
     319        1253 :                         pabyDXFColors[nColor * 3 + 1],
     320        1253 :                         pabyDXFColors[nColor * 3 + 2]);
     321             :     }
     322             : 
     323        1268 :     if (iHidden)
     324         199 :         osResult += "00";
     325             : 
     326        2536 :     return osResult;
     327             : }

Generated by: LCOV version 1.14