LTP GCOV extension - code coverage report
Current view: directory - ogr/ogrsf_frmts/dgn - ogrdgnlayer.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 412
Code covered: 67.5 % Executed lines: 278

       1                 : /******************************************************************************
       2                 :  * $Id: ogrdgnlayer.cpp 14288 2008-04-13 15:56:22Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements OGRDGNLayer class.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2000, 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_dgn.h"
      31                 : #include "cpl_conv.h"
      32                 : #include "ogr_featurestyle.h"
      33                 : #include "ogr_api.h"
      34                 : 
      35                 : CPL_CVSID("$Id: ogrdgnlayer.cpp 14288 2008-04-13 15:56:22Z rouault $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                           OGRDGNLayer()                              */
      39                 : /************************************************************************/
      40                 : 
      41                 : OGRDGNLayer::OGRDGNLayer( const char * pszName, DGNHandle hDGN,
      42               4 :                           int bUpdate )
      43                 :     
      44                 : {
      45               4 :     this->hDGN = hDGN;
      46               4 :     this->bUpdate = bUpdate;
      47                 : 
      48                 : /* -------------------------------------------------------------------- */
      49                 : /*      Work out what link format we are using.                         */
      50                 : /* -------------------------------------------------------------------- */
      51                 :     OGRFieldType eLinkFieldType;
      52                 : 
      53               4 :     pszLinkFormat = (char *) CPLGetConfigOption( "DGN_LINK_FORMAT", "FIRST" );
      54               4 :     if( EQUAL(pszLinkFormat,"FIRST") )
      55               4 :         eLinkFieldType = OFTInteger;
      56               0 :     else if( EQUAL(pszLinkFormat,"LIST") )
      57               0 :         eLinkFieldType = OFTIntegerList;
      58               0 :     else if( EQUAL(pszLinkFormat,"STRING") )
      59               0 :         eLinkFieldType = OFTString;
      60                 :     else
      61                 :     {
      62                 :         CPLError( CE_Warning, CPLE_AppDefined, 
      63                 :                   "DGN_LINK_FORMAT=%s, but only FIRST, LIST or STRING supported.",
      64               0 :                   pszLinkFormat );
      65               0 :         pszLinkFormat = (char *) "FIRST";
      66               0 :         eLinkFieldType = OFTInteger;
      67                 :     }
      68               4 :     pszLinkFormat = CPLStrdup(pszLinkFormat);
      69                 : 
      70                 : /* -------------------------------------------------------------------- */
      71                 : /*      Create the feature definition.                                  */
      72                 : /* -------------------------------------------------------------------- */
      73               4 :     poFeatureDefn = new OGRFeatureDefn( pszName );
      74               4 :     poFeatureDefn->Reference();
      75                 :     
      76               4 :     OGRFieldDefn        oField( "", OFTInteger );
      77                 : 
      78                 : /* -------------------------------------------------------------------- */
      79                 : /*      Element type                                                    */
      80                 : /* -------------------------------------------------------------------- */
      81               4 :     oField.SetName( "Type" );
      82               4 :     oField.SetType( OFTInteger );
      83               4 :     oField.SetWidth( 2 );
      84               4 :     oField.SetPrecision( 0 );
      85               4 :     poFeatureDefn->AddFieldDefn( &oField );
      86                 : 
      87                 : /* -------------------------------------------------------------------- */
      88                 : /*      Level number.                                                   */
      89                 : /* -------------------------------------------------------------------- */
      90               4 :     oField.SetName( "Level" );
      91               4 :     oField.SetType( OFTInteger );
      92               4 :     oField.SetWidth( 2 );
      93               4 :     oField.SetPrecision( 0 );
      94               4 :     poFeatureDefn->AddFieldDefn( &oField );
      95                 : 
      96                 : /* -------------------------------------------------------------------- */
      97                 : /*      graphic group                                                   */
      98                 : /* -------------------------------------------------------------------- */
      99               4 :     oField.SetName( "GraphicGroup" );
     100               4 :     oField.SetType( OFTInteger );
     101               4 :     oField.SetWidth( 4 );
     102               4 :     oField.SetPrecision( 0 );
     103               4 :     poFeatureDefn->AddFieldDefn( &oField );
     104                 : 
     105                 : /* -------------------------------------------------------------------- */
     106                 : /*      ColorIndex                                                      */
     107                 : /* -------------------------------------------------------------------- */
     108               4 :     oField.SetName( "ColorIndex" );
     109               4 :     oField.SetType( OFTInteger );
     110               4 :     oField.SetWidth( 3 );
     111               4 :     oField.SetPrecision( 0 );
     112               4 :     poFeatureDefn->AddFieldDefn( &oField );
     113                 : 
     114                 : /* -------------------------------------------------------------------- */
     115                 : /*      Weight                                                          */
     116                 : /* -------------------------------------------------------------------- */
     117               4 :     oField.SetName( "Weight" );
     118               4 :     oField.SetType( OFTInteger );
     119               4 :     oField.SetWidth( 2 );
     120               4 :     oField.SetPrecision( 0 );
     121               4 :     poFeatureDefn->AddFieldDefn( &oField );
     122                 : 
     123                 : /* -------------------------------------------------------------------- */
     124                 : /*      Style                                                           */
     125                 : /* -------------------------------------------------------------------- */
     126               4 :     oField.SetName( "Style" );
     127               4 :     oField.SetType( OFTInteger );
     128               4 :     oField.SetWidth( 1 );
     129               4 :     oField.SetPrecision( 0 );
     130               4 :     poFeatureDefn->AddFieldDefn( &oField );
     131                 : 
     132                 : /* -------------------------------------------------------------------- */
     133                 : /*      EntityNum                                                       */
     134                 : /* -------------------------------------------------------------------- */
     135               4 :     oField.SetName( "EntityNum" );
     136               4 :     oField.SetType( eLinkFieldType );
     137               4 :     oField.SetWidth( 0 );
     138               4 :     oField.SetPrecision( 0 );
     139               4 :     poFeatureDefn->AddFieldDefn( &oField );
     140                 : 
     141                 : /* -------------------------------------------------------------------- */
     142                 : /*      MSLink                                                          */
     143                 : /* -------------------------------------------------------------------- */
     144               4 :     oField.SetName( "MSLink" );
     145               4 :     oField.SetType( eLinkFieldType );
     146               4 :     oField.SetWidth( 0 );
     147               4 :     oField.SetPrecision( 0 );
     148               4 :     poFeatureDefn->AddFieldDefn( &oField );
     149                 : 
     150                 : /* -------------------------------------------------------------------- */
     151                 : /*      Text                                                            */
     152                 : /* -------------------------------------------------------------------- */
     153               4 :     oField.SetName( "Text" );
     154               4 :     oField.SetType( OFTString );
     155               4 :     oField.SetWidth( 0 );
     156               4 :     oField.SetPrecision( 0 );
     157               4 :     poFeatureDefn->AddFieldDefn( &oField );
     158                 : 
     159                 : /* -------------------------------------------------------------------- */
     160                 : /*      Create template feature for evaluating simple expressions.      */
     161                 : /* -------------------------------------------------------------------- */
     162               4 :     bHaveSimpleQuery = FALSE;
     163               4 :     poEvalFeature = new OGRFeature( poFeatureDefn );
     164                 : 
     165                 :     /* TODO: I am intending to keep track of simple attribute queries (ones
     166                 :        using only FID, Type and Level and short circuiting their operation
     167                 :        based on the index.  However, there are some complexities with
     168                 :        complex elements, and spatial queries that have caused me to put it
     169                 :        off for now.
     170                 :     */
     171               4 : }
     172                 : 
     173                 : /************************************************************************/
     174                 : /*                           ~OGRDGNLayer()                             */
     175                 : /************************************************************************/
     176                 : 
     177               4 : OGRDGNLayer::~OGRDGNLayer()
     178                 : 
     179                 : {
     180               4 :     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     181                 :     {
     182                 :         CPLDebug( "Mem", "%d features read on layer '%s'.",
     183                 :                   (int) m_nFeaturesRead, 
     184               3 :                   poFeatureDefn->GetName() );
     185                 :     }
     186                 : 
     187               4 :     delete poEvalFeature;
     188                 : 
     189               4 :     poFeatureDefn->Release();
     190                 : 
     191               4 :     CPLFree( pszLinkFormat );
     192               4 : }
     193                 : 
     194                 : /************************************************************************/
     195                 : /*                          SetSpatialFilter()                          */
     196                 : /************************************************************************/
     197                 : 
     198               4 : void OGRDGNLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
     199                 : 
     200                 : {
     201               4 :     if( !InstallFilter(poGeomIn) )
     202               2 :         return;
     203                 : 
     204               2 :     if( m_poFilterGeom != NULL )
     205                 :     {
     206                 :         DGNSetSpatialFilter( hDGN, 
     207                 :                              m_sFilterEnvelope.MinX, 
     208                 :                              m_sFilterEnvelope.MinY, 
     209                 :                              m_sFilterEnvelope.MaxX, 
     210               1 :                              m_sFilterEnvelope.MaxY );
     211                 :     }
     212                 :     else
     213                 :     {
     214               1 :         DGNSetSpatialFilter( hDGN, 0.0, 0.0, 0.0, 0.0 );
     215                 :     }
     216                 : 
     217               2 :     ResetReading();
     218                 : }
     219                 : 
     220                 : /************************************************************************/
     221                 : /*                            ResetReading()                            */
     222                 : /************************************************************************/
     223                 : 
     224               9 : void OGRDGNLayer::ResetReading()
     225                 : 
     226                 : {
     227               9 :     iNextShapeId = 0;
     228               9 :     DGNRewind( hDGN );
     229               9 : }
     230                 : 
     231                 : /************************************************************************/
     232                 : /*                             GetFeature()                             */
     233                 : /************************************************************************/
     234                 : 
     235               0 : OGRFeature *OGRDGNLayer::GetFeature( long nFeatureId )
     236                 : 
     237                 : {
     238                 :     OGRFeature *poFeature;
     239                 :     DGNElemCore *psElement;
     240                 : 
     241               0 :     if( !DGNGotoElement( hDGN, nFeatureId ) )
     242               0 :         return NULL;
     243                 : 
     244                 :     // We should likely clear the spatial search region as it affects 
     245                 :     // DGNReadElement() but I will defer that for now. 
     246                 : 
     247               0 :     psElement = DGNReadElement( hDGN );
     248               0 :     poFeature = ElementToFeature( psElement );
     249               0 :     DGNFreeElement( hDGN, psElement );
     250                 : 
     251               0 :     if( poFeature == NULL )
     252               0 :         return NULL;
     253                 : 
     254               0 :     if( poFeature->GetFID() != nFeatureId )
     255                 :     {
     256               0 :         delete poFeature;
     257               0 :         return NULL;
     258                 :     }
     259                 : 
     260               0 :     return poFeature;
     261                 : }
     262                 : 
     263                 : /************************************************************************/
     264                 : /*                           ConsiderBrush()                            */
     265                 : /*                                                                      */
     266                 : /*      Method to set the style for a polygon, including a brush if     */
     267                 : /*      appropriate.                                                    */
     268                 : /************************************************************************/
     269                 : 
     270                 : void OGRDGNLayer::ConsiderBrush( DGNElemCore *psElement, const char *pszPen,
     271               6 :                                  OGRFeature *poFeature )
     272                 : 
     273                 : {
     274                 :     int         gv_red, gv_green, gv_blue;
     275                 :     char                szFullStyle[256];
     276                 :     int                 nFillColor;
     277                 : 
     278               6 :     if( DGNGetShapeFillInfo( hDGN, psElement, &nFillColor ) 
     279                 :         && DGNLookupColor( hDGN, nFillColor, 
     280                 :                            &gv_red, &gv_green, &gv_blue ) )
     281                 :     {
     282                 :         sprintf( szFullStyle, 
     283                 :                  "BRUSH(fc:#%02x%02x%02x,id:\"ogr-brush-0\")",
     284               4 :                  gv_red, gv_green, gv_blue );
     285                 :               
     286               4 :         if( nFillColor != psElement->color )
     287                 :         {
     288               0 :             strcat( szFullStyle, ";" );
     289               0 :             strcat( szFullStyle, pszPen );
     290                 :         }
     291               4 :         poFeature->SetStyleString( szFullStyle );
     292                 :     }
     293                 :     else
     294               2 :         poFeature->SetStyleString( pszPen );
     295               6 : }
     296                 : 
     297                 : /************************************************************************/
     298                 : /*                          ElementToFeature()                          */
     299                 : /************************************************************************/
     300                 : 
     301              88 : OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
     302                 : 
     303                 : {
     304              88 :     OGRFeature  *poFeature = new OGRFeature( poFeatureDefn );
     305                 : 
     306              88 :     poFeature->SetFID( psElement->element_id );
     307              88 :     poFeature->SetField( "Type", psElement->type );
     308              88 :     poFeature->SetField( "Level", psElement->level );
     309              88 :     poFeature->SetField( "GraphicGroup", psElement->graphic_group );
     310              88 :     poFeature->SetField( "ColorIndex", psElement->color );
     311              88 :     poFeature->SetField( "Weight", psElement->weight );
     312              88 :     poFeature->SetField( "Style", psElement->style );
     313                 :     
     314                 : 
     315              88 :     m_nFeaturesRead++;
     316                 : 
     317                 : /* -------------------------------------------------------------------- */
     318                 : /*      Collect linkage information                                     */
     319                 : /* -------------------------------------------------------------------- */
     320                 : #define MAX_LINK 100    
     321                 :     int anEntityNum[MAX_LINK], anMSLink[MAX_LINK];
     322                 :     unsigned char *pabyData;
     323              88 :     int iLink=0, nLinkCount=0;
     324                 : 
     325              88 :     anEntityNum[0] = 0;
     326              88 :     anMSLink[0] = 0;
     327                 : 
     328                 :     pabyData = DGNGetLinkage( hDGN, psElement, iLink, NULL, 
     329              88 :                               anEntityNum+iLink, anMSLink+iLink, NULL );
     330             181 :     while( pabyData && nLinkCount < MAX_LINK )
     331                 :     {
     332               5 :         iLink++;
     333                 : 
     334               5 :         if( anEntityNum[nLinkCount] != 0 || anMSLink[nLinkCount] != 0 )
     335               0 :             nLinkCount++;
     336                 : 
     337               5 :         anEntityNum[nLinkCount] = 0;
     338               5 :         anMSLink[nLinkCount] = 0;
     339                 : 
     340                 :         pabyData = DGNGetLinkage( hDGN, psElement, iLink, NULL, 
     341                 :                                   anEntityNum+nLinkCount, anMSLink+nLinkCount, 
     342               5 :                                   NULL );
     343                 :     }
     344                 : 
     345                 : /* -------------------------------------------------------------------- */
     346                 : /*      Apply attribute linkage to feature.                             */
     347                 : /* -------------------------------------------------------------------- */
     348              88 :     if( nLinkCount > 0 )
     349                 :     {
     350               0 :         if( EQUAL(pszLinkFormat,"FIRST") )
     351                 :         {
     352               0 :             poFeature->SetField( "EntityNum", anEntityNum[0] );
     353               0 :             poFeature->SetField( "MSLink", anMSLink[0] );
     354                 :         }
     355               0 :         else if( EQUAL(pszLinkFormat,"LIST") )
     356                 :         {
     357               0 :             poFeature->SetField( "EntityNum", nLinkCount, anEntityNum );
     358               0 :             poFeature->SetField( "MSLink", nLinkCount, anMSLink );
     359                 :         }
     360               0 :         else if( EQUAL(pszLinkFormat,"STRING") )
     361                 :         {
     362                 :             char szEntityList[MAX_LINK*9], szMSLinkList[MAX_LINK*9];
     363               0 :             int nEntityLen = 0, nMSLinkLen = 0;
     364                 : 
     365               0 :             for( iLink = 0; iLink < nLinkCount; iLink++ )
     366                 :             {
     367               0 :                 if( iLink != 0 )
     368                 :                 {
     369               0 :                     szEntityList[nEntityLen++] = ',';
     370               0 :                     szMSLinkList[nMSLinkLen++] = ',';
     371                 :                 }
     372                 : 
     373               0 :                 sprintf( szEntityList + nEntityLen, "%d", anEntityNum[iLink]);
     374               0 :                 sprintf( szMSLinkList + nMSLinkLen, "%d", anMSLink[iLink] );
     375                 :                 
     376               0 :                 nEntityLen += strlen(szEntityList + nEntityLen );
     377               0 :                 nMSLinkLen += strlen(szMSLinkList + nMSLinkLen );
     378                 :             }
     379                 : 
     380               0 :             poFeature->SetField( "EntityNum", szEntityList );
     381               0 :             poFeature->SetField( "MSLink", szMSLinkList );
     382                 :         }
     383                 :     }
     384                 : 
     385                 : /* -------------------------------------------------------------------- */
     386                 : /*      Lookup color.                                                   */
     387                 : /* -------------------------------------------------------------------- */
     388                 :     char        gv_color[128];
     389                 :     int         gv_red, gv_green, gv_blue;
     390                 :     char        szFSColor[128], szPen[256];
     391                 : 
     392              88 :     szFSColor[0] = '\0';
     393              88 :     if( DGNLookupColor( hDGN, psElement->color, 
     394                 :                         &gv_red, &gv_green, &gv_blue ) )
     395                 :     {
     396                 :         sprintf( gv_color, "%f %f %f 1.0", 
     397              88 :                  gv_red / 255.0, gv_green / 255.0, gv_blue / 255.0 );
     398                 : 
     399                 :         sprintf( szFSColor, "c:#%02x%02x%02x", 
     400              88 :                  gv_red, gv_green, gv_blue );
     401                 :     }
     402                 : 
     403                 : /* -------------------------------------------------------------------- */
     404                 : /*      Generate corresponding PEN style.                               */
     405                 : /* -------------------------------------------------------------------- */
     406              88 :     if( psElement->style == DGNS_SOLID )
     407              82 :         sprintf( szPen, "PEN(id:\"ogr-pen-0\"" );
     408               6 :     else if( psElement->style == DGNS_DOTTED )
     409               6 :         sprintf( szPen, "PEN(id:\"ogr-pen-5\"" );
     410               0 :     else if( psElement->style == DGNS_MEDIUM_DASH )
     411               0 :         sprintf( szPen, "PEN(id:\"ogr-pen-2\"" );
     412               0 :     else if( psElement->style == DGNS_LONG_DASH )
     413               0 :         sprintf( szPen, "PEN(id:\"ogr-pen-4\"" );
     414               0 :     else if( psElement->style == DGNS_DOT_DASH )
     415               0 :         sprintf( szPen, "PEN(id:\"ogr-pen-6\"" );
     416               0 :     else if( psElement->style == DGNS_SHORT_DASH )
     417               0 :         sprintf( szPen, "PEN(id:\"ogr-pen-3\"" );
     418               0 :     else if( psElement->style == DGNS_DASH_DOUBLE_DOT )
     419               0 :         sprintf( szPen, "PEN(id:\"ogr-pen-7\"" );
     420               0 :     else if( psElement->style == DGNS_LONG_DASH_SHORT_DASH )
     421               0 :         sprintf( szPen, "PEN(p:\"10px 5px 4px 5px\"" );
     422                 :     else
     423               0 :         sprintf( szPen, "PEN(id:\"ogr-pen-0\"" );
     424                 : 
     425              88 :     if( strlen(szFSColor) > 0 )
     426              88 :         sprintf( szPen+strlen(szPen), ",%s", szFSColor );
     427                 : 
     428              88 :     if( psElement->weight > 1 )
     429               0 :         sprintf( szPen+strlen(szPen), ",w:%dpx", psElement->weight );
     430                 :         
     431              88 :     strcat( szPen, ")" );
     432                 : 
     433              88 :     switch( psElement->stype )
     434                 :     {
     435                 :       case DGNST_MULTIPOINT:
     436              10 :         if( psElement->type == DGNT_SHAPE )
     437                 :         {
     438               5 :             OGRLinearRing       *poLine = new OGRLinearRing();
     439              10 :             OGRPolygon          *poPolygon = new OGRPolygon();
     440               5 :             DGNElemMultiPoint *psEMP = (DGNElemMultiPoint *) psElement;
     441                 :             
     442               5 :             poLine->setNumPoints( psEMP->num_vertices );
     443              30 :             for( int i = 0; i < psEMP->num_vertices; i++ )
     444                 :             {
     445                 :                 poLine->setPoint( i, 
     446                 :                                   psEMP->vertices[i].x,
     447                 :                                   psEMP->vertices[i].y,
     448              25 :                                   psEMP->vertices[i].z );
     449                 :             }
     450                 : 
     451               5 :             poPolygon->addRingDirectly( poLine );
     452                 : 
     453               5 :             poFeature->SetGeometryDirectly( poPolygon );
     454                 : 
     455               5 :             ConsiderBrush( psElement, szPen, poFeature );
     456                 :         }
     457               5 :         else if( psElement->type == DGNT_CURVE )
     458                 :         {
     459               0 :             DGNElemMultiPoint *psEMP = (DGNElemMultiPoint *) psElement;
     460               0 :             OGRLineString       *poLine = new OGRLineString();
     461                 :             DGNPoint            *pasPoints;
     462                 :             int                 nPoints;
     463                 : 
     464               0 :             nPoints = 5 * psEMP->num_vertices;
     465               0 :             pasPoints = (DGNPoint *) CPLMalloc(sizeof(DGNPoint) * nPoints);
     466                 :             
     467               0 :             DGNStrokeCurve( hDGN, psEMP, nPoints, pasPoints );
     468                 : 
     469               0 :             poLine->setNumPoints( nPoints );
     470               0 :             for( int i = 0; i < nPoints; i++ )
     471                 :             {
     472                 :                 poLine->setPoint( i, 
     473                 :                                   pasPoints[i].x,
     474                 :                                   pasPoints[i].y,
     475               0 :                                   pasPoints[i].z );
     476                 :             }
     477                 : 
     478               0 :             poFeature->SetGeometryDirectly( poLine );
     479               0 :             CPLFree( pasPoints );
     480                 : 
     481               0 :             poFeature->SetStyleString( szPen );
     482                 :         }
     483                 :         else
     484                 :         {
     485               5 :             OGRLineString       *poLine = new OGRLineString();
     486               5 :             DGNElemMultiPoint *psEMP = (DGNElemMultiPoint *) psElement;
     487                 :             
     488               5 :             if( psEMP->num_vertices > 0 )
     489                 :             {
     490               5 :                 poLine->setNumPoints( psEMP->num_vertices );
     491              85 :                 for( int i = 0; i < psEMP->num_vertices; i++ )
     492                 :                 {
     493                 :                     poLine->setPoint( i, 
     494                 :                                       psEMP->vertices[i].x,
     495                 :                                       psEMP->vertices[i].y,
     496              80 :                                       psEMP->vertices[i].z );
     497                 :                 }
     498                 :                 
     499               5 :                 poFeature->SetGeometryDirectly( poLine );
     500                 :             }
     501                 : 
     502               5 :             poFeature->SetStyleString( szPen );
     503                 :         }
     504              10 :         break;
     505                 : 
     506                 :       case DGNST_ARC:
     507                 :       {
     508               5 :           OGRLineString *poLine = new OGRLineString();
     509               5 :           DGNElemArc    *psArc = (DGNElemArc *) psElement;
     510                 :           DGNPoint      asPoints[90];
     511                 :           int           nPoints;
     512                 : 
     513               5 :           nPoints = (int) (MAX(1,ABS(psArc->sweepang) / 5) + 1);
     514               5 :           DGNStrokeArc( hDGN, psArc, nPoints, asPoints );
     515                 : 
     516               5 :           poLine->setNumPoints( nPoints );
     517             370 :           for( int i = 0; i < nPoints; i++ )
     518                 :           {
     519                 :               poLine->setPoint( i, 
     520                 :                                 asPoints[i].x,
     521                 :                                 asPoints[i].y,
     522             365 :                                 asPoints[i].z );
     523                 :           }
     524                 : 
     525               5 :           poFeature->SetGeometryDirectly( poLine );
     526               5 :           poFeature->SetStyleString( szPen );
     527                 :       }
     528               5 :       break;
     529                 : 
     530                 :       case DGNST_TEXT:
     531                 :       {
     532               5 :           OGRPoint      *poPoint = new OGRPoint();
     533               5 :           DGNElemText   *psText = (DGNElemText *) psElement;
     534                 :           char          *pszOgrFS;
     535                 : 
     536               5 :           poPoint->setX( psText->origin.x );
     537               5 :           poPoint->setY( psText->origin.y );
     538               5 :           poPoint->setZ( psText->origin.z );
     539                 : 
     540               5 :           poFeature->SetGeometryDirectly( poPoint );
     541                 : 
     542               5 :           pszOgrFS = (char *) CPLMalloc(strlen(psText->string) + 150);
     543                 : 
     544                 :           // setup the basic label.
     545               5 :           sprintf( pszOgrFS, "LABEL(t:\"%s\"",  psText->string );
     546                 : 
     547                 :           // set the color if we have it. 
     548               5 :           if( strlen(szFSColor) > 0 )
     549               5 :               sprintf( pszOgrFS+strlen(pszOgrFS), ",%s", szFSColor );
     550                 : 
     551                 :           // Add the size info in ground units.
     552               5 :           if( ABS(psText->height_mult) >= 6.0 )
     553                 :               sprintf( pszOgrFS+strlen(pszOgrFS), ",s:%dg", 
     554               0 :                        (int) psText->height_mult );
     555               5 :           else if( ABS(psText->height_mult) > 0.1 )
     556                 :               sprintf( pszOgrFS+strlen(pszOgrFS), ",s:%.3fg", 
     557               5 :                        psText->height_mult );
     558                 :           else
     559                 :               sprintf( pszOgrFS+strlen(pszOgrFS), ",s:%.12fg", 
     560               0 :                        psText->height_mult );
     561                 : 
     562                 :           // Add the angle, if not horizontal
     563               5 :           if( psText->rotation != 0.0 )
     564                 :               sprintf( pszOgrFS+strlen(pszOgrFS), ",a:%d", 
     565               0 :                        (int) (psText->rotation+0.5) );
     566                 : 
     567               5 :           strcat( pszOgrFS, ")" );
     568                 : 
     569               5 :           poFeature->SetStyleString( pszOgrFS );
     570               5 :           CPLFree( pszOgrFS );
     571                 : 
     572               5 :           poFeature->SetField( "Text", psText->string );
     573                 :       }
     574               5 :       break;
     575                 : 
     576                 :       case DGNST_COMPLEX_HEADER:
     577                 :       {
     578               1 :           DGNElemComplexHeader *psHdr = (DGNElemComplexHeader *) psElement;
     579                 :           int           iChild;
     580               1 :           OGRMultiLineString  oChildren;
     581                 : 
     582                 :           /* collect subsequent child geometries. */
     583                 :           // we should disable the spatial filter ... add later.
     584               3 :           for( iChild = 0; iChild < psHdr->numelems; iChild++ )
     585                 :           {
     586               2 :               OGRFeature *poChildFeature = NULL;
     587                 :               DGNElemCore *psChildElement;
     588                 : 
     589               2 :               psChildElement = DGNReadElement( hDGN );
     590                 :               // should verify complex bit set, not another header.
     591                 : 
     592               2 :               if( psChildElement != NULL )
     593                 :               {
     594               2 :                   poChildFeature = ElementToFeature( psChildElement );
     595               2 :                   DGNFreeElement( hDGN, psChildElement );
     596                 :               }
     597                 : 
     598               2 :               if( poChildFeature != NULL
     599                 :                   && poChildFeature->GetGeometryRef() != NULL )
     600                 :               {
     601                 :                   OGRGeometry *poGeom;
     602                 : 
     603               2 :                   poGeom = poChildFeature->GetGeometryRef();
     604               2 :                   if( wkbFlatten(poGeom->getGeometryType()) == wkbLineString )
     605               2 :                       oChildren.addGeometry( poGeom );
     606                 :               }
     607                 : 
     608               2 :               if( poChildFeature != NULL )
     609               2 :                   delete poChildFeature;
     610                 :           }
     611                 : 
     612                 :           // Try to assemble into polygon geometry.
     613                 :           OGRGeometry *poGeom;
     614                 : 
     615               1 :           if( psElement->type == DGNT_COMPLEX_SHAPE_HEADER )
     616                 :               poGeom = (OGRPolygon *) 
     617                 :                   OGRBuildPolygonFromEdges( (OGRGeometryH) &oChildren, 
     618               0 :                                             TRUE, TRUE, 100000, NULL );
     619                 :           else
     620               1 :               poGeom = oChildren.clone();
     621                 : 
     622               1 :           if( poGeom != NULL )
     623               1 :               poFeature->SetGeometryDirectly( poGeom );
     624                 : 
     625               1 :           ConsiderBrush( psElement, szPen, poFeature );
     626                 :       }
     627                 :       break;
     628                 : 
     629                 :       default:
     630                 :         break;
     631                 :     }
     632                 :     
     633                 : /* -------------------------------------------------------------------- */
     634                 : /*      Fixup geometry dimension.                                       */
     635                 : /* -------------------------------------------------------------------- */
     636              88 :     if( poFeature->GetGeometryRef() != NULL )
     637                 :         poFeature->GetGeometryRef()->setCoordinateDimension( 
     638              21 :             DGNGetDimension( hDGN ) );
     639                 : 
     640              88 :     return poFeature;
     641                 : }
     642                 : 
     643                 : /************************************************************************/
     644                 : /*                           GetNextFeature()                           */
     645                 : /************************************************************************/
     646                 : 
     647              16 : OGRFeature *OGRDGNLayer::GetNextFeature()
     648                 : 
     649                 : {
     650                 :     DGNElemCore *psElement;
     651                 : 
     652              16 :     DGNGetElementIndex( hDGN, NULL );
     653                 : 
     654             105 :     while( (psElement = DGNReadElement( hDGN )) != NULL )
     655                 :     {
     656                 :         OGRFeature      *poFeature;
     657                 : 
     658              86 :         if( psElement->deleted )
     659                 :         {
     660               0 :             DGNFreeElement( hDGN, psElement );
     661               0 :             continue;
     662                 :         }
     663                 : 
     664              86 :         poFeature = ElementToFeature( psElement );
     665              86 :         DGNFreeElement( hDGN, psElement );
     666                 : 
     667              86 :         if( poFeature == NULL )
     668               0 :             continue;
     669                 : 
     670              86 :         if( poFeature->GetGeometryRef() == NULL )
     671                 :         {
     672              67 :             delete poFeature;
     673              67 :             continue;
     674                 :         }
     675                 : 
     676              19 :         if( (m_poAttrQuery == NULL
     677                 :              || m_poAttrQuery->Evaluate( poFeature ))
     678                 :             && FilterGeometry( poFeature->GetGeometryRef() ) )
     679              13 :             return poFeature;
     680                 : 
     681               6 :         delete poFeature;
     682                 :     }        
     683                 : 
     684               3 :     return NULL;
     685                 : }
     686                 : 
     687                 : /************************************************************************/
     688                 : /*                           TestCapability()                           */
     689                 : /************************************************************************/
     690                 : 
     691               0 : int OGRDGNLayer::TestCapability( const char * pszCap )
     692                 : 
     693                 : {
     694               0 :     if( EQUAL(pszCap,OLCRandomRead) )
     695               0 :         return TRUE;
     696                 : 
     697               0 :     else if( EQUAL(pszCap,OLCSequentialWrite) )
     698               0 :         return bUpdate;
     699               0 :     else if( EQUAL(pszCap,OLCRandomWrite) )
     700               0 :         return FALSE; /* maybe later? */
     701                 : 
     702               0 :     else if( EQUAL(pszCap,OLCFastFeatureCount) )
     703               0 :         return m_poFilterGeom == NULL || m_poAttrQuery == NULL;
     704                 : 
     705               0 :     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
     706               0 :         return FALSE;
     707                 : 
     708               0 :     else if( EQUAL(pszCap,OLCFastGetExtent) )
     709               0 :         return TRUE;
     710                 : 
     711                 :     else 
     712               0 :         return FALSE;
     713                 : }
     714                 : 
     715                 : /************************************************************************/
     716                 : /*                          GetFeatureCount()                           */
     717                 : /************************************************************************/
     718                 : 
     719               0 : int OGRDGNLayer::GetFeatureCount( int bForce )
     720                 : 
     721                 : {
     722                 : /* -------------------------------------------------------------------- */
     723                 : /*      If any odd conditions are in effect collect the information     */
     724                 : /*      normally.                                                       */
     725                 : /* -------------------------------------------------------------------- */
     726               0 :     if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
     727               0 :         return OGRLayer::GetFeatureCount( bForce );
     728                 : 
     729                 : /* -------------------------------------------------------------------- */
     730                 : /*      Otherwise scan the index.                                       */
     731                 : /* -------------------------------------------------------------------- */
     732               0 :     int nElementCount, i, nFeatureCount = 0;
     733               0 :     int bInComplexShape = FALSE;
     734               0 :     const DGNElementInfo *pasIndex = DGNGetElementIndex(hDGN,&nElementCount);
     735                 : 
     736               0 :     for( i = 0; i < nElementCount; i++ )
     737                 :     {
     738               0 :         if( pasIndex[i].flags & DGNEIF_DELETED )
     739               0 :             continue;
     740                 : 
     741               0 :         switch( pasIndex[i].stype )
     742                 :         {
     743                 :           case DGNST_MULTIPOINT:
     744                 :           case DGNST_ARC:
     745                 :           case DGNST_TEXT:
     746               0 :             if( !(pasIndex[i].flags & DGNEIF_COMPLEX) || !bInComplexShape )
     747                 :             {
     748               0 :                 nFeatureCount++;
     749               0 :                 bInComplexShape = FALSE;
     750                 :             }
     751               0 :             break;
     752                 : 
     753                 :           case DGNST_COMPLEX_HEADER:
     754               0 :             nFeatureCount++;
     755               0 :             bInComplexShape = TRUE;
     756                 :             break;
     757                 : 
     758                 :           default:
     759                 :             break;
     760                 :         }
     761                 :     }
     762                 : 
     763               0 :     return nFeatureCount;
     764                 : }
     765                 : 
     766                 : /************************************************************************/
     767                 : /*                             GetExtent()                              */
     768                 : /************************************************************************/
     769                 : 
     770               0 : OGRErr OGRDGNLayer::GetExtent( OGREnvelope *psExtent, int bForce )
     771                 : 
     772                 : {
     773                 :     double      adfExtents[6];
     774                 : 
     775               0 :     if( !DGNGetExtents( hDGN, adfExtents ) )
     776               0 :         return OGRERR_FAILURE;
     777                 :     
     778               0 :     psExtent->MinX = adfExtents[0];
     779               0 :     psExtent->MinY = adfExtents[1];
     780               0 :     psExtent->MaxX = adfExtents[3];
     781               0 :     psExtent->MaxY = adfExtents[4];
     782                 :     
     783               0 :     return OGRERR_NONE;
     784                 : }
     785                 : 
     786                 : /************************************************************************/
     787                 : /*                      LineStringToElementGroup()                      */
     788                 : /*                                                                      */
     789                 : /*      Convert an OGR line string to one or more DGN elements.  If     */
     790                 : /*      the input is too long for a single element (more than 38        */
     791                 : /*      points) we split it into multiple LINE_STRING elements, and     */
     792                 : /*      prefix with a complex group header element.                     */
     793                 : /*                                                                      */
     794                 : /*      This method can create handle creating shapes, or line          */
     795                 : /*      strings for the aggregate object, but the components of a       */
     796                 : /*      complex shape group are always line strings.                    */
     797                 : /************************************************************************/
     798                 : 
     799                 : #define MAX_ELEM_POINTS 38
     800                 : 
     801                 : DGNElemCore **OGRDGNLayer::LineStringToElementGroup( OGRLineString *poLS,
     802               3 :                                                      int nGroupType )
     803                 : 
     804                 : {
     805               3 :     int nTotalPoints = poLS->getNumPoints();
     806               3 :     int iNextPoint = 0, iGeom = 0;
     807                 :     DGNElemCore **papsGroup;
     808                 : 
     809                 :     papsGroup = (DGNElemCore **) 
     810               3 :         CPLCalloc( sizeof(void*), (nTotalPoints/(MAX_ELEM_POINTS-1))+3 );
     811                 : 
     812              10 :     for( iNextPoint = 0; iNextPoint < nTotalPoints;  )
     813                 :     {
     814                 :         DGNPoint asPoints[38];
     815               4 :         int nThisCount = 0;
     816                 : 
     817                 :         // we need to repeat end points of elements.
     818               4 :         if( iNextPoint != 0 )
     819               1 :             iNextPoint--;
     820                 : 
     821              85 :         for( ; iNextPoint < nTotalPoints && nThisCount < MAX_ELEM_POINTS; 
     822                 :              iNextPoint++, nThisCount++ )
     823                 :         {
     824              81 :             asPoints[nThisCount].x = poLS->getX( iNextPoint );
     825              81 :             asPoints[nThisCount].y = poLS->getY( iNextPoint );
     826              81 :             asPoints[nThisCount].z = poLS->getZ( iNextPoint );
     827                 :         }
     828                 :         
     829               4 :         if( nTotalPoints <= MAX_ELEM_POINTS )
     830                 :             papsGroup[0] = DGNCreateMultiPointElem( hDGN, nGroupType,
     831               2 :                                                  nThisCount, asPoints);
     832                 :         else
     833                 :             papsGroup[++iGeom] = 
     834                 :                 DGNCreateMultiPointElem( hDGN, DGNT_LINE_STRING,
     835               2 :                                          nThisCount, asPoints);
     836                 :     }
     837                 : 
     838                 : /* -------------------------------------------------------------------- */
     839                 : /*      We needed to make into a group.  Create the complex header      */
     840                 : /*      from the rest of the group.                                     */
     841                 : /* -------------------------------------------------------------------- */
     842               3 :     if( papsGroup[0] == NULL )
     843                 :     {
     844               1 :         if( nGroupType == DGNT_SHAPE )
     845               0 :             nGroupType = DGNT_COMPLEX_SHAPE_HEADER;
     846                 :         else
     847               1 :             nGroupType = DGNT_COMPLEX_CHAIN_HEADER;
     848                 :         
     849                 :         papsGroup[0] = 
     850                 :             DGNCreateComplexHeaderFromGroup( hDGN, nGroupType, 
     851               1 :                                              iGeom, papsGroup + 1 );
     852                 :     }
     853                 : 
     854               3 :     return papsGroup;
     855                 : }
     856                 : 
     857                 : /************************************************************************/
     858                 : /*                           TranslateLabel()                           */
     859                 : /*                                                                      */
     860                 : /*      Translate LABEL feature.                                        */
     861                 : /************************************************************************/
     862                 : 
     863               1 : DGNElemCore **OGRDGNLayer::TranslateLabel( OGRFeature *poFeature )
     864                 : 
     865                 : {
     866                 :     DGNElemCore **papsGroup;
     867               1 :     OGRPoint *poPoint = (OGRPoint *) poFeature->GetGeometryRef();
     868               1 :     OGRStyleMgr oMgr;
     869                 :     OGRStyleLabel *poLabel;
     870               1 :     const char *pszText = poFeature->GetFieldAsString( "Text" );
     871               1 :     double dfRotation = 0.0;
     872               1 :     double dfCharHeight = 100.0;
     873                 : 
     874               1 :     oMgr.InitFromFeature( poFeature );
     875               1 :     poLabel = (OGRStyleLabel *) oMgr.GetPart( 0 );
     876               1 :     if( poLabel != NULL && poLabel->GetType() != OGRSTCLabel )
     877                 :     {
     878               0 :         delete poLabel;
     879               0 :         poLabel = NULL;
     880                 :     }
     881                 : 
     882               1 :     if( poLabel != NULL )
     883                 :     {
     884                 :         GBool bDefault;
     885                 : 
     886               1 :         if( poLabel->TextString(bDefault) != NULL && !bDefault )
     887               1 :             pszText = poLabel->TextString(bDefault);
     888               1 :         dfRotation = poLabel->Angle(bDefault);
     889                 : 
     890               1 :         poLabel->Size( bDefault );
     891               1 :         if( !bDefault && poLabel->GetUnit() == OGRSTUGround )
     892               0 :             dfCharHeight = poLabel->Size(bDefault);
     893                 :         // this part is really kind of bogus.
     894               1 :         if( !bDefault && poLabel->GetUnit() == OGRSTUMM )
     895               1 :             dfCharHeight = poLabel->Size(bDefault)/1000.0;
     896                 : 
     897                 :         /* poLabel->ForeColor(); */
     898                 : 
     899                 :         /* get font id */
     900                 : 
     901                 :     }
     902                 : 
     903               1 :     papsGroup = (DGNElemCore **) CPLCalloc(sizeof(void*),2);
     904                 :     papsGroup[0] = 
     905                 :         DGNCreateTextElem( hDGN, pszText, 0, DGNJ_LEFT_BOTTOM, 
     906                 :                            dfCharHeight, dfCharHeight, dfRotation, NULL,
     907                 :                            poPoint->getX(), 
     908                 :                            poPoint->getY(), 
     909               1 :                            poPoint->getZ() );
     910                 : 
     911               1 :     if( poLabel )
     912               1 :         delete poLabel;
     913                 : 
     914               1 :     return papsGroup;
     915                 : }
     916                 : 
     917                 : /************************************************************************/
     918                 : /*                           CreateFeature()                            */
     919                 : /*                                                                      */
     920                 : /*      Create a new feature and write to file.                         */
     921                 : /************************************************************************/
     922                 : 
     923               4 : OGRErr OGRDGNLayer::CreateFeature( OGRFeature *poFeature )
     924                 : 
     925                 : {
     926               4 :     if( !bUpdate )
     927                 :     {
     928                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     929               0 :                   "Attempt to create feature on read-only DGN file." );
     930               0 :         return OGRERR_FAILURE;
     931                 :     }
     932                 :     
     933               4 :     if( poFeature->GetGeometryRef() == NULL )
     934                 :     {
     935                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     936                 :                   "Features with empty, geometry collection geometries not\n"
     937               0 :                   "supported in DGN format." );
     938               0 :         return OGRERR_FAILURE;
     939                 :     }
     940                 : 
     941               4 :     return CreateFeatureWithGeom( poFeature, poFeature->GetGeometryRef() );
     942                 : }
     943                 : 
     944                 : /************************************************************************/
     945                 : /*                       CreateFeatureWithGeom()                        */
     946                 : /*                                                                      */
     947                 : /*      Create an element or element group from a given geometry and    */
     948                 : /*      the given feature.  This method recurses to handle              */
     949                 : /*      collections as essentially independent features.                */
     950                 : /************************************************************************/
     951                 : 
     952                 : OGRErr OGRDGNLayer::CreateFeatureWithGeom( OGRFeature *poFeature,
     953               4 :                                            OGRGeometry *poGeom)
     954                 : 
     955                 : {
     956                 : /* -------------------------------------------------------------------- */
     957                 : /*      Translate the geometry.                                         */
     958                 : /* -------------------------------------------------------------------- */
     959               4 :     DGNElemCore **papsGroup = NULL;
     960                 :     int i;
     961               4 :     const char *pszStyle = poFeature->GetStyleString();
     962                 : 
     963               4 :     if( wkbFlatten(poGeom->getGeometryType()) == wkbPoint )
     964                 :     {
     965               1 :         OGRPoint *poPoint = (OGRPoint *) poGeom;
     966               1 :         const char *pszText = poFeature->GetFieldAsString("Text");
     967                 : 
     968               1 :         if( (pszText == NULL || strlen(pszText) == 0)
     969                 :             && (pszStyle == NULL || strstr(pszStyle,"LABEL") == NULL) )
     970                 :         {
     971                 :             DGNPoint asPoints[2];
     972                 : 
     973               0 :             papsGroup = (DGNElemCore **) CPLCalloc(sizeof(void*),2);
     974                 : 
     975                 :             // Treat a non text point as a degenerate line.
     976               0 :             asPoints[0].x = poPoint->getX();
     977               0 :             asPoints[0].y = poPoint->getY();
     978               0 :             asPoints[0].z = poPoint->getZ();
     979               0 :             asPoints[1] = asPoints[0];
     980                 :             
     981                 :             papsGroup[0] = DGNCreateMultiPointElem( hDGN, DGNT_LINE, 
     982               0 :                                                     2, asPoints );
     983                 :         }
     984                 :         else
     985                 :         {
     986               1 :             papsGroup = TranslateLabel( poFeature );
     987                 :         }
     988                 :     }
     989               3 :     else if( wkbFlatten(poGeom->getGeometryType()) == wkbLineString )
     990                 :     {
     991                 :         papsGroup = LineStringToElementGroup( (OGRLineString *) poGeom, 
     992               2 :                                               DGNT_LINE_STRING );
     993                 :     }
     994               1 :     else if( wkbFlatten(poGeom->getGeometryType()) == wkbPolygon )
     995                 :     {
     996               1 :         OGRPolygon *poPoly = ((OGRPolygon *) poGeom);
     997                 : 
     998                 :         // Ignore all but the exterior ring. 
     999                 :         papsGroup = LineStringToElementGroup( poPoly->getExteriorRing(),
    1000               1 :                                               DGNT_SHAPE );
    1001                 :     }
    1002               0 :     else if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon 
    1003                 :              || wkbFlatten(poGeom->getGeometryType()) == wkbMultiPoint
    1004                 :              || wkbFlatten(poGeom->getGeometryType()) == wkbMultiLineString
    1005                 :              || wkbFlatten(poGeom->getGeometryType()) == wkbGeometryCollection)
    1006                 :     {
    1007               0 :         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
    1008                 :         int iGeom;
    1009                 : 
    1010               0 :         for( iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
    1011                 :         {
    1012                 :             OGRErr eErr = CreateFeatureWithGeom( poFeature, 
    1013               0 :                                                  poGC->getGeometryRef(iGeom) );
    1014               0 :             if( eErr != OGRERR_NONE )
    1015               0 :                 return eErr;
    1016                 :         }
    1017                 : 
    1018               0 :         return OGRERR_NONE;
    1019                 :     }
    1020                 :     else
    1021                 :     {
    1022                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1023                 :                   "Unsupported geometry type (%s) for DGN.",
    1024               0 :                   OGRGeometryTypeToName( poGeom->getGeometryType() ) );
    1025               0 :         return OGRERR_FAILURE;
    1026                 :     }
    1027                 : 
    1028                 : /* -------------------------------------------------------------------- */
    1029                 : /*      Add other attributes.                                           */
    1030                 : /* -------------------------------------------------------------------- */
    1031               4 :     int nLevel = poFeature->GetFieldAsInteger( "Level" );
    1032               4 :     int nGraphicGroup = poFeature->GetFieldAsInteger( "GraphicGroup" );
    1033               4 :     int nColor = poFeature->GetFieldAsInteger( "ColorIndex" );
    1034               4 :     int nWeight = poFeature->GetFieldAsInteger( "Weight" );
    1035               4 :     int nStyle = poFeature->GetFieldAsInteger( "Style" );
    1036                 : 
    1037               4 :     nLevel = MAX(0,MIN(63,nLevel));
    1038               4 :     nColor = MAX(0,MIN(255,nColor));
    1039               4 :     nWeight = MAX(0,MIN(31,nWeight));
    1040               4 :     nStyle = MAX(0,MIN(7,nStyle));
    1041                 : 
    1042                 :     DGNUpdateElemCore( hDGN, papsGroup[0], nLevel, nGraphicGroup, nColor, 
    1043               4 :                        nWeight, nStyle );
    1044                 :     
    1045                 : /* -------------------------------------------------------------------- */
    1046                 : /*      Write to file.                                                  */
    1047                 : /* -------------------------------------------------------------------- */
    1048              10 :     for( i = 0; papsGroup[i] != NULL; i++ )
    1049                 :     {
    1050               6 :         DGNWriteElement( hDGN, papsGroup[i] );
    1051                 : 
    1052               6 :         if( i == 0 )
    1053               4 :             poFeature->SetFID( papsGroup[i]->element_id );
    1054                 : 
    1055               6 :         DGNFreeElement( hDGN, papsGroup[i] );
    1056                 :     }
    1057                 : 
    1058               4 :     CPLFree( papsGroup );
    1059                 : 
    1060               4 :     return OGRERR_NONE;
    1061                 : }

Generated by: LTP GCOV extension version 1.5