LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/dxf - ogrdxfdatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 193 163 84.5 %
Date: 2013-03-30 Functions: 16 13 81.2 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrdxfdatasource.cpp 25811 2013-03-29 22:16:56Z rouault $
       3                 :  *
       4                 :  * Project:  DXF Translator
       5                 :  * Purpose:  Implements OGRDXFDataSource class
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2009, Frank Warmerdam <warmerdam@pobox.com>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "ogr_dxf.h"
      31                 : #include "cpl_conv.h"
      32                 : #include "cpl_string.h"
      33                 : 
      34                 : CPL_CVSID("$Id: ogrdxfdatasource.cpp 25811 2013-03-29 22:16:56Z rouault $");
      35                 : 
      36                 : /************************************************************************/
      37                 : /*                          OGRDXFDataSource()                          */
      38                 : /************************************************************************/
      39                 : 
      40             239 : OGRDXFDataSource::OGRDXFDataSource()
      41                 : 
      42                 : {
      43             239 :     fp = NULL;
      44             239 : }
      45                 : 
      46                 : /************************************************************************/
      47                 : /*                         ~OGRDXFDataSource()                          */
      48                 : /************************************************************************/
      49                 : 
      50             239 : OGRDXFDataSource::~OGRDXFDataSource()
      51                 : 
      52                 : {
      53                 : /* -------------------------------------------------------------------- */
      54                 : /*      Destroy layers.                                                 */
      55                 : /* -------------------------------------------------------------------- */
      56             502 :     while( apoLayers.size() > 0 )
      57                 :     {
      58              24 :         delete apoLayers.back();
      59              24 :         apoLayers.pop_back();
      60                 :     }
      61                 : 
      62                 : /* -------------------------------------------------------------------- */
      63                 : /*      Close file.                                                     */
      64                 : /* -------------------------------------------------------------------- */
      65             239 :     if( fp != NULL )
      66                 :     {
      67              23 :         VSIFCloseL( fp );
      68              23 :         fp = NULL;
      69                 :     }
      70             239 : }
      71                 : 
      72                 : /************************************************************************/
      73                 : /*                           TestCapability()                           */
      74                 : /************************************************************************/
      75                 : 
      76               0 : int OGRDXFDataSource::TestCapability( const char * pszCap )
      77                 : 
      78                 : {
      79               0 :     return FALSE;
      80                 : }
      81                 : 
      82                 : /************************************************************************/
      83                 : /*                              GetLayer()                              */
      84                 : /************************************************************************/
      85                 : 
      86                 : 
      87              55 : OGRLayer *OGRDXFDataSource::GetLayer( int iLayer )
      88                 : 
      89                 : {
      90              55 :     if( iLayer < 0 || iLayer >= (int) apoLayers.size() )
      91               0 :         return NULL;
      92                 :     else
      93              55 :         return apoLayers[iLayer];
      94                 : }
      95                 : 
      96                 : /************************************************************************/
      97                 : /*                                Open()                                */
      98                 : /************************************************************************/
      99                 : 
     100             239 : int OGRDXFDataSource::Open( const char * pszFilename, int bHeaderOnly )
     101                 : 
     102                 : {
     103             239 :     if( !EQUAL(CPLGetExtension(pszFilename),"dxf") )
     104             216 :         return FALSE;
     105                 : 
     106              23 :     osEncoding = CPL_ENC_ISO8859_1;
     107                 : 
     108              46 :     osName = pszFilename;
     109                 : 
     110                 :     bInlineBlocks = CSLTestBoolean(
     111              23 :         CPLGetConfigOption( "DXF_INLINE_BLOCKS", "TRUE" ) );
     112                 : 
     113              23 :     if( CSLTestBoolean(
     114                 :             CPLGetConfigOption( "DXF_HEADER_ONLY", "FALSE" ) ) )
     115               0 :         bHeaderOnly = TRUE;
     116                 : 
     117                 : /* -------------------------------------------------------------------- */
     118                 : /*      Open the file.                                                  */
     119                 : /* -------------------------------------------------------------------- */
     120              23 :     fp = VSIFOpenL( pszFilename, "r" );
     121              23 :     if( fp == NULL )
     122               0 :         return FALSE;
     123                 : 
     124              23 :     oReader.Initialize( fp );
     125                 :     
     126                 : /* -------------------------------------------------------------------- */
     127                 : /*      Confirm we have a header section.                               */
     128                 : /* -------------------------------------------------------------------- */
     129                 :     char szLineBuf[257];
     130                 :     int  nCode;
     131              23 :     int  bEntitiesOnly = FALSE;
     132                 : 
     133              23 :     if( ReadValue( szLineBuf ) != 0 || !EQUAL(szLineBuf,"SECTION") )
     134               0 :         return FALSE;
     135                 : 
     136              23 :     if( ReadValue( szLineBuf ) != 2 
     137                 :         || (!EQUAL(szLineBuf,"HEADER") && !EQUAL(szLineBuf,"ENTITIES")) )
     138               0 :         return FALSE;
     139                 : 
     140              23 :     if( EQUAL(szLineBuf,"ENTITIES") )
     141               5 :         bEntitiesOnly = TRUE;
     142                 : 
     143                 : /* -------------------------------------------------------------------- */
     144                 : /*      Process the header, picking up a few useful pieces of           */
     145                 : /*      information.                                                    */
     146                 : /* -------------------------------------------------------------------- */
     147              23 :     if( !bEntitiesOnly )
     148                 :     {
     149              18 :         ReadHeaderSection();
     150              18 :         ReadValue(szLineBuf);
     151                 : 
     152                 : /* -------------------------------------------------------------------- */
     153                 : /*      Process the CLASSES section, if present.                        */
     154                 : /* -------------------------------------------------------------------- */
     155              18 :         if( EQUAL(szLineBuf,"ENDSEC") )
     156               0 :             ReadValue(szLineBuf);
     157                 : 
     158              18 :         if( EQUAL(szLineBuf,"SECTION") )
     159              18 :             ReadValue(szLineBuf);
     160                 :         
     161              18 :         if( EQUAL(szLineBuf,"CLASSES") )
     162                 :         {
     163             238 :             while( (nCode = ReadValue( szLineBuf,sizeof(szLineBuf) )) > -1 
     164                 :                    && !EQUAL(szLineBuf,"ENDSEC") )
     165                 :             {
     166                 :                 //printf("C:%d/%s\n", nCode, szLineBuf );
     167                 :             }
     168                 :         }
     169                 : 
     170                 : /* -------------------------------------------------------------------- */
     171                 : /*      Process the TABLES section, if present.                         */
     172                 : /* -------------------------------------------------------------------- */
     173              18 :         if( EQUAL(szLineBuf,"ENDSEC") )
     174              14 :             ReadValue(szLineBuf);
     175                 :         
     176              18 :         if( EQUAL(szLineBuf,"SECTION") )
     177              14 :             ReadValue(szLineBuf);
     178                 :         
     179              18 :         if( EQUAL(szLineBuf,"TABLES") )
     180                 :         {
     181              17 :             ReadTablesSection();
     182              17 :             ReadValue(szLineBuf);
     183                 :         }
     184                 :     }
     185                 : 
     186                 : /* -------------------------------------------------------------------- */
     187                 : /*      Create a blocks layer if we are not in inlining mode.           */
     188                 : /* -------------------------------------------------------------------- */
     189              23 :     if( !bInlineBlocks )
     190               1 :         apoLayers.push_back( new OGRDXFBlocksLayer( this ) );
     191                 : 
     192                 : /* -------------------------------------------------------------------- */
     193                 : /*      Create out layer object - we will need it when interpreting     */
     194                 : /*      blocks.                                                         */
     195                 : /* -------------------------------------------------------------------- */
     196              23 :     apoLayers.push_back( new OGRDXFLayer( this ) );
     197                 : 
     198                 : /* -------------------------------------------------------------------- */
     199                 : /*      Process the BLOCKS section if present.                          */
     200                 : /* -------------------------------------------------------------------- */
     201              23 :     if( !bEntitiesOnly )
     202                 :     {
     203              18 :         if( EQUAL(szLineBuf,"ENDSEC") )
     204               0 :             ReadValue(szLineBuf);
     205                 :         
     206              18 :         if( EQUAL(szLineBuf,"SECTION") )
     207              17 :             ReadValue(szLineBuf);
     208                 :         
     209              18 :         if( EQUAL(szLineBuf,"BLOCKS") )
     210                 :         {
     211              18 :             ReadBlocksSection();
     212              18 :             ReadValue(szLineBuf);
     213                 :         }
     214                 :     }
     215                 : 
     216              23 :     if( bHeaderOnly )
     217               7 :         return TRUE;
     218                 : 
     219                 : /* -------------------------------------------------------------------- */
     220                 : /*      Now we are at the entities section, hopefully.  Confirm.        */
     221                 : /* -------------------------------------------------------------------- */
     222              16 :     if( EQUAL(szLineBuf,"SECTION") )
     223              11 :         ReadValue(szLineBuf);
     224                 : 
     225              16 :     if( !EQUAL(szLineBuf,"ENTITIES") )
     226               0 :         return FALSE;
     227                 : 
     228              16 :     iEntitiesSectionOffset = oReader.iSrcBufferFileOffset + oReader.iSrcBufferOffset;
     229              16 :     apoLayers[0]->ResetReading();
     230                 : 
     231              16 :     return TRUE;
     232                 : }
     233                 : 
     234                 : /************************************************************************/
     235                 : /*                         ReadTablesSection()                          */
     236                 : /************************************************************************/
     237                 : 
     238              17 : void OGRDXFDataSource::ReadTablesSection()
     239                 : 
     240                 : {
     241                 :     char szLineBuf[257];
     242                 :     int  nCode;
     243                 : 
     244             187 :     while( (nCode = ReadValue( szLineBuf, sizeof(szLineBuf) )) > -1 
     245                 :            && !EQUAL(szLineBuf,"ENDSEC") )
     246                 :     {
     247                 :         // We are only interested in extracting tables.
     248             153 :         if( nCode != 0 || !EQUAL(szLineBuf,"TABLE") )
     249               0 :             continue;
     250                 : 
     251                 :         // Currently we are only interested in the LAYER table.
     252             153 :         nCode = ReadValue( szLineBuf, sizeof(szLineBuf) );
     253                 : 
     254             153 :         if( nCode != 2 )
     255               0 :             continue;
     256                 : 
     257                 :         //CPLDebug( "DXF", "Found table %s.", szLineBuf );
     258                 : 
     259            2888 :         while( (nCode = ReadValue( szLineBuf, sizeof(szLineBuf) )) > -1
     260                 :                && !EQUAL(szLineBuf,"ENDTAB") )
     261                 :         {
     262            2582 :             if( nCode == 0 && EQUAL(szLineBuf,"LAYER") )
     263              20 :                 ReadLayerDefinition();
     264            2582 :             if( nCode == 0 && EQUAL(szLineBuf,"LTYPE") )
     265             113 :                 ReadLineTypeDefinition();
     266                 :         }
     267                 :     }
     268                 : 
     269              17 :     CPLDebug( "DXF", "Read %d layer definitions.", (int) oLayerTable.size() );
     270              17 : }
     271                 : 
     272                 : /************************************************************************/
     273                 : /*                        ReadLayerDefinition()                         */
     274                 : /************************************************************************/
     275                 : 
     276              20 : void OGRDXFDataSource::ReadLayerDefinition()
     277                 : 
     278                 : {
     279                 :     char szLineBuf[257];
     280                 :     int  nCode;
     281              20 :     std::map<CPLString,CPLString> oLayerProperties;
     282              20 :     CPLString osLayerName = "";
     283                 : 
     284              20 :     oLayerProperties["Hidden"] = "0";
     285                 : 
     286             237 :     while( (nCode = ReadValue( szLineBuf, sizeof(szLineBuf) )) > 0 )
     287                 :     {
     288             197 :         switch( nCode )
     289                 :         {
     290                 :           case 2:
     291              20 :             osLayerName = ACTextUnescape(szLineBuf,GetEncoding());
     292              20 :             oLayerProperties["Exists"] = "1";
     293              20 :             break;
     294                 : 
     295                 :           case 6:
     296                 :             oLayerProperties["Linetype"] = ACTextUnescape(szLineBuf,
     297              20 :                                                           GetEncoding());
     298              20 :             break;
     299                 :             
     300                 :           case 62:
     301              20 :             oLayerProperties["Color"] = szLineBuf;
     302                 : 
     303              20 :             if( atoi(szLineBuf) < 0 ) // Is layer off?
     304               0 :                 oLayerProperties["Hidden"] = "1";
     305              20 :             break;
     306                 :             
     307                 :           case 70:
     308              20 :             oLayerProperties["Flags"] = szLineBuf;
     309              20 :             if( atoi(szLineBuf) & 0x01 ) // Is layer frozen?
     310               0 :                 oLayerProperties["Hidden"] = "1";
     311              20 :             break;
     312                 : 
     313                 :           case 370:
     314                 :           case 39:
     315              20 :             oLayerProperties["LineWeight"] = szLineBuf;
     316                 :             break;
     317                 : 
     318                 :           default:
     319                 :             break;
     320                 :         }
     321                 :     }
     322                 : 
     323              20 :     if( oLayerProperties.size() > 0 )
     324              20 :         oLayerTable[osLayerName] = oLayerProperties;
     325                 :     
     326              20 :     if( nCode == 0 )
     327              20 :         UnreadValue();
     328              20 : }
     329                 : 
     330                 : /************************************************************************/
     331                 : /*                        LookupLayerProperty()                         */
     332                 : /************************************************************************/
     333                 : 
     334             263 : const char *OGRDXFDataSource::LookupLayerProperty( const char *pszLayer,
     335                 :                                                    const char *pszProperty )
     336                 : 
     337                 : {
     338             263 :     if( pszLayer == NULL )
     339               0 :         return NULL;
     340                 : 
     341                 :     try {
     342             263 :         return (oLayerTable[pszLayer])[pszProperty];
     343               0 :     } catch( ... ) {
     344               0 :         return NULL;
     345                 :     }
     346                 : }
     347                 : 
     348                 : /************************************************************************/
     349                 : /*                       ReadLineTypeDefinition()                       */
     350                 : /************************************************************************/
     351                 : 
     352             113 : void OGRDXFDataSource::ReadLineTypeDefinition()
     353                 : 
     354                 : {
     355                 :     char szLineBuf[257];
     356                 :     int  nCode;
     357             113 :     CPLString osLineTypeName;
     358             113 :     CPLString osLineTypeDef;
     359                 : 
     360            1749 :     while( (nCode = ReadValue( szLineBuf, sizeof(szLineBuf) )) > 0 )
     361                 :     {
     362            1523 :         switch( nCode )
     363                 :         {
     364                 :           case 2:
     365             113 :             osLineTypeName = ACTextUnescape(szLineBuf,GetEncoding());
     366             113 :             break;
     367                 : 
     368                 :           case 49:
     369                 :           {
     370             232 :               if( osLineTypeDef != "" )
     371             170 :                   osLineTypeDef += " ";
     372                 : 
     373             232 :               if( szLineBuf[0] == '-' )
     374             116 :                   osLineTypeDef += szLineBuf+1;
     375                 :               else
     376             116 :                   osLineTypeDef += szLineBuf;
     377                 : 
     378             232 :               osLineTypeDef += "g";
     379                 :           }
     380                 :           break;
     381                 :             
     382                 :           default:
     383                 :             break;
     384                 :         }
     385                 :     }
     386                 : 
     387             113 :     if( osLineTypeDef != "" )
     388              62 :         oLineTypeTable[osLineTypeName] = osLineTypeDef;
     389                 :     
     390             113 :     if( nCode == 0 )
     391             113 :         UnreadValue();
     392             113 : }
     393                 : 
     394                 : /************************************************************************/
     395                 : /*                           LookupLineType()                           */
     396                 : /************************************************************************/
     397                 : 
     398              87 : const char *OGRDXFDataSource::LookupLineType( const char *pszName )
     399                 : 
     400                 : {
     401              87 :     if( oLineTypeTable.count(pszName) > 0 )
     402               4 :         return oLineTypeTable[pszName];
     403                 :     else
     404              83 :         return NULL;
     405                 : }
     406                 : 
     407                 : /************************************************************************/
     408                 : /*                         ReadHeaderSection()                          */
     409                 : /************************************************************************/
     410                 : 
     411              18 : void OGRDXFDataSource::ReadHeaderSection()
     412                 : 
     413                 : {
     414                 :     char szLineBuf[257];
     415                 :     int  nCode;
     416                 : 
     417            3242 :     while( (nCode = ReadValue( szLineBuf, sizeof(szLineBuf) )) > -1 
     418                 :            && !EQUAL(szLineBuf,"ENDSEC") )
     419                 :     {
     420            4010 :         if( nCode != 9 )
     421             786 :             continue;
     422                 : 
     423            3224 :         CPLString osName = szLineBuf;
     424                 : 
     425            3224 :         ReadValue( szLineBuf, sizeof(szLineBuf) );
     426                 : 
     427            3224 :         CPLString osValue = szLineBuf;
     428                 : 
     429            3224 :         oHeaderVariables[osName] = osValue;
     430                 :     }
     431                 : 
     432              18 :     if (nCode != -1)
     433                 :     {
     434              18 :         nCode = ReadValue( szLineBuf, sizeof(szLineBuf) );
     435              18 :         UnreadValue();
     436                 :     }
     437                 : 
     438                 :     /* Unusual DXF files produced by dxflib */
     439                 :     /* such as http://www.ribbonsoft.com/library/architecture/plants/decd5.dxf */
     440                 :     /* where there is a spurious ENDSEC in the middle of the header variables */
     441              18 :     if (nCode == 9 && EQUALN(szLineBuf,"$", 1) )
     442                 :     {
     443               0 :         while( (nCode = ReadValue( szLineBuf, sizeof(szLineBuf) )) > -1
     444                 :             && !EQUAL(szLineBuf,"ENDSEC") )
     445                 :         {
     446               0 :             if( nCode != 9 )
     447               0 :                 continue;
     448                 : 
     449               0 :             CPLString osName = szLineBuf;
     450                 : 
     451               0 :             ReadValue( szLineBuf, sizeof(szLineBuf) );
     452                 : 
     453               0 :             CPLString osValue = szLineBuf;
     454                 : 
     455               0 :             oHeaderVariables[osName] = osValue;
     456                 :         }
     457                 :     }
     458                 : 
     459                 :     CPLDebug( "DXF", "Read %d header variables.", 
     460              18 :               (int) oHeaderVariables.size() );
     461                 : 
     462                 : /* -------------------------------------------------------------------- */
     463                 : /*      Decide on what CPLRecode() name to use for the files            */
     464                 : /*      encoding or allow the encoding to be overridden.                */
     465                 : /* -------------------------------------------------------------------- */
     466              18 :     CPLString osCodepage = GetVariable( "$DWGCODEPAGE", "ANSI_1252" );
     467                 : 
     468                 :     // not strictly accurate but works even without iconv.
     469              18 :     if( osCodepage == "ANSI_1252" )
     470              18 :         osEncoding = CPL_ENC_ISO8859_1; 
     471               0 :     else if( EQUALN(osCodepage,"ANSI_",5) )
     472                 :     {
     473               0 :         osEncoding = "CP";
     474               0 :         osEncoding += osCodepage + 5;
     475                 :     }
     476                 :     else
     477                 :     {
     478                 :         // fallback to the default 
     479               0 :         osEncoding = CPL_ENC_ISO8859_1;
     480                 :     }
     481                 :                                        
     482              18 :     if( CPLGetConfigOption( "DXF_ENCODING", NULL ) != NULL )
     483               0 :         osEncoding = CPLGetConfigOption( "DXF_ENCODING", NULL );
     484                 : 
     485              18 :     if( osEncoding != CPL_ENC_ISO8859_1 )
     486                 :         CPLDebug( "DXF", "Treating DXF as encoding '%s', $DWGCODEPAGE='%s'", 
     487               0 :                   osEncoding.c_str(), osCodepage.c_str() );
     488              18 : }
     489                 : 
     490                 : /************************************************************************/
     491                 : /*                            GetVariable()                             */
     492                 : /*                                                                      */
     493                 : /*      Fetch a variable that came from the HEADER section.             */
     494                 : /************************************************************************/
     495                 : 
     496              36 : const char *OGRDXFDataSource::GetVariable( const char *pszName, 
     497                 :                                            const char *pszDefault )
     498                 : 
     499                 : {
     500              36 :     if( oHeaderVariables.count(pszName) == 0 )
     501              12 :         return pszDefault;
     502                 :     else 
     503              24 :         return oHeaderVariables[pszName];
     504                 : }
     505                 : 
     506                 : /************************************************************************/
     507                 : /*                         AddStandardFields()                          */
     508                 : /************************************************************************/
     509                 : 
     510              24 : void OGRDXFDataSource::AddStandardFields( OGRFeatureDefn *poFeatureDefn )
     511                 : 
     512                 : {
     513              24 :     OGRFieldDefn  oLayerField( "Layer", OFTString );
     514              24 :     poFeatureDefn->AddFieldDefn( &oLayerField );
     515                 : 
     516              24 :     OGRFieldDefn  oClassField( "SubClasses", OFTString );
     517              24 :     poFeatureDefn->AddFieldDefn( &oClassField );
     518                 : 
     519              24 :     OGRFieldDefn  oExtendedField( "ExtendedEntity", OFTString );
     520              24 :     poFeatureDefn->AddFieldDefn( &oExtendedField );
     521                 : 
     522              24 :     OGRFieldDefn  oLinetypeField( "Linetype", OFTString );
     523              24 :     poFeatureDefn->AddFieldDefn( &oLinetypeField );
     524                 : 
     525              24 :     OGRFieldDefn  oEntityHandleField( "EntityHandle", OFTString );
     526              24 :     poFeatureDefn->AddFieldDefn( &oEntityHandleField );
     527                 : 
     528              24 :     OGRFieldDefn  oTextField( "Text", OFTString );
     529              24 :     poFeatureDefn->AddFieldDefn( &oTextField );
     530                 : 
     531              24 :     if( !bInlineBlocks )
     532                 :     {
     533               2 :         OGRFieldDefn  oTextField( "BlockName", OFTString );
     534               2 :         poFeatureDefn->AddFieldDefn( &oTextField );
     535              24 :     }
     536              24 : }

Generated by: LCOV version 1.7