LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/dxf - ogrdxfwriterlayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 393 318 80.9 %
Date: 2012-12-26 Functions: 21 16 76.2 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrdxfwriterlayer.cpp 24991 2012-09-29 10:13:28Z rouault $
       3                 :  *
       4                 :  * Project:  DXF Translator
       5                 :  * Purpose:  Implements OGRDXFWriterLayer - the OGRLayer class used for
       6                 :  *           writing a DXF file.
       7                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2009, Frank Warmerdam <warmerdam@pobox.com>
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "ogr_dxf.h"
      32                 : #include "cpl_conv.h"
      33                 : #include "cpl_string.h"
      34                 : #include "ogr_featurestyle.h"
      35                 : 
      36                 : CPL_CVSID("$Id: ogrdxfwriterlayer.cpp 24991 2012-09-29 10:13:28Z rouault $");
      37                 : 
      38                 : #ifndef PI
      39                 : #define PI  3.14159265358979323846
      40                 : #endif 
      41                 : 
      42                 : /************************************************************************/
      43                 : /*                         OGRDXFWriterLayer()                          */
      44                 : /************************************************************************/
      45                 : 
      46               7 : OGRDXFWriterLayer::OGRDXFWriterLayer( OGRDXFWriterDS *poDS, VSILFILE *fp )
      47                 : 
      48                 : {
      49               7 :     this->fp = fp;
      50               7 :     this->poDS = poDS;
      51                 : 
      52               7 :     nNextAutoID = 1;
      53               7 :     bWriteHatch = CSLTestBoolean(CPLGetConfigOption("DXF_WRITE_HATCH", "YES"));
      54                 : 
      55               7 :     poFeatureDefn = new OGRFeatureDefn( "entities" );
      56               7 :     poFeatureDefn->Reference();
      57                 : 
      58               7 :     OGRFieldDefn  oLayerField( "Layer", OFTString );
      59               7 :     poFeatureDefn->AddFieldDefn( &oLayerField );
      60                 : 
      61               7 :     OGRFieldDefn  oClassField( "SubClasses", OFTString );
      62               7 :     poFeatureDefn->AddFieldDefn( &oClassField );
      63                 : 
      64               7 :     OGRFieldDefn  oExtendedField( "ExtendedEntity", OFTString );
      65               7 :     poFeatureDefn->AddFieldDefn( &oExtendedField );
      66                 : 
      67               7 :     OGRFieldDefn  oLinetypeField( "Linetype", OFTString );
      68               7 :     poFeatureDefn->AddFieldDefn( &oLinetypeField );
      69                 : 
      70               7 :     OGRFieldDefn  oEntityHandleField( "EntityHandle", OFTString );
      71               7 :     poFeatureDefn->AddFieldDefn( &oEntityHandleField );
      72                 : 
      73               7 :     OGRFieldDefn  oTextField( "Text", OFTString );
      74               7 :     poFeatureDefn->AddFieldDefn( &oTextField );
      75                 : 
      76               7 :     OGRFieldDefn  oBlockField( "BlockName", OFTString );
      77               7 :     poFeatureDefn->AddFieldDefn( &oBlockField );
      78                 :     
      79               7 :     OGRFieldDefn  oScaleField( "BlockScale", OFTRealList );
      80               7 :     poFeatureDefn->AddFieldDefn( &oScaleField );
      81                 :     
      82               7 :     OGRFieldDefn  oBlockAngleField( "BlockAngle", OFTReal );
      83               7 :     poFeatureDefn->AddFieldDefn( &oBlockAngleField );
      84               7 : }
      85                 : 
      86                 : /************************************************************************/
      87                 : /*                         ~OGRDXFWriterLayer()                         */
      88                 : /************************************************************************/
      89                 : 
      90               7 : OGRDXFWriterLayer::~OGRDXFWriterLayer()
      91                 : 
      92                 : {
      93               7 :     if( poFeatureDefn )
      94               7 :         poFeatureDefn->Release();
      95               7 : }
      96                 : 
      97                 : /************************************************************************/
      98                 : /*                              ResetFP()                               */
      99                 : /*                                                                      */
     100                 : /*      Redirect output.  Mostly used for writing block definitions.    */
     101                 : /************************************************************************/
     102                 : 
     103               1 : void OGRDXFWriterLayer::ResetFP( VSILFILE *fpNew )
     104                 : 
     105                 : {
     106               1 :     fp = fpNew;
     107               1 : }
     108                 : 
     109                 : /************************************************************************/
     110                 : /*                           TestCapability()                           */
     111                 : /************************************************************************/
     112                 : 
     113               0 : int OGRDXFWriterLayer::TestCapability( const char * pszCap )
     114                 : 
     115                 : {
     116               0 :     if( EQUAL(pszCap,OLCStringsAsUTF8) )
     117               0 :         return TRUE;
     118               0 :     else if( EQUAL(pszCap,OLCSequentialWrite) )
     119               0 :         return TRUE;
     120                 :     else 
     121               0 :         return FALSE;
     122                 : }
     123                 : 
     124                 : /************************************************************************/
     125                 : /*                            CreateField()                             */
     126                 : /*                                                                      */
     127                 : /*      This is really a dummy as our fields are precreated.            */
     128                 : /************************************************************************/
     129                 : 
     130               0 : OGRErr OGRDXFWriterLayer::CreateField( OGRFieldDefn *poField,
     131                 :                                        int bApproxOK )
     132                 : 
     133                 : {
     134               0 :     if( poFeatureDefn->GetFieldIndex(poField->GetNameRef()) >= 0
     135                 :         && bApproxOK )
     136               0 :         return OGRERR_NONE;
     137                 : 
     138                 :     CPLError( CE_Failure, CPLE_AppDefined,
     139                 :               "DXF layer does not support arbitrary field creation, field '%s' not created.",
     140               0 :               poField->GetNameRef() );
     141                 : 
     142               0 :     return OGRERR_FAILURE;
     143                 : }
     144                 : 
     145                 : /************************************************************************/
     146                 : /*                             WriteValue()                             */
     147                 : /************************************************************************/
     148                 : 
     149              75 : int OGRDXFWriterLayer::WriteValue( int nCode, const char *pszValue )
     150                 : 
     151                 : {
     152              75 :     CPLString osLinePair;
     153                 : 
     154              75 :     osLinePair.Printf( "%3d\n", nCode );
     155                 : 
     156              75 :     if( strlen(pszValue) < 255 )
     157              75 :         osLinePair += pszValue;
     158                 :     else
     159               0 :         osLinePair.append( pszValue, 255 );
     160                 : 
     161              75 :     osLinePair += "\n";
     162                 : 
     163                 :     return VSIFWriteL( osLinePair.c_str(), 
     164              75 :                        1, osLinePair.size(), fp ) == osLinePair.size();
     165                 : }
     166                 : 
     167                 : /************************************************************************/
     168                 : /*                             WriteValue()                             */
     169                 : /************************************************************************/
     170                 : 
     171              75 : int OGRDXFWriterLayer::WriteValue( int nCode, int nValue )
     172                 : 
     173                 : {
     174              75 :     CPLString osLinePair;
     175                 : 
     176              75 :     osLinePair.Printf( "%3d\n%d\n", nCode, nValue );
     177                 : 
     178                 :     return VSIFWriteL( osLinePair.c_str(), 
     179              75 :                        1, osLinePair.size(), fp ) == osLinePair.size();
     180                 : }
     181                 : 
     182                 : /************************************************************************/
     183                 : /*                             WriteValue()                             */
     184                 : /************************************************************************/
     185                 : 
     186              86 : int OGRDXFWriterLayer::WriteValue( int nCode, double dfValue )
     187                 : 
     188                 : {
     189                 :     char szLinePair[64];
     190                 : 
     191              86 :     snprintf(szLinePair, sizeof(szLinePair), "%3d\n%.15g\n", nCode, dfValue );
     192              86 :     char* pszComma = strchr(szLinePair, ',');
     193              86 :     if (pszComma)
     194               0 :         *pszComma = '.';
     195              86 :     size_t nLen = strlen(szLinePair);
     196                 : 
     197                 :     return VSIFWriteL( szLinePair, 
     198              86 :                        1, nLen, fp ) == nLen;
     199                 : }
     200                 : 
     201                 : /************************************************************************/
     202                 : /*                             WriteCore()                              */
     203                 : /*                                                                      */
     204                 : /*      Write core fields common to all sorts of elements.              */
     205                 : /************************************************************************/
     206                 : 
     207              16 : OGRErr OGRDXFWriterLayer::WriteCore( OGRFeature *poFeature )
     208                 : 
     209                 : {
     210                 : /* -------------------------------------------------------------------- */
     211                 : /*      Write out an entity id.  I'm not sure why this is critical,     */
     212                 : /*      but it seems that VoloView will just quietly fail to open       */
     213                 : /*      dxf files without entity ids set on most/all entities.          */
     214                 : /*      Also, for reasons I don't understand these ids seem to have     */
     215                 : /*      to start somewhere around 0x50 hex (80 decimal).                */
     216                 : /* -------------------------------------------------------------------- */
     217              16 :     poFeature->SetFID( poDS->WriteEntityID(fp,poFeature->GetFID()) );
     218                 : 
     219                 : /* -------------------------------------------------------------------- */
     220                 : /*      For now we assign everything to the default layer - layer       */
     221                 : /*      "0" - if there is no layer property on the source features.     */
     222                 : /* -------------------------------------------------------------------- */
     223              16 :     const char *pszLayer = poFeature->GetFieldAsString( "Layer" );
     224              27 :     if( pszLayer == NULL || strlen(pszLayer) == 0 )
     225                 :     {
     226              11 :         WriteValue( 8, "0" );
     227                 :     }
     228                 :     else
     229                 :     {
     230                 :         const char *pszExists = 
     231               5 :             poDS->oHeaderDS.LookupLayerProperty( pszLayer, "Exists" );
     232               5 :         if( (pszExists == NULL || strlen(pszExists) == 0)
     233                 :             && CSLFindString( poDS->papszLayersToCreate, pszLayer ) == -1 )
     234                 :         {
     235                 :             poDS->papszLayersToCreate = 
     236               3 :                 CSLAddString( poDS->papszLayersToCreate, pszLayer );
     237                 :         }
     238                 : 
     239               5 :         WriteValue( 8, pszLayer );
     240                 :     }
     241                 : 
     242              16 :     return OGRERR_NONE;
     243                 : }
     244                 : 
     245                 : /************************************************************************/
     246                 : /*                            WriteINSERT()                             */
     247                 : /************************************************************************/
     248                 : 
     249               4 : OGRErr OGRDXFWriterLayer::WriteINSERT( OGRFeature *poFeature )
     250                 : 
     251                 : {
     252               4 :     WriteValue( 0, "INSERT" );
     253               4 :     WriteCore( poFeature );
     254               4 :     WriteValue( 100, "AcDbEntity" );
     255               4 :     WriteValue( 100, "AcDbBlockReference" );
     256               4 :     WriteValue( 2, poFeature->GetFieldAsString("BlockName") );
     257                 : 
     258                 :     // Write style symbol color
     259               4 :     OGRStyleTool *poTool = NULL;
     260               4 :     OGRStyleMgr oSM;
     261               4 :     if( poFeature->GetStyleString() != NULL )
     262                 :     {
     263               0 :         oSM.InitFromFeature( poFeature );
     264                 : 
     265               0 :         if( oSM.GetPartCount() > 0 )
     266               0 :             poTool = oSM.GetPart(0);
     267                 :     }
     268               4 :     if( poTool && poTool->GetType() == OGRSTCSymbol )
     269                 :     {
     270               0 :         OGRStyleSymbol *poSymbol = (OGRStyleSymbol *) poTool;
     271                 :         GBool  bDefault;
     272                 : 
     273               0 :         if( poSymbol->Color(bDefault) != NULL && !bDefault )
     274               0 :             WriteValue( 62, ColorStringToDXFColor( poSymbol->Color(bDefault) ) );
     275                 :     }
     276               4 :     delete poTool;
     277                 :     
     278                 : /* -------------------------------------------------------------------- */
     279                 : /*      Write location.                                                 */
     280                 : /* -------------------------------------------------------------------- */
     281               4 :     OGRPoint *poPoint = (OGRPoint *) poFeature->GetGeometryRef();
     282                 : 
     283               4 :     WriteValue( 10, poPoint->getX() );
     284               4 :     if( !WriteValue( 20, poPoint->getY() ) ) 
     285               0 :         return OGRERR_FAILURE;
     286                 : 
     287               4 :     if( poPoint->getGeometryType() == wkbPoint25D )
     288                 :     {
     289               0 :         if( !WriteValue( 30, poPoint->getZ() ) )
     290               0 :             return OGRERR_FAILURE;
     291                 :     }
     292                 :     
     293                 : /* -------------------------------------------------------------------- */
     294                 : /*      Write scaling.                                                  */
     295                 : /* -------------------------------------------------------------------- */
     296                 :     int nScaleCount;
     297                 :     const double *padfScale = 
     298               4 :         poFeature->GetFieldAsDoubleList( "BlockScale", &nScaleCount );
     299                 : 
     300               4 :     if( nScaleCount == 3 )
     301                 :     {
     302               1 :         WriteValue( 41, padfScale[0] );
     303               1 :         WriteValue( 42, padfScale[1] );
     304               1 :         WriteValue( 43, padfScale[2] );
     305                 :     }
     306                 : 
     307                 : /* -------------------------------------------------------------------- */
     308                 : /*      Write rotation.                                                 */
     309                 : /* -------------------------------------------------------------------- */
     310               4 :     double dfAngle = poFeature->GetFieldAsDouble( "BlockAngle" );
     311                 : 
     312               4 :     if( dfAngle != 0.0 )
     313                 :     {
     314               1 :         WriteValue( 50, dfAngle ); // degrees
     315                 :     }
     316                 : 
     317               4 :     return OGRERR_NONE;
     318                 : }
     319                 : 
     320                 : /************************************************************************/
     321                 : /*                             WritePOINT()                             */
     322                 : /************************************************************************/
     323                 : 
     324               1 : OGRErr OGRDXFWriterLayer::WritePOINT( OGRFeature *poFeature )
     325                 : 
     326                 : {
     327               1 :     WriteValue( 0, "POINT" );
     328               1 :     WriteCore( poFeature );
     329               1 :     WriteValue( 100, "AcDbEntity" );
     330               1 :     WriteValue( 100, "AcDbPoint" );
     331                 : 
     332                 :     // Write style pen color
     333               1 :     OGRStyleTool *poTool = NULL;
     334               1 :     OGRStyleMgr oSM;
     335               1 :     if( poFeature->GetStyleString() != NULL )
     336                 :     {
     337               0 :         oSM.InitFromFeature( poFeature );
     338                 : 
     339               0 :         if( oSM.GetPartCount() > 0 )
     340               0 :             poTool = oSM.GetPart(0);
     341                 :     }
     342               1 :     if( poTool && poTool->GetType() == OGRSTCPen )
     343                 :     {
     344               0 :         OGRStylePen *poPen = (OGRStylePen *) poTool;
     345                 :         GBool  bDefault;
     346                 : 
     347               0 :         if( poPen->Color(bDefault) != NULL && !bDefault )
     348               0 :             WriteValue( 62, ColorStringToDXFColor( poPen->Color(bDefault) ) );
     349                 :     }
     350               1 :     delete poTool;
     351                 : 
     352               1 :     OGRPoint *poPoint = (OGRPoint *) poFeature->GetGeometryRef();
     353                 : 
     354               1 :     WriteValue( 10, poPoint->getX() );
     355               1 :     if( !WriteValue( 20, poPoint->getY() ) ) 
     356               0 :         return OGRERR_FAILURE;
     357                 : 
     358               1 :     if( poPoint->getGeometryType() == wkbPoint25D )
     359                 :     {
     360               0 :         if( !WriteValue( 30, poPoint->getZ() ) )
     361               0 :             return OGRERR_FAILURE;
     362                 :     }
     363                 :     
     364               1 :     return OGRERR_NONE;
     365                 : }
     366                 : 
     367                 : /************************************************************************/
     368                 : /*                             TextEscape()                             */
     369                 : /*                                                                      */
     370                 : /*      Translate UTF8 to Win1252 and escape special characters like    */
     371                 : /*      newline and space with DXF style escapes.  Note that            */
     372                 : /*      non-win1252 unicode characters are translated using the         */
     373                 : /*      unicode escape sequence.                                        */
     374                 : /************************************************************************/
     375                 : 
     376               1 : CPLString OGRDXFWriterLayer::TextEscape( const char *pszInput )
     377                 : 
     378                 : {
     379               1 :     CPLString osResult;
     380                 :     wchar_t *panInput = CPLRecodeToWChar( pszInput, 
     381                 :                                           CPL_ENC_UTF8, 
     382               1 :                                           CPL_ENC_UCS2 );
     383                 :     int i;
     384                 : 
     385                 : 
     386              10 :     for( i = 0; panInput[i] != 0; i++ )
     387                 :     {
     388               9 :         if( panInput[i] == '\n' )
     389               0 :             osResult += "\\P";
     390               9 :         else if( panInput[i] == ' ' )
     391               0 :             osResult += "\\~";
     392               9 :         else if( panInput[i] == '\\' )
     393               0 :             osResult += "\\\\";
     394               9 :         else if( panInput[i] > 255 )
     395                 :         {
     396               0 :             CPLString osUnicode;
     397               0 :             osUnicode.Printf( "\\U+%04x", (int) panInput[i] );
     398               0 :             osResult += osUnicode;
     399                 :         }
     400                 :         else
     401               9 :             osResult += (char) panInput[i];
     402                 :     }
     403                 : 
     404               1 :     CPLFree(panInput);
     405                 :     
     406               0 :     return osResult;
     407                 : }
     408                 : 
     409                 : /************************************************************************/
     410                 : /*                             WriteTEXT()                              */
     411                 : /************************************************************************/
     412                 : 
     413               1 : OGRErr OGRDXFWriterLayer::WriteTEXT( OGRFeature *poFeature )
     414                 : 
     415                 : {
     416               1 :     WriteValue( 0, "MTEXT" );
     417               1 :     WriteCore( poFeature );
     418               1 :     WriteValue( 100, "AcDbEntity" );
     419               1 :     WriteValue( 100, "AcDbMText" );
     420                 : 
     421                 : /* -------------------------------------------------------------------- */
     422                 : /*      Do we have styling information?                                 */
     423                 : /* -------------------------------------------------------------------- */
     424               1 :     OGRStyleTool *poTool = NULL;
     425               1 :     OGRStyleMgr oSM;
     426                 : 
     427               1 :     if( poFeature->GetStyleString() != NULL )
     428                 :     {
     429               1 :         oSM.InitFromFeature( poFeature );
     430                 : 
     431               1 :         if( oSM.GetPartCount() > 0 )
     432               1 :             poTool = oSM.GetPart(0);
     433                 :     }
     434                 : 
     435                 : /* ==================================================================== */
     436                 : /*      Process the LABEL tool.                                         */
     437                 : /* ==================================================================== */
     438               1 :     if( poTool && poTool->GetType() == OGRSTCLabel )
     439                 :     {
     440               1 :         OGRStyleLabel *poLabel = (OGRStyleLabel *) poTool;
     441                 :         GBool  bDefault;
     442                 : 
     443                 : /* -------------------------------------------------------------------- */
     444                 : /*      Color                                                           */
     445                 : /* -------------------------------------------------------------------- */
     446               1 :         if( poLabel->ForeColor(bDefault) != NULL && !bDefault )
     447                 :             WriteValue( 62, ColorStringToDXFColor( 
     448               1 :                             poLabel->ForeColor(bDefault) ) );
     449                 : 
     450                 : /* -------------------------------------------------------------------- */
     451                 : /*      Angle                                                           */
     452                 : /* -------------------------------------------------------------------- */
     453               1 :         double dfAngle = poLabel->Angle(bDefault);
     454                 : 
     455                 :         // The DXF2000 reference says this is in radians, but in files
     456                 :         // I see it seems to be in degrees. Perhaps this is version dependent?
     457               1 :         if( !bDefault )
     458               1 :             WriteValue( 50, dfAngle );
     459                 : 
     460                 : /* -------------------------------------------------------------------- */
     461                 : /*      Height - We need to fetch this in georeferenced units - I'm     */
     462                 : /*      doubt the default translation mechanism will be much good.      */
     463                 : /* -------------------------------------------------------------------- */
     464               1 :         poTool->SetUnit( OGRSTUGround );
     465               1 :         double dfHeight = poLabel->Size(bDefault);
     466                 : 
     467               1 :         if( !bDefault )
     468               1 :             WriteValue( 40, dfHeight );
     469                 : 
     470                 : /* -------------------------------------------------------------------- */
     471                 : /*      Anchor / Attachment Point                                       */
     472                 : /* -------------------------------------------------------------------- */
     473               1 :         int nAnchor = poLabel->Anchor(bDefault);
     474                 :         
     475               1 :         if( !bDefault )
     476                 :         {
     477                 :             const static int anAnchorMap[] = 
     478                 :                 { -1, 7, 8, 9, 4, 5, 6, 1, 2, 3, 7, 8, 9 };
     479                 : 
     480               0 :             if( nAnchor > 0 && nAnchor < 13 )
     481               0 :                 WriteValue( 71, anAnchorMap[nAnchor] );
     482                 :         }
     483                 : 
     484                 : /* -------------------------------------------------------------------- */
     485                 : /*      Escape the text, and convert to ISO8859.                        */
     486                 : /* -------------------------------------------------------------------- */
     487               1 :         const char *pszText = poLabel->TextString( bDefault );
     488                 : 
     489               1 :         if( pszText != NULL && !bDefault )
     490                 :         {
     491               1 :             CPLString osEscaped = TextEscape( pszText );
     492               1 :             WriteValue( 1, osEscaped );
     493                 :         }
     494                 :     }
     495                 : 
     496               1 :     delete poTool;
     497                 : 
     498                 : /* -------------------------------------------------------------------- */
     499                 : /*      Write the location.                                             */
     500                 : /* -------------------------------------------------------------------- */
     501               1 :     OGRPoint *poPoint = (OGRPoint *) poFeature->GetGeometryRef();
     502                 : 
     503               1 :     WriteValue( 10, poPoint->getX() );
     504               1 :     if( !WriteValue( 20, poPoint->getY() ) ) 
     505               0 :         return OGRERR_FAILURE;
     506                 : 
     507               1 :     if( poPoint->getGeometryType() == wkbPoint25D )
     508                 :     {
     509               1 :         if( !WriteValue( 30, poPoint->getZ() ) )
     510               0 :             return OGRERR_FAILURE;
     511                 :     }
     512                 :     
     513               1 :     return OGRERR_NONE;
     514                 : 
     515                 : }
     516                 : 
     517                 : /************************************************************************/
     518                 : /*                     PrepareLineTypeDefinition()                      */
     519                 : /************************************************************************/
     520                 : CPLString 
     521               2 : OGRDXFWriterLayer::PrepareLineTypeDefinition( OGRFeature *poFeature, 
     522                 :                                               OGRStyleTool *poTool )
     523                 : 
     524                 : {
     525               2 :     CPLString osDef;
     526               2 :     OGRStylePen *poPen = (OGRStylePen *) poTool;
     527                 :     GBool  bDefault;
     528                 :     const char *pszPattern;
     529                 :     
     530                 : /* -------------------------------------------------------------------- */
     531                 : /*      Fetch pattern.                                                  */
     532                 : /* -------------------------------------------------------------------- */
     533               2 :     pszPattern = poPen->Pattern( bDefault );
     534               2 :     if( bDefault || strlen(pszPattern) == 0 ) 
     535               0 :         return "";
     536                 : 
     537                 : /* -------------------------------------------------------------------- */
     538                 : /*      Split into pen up / pen down bits.                              */
     539                 : /* -------------------------------------------------------------------- */
     540               2 :     char **papszTokens = CSLTokenizeString(pszPattern);
     541                 :     int i;
     542               2 :     double dfTotalLength = 0;
     543                 : 
     544               6 :     for( i = 0; papszTokens != NULL && papszTokens[i] != NULL; i++ )
     545                 :     {
     546               4 :         const char *pszToken = papszTokens[i];
     547                 :         const char *pszUnit;
     548               4 :         CPLString osAmount;
     549               4 :         CPLString osDXFEntry;
     550                 : 
     551                 :         // Split amount and unit.
     552               4 :         for( pszUnit = pszToken; 
     553                 :              strchr( "0123456789.", *pszUnit) != NULL;
     554                 :              pszUnit++ ) {}
     555                 : 
     556               4 :         osAmount.assign(pszToken,(int) (pszUnit-pszToken));
     557                 :         
     558                 :         // If the unit is other than 'g' we really should be trying to 
     559                 :         // do some type of transformation - but what to do?  Pretty hard.
     560                 :         
     561                 :         // 
     562                 : 
     563                 :         // Even entries are "pen down" represented as negative in DXF.
     564               4 :         if( i%2 == 0 )
     565               2 :             osDXFEntry.Printf( " 49\n-%s\n 74\n0\n", osAmount.c_str() );
     566                 :         else
     567               2 :             osDXFEntry.Printf( " 49\n%s\n 74\n0\n", osAmount.c_str() );
     568                 :         
     569               4 :         osDef += osDXFEntry;
     570                 : 
     571               4 :         dfTotalLength += atof(osAmount);
     572                 :     }
     573                 : 
     574                 : /* -------------------------------------------------------------------- */
     575                 : /*      Prefix 73 and 40 items to the definition.                       */
     576                 : /* -------------------------------------------------------------------- */
     577               2 :     CPLString osPrefix;
     578                 :     
     579                 :     osPrefix.Printf( " 73\n%d\n 40\n%.6g\n", 
     580                 :                      CSLCount(papszTokens), 
     581               2 :                      dfTotalLength );
     582               2 :     osDef = osPrefix + osDef;
     583                 : 
     584               2 :     CSLDestroy( papszTokens );
     585                 : 
     586               2 :     return osDef;
     587                 : }
     588                 : 
     589                 : /************************************************************************/
     590                 : /*                           WritePOLYLINE()                            */
     591                 : /************************************************************************/
     592                 : 
     593               7 : OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
     594                 :                                          OGRGeometry *poGeom )
     595                 : 
     596                 : {
     597                 : /* -------------------------------------------------------------------- */
     598                 : /*      For now we handle multilinestrings by writing a series of       */
     599                 : /*      entities.                                                       */
     600                 : /* -------------------------------------------------------------------- */
     601               7 :     if( poGeom == NULL )
     602               7 :         poGeom = poFeature->GetGeometryRef();
     603                 : 
     604               7 :     if ( poGeom->IsEmpty() )
     605                 :     {
     606               0 :         return OGRERR_NONE;
     607                 :     }
     608                 :             
     609              14 :     if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon 
     610               7 :         || wkbFlatten(poGeom->getGeometryType()) == wkbMultiLineString )
     611                 :     {
     612               0 :         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
     613                 :         int iGeom;
     614               0 :         OGRErr eErr = OGRERR_NONE;
     615                 : 
     616               0 :         for( iGeom = 0; 
     617                 :              eErr == OGRERR_NONE && iGeom < poGC->getNumGeometries(); 
     618                 :              iGeom++ )
     619                 :         {
     620               0 :             eErr = WritePOLYLINE( poFeature, poGC->getGeometryRef( iGeom ) );
     621                 :         }
     622                 : 
     623               0 :         return eErr;
     624                 :     }
     625                 : 
     626                 : /* -------------------------------------------------------------------- */
     627                 : /*      Polygons are written with on entity per ring.                   */
     628                 : /* -------------------------------------------------------------------- */
     629               7 :     if( wkbFlatten(poGeom->getGeometryType()) == wkbPolygon )
     630                 :     {
     631               0 :         OGRPolygon *poPoly = (OGRPolygon *) poGeom;
     632                 :         int iGeom;
     633                 :         OGRErr eErr;
     634                 : 
     635               0 :         eErr = WritePOLYLINE( poFeature, poPoly->getExteriorRing() );
     636               0 :         for( iGeom = 0; 
     637                 :              eErr == OGRERR_NONE && iGeom < poPoly->getNumInteriorRings(); 
     638                 :              iGeom++ )
     639                 :         {
     640               0 :             eErr = WritePOLYLINE( poFeature, poPoly->getInteriorRing(iGeom) );
     641                 :         }
     642                 : 
     643               0 :         return eErr;
     644                 :     }
     645                 : 
     646                 : /* -------------------------------------------------------------------- */
     647                 : /*      Do we now have a geometry we can work with?                     */
     648                 : /* -------------------------------------------------------------------- */
     649               7 :     if( wkbFlatten(poGeom->getGeometryType()) != wkbLineString )
     650               0 :         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     651                 : 
     652               7 :     OGRLineString *poLS = (OGRLineString *) poGeom;
     653                 : 
     654                 : /* -------------------------------------------------------------------- */
     655                 : /*      Write as a lightweight polygon.                                 */
     656                 : /* -------------------------------------------------------------------- */
     657               7 :     WriteValue( 0, "LWPOLYLINE" );
     658               7 :     WriteCore( poFeature );
     659               7 :     WriteValue( 100, "AcDbEntity" );
     660               7 :     WriteValue( 100, "AcDbPolyline" );
     661               7 :     if( EQUAL( poGeom->getGeometryName(), "LINEARRING" ) )
     662               0 :         WriteValue( 70, 1 );
     663                 :     else
     664               7 :         WriteValue( 70, 0 );
     665               7 :     WriteValue( 90, poLS->getNumPoints() );
     666                 : 
     667                 : /* -------------------------------------------------------------------- */
     668                 : /*      Do we have styling information?                                 */
     669                 : /* -------------------------------------------------------------------- */
     670               7 :     OGRStyleTool *poTool = NULL;
     671               7 :     OGRStyleMgr oSM;
     672                 : 
     673               7 :     if( poFeature->GetStyleString() != NULL )
     674                 :     {
     675               3 :         oSM.InitFromFeature( poFeature );
     676                 : 
     677               3 :         if( oSM.GetPartCount() > 0 )
     678               3 :             poTool = oSM.GetPart(0);
     679                 :     }
     680                 : 
     681                 : /* -------------------------------------------------------------------- */
     682                 : /*      Handle a PEN tool to control drawing color and width.           */
     683                 : /*      Perhaps one day also dottedness, etc.                           */
     684                 : /* -------------------------------------------------------------------- */
     685               7 :     if( poTool && poTool->GetType() == OGRSTCPen )
     686                 :     {
     687               3 :         OGRStylePen *poPen = (OGRStylePen *) poTool;
     688                 :         GBool  bDefault;
     689                 : 
     690               3 :         if( poPen->Color(bDefault) != NULL && !bDefault )
     691               3 :             WriteValue( 62, ColorStringToDXFColor( poPen->Color(bDefault) ) );
     692                 : 
     693                 :         // we want to fetch the width in ground units. 
     694               3 :         poPen->SetUnit( OGRSTUGround, 1.0 );
     695               3 :         double dfWidth = poPen->Width(bDefault);
     696                 : 
     697               3 :         if( !bDefault )
     698               3 :             WriteValue( 370, (int) floor(dfWidth * 100 + 0.5) );
     699                 :     }
     700                 : 
     701                 : /* -------------------------------------------------------------------- */
     702                 : /*      Do we have a Linetype for the feature?                          */
     703                 : /* -------------------------------------------------------------------- */
     704               7 :     CPLString osLineType = poFeature->GetFieldAsString( "Linetype" );
     705                 : 
     706               7 :     if( osLineType.size() > 0 
     707                 :         && (poDS->oHeaderDS.LookupLineType( osLineType ) != NULL 
     708                 :             || oNewLineTypes.count(osLineType) > 0 ) )
     709                 :     {
     710                 :         // Already define -> just reference it.
     711               1 :         WriteValue( 6, osLineType );
     712                 :     }
     713               6 :     else if( poTool != NULL && poTool->GetType() == OGRSTCPen )
     714                 :     {
     715                 :         CPLString osDefinition = PrepareLineTypeDefinition( poFeature, 
     716               2 :                                                             poTool );
     717                 : 
     718               2 :         if( osDefinition != "" && osLineType == "" )
     719                 :         {
     720                 :             // Is this definition already created and named?
     721               1 :             std::map<CPLString,CPLString>::iterator it;
     722                 : 
     723               2 :             for( it = oNewLineTypes.begin();
     724                 :                  it != oNewLineTypes.end();
     725                 :                  it++ )
     726                 :             {
     727               1 :                 if( (*it).second == osDefinition )
     728                 :                 {
     729               0 :                     osLineType = (*it).first;
     730               0 :                     break;
     731                 :                 }
     732                 :             }
     733                 : 
     734                 :             // create an automatic name for it.
     735               1 :             if( osLineType == "" )
     736                 :             {
     737               1 :                 do 
     738                 :                 { 
     739               1 :                     osLineType.Printf( "AutoLineType-%d", nNextAutoID++ );
     740                 :                 }
     741                 :                 while( poDS->oHeaderDS.LookupLineType(osLineType) != NULL );
     742                 :             }
     743                 :         }
     744                 : 
     745                 :         // If it isn't already defined, add it now.
     746               2 :         if( osDefinition != "" && oNewLineTypes.count(osLineType) == 0 )
     747                 :         {
     748               2 :             oNewLineTypes[osLineType] = osDefinition;
     749               2 :             WriteValue( 6, osLineType );
     750               2 :         }
     751                 :     }
     752                 : 
     753                 : /* -------------------------------------------------------------------- */
     754                 : /*      Write the vertices                                              */
     755                 : /* -------------------------------------------------------------------- */
     756                 :     int iVert;
     757                 : 
     758              21 :     for( iVert = 0; iVert < poLS->getNumPoints(); iVert++ )
     759                 :     {
     760              14 :         WriteValue( 10, poLS->getX(iVert) );
     761              14 :         if( !WriteValue( 20, poLS->getY(iVert) ) ) 
     762               0 :             return OGRERR_FAILURE;
     763                 : 
     764              14 :         if( poLS->getGeometryType() == wkbLineString25D )
     765                 :         {
     766               0 :             if( !WriteValue( 38, poLS->getZ(iVert) ) )
     767               0 :                 return OGRERR_FAILURE;
     768                 :         }
     769                 :     }
     770                 :     
     771               7 :     delete poTool;
     772                 : 
     773               7 :     return OGRERR_NONE;
     774                 : 
     775                 : #ifdef notdef
     776                 : /* -------------------------------------------------------------------- */
     777                 : /*      Alternate unmaintained implementation as a polyline entity.     */
     778                 : /* -------------------------------------------------------------------- */
     779                 :     WriteValue( 0, "POLYLINE" );
     780                 :     WriteCore( poFeature );
     781                 :     WriteValue( 100, "AcDbEntity" );
     782                 :     WriteValue( 100, "AcDbPolyline" );
     783                 :     if( EQUAL( poGeom->getGeometryName(), "LINEARRING" ) )
     784                 :         WriteValue( 70, 1 );
     785                 :     else
     786                 :         WriteValue( 70, 0 );
     787                 :     WriteValue( 66, "1" );
     788                 : 
     789                 :     int iVert;
     790                 : 
     791                 :     for( iVert = 0; iVert < poLS->getNumPoints(); iVert++ )
     792                 :     {
     793                 :         WriteValue( 0, "VERTEX" );
     794                 :         WriteValue( 8, "0" );
     795                 :         WriteValue( 10, poLS->getX(iVert) );
     796                 :         if( !WriteValue( 20, poLS->getY(iVert) ) ) 
     797                 :             return OGRERR_FAILURE;
     798                 : 
     799                 :         if( poLS->getGeometryType() == wkbLineString25D )
     800                 :         {
     801                 :             if( !WriteValue( 30, poLS->getZ(iVert) ) )
     802                 :                 return OGRERR_FAILURE;
     803                 :         }
     804                 :     }
     805                 : 
     806                 :     WriteValue( 0, "SEQEND" );
     807                 :     WriteValue( 8, "0" );
     808                 :     
     809                 :     return OGRERR_NONE;
     810                 : #endif
     811                 : }
     812                 : 
     813                 : /************************************************************************/
     814                 : /*                             WriteHATCH()                             */
     815                 : /************************************************************************/
     816                 : 
     817               3 : OGRErr OGRDXFWriterLayer::WriteHATCH( OGRFeature *poFeature,
     818                 :                                       OGRGeometry *poGeom )
     819                 : 
     820                 : {
     821                 : /* -------------------------------------------------------------------- */
     822                 : /*      For now we handle multipolygons by writing a series of          */
     823                 : /*      entities.                                                       */
     824                 : /* -------------------------------------------------------------------- */
     825               3 :     if( poGeom == NULL )
     826               3 :         poGeom = poFeature->GetGeometryRef();
     827                 : 
     828               3 :     if ( poGeom->IsEmpty() )
     829                 :     {
     830               0 :         return OGRERR_NONE;
     831                 :     }
     832                 :             
     833               3 :     if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon )
     834                 :     {
     835               0 :         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
     836                 :         int iGeom;
     837               0 :         OGRErr eErr = OGRERR_NONE;
     838                 : 
     839               0 :         for( iGeom = 0; 
     840                 :              eErr == OGRERR_NONE && iGeom < poGC->getNumGeometries(); 
     841                 :              iGeom++ )
     842                 :         {
     843               0 :             eErr = WriteHATCH( poFeature, poGC->getGeometryRef( iGeom ) );
     844                 :         }
     845                 : 
     846               0 :         return eErr;
     847                 :     }
     848                 : 
     849                 : /* -------------------------------------------------------------------- */
     850                 : /*      Do we now have a geometry we can work with?                     */
     851                 : /* -------------------------------------------------------------------- */
     852               3 :     if( wkbFlatten(poGeom->getGeometryType()) != wkbPolygon )
     853               0 :         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     854                 : 
     855                 : /* -------------------------------------------------------------------- */
     856                 : /*      Write as a hatch.                                               */
     857                 : /* -------------------------------------------------------------------- */
     858               3 :     WriteValue( 0, "HATCH" );
     859               3 :     WriteCore( poFeature );
     860               3 :     WriteValue( 100, "AcDbEntity" );
     861               3 :     WriteValue( 100, "AcDbHatch" );
     862                 : 
     863               3 :     WriteValue( 10, 0 ); // elevation point X. 0 for DXF
     864               3 :     WriteValue( 20, 0 ); // elevation point Y
     865               3 :     WriteValue( 30, 0 ); // elevation point Z
     866               3 :     WriteValue(210, 0 ); // extrusion direction X
     867               3 :     WriteValue(220, 0 ); // extrusion direction Y
     868               3 :     WriteValue(230,1.0); // extrusion direction Z
     869                 : 
     870               3 :     WriteValue( 2, "SOLID" ); // fill pattern
     871               3 :     WriteValue( 70, 1 ); // solid fill
     872               3 :     WriteValue( 71, 0 ); // associativity 
     873                 : 
     874                 : /* -------------------------------------------------------------------- */
     875                 : /*      Do we have styling information?                                 */
     876                 : /* -------------------------------------------------------------------- */
     877               3 :     OGRStyleTool *poTool = NULL;
     878               3 :     OGRStyleMgr oSM;
     879                 : 
     880               3 :     if( poFeature->GetStyleString() != NULL )
     881                 :     {
     882               1 :         oSM.InitFromFeature( poFeature );
     883                 : 
     884               1 :         if( oSM.GetPartCount() > 0 )
     885               1 :             poTool = oSM.GetPart(0);
     886                 :     }
     887                 :     // Write style brush fore color
     888               3 :     if( poTool && poTool->GetType() == OGRSTCBrush )
     889                 :     {
     890               1 :         OGRStyleBrush *poBrush = (OGRStyleBrush *) poTool;
     891                 :         GBool  bDefault;
     892                 : 
     893               1 :         if( poBrush->ForeColor(bDefault) != NULL && !bDefault )
     894               1 :             WriteValue( 62, ColorStringToDXFColor( poBrush->ForeColor(bDefault) ) );
     895                 :     }
     896               3 :     delete poTool;
     897                 : 
     898                 : /* -------------------------------------------------------------------- */
     899                 : /*      Handle a PEN tool to control drawing color and width.           */
     900                 : /*      Perhaps one day also dottedness, etc.                           */
     901                 : /* -------------------------------------------------------------------- */
     902                 : #ifdef notdef
     903                 :     if( poTool && poTool->GetType() == OGRSTCPen )
     904                 :     {
     905                 :         OGRStylePen *poPen = (OGRStylePen *) poTool;
     906                 :         GBool  bDefault;
     907                 : 
     908                 :         if( poPen->Color(bDefault) != NULL && !bDefault )
     909                 :             WriteValue( 62, ColorStringToDXFColor( poPen->Color(bDefault) ) );
     910                 :         
     911                 :         double dfWidthInMM = poPen->Width(bDefault);
     912                 : 
     913                 :         if( !bDefault )
     914                 :             WriteValue( 370, (int) floor(dfWidthInMM * 100 + 0.5) );
     915                 :     }
     916                 : 
     917                 : /* -------------------------------------------------------------------- */
     918                 : /*      Do we have a Linetype for the feature?                          */
     919                 : /* -------------------------------------------------------------------- */
     920                 :     CPLString osLineType = poFeature->GetFieldAsString( "Linetype" );
     921                 : 
     922                 :     if( osLineType.size() > 0 
     923                 :         && (poDS->oHeaderDS.LookupLineType( osLineType ) != NULL 
     924                 :             || oNewLineTypes.count(osLineType) > 0 ) )
     925                 :     {
     926                 :         // Already define -> just reference it.
     927                 :         WriteValue( 6, osLineType );
     928                 :     }
     929                 :     else if( poTool != NULL && poTool->GetType() == OGRSTCPen )
     930                 :     {
     931                 :         CPLString osDefinition = PrepareLineTypeDefinition( poFeature, 
     932                 :                                                             poTool );
     933                 : 
     934                 :         if( osDefinition != "" && osLineType == "" )
     935                 :         {
     936                 :             // Is this definition already created and named?
     937                 :             std::map<CPLString,CPLString>::iterator it;
     938                 : 
     939                 :             for( it = oNewLineTypes.begin();
     940                 :                  it != oNewLineTypes.end();
     941                 :                  it++ )
     942                 :             {
     943                 :                 if( (*it).second == osDefinition )
     944                 :                 {
     945                 :                     osLineType = (*it).first;
     946                 :                     break;
     947                 :                 }
     948                 :             }
     949                 : 
     950                 :             // create an automatic name for it.
     951                 :             if( osLineType == "" )
     952                 :             {
     953                 :                 do 
     954                 :                 { 
     955                 :                     osLineType.Printf( "AutoLineType-%d", nNextAutoID++ );
     956                 :                 }
     957                 :                 while( poDS->oHeaderDS.LookupLineType(osLineType) != NULL );
     958                 :             }
     959                 :         }
     960                 : 
     961                 :         // If it isn't already defined, add it now.
     962                 :         if( osDefinition != "" && oNewLineTypes.count(osLineType) == 0 )
     963                 :         {
     964                 :             oNewLineTypes[osLineType] = osDefinition;
     965                 :             WriteValue( 6, osLineType );
     966                 :         }
     967                 :     }
     968                 :     delete poTool;
     969                 : #endif
     970                 : 
     971                 : /* -------------------------------------------------------------------- */
     972                 : /*      Process the loops (rings).                                      */
     973                 : /* -------------------------------------------------------------------- */
     974               3 :     OGRPolygon *poPoly = (OGRPolygon *) poGeom;
     975                 : 
     976               3 :     WriteValue( 91, poPoly->getNumInteriorRings() + 1 );
     977                 : 
     978               7 :     for( int iRing = -1; iRing < poPoly->getNumInteriorRings(); iRing++ )
     979                 :     {
     980                 :         OGRLinearRing *poLR;
     981                 : 
     982               4 :         if( iRing == -1 )
     983               3 :             poLR = poPoly->getExteriorRing();
     984                 :         else
     985               1 :             poLR = poPoly->getInteriorRing( iRing );
     986                 : 
     987               4 :         WriteValue( 92, 2 ); // Polyline
     988               4 :         WriteValue( 72, 0 ); // has bulge
     989               4 :         WriteValue( 73, 1 ); // is closed
     990               4 :         WriteValue( 93, poLR->getNumPoints() );
     991                 :         
     992              22 :         for( int iVert = 0; iVert < poLR->getNumPoints(); iVert++ )
     993                 :         {
     994              18 :             WriteValue( 10, poLR->getX(iVert) );
     995              18 :             WriteValue( 20, poLR->getY(iVert) );
     996                 :         }
     997                 : 
     998               4 :         WriteValue( 97, 0 ); // 0 source boundary objects
     999                 :     }
    1000                 : 
    1001               3 :     WriteValue( 75, 0 ); // hatch style = Hatch "odd parity" area (Normal style)
    1002               3 :     WriteValue( 76, 1 ); // hatch pattern type = predefined
    1003               3 :     WriteValue( 98, 0 ); // 0 seed points
    1004                 :     
    1005               3 :     return OGRERR_NONE;
    1006                 : 
    1007                 : #ifdef notdef
    1008                 : /* -------------------------------------------------------------------- */
    1009                 : /*      Alternate unmaintained implementation as a polyline entity.     */
    1010                 : /* -------------------------------------------------------------------- */
    1011                 :     WriteValue( 0, "POLYLINE" );
    1012                 :     WriteCore( poFeature );
    1013                 :     WriteValue( 100, "AcDbEntity" );
    1014                 :     WriteValue( 100, "AcDbPolyline" );
    1015                 :     if( EQUAL( poGeom->getGeometryName(), "LINEARRING" ) )
    1016                 :         WriteValue( 70, 1 );
    1017                 :     else
    1018                 :         WriteValue( 70, 0 );
    1019                 :     WriteValue( 66, "1" );
    1020                 : 
    1021                 :     int iVert;
    1022                 : 
    1023                 :     for( iVert = 0; iVert < poLS->getNumPoints(); iVert++ )
    1024                 :     {
    1025                 :         WriteValue( 0, "VERTEX" );
    1026                 :         WriteValue( 8, "0" );
    1027                 :         WriteValue( 10, poLS->getX(iVert) );
    1028                 :         if( !WriteValue( 20, poLS->getY(iVert) ) ) 
    1029                 :             return OGRERR_FAILURE;
    1030                 : 
    1031                 :         if( poLS->getGeometryType() == wkbLineString25D )
    1032                 :         {
    1033                 :             if( !WriteValue( 30, poLS->getZ(iVert) ) )
    1034                 :                 return OGRERR_FAILURE;
    1035                 :         }
    1036                 :     }
    1037                 : 
    1038                 :     WriteValue( 0, "SEQEND" );
    1039                 :     WriteValue( 8, "0" );
    1040                 :     
    1041                 :     return OGRERR_NONE;
    1042                 : #endif
    1043                 : }
    1044                 : 
    1045                 : /************************************************************************/
    1046                 : /*                           CreateFeature()                            */
    1047                 : /************************************************************************/
    1048                 : 
    1049              17 : OGRErr OGRDXFWriterLayer::CreateFeature( OGRFeature *poFeature )
    1050                 : 
    1051                 : {
    1052              17 :     OGRGeometry *poGeom = poFeature->GetGeometryRef();
    1053              17 :     OGRwkbGeometryType eGType = wkbNone;
    1054                 :     
    1055              17 :     if( poGeom != NULL )
    1056                 :     {
    1057              17 :         if( !poGeom->IsEmpty() )
    1058                 :         {
    1059              17 :             OGREnvelope sEnvelope;
    1060              17 :             poGeom->getEnvelope(&sEnvelope);
    1061              17 :             poDS->UpdateExtent(&sEnvelope);
    1062                 :         }
    1063              17 :         eGType = wkbFlatten(poGeom->getGeometryType());
    1064                 :     }
    1065                 : 
    1066              17 :     if( eGType == wkbPoint )
    1067                 :     {
    1068               6 :         const char *pszBlockName = poFeature->GetFieldAsString("BlockName");
    1069                 : 
    1070                 :         // we don't want to treat as a block ref if we are writing blocks layer
    1071              10 :         if( pszBlockName != NULL
    1072                 :             && poDS->poBlocksLayer != NULL 
    1073               4 :             && poFeature->GetDefnRef() == poDS->poBlocksLayer->GetLayerDefn())
    1074               0 :             pszBlockName = NULL;
    1075                 : 
    1076                 :         // We don't want to treat as a blocks ref if the block is not defined
    1077               6 :         if( pszBlockName 
    1078                 :             && poDS->oHeaderDS.LookupBlock(pszBlockName) == NULL )
    1079                 :         {
    1080               4 :             if( poDS->poBlocksLayer == NULL
    1081                 :                 || poDS->poBlocksLayer->FindBlock(pszBlockName) == NULL )
    1082               2 :                 pszBlockName = NULL;
    1083                 :         }
    1084                 :                                   
    1085               6 :         if( pszBlockName != NULL )
    1086               4 :             return WriteINSERT( poFeature );
    1087                 :             
    1088               3 :         else if( poFeature->GetStyleString() != NULL
    1089               1 :             && EQUALN(poFeature->GetStyleString(),"LABEL",5) )
    1090               1 :             return WriteTEXT( poFeature );
    1091                 :         else
    1092               1 :             return WritePOINT( poFeature );
    1093                 :     }
    1094              11 :     else if( eGType == wkbLineString 
    1095                 :              || eGType == wkbMultiLineString )
    1096               7 :         return WritePOLYLINE( poFeature );
    1097                 : 
    1098               4 :     else if( eGType == wkbPolygon 
    1099                 :              || eGType == wkbMultiPolygon )
    1100                 :     {
    1101               3 :         if( bWriteHatch )
    1102               3 :             return WriteHATCH( poFeature );
    1103                 :         else
    1104               0 :             return WritePOLYLINE( poFeature );
    1105                 :     }
    1106                 : 
    1107                 :     // Explode geometry collections into multiple entities.
    1108               1 :     else if( eGType == wkbGeometryCollection )
    1109                 :     {
    1110                 :         OGRGeometryCollection *poGC = (OGRGeometryCollection *)
    1111               1 :             poFeature->StealGeometry();
    1112                 :         int iGeom;
    1113                 : 
    1114               3 :         for( iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
    1115                 :         {
    1116               2 :             poFeature->SetGeometry( poGC->getGeometryRef(iGeom) );
    1117                 :                                     
    1118               2 :             OGRErr eErr = CreateFeature( poFeature );
    1119                 :             
    1120               2 :             if( eErr != OGRERR_NONE )
    1121               0 :                 return eErr;
    1122                 : 
    1123                 :         }
    1124                 :         
    1125               1 :         poFeature->SetGeometryDirectly( poGC );
    1126               1 :         return OGRERR_NONE;
    1127                 :     }
    1128                 :     else 
    1129                 :     {
    1130                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1131                 :                   "No known way to write feature with geometry '%s'.",
    1132               0 :                   OGRGeometryTypeToName(eGType) );
    1133               0 :         return OGRERR_FAILURE;
    1134                 :     }
    1135                 : }
    1136                 : 
    1137                 : /************************************************************************/
    1138                 : /*                       ColorStringToDXFColor()                        */
    1139                 : /************************************************************************/
    1140                 : 
    1141               5 : int OGRDXFWriterLayer::ColorStringToDXFColor( const char *pszRGB )
    1142                 : 
    1143                 : {
    1144                 : /* -------------------------------------------------------------------- */
    1145                 : /*      Parse the RGB string.                                           */
    1146                 : /* -------------------------------------------------------------------- */
    1147               5 :     if( pszRGB == NULL )
    1148               0 :         return -1;
    1149                 : 
    1150               5 :     int nRed, nGreen, nBlue, nTransparency = 255;
    1151                 : 
    1152                 :     int nCount  = sscanf(pszRGB,"#%2x%2x%2x%2x",&nRed,&nGreen,&nBlue, 
    1153               5 :                          &nTransparency);
    1154                 :    
    1155               5 :     if (nCount < 3 )
    1156               0 :         return -1;
    1157                 : 
    1158                 : /* -------------------------------------------------------------------- */
    1159                 : /*      Find near color in DXF palette.                                 */
    1160                 : /* -------------------------------------------------------------------- */
    1161               5 :     const unsigned char *pabyDXFColors = ACGetColorTable();
    1162                 :     int i;
    1163               5 :     int nMinDist = 768;
    1164               5 :     int nBestColor = -1;
    1165                 : 
    1166            1280 :     for( i = 1; i < 256; i++ )
    1167                 :     {
    1168            1275 :         int nDist = ABS(nRed - pabyDXFColors[i*3+0])
    1169            1275 :             + ABS(nGreen - pabyDXFColors[i*3+1])
    1170            3825 :             + ABS(nBlue  - pabyDXFColors[i*3+2]);
    1171                 : 
    1172            1275 :         if( nDist < nMinDist )
    1173                 :         {
    1174               8 :             nBestColor = i;
    1175               8 :             nMinDist = nDist;
    1176                 :         }
    1177                 :     }
    1178                 :     
    1179               5 :     return nBestColor;
    1180                 : }

Generated by: LCOV version 1.7