LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/bna - ogrbnalayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 387 311 80.4 %
Date: 2010-01-09 Functions: 13 12 92.3 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrbnalayer.cpp
       3                 :  *
       4                 :  * Project:  BNA Translator
       5                 :  * Purpose:  Implements OGRBNALayer class.
       6                 :  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2007, Even Rouault
      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_bna.h"
      31                 : #include "cpl_conv.h"
      32                 : #include "cpl_string.h"
      33                 : #include "cpl_csv.h"
      34                 : 
      35                 : #ifndef M_PI
      36                 : # define M_PI  3.1415926535897932384626433832795
      37                 : #endif
      38                 : 
      39                 : /************************************************************************/
      40                 : /*                            OGRBNALayer()                             */
      41                 : /*                                                                      */
      42                 : /*      Note that the OGRBNALayer assumes ownership of the passed       */
      43                 : /*      file pointer.                                                   */
      44                 : /************************************************************************/
      45                 : 
      46              41 : OGRBNALayer::OGRBNALayer( const char *pszFilename,
      47                 :                           const char* layerName,
      48                 :                           BNAFeatureType bnaFeatureType,
      49                 :                           OGRwkbGeometryType eLayerGeomType,
      50                 :                           int bWriter,
      51                 :                           OGRBNADataSource* poDS,
      52              41 :                           int nIDs)
      53                 : 
      54                 : {
      55              41 :     eof = FALSE;
      56              41 :     failed = FALSE;
      57              41 :     curLine = 0;
      58              41 :     nNextFID = 0;
      59                 :     
      60              41 :     this->bWriter = bWriter;
      61              41 :     this->poDS = poDS;
      62              41 :     this->nIDs = nIDs;
      63                 : 
      64              41 :     nFeatures = 0;
      65              41 :     partialIndexTable = TRUE;
      66              41 :     offsetAndLineFeaturesTable = NULL;
      67                 : 
      68              41 :     const char* iKnowHowToCount[] = { "Primary", "Secondary", "Third", "Fourth", "Fifth" };
      69                 :     char tmp[32];
      70                 : 
      71                 :     poFeatureDefn = new OGRFeatureDefn( CPLSPrintf("%s_%s", 
      72                 :                                                    CPLGetBasename( pszFilename ) , 
      73              41 :                                                    layerName ));
      74              41 :     poFeatureDefn->Reference();
      75              41 :     poFeatureDefn->SetGeomType( eLayerGeomType );
      76              41 :     this->bnaFeatureType = bnaFeatureType;
      77                 : 
      78              41 :     if (! bWriter )
      79                 :     {
      80                 :         int i;
      81              88 :         for(i=0;i<nIDs;i++)
      82                 :         {
      83              59 :             if (i < (int) (sizeof(iKnowHowToCount)/sizeof(iKnowHowToCount[0])) )
      84                 :             {
      85              59 :                 sprintf(tmp, "%s ID", iKnowHowToCount[i]);
      86              59 :                 OGRFieldDefn oFieldID(tmp, OFTString );
      87              59 :                 poFeatureDefn->AddFieldDefn( &oFieldID );
      88                 :             }
      89                 :             else
      90                 :             {
      91               0 :                 sprintf(tmp, "%dth ID", i+1);
      92               0 :                 OGRFieldDefn oFieldID(tmp, OFTString );
      93               0 :                 poFeatureDefn->AddFieldDefn( &oFieldID );
      94                 :             }
      95                 :         }
      96                 : 
      97              29 :         if (bnaFeatureType == BNA_ELLIPSE)
      98                 :         {
      99               7 :             OGRFieldDefn oFieldMajorRadius( "Major radius", OFTReal );
     100               7 :             poFeatureDefn->AddFieldDefn( &oFieldMajorRadius );
     101                 : 
     102               7 :             OGRFieldDefn oFieldMinorRadius( "Minor radius", OFTReal );
     103               7 :             poFeatureDefn->AddFieldDefn( &oFieldMinorRadius );
     104                 :         }
     105                 : 
     106              29 :         fpBNA = VSIFOpen( pszFilename, "rb" );
     107              29 :         if( fpBNA == NULL )
     108               0 :             return;
     109                 :     }
     110                 :     else
     111                 :     {
     112              12 :         fpBNA = NULL;
     113                 :     }
     114               0 : }
     115                 : 
     116                 : /************************************************************************/
     117                 : /*                            ~OGRBNALayer()                            */
     118                 : /************************************************************************/
     119                 : 
     120              82 : OGRBNALayer::~OGRBNALayer()
     121                 : 
     122                 : {
     123              41 :     poFeatureDefn->Release();
     124                 : 
     125              41 :     CPLFree(offsetAndLineFeaturesTable);
     126                 : 
     127              41 :     if (fpBNA)
     128              29 :         VSIFClose( fpBNA );
     129              82 : }
     130                 : 
     131                 : /************************************************************************/
     132                 : /*                         SetFeatureIndexTable()                       */
     133                 : /************************************************************************/
     134              29 : void  OGRBNALayer::SetFeatureIndexTable(int nFeatures, OffsetAndLine* offsetAndLineFeaturesTable, int partialIndexTable)
     135                 : {
     136              29 :     this->nFeatures = nFeatures;
     137              29 :     this->offsetAndLineFeaturesTable = offsetAndLineFeaturesTable;
     138              29 :     this->partialIndexTable = partialIndexTable;
     139              29 : }
     140                 : 
     141                 : /************************************************************************/
     142                 : /*                            ResetReading()                            */
     143                 : /************************************************************************/
     144                 : 
     145              65 : void OGRBNALayer::ResetReading()
     146                 : 
     147                 : {
     148              65 :     eof = FALSE;
     149              65 :     failed = FALSE;
     150              65 :     curLine = 0;
     151              65 :     nNextFID = 0;
     152              65 :     VSIFSeek( fpBNA, 0, SEEK_SET );
     153              65 : }
     154                 : 
     155                 : 
     156                 : /************************************************************************/
     157                 : /*                           GetNextFeature()                           */
     158                 : /************************************************************************/
     159                 : 
     160             202 : OGRFeature *OGRBNALayer::GetNextFeature()
     161                 : {
     162                 :     OGRFeature  *poFeature;
     163                 :     BNARecord* record;
     164                 :     int offset, line;
     165                 : 
     166             202 :     if (failed || eof) return NULL;
     167                 : 
     168             172 :     while(1)
     169                 :     {
     170             374 :         int ok = FALSE;
     171             374 :         offset = VSIFTell(fpBNA);
     172             374 :         line = curLine;
     173             374 :         if (nNextFID < nFeatures)
     174                 :         {
     175             137 :             VSIFSeek( fpBNA, offsetAndLineFeaturesTable[nNextFID].offset, SEEK_SET );
     176             137 :             curLine = offsetAndLineFeaturesTable[nNextFID].line;
     177                 :         }
     178             374 :         record =  BNA_GetNextRecord(fpBNA, &ok, &curLine, TRUE, bnaFeatureType);
     179             374 :         if (ok == FALSE)
     180                 :         {
     181               0 :             BNA_FreeRecord(record);
     182               0 :             failed = TRUE;
     183               0 :             return NULL;
     184                 :         }
     185             374 :         if (record == NULL)
     186                 :         {
     187                 :             /* end of file */
     188              65 :             eof = TRUE;
     189                 : 
     190                 :             /* and we have finally build the whole index table */
     191              65 :             partialIndexTable = FALSE;
     192              65 :             return NULL;
     193                 :         }
     194                 : 
     195             309 :         if (record->featureType == bnaFeatureType)
     196                 :         {
     197             137 :             if (nNextFID >= nFeatures)
     198                 :             {
     199               0 :                 nFeatures++;
     200                 :                 offsetAndLineFeaturesTable =
     201               0 :                     (OffsetAndLine*)CPLRealloc(offsetAndLineFeaturesTable, nFeatures * sizeof(OffsetAndLine));
     202               0 :                 offsetAndLineFeaturesTable[nFeatures-1].offset = offset;
     203               0 :                 offsetAndLineFeaturesTable[nFeatures-1].line = line;
     204                 :             }
     205                 : 
     206             137 :             poFeature = BuildFeatureFromBNARecord(record, nNextFID++);
     207                 : 
     208             137 :             BNA_FreeRecord(record);
     209                 : 
     210             137 :             if(   (m_poFilterGeom == NULL
     211                 :                 || FilterGeometry( poFeature->GetGeometryRef() ) )
     212                 :             && (m_poAttrQuery == NULL
     213                 :                 || m_poAttrQuery->Evaluate( poFeature )) )
     214                 :             {
     215             137 :                  return poFeature;
     216                 :             }
     217                 : 
     218               0 :             delete poFeature;
     219                 :         }
     220                 :         else
     221                 :         {
     222             172 :             BNA_FreeRecord(record);
     223                 :         }
     224                 :     }
     225                 : }
     226                 : 
     227                 : 
     228              24 : void OGRBNALayer::WriteFeatureAttributes(FILE* fp, OGRFeature *poFeature )
     229                 : {
     230                 :     int i;
     231                 :     OGRFieldDefn *poField;
     232              24 :     int nbOutID = poDS->GetNbOutId();
     233              24 :     if (nbOutID < 0)
     234               0 :         nbOutID = poFeatureDefn->GetFieldCount();
     235              72 :     for(i=0;i<nbOutID;i++)
     236                 :     { 
     237              48 :         if (i < poFeatureDefn->GetFieldCount())
     238                 :         {
     239              48 :             poField = poFeatureDefn->GetFieldDefn( i );
     240              48 :             if( poFeature->IsFieldSet( i ) )
     241                 :             {
     242              48 :                 const char *pszRaw = poFeature->GetFieldAsString( i );
     243              48 :                 VSIFPrintf( fp, "\"%s\",", pszRaw);
     244                 :             }
     245                 :             else
     246                 :             {
     247               0 :                 VSIFPrintf( fp, "\"\",");
     248                 :             }
     249                 :         }
     250                 :         else
     251                 :         {
     252               0 :             VSIFPrintf( fp, "\"\",");
     253                 :         }
     254                 :     }
     255              24 : }
     256                 : 
     257                 : /************************************************************************/
     258                 : /*                           CreateFeature()                            */
     259                 : /************************************************************************/
     260                 : 
     261              24 : OGRErr OGRBNALayer::CreateFeature( OGRFeature *poFeature )
     262                 : 
     263                 : {
     264                 :     int i,j,k,n;
     265              24 :     OGRGeometry     *poGeom = poFeature->GetGeometryRef();
     266                 :     char eol[3];
     267              24 :     const char* partialEol = (poDS->GetMultiLine()) ? eol : poDS->GetCoordinateSeparator();
     268                 : 
     269              24 :     if (poGeom == NULL || poGeom->IsEmpty() )
     270                 :     {
     271                 :         CPLError(CE_Failure, CPLE_AppDefined,
     272               0 :                  "OGR BNA driver cannot write features with empty geometries.");
     273               0 :         return OGRERR_FAILURE;
     274                 :     }
     275                 : 
     276              24 :     if (poDS->GetUseCRLF())
     277                 :     {
     278               8 :         eol[0] = 13;
     279               8 :         eol[1] = 10;
     280               8 :         eol[2] = 0;
     281                 :     }
     282                 :     else
     283                 :     {
     284              16 :         eol[0] = 10;
     285              16 :         eol[1] = 0;
     286                 :     }
     287                 :     
     288              24 :     if ( ! bWriter )
     289                 :     {
     290               0 :         return OGRERR_FAILURE;
     291                 :     }
     292                 :     
     293              24 :     if( poFeature->GetFID() == OGRNullFID )
     294              24 :         poFeature->SetFID( nFeatures++ );
     295                 :     
     296              24 :     FILE* fp = poDS->GetOutputFP();
     297              24 :     int nbPairPerLine = poDS->GetNbPairPerLine();
     298                 :     char formatCoordinates[32];
     299                 :     sprintf(formatCoordinates, "%%s%%.%df%s%%.%df",
     300              24 :             poDS->GetCoordinatePrecision(), poDS->GetCoordinateSeparator(), poDS->GetCoordinatePrecision());
     301                 : 
     302              24 :     switch( poGeom->getGeometryType() )
     303                 :     {
     304                 :         case wkbPoint:
     305                 :         case wkbPoint25D:
     306                 :         {
     307               6 :             OGRPoint* point = (OGRPoint*)poGeom;
     308               6 :             WriteFeatureAttributes(fp, poFeature);
     309               6 :             VSIFPrintf( fp, "1");
     310               6 :             VSIFPrintf( fp, formatCoordinates, partialEol, point->getX(), point->getY());
     311               6 :             VSIFPrintf( fp, "%s", eol);
     312               6 :             break;
     313                 :         }
     314                 :             
     315                 :         case wkbPolygon:
     316                 :         case wkbPolygon25D:
     317                 :         {
     318               6 :             OGRPolygon* polygon = (OGRPolygon*)poGeom;
     319               6 :             OGRLinearRing* ring = polygon->getExteriorRing();
     320               6 :             if (ring == NULL)
     321                 :             {
     322               0 :                 return OGRERR_FAILURE;
     323                 :             }
     324                 :             
     325               6 :             double firstX = ring->getX(0);
     326               6 :             double firstY = ring->getY(0);
     327               6 :             int nBNAPoints = ring->getNumPoints();
     328               6 :             int is_ellipse = FALSE;
     329                 :             
     330                 :             /* This code tries to detect an ellipse in a polygon geometry */
     331                 :             /* This will only work presumably on ellipses already read from a BNA file */
     332                 :             /* Mostly a BNA to BNA feature... */
     333               6 :             if (poDS->GetEllipsesAsEllipses() &&
     334                 :                 polygon->getNumInteriorRings() == 0 &&
     335                 :                 nBNAPoints == 361)
     336                 :             {
     337               3 :                 double oppositeX = ring->getX(180);
     338               3 :                 double oppositeY = ring->getY(180);
     339               3 :                 double quarterX = ring->getX(90);
     340               3 :                 double quarterY = ring->getY(90);
     341               3 :                 double antiquarterX = ring->getX(270);
     342               3 :                 double antiquarterY = ring->getY(270);
     343               3 :                 double center1X = 0.5*(firstX + oppositeX);
     344               3 :                 double center1Y = 0.5*(firstY + oppositeY);
     345               3 :                 double center2X = 0.5*(quarterX + antiquarterX);
     346               3 :                 double center2Y = 0.5*(quarterY + antiquarterY);
     347               3 :                 if (fabs(center1X - center2X) < 1e-5 && fabs(center1Y - center2Y) < 1e-5 &&
     348                 :                     fabs(oppositeY - firstY) < 1e-5 &&
     349                 :                     fabs(quarterX - antiquarterX) < 1e-5)
     350                 :                 {
     351               3 :                     double major_radius = fabs(firstX - center1X);
     352               3 :                     double minor_radius = fabs(quarterY - center1Y);
     353               3 :                     is_ellipse = TRUE;
     354            1083 :                     for(i=0;i<360;i++)
     355                 :                     {
     356            1080 :                         if (!(fabs(center1X + major_radius * cos(i * (M_PI / 180)) - ring->getX(i)) < 1e-5 &&
     357                 :                               fabs(center1Y + minor_radius * sin(i * (M_PI / 180)) - ring->getY(i)) < 1e-5))
     358                 :                         {
     359               0 :                             is_ellipse = FALSE;
     360               0 :                             break;
     361                 :                         }
     362                 :                     }
     363               3 :                     if ( is_ellipse == TRUE )
     364                 :                     {
     365               3 :                         WriteFeatureAttributes(fp, poFeature);
     366               3 :                         VSIFPrintf( fp, "2");
     367               3 :                         VSIFPrintf( fp, formatCoordinates, partialEol, center1X, center1Y);
     368               3 :                         VSIFPrintf( fp, formatCoordinates,  partialEol, major_radius, minor_radius);
     369               3 :                         VSIFPrintf( fp, "%s", eol);
     370                 :                     }
     371                 :                 }
     372                 :             }
     373                 : 
     374               6 :             if ( is_ellipse == FALSE)
     375                 :             {
     376               3 :                 int nInteriorRings = polygon->getNumInteriorRings();
     377               6 :                 for(i=0;i<nInteriorRings;i++)
     378                 :                 {
     379               3 :                     nBNAPoints += polygon->getInteriorRing(i)->getNumPoints() + 1;
     380                 :                 }
     381               3 :                 if (nBNAPoints <= 3)
     382                 :                 {
     383               0 :                     CPLError( CE_Failure, CPLE_AppDefined, "Invalid geometry" );
     384               0 :                     return OGRERR_FAILURE;
     385                 :                 }
     386               3 :                 WriteFeatureAttributes(fp, poFeature);
     387               3 :                 VSIFPrintf( fp, "%d", nBNAPoints);
     388               3 :                 n = ring->getNumPoints();
     389               3 :                 int nbPair = 0;
     390              18 :                 for(i=0;i<n;i++)
     391                 :                 {
     392                 :                     VSIFPrintf( fp, formatCoordinates,
     393              15 :                                 ((nbPair % nbPairPerLine) == 0) ? partialEol : " ", ring->getX(i), ring->getY(i));
     394              15 :                     nbPair++;
     395                 :                 }
     396               6 :                 for(i=0;i<nInteriorRings;i++)
     397                 :                 {
     398               3 :                     ring = polygon->getInteriorRing(i);
     399               3 :                     n = ring->getNumPoints();
     400              18 :                     for(j=0;j<n;j++)
     401                 :                     {
     402                 :                         VSIFPrintf( fp, formatCoordinates,
     403              15 :                                     ((nbPair % nbPairPerLine) == 0) ? partialEol : " ", ring->getX(j), ring->getY(j));
     404              15 :                         nbPair++;
     405                 :                     }
     406                 :                     VSIFPrintf( fp, formatCoordinates,
     407               3 :                                 ((nbPair % nbPairPerLine) == 0) ? partialEol : " ", firstX, firstY);
     408               3 :                     nbPair++;
     409                 :                 }
     410               3 :                 VSIFPrintf( fp, "%s", eol);
     411                 :             }
     412               6 :             break;
     413                 :         }
     414                 : 
     415                 :         case wkbMultiPolygon:
     416                 :         case wkbMultiPolygon25D:
     417                 :         {
     418               9 :             OGRMultiPolygon* multipolygon = (OGRMultiPolygon*)poGeom;
     419               9 :             int N = multipolygon->getNumGeometries();
     420               9 :             int nBNAPoints = 0;
     421               9 :             double firstX = 0, firstY = 0; 
     422              30 :             for(i=0;i<N;i++)
     423                 :             {
     424              21 :                 OGRPolygon* polygon = (OGRPolygon*)multipolygon->getGeometryRef(i);
     425              21 :                 OGRLinearRing* ring = polygon->getExteriorRing();
     426              21 :                 if (ring == NULL)
     427               0 :                     continue;
     428                 : 
     429              21 :                 if (nBNAPoints)
     430              12 :                     nBNAPoints ++;
     431                 :                 else
     432                 :                 {
     433               9 :                     firstX = ring->getX(0);
     434               9 :                     firstY = ring->getY(0);
     435                 :                 }
     436              21 :                 nBNAPoints += ring->getNumPoints();
     437              21 :                 int nInteriorRings = polygon->getNumInteriorRings();
     438              36 :                 for(j=0;j<nInteriorRings;j++)
     439                 :                 {
     440              15 :                     nBNAPoints += polygon->getInteriorRing(j)->getNumPoints() + 1;
     441                 :                 }
     442                 :             }
     443               9 :             if (nBNAPoints <= 3)
     444                 :             {
     445               0 :                 CPLError( CE_Failure, CPLE_AppDefined, "Invalid geometry" );
     446               0 :                 return OGRERR_FAILURE;
     447                 :             }
     448               9 :             WriteFeatureAttributes(fp, poFeature);
     449               9 :             VSIFPrintf( fp, "%d", nBNAPoints);
     450               9 :             int nbPair = 0;
     451              30 :             for(i=0;i<N;i++)
     452                 :             {
     453              21 :                 OGRPolygon* polygon = (OGRPolygon*)multipolygon->getGeometryRef(i);
     454              21 :                 OGRLinearRing* ring = polygon->getExteriorRing();
     455              21 :                 if (ring == NULL)
     456               0 :                     continue;
     457                 : 
     458              21 :                 n = ring->getNumPoints();
     459              21 :                 int nInteriorRings = polygon->getNumInteriorRings();
     460             135 :                 for(j=0;j<n;j++)
     461                 :                 {
     462                 :                     VSIFPrintf( fp, formatCoordinates,
     463             114 :                                 ((nbPair % nbPairPerLine) == 0) ? partialEol : " ",ring->getX(j), ring->getY(j));
     464             114 :                     nbPair++;
     465                 :                 }
     466              21 :                 if (i != 0)
     467                 :                 {
     468                 :                     VSIFPrintf( fp, formatCoordinates,
     469              12 :                                 ((nbPair % nbPairPerLine) == 0) ? partialEol : " ",firstX, firstY);
     470              12 :                     nbPair++;
     471                 :                 }
     472              36 :                 for(j=0;j<nInteriorRings;j++)
     473                 :                 {
     474              15 :                     ring = polygon->getInteriorRing(j);
     475              15 :                     n = ring->getNumPoints();
     476             102 :                     for(k=0;k<n;k++)
     477                 :                     {
     478                 :                         VSIFPrintf( fp, formatCoordinates, 
     479              87 :                                     ((nbPair % nbPairPerLine) == 0) ? partialEol : " ", ring->getX(k), ring->getY(k));
     480              87 :                         nbPair++;
     481                 :                     }
     482                 :                     VSIFPrintf( fp, formatCoordinates,
     483              15 :                                 ((nbPair % nbPairPerLine) == 0) ? partialEol : " ", firstX, firstY);
     484              15 :                     nbPair++;
     485                 :                 }
     486                 :             }
     487               9 :             VSIFPrintf( fp, "%s", eol);
     488               9 :             break;
     489                 :         }
     490                 : 
     491                 :         case wkbLineString:
     492                 :         case wkbLineString25D:
     493                 :         {
     494               3 :             OGRLineString* line = (OGRLineString*)poGeom;
     495               3 :             int n = line->getNumPoints();
     496                 :             int i;
     497               3 :             if (n < 2)
     498                 :             {
     499               0 :                 CPLError( CE_Failure, CPLE_AppDefined, "Invalid geometry" );
     500               0 :                 return OGRERR_FAILURE;
     501                 :             }
     502               3 :             WriteFeatureAttributes(fp, poFeature);
     503               3 :             VSIFPrintf( fp, "-%d", n);
     504               3 :             int nbPair = 0;
     505              12 :             for(i=0;i<n;i++)
     506                 :             {
     507                 :                 VSIFPrintf( fp, formatCoordinates,
     508               9 :                             ((nbPair % nbPairPerLine) == 0) ? partialEol : " ", line->getX(i), line->getY(i));
     509               9 :                 nbPair++;
     510                 :             }
     511               3 :             VSIFPrintf( fp, "%s", eol);
     512               3 :             break;
     513                 :         }
     514                 :             
     515                 :         default:
     516                 :         {
     517                 :             CPLError( CE_Failure, CPLE_AppDefined,
     518                 :                       "Unsupported geometry type : %s.",
     519               0 :                       poGeom->getGeometryName() );
     520                 : 
     521               0 :             return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     522                 :         }
     523                 :     }
     524                 :     
     525              24 :     return OGRERR_NONE;
     526                 : }
     527                 : 
     528                 : 
     529                 : 
     530                 : /************************************************************************/
     531                 : /*                            CreateField()                             */
     532                 : /************************************************************************/
     533                 : 
     534              30 : OGRErr OGRBNALayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
     535                 : 
     536                 : {
     537              30 :     if( !bWriter || nFeatures != 0)
     538               0 :         return OGRERR_FAILURE;
     539                 : 
     540              30 :     poFeatureDefn->AddFieldDefn( poField );
     541                 : 
     542              30 :     return OGRERR_NONE;
     543                 : }
     544                 : 
     545                 : 
     546                 : /************************************************************************/
     547                 : /*                           BuildFeatureFromBNARecord()                */
     548                 : /************************************************************************/
     549             139 : OGRFeature *    OGRBNALayer::BuildFeatureFromBNARecord (BNARecord* record, long fid)
     550                 : {
     551                 :     OGRFeature  *poFeature;
     552                 :     int i;
     553                 : 
     554             139 :     poFeature = new OGRFeature( poFeatureDefn );
     555             419 :     for(i=0;i<nIDs;i++)
     556                 :     {
     557             280 :         poFeature->SetField( i, record->ids[i] ? record->ids[i] : "");
     558                 :     }
     559             139 :     poFeature->SetFID( fid );
     560             139 :     if (bnaFeatureType == BNA_POINT)
     561                 :     {
     562              36 :         poFeature->SetGeometryDirectly( new OGRPoint( record->tabCoords[0][0], record->tabCoords[0][1] ) );
     563                 :     }
     564             103 :     else if (bnaFeatureType == BNA_POLYLINE)
     565                 :     {
     566              17 :         OGRLineString* lineString = new OGRLineString ();
     567              17 :         lineString->setCoordinateDimension(2);
     568              17 :         lineString->setNumPoints(record->nCoords);
     569              68 :         for(i=0;i<record->nCoords;i++)
     570                 :         {
     571              51 :             lineString->setPoint(i, record->tabCoords[i][0], record->tabCoords[i][1] );
     572                 :         }
     573              17 :         poFeature->SetGeometryDirectly(lineString);
     574                 :     }
     575              86 :     else if (bnaFeatureType == BNA_POLYGON)
     576                 :     {
     577              69 :         double firstX = record->tabCoords[0][0];
     578              69 :         double firstY = record->tabCoords[0][1];
     579              69 :         int isFirstPolygon = 1;
     580              69 :         double secondaryFirstX = 0, secondaryFirstY = 0;
     581                 :   
     582              69 :         OGRLinearRing* ring = new OGRLinearRing ();
     583              69 :         ring->setCoordinateDimension(2);
     584              69 :         ring->addPoint(record->tabCoords[0][0], record->tabCoords[0][1] );
     585                 :   
     586                 :         /* record->nCoords is really a safe upper bound */
     587              69 :         int nbPolygons = 0;
     588                 :         OGRPolygon** tabPolygons =
     589              69 :             (OGRPolygon**)CPLMalloc(record->nCoords * sizeof(OGRPolygon*));
     590                 : 
     591            1075 :         for(i=1;i<record->nCoords;i++)
     592                 :         {
     593            1075 :             ring->addPoint(record->tabCoords[i][0], record->tabCoords[i][1] );
     594            1523 :             if (isFirstPolygon == 1 &&
     595             293 :                 record->tabCoords[i][0] == firstX &&
     596             104 :                 record->tabCoords[i][1] == firstY)
     597                 :             {
     598              69 :                 OGRPolygon* polygon = new OGRPolygon ();
     599              69 :                 polygon->addRingDirectly(ring);
     600              69 :                 tabPolygons[nbPolygons] = polygon;
     601              69 :                 nbPolygons++;
     602                 :     
     603              69 :                 if (i == record->nCoords - 1)
     604                 :                 {
     605              18 :                     break;
     606                 :                 }
     607                 :     
     608              51 :                 isFirstPolygon = 0;
     609                 :     
     610              51 :                 i ++;
     611              51 :                 secondaryFirstX = record->tabCoords[i][0];
     612              51 :                 secondaryFirstY = record->tabCoords[i][1];
     613              51 :                 ring = new OGRLinearRing ();
     614              51 :                 ring->setCoordinateDimension(2);
     615              51 :                 ring->addPoint(record->tabCoords[i][0], record->tabCoords[i][1] );
     616                 :             }
     617            1975 :             else if (isFirstPolygon == 0 &&
     618             782 :                     record->tabCoords[i][0] == secondaryFirstX &&
     619             187 :                     record->tabCoords[i][1] == secondaryFirstY)
     620                 :             {
     621                 : 
     622             170 :                 OGRPolygon* polygon = new OGRPolygon ();
     623             170 :                 polygon->addRingDirectly(ring);
     624             170 :                 tabPolygons[nbPolygons] = polygon;
     625             170 :                 nbPolygons++;
     626                 : 
     627             170 :                 if (i < record->nCoords - 1)
     628                 :                 {
     629                 :                     /* After the closing of a subpolygon, the first coordinates of the first polygon */
     630                 :                     /* should be recalled... in theory */
     631             170 :                     if (record->tabCoords[i+1][0] == firstX &&  record->tabCoords[i+1][1] == firstY)
     632                 :                     {
     633             170 :                         if (i + 1 == record->nCoords - 1)
     634              51 :                             break;
     635             119 :                         i ++;
     636                 :                     }
     637                 :                     else
     638                 :                     {
     639                 : #if 0
     640                 :                         CPLError(CE_Warning, CPLE_AppDefined, 
     641                 :                                  "Geometry of polygon of fid %d starting at line %d is not strictly conformant. "
     642                 :                                  "Trying to go on...\n",
     643                 :                                  fid,
     644                 :                                  offsetAndLineFeaturesTable[fid].line + 1);
     645                 : #endif
     646                 :                     }
     647                 : 
     648             119 :                     i ++;
     649             119 :                     secondaryFirstX = record->tabCoords[i][0];
     650             119 :                     secondaryFirstY = record->tabCoords[i][1];
     651             119 :                     ring = new OGRLinearRing ();
     652             119 :                     ring->setCoordinateDimension(2);
     653             119 :                     ring->addPoint(record->tabCoords[i][0], record->tabCoords[i][1] );
     654                 :                 }
     655                 :                 else
     656                 :                 {
     657                 : #if 0
     658                 :                     CPLError(CE_Warning, CPLE_AppDefined, 
     659                 :                         "Geometry of polygon of fid %d starting at line %d is not strictly conformant. Trying to go on...\n",
     660                 :                         fid,
     661                 :                         offsetAndLineFeaturesTable[fid].line + 1);
     662                 : #endif
     663                 :                 }
     664                 :             }
     665                 :         }
     666              69 :         if (i == record->nCoords)
     667                 :         {
     668                 :             /* Let's be a bit tolerant abount non closing polygons */
     669               0 :             if (isFirstPolygon)
     670                 :             {
     671               0 :                 ring->addPoint(record->tabCoords[0][0], record->tabCoords[0][1] );
     672                 : 
     673               0 :                 OGRPolygon* polygon = new OGRPolygon ();
     674               0 :                 polygon->addRingDirectly(ring);
     675               0 :                 tabPolygons[nbPolygons] = polygon;
     676               0 :                 nbPolygons++;
     677                 :             }
     678                 :         }
     679                 :         
     680              69 :         if (nbPolygons == 1)
     681                 :         {
     682                 :             /* Special optimization here : we directly put the polygon into the multipolygon. */
     683                 :             /* This should save quite a few useless copies */
     684              18 :             OGRMultiPolygon* multipolygon = new OGRMultiPolygon();
     685              18 :             multipolygon->addGeometryDirectly(tabPolygons[0]);
     686              18 :             poFeature->SetGeometryDirectly(multipolygon);
     687                 :         }
     688                 :         else
     689                 :         {
     690                 :             int isValidGeometry;
     691                 :             poFeature->SetGeometryDirectly(
     692              51 :                 OGRGeometryFactory::organizePolygons((OGRGeometry**)tabPolygons, nbPolygons, &isValidGeometry, NULL));
     693                 :             
     694              51 :             if (!isValidGeometry)
     695                 :             {
     696                 :                 CPLError(CE_Warning, CPLE_AppDefined, 
     697                 :                         "Geometry of polygon of fid %ld starting at line %d cannot be translated to Simple Geometry. "
     698                 :                         "All polygons will be contained in a multipolygon.\n",
     699                 :                         fid,
     700               0 :                         offsetAndLineFeaturesTable[fid].line + 1);
     701                 :             }
     702                 :         }
     703                 : 
     704              69 :         CPLFree(tabPolygons);
     705                 :     }
     706                 :     else
     707                 :     {
     708                 :         /* Circle or ellipses are not part of the OGR Simple Geometry, so we discretize them
     709                 :            into polygons by 1 degree step */
     710              17 :         OGRPolygon* polygon = new OGRPolygon ();
     711              34 :         OGRLinearRing* ring = new OGRLinearRing ();
     712              17 :         ring->setCoordinateDimension(2);
     713              17 :         double center_x = record->tabCoords[0][0];
     714              17 :         double center_y = record->tabCoords[0][1];
     715              17 :         double major_radius = record->tabCoords[1][0];
     716              17 :         double minor_radius = record->tabCoords[1][1];
     717              17 :         if (minor_radius == 0)
     718              11 :             minor_radius = major_radius;
     719            6137 :         for(i=0;i<360;i++)
     720                 :         {
     721                 :             ring->addPoint(center_x + major_radius * cos(i * (M_PI / 180)),
     722            6120 :                            center_y + minor_radius * sin(i * (M_PI / 180)) );
     723                 :         }
     724              17 :         ring->addPoint(center_x + major_radius, center_y);
     725              17 :         polygon->addRingDirectly  (  ring );
     726              17 :         poFeature->SetGeometryDirectly(polygon);
     727                 : 
     728              17 :         poFeature->SetField( nIDs, major_radius);
     729              17 :         poFeature->SetField( nIDs+1, minor_radius);
     730                 :     }
     731                 :     
     732             139 :     return poFeature;
     733                 : }
     734                 : 
     735                 : 
     736                 : /************************************************************************/
     737                 : /*                           FastParseUntil()                           */
     738                 : /************************************************************************/
     739               2 : void OGRBNALayer::FastParseUntil ( int interestFID)
     740                 : {
     741               2 :     if (partialIndexTable)
     742                 :     {
     743               0 :         ResetReading();
     744                 : 
     745                 :         BNARecord* record;
     746                 : 
     747               0 :         if (nFeatures > 0)
     748                 :         {
     749               0 :             VSIFSeek( fpBNA, offsetAndLineFeaturesTable[nFeatures-1].offset, SEEK_SET );
     750               0 :             curLine = offsetAndLineFeaturesTable[nFeatures-1].line;
     751                 : 
     752                 :             /* Just skip the last read one */
     753               0 :             int ok = FALSE;
     754               0 :             record =  BNA_GetNextRecord(fpBNA, &ok, &curLine, TRUE, BNA_READ_NONE);
     755               0 :             BNA_FreeRecord(record);
     756                 :         }
     757                 : 
     758               0 :         while(1)
     759                 :         {
     760               0 :             int ok = FALSE;
     761               0 :             int offset = VSIFTell(fpBNA);
     762               0 :             int line = curLine;
     763               0 :             record =  BNA_GetNextRecord(fpBNA, &ok, &curLine, TRUE, BNA_READ_NONE);
     764               0 :             if (ok == FALSE)
     765                 :             {
     766               0 :                 failed = TRUE;
     767               0 :                 return;
     768                 :             }
     769               0 :             if (record == NULL)
     770                 :             {
     771                 :                 /* end of file */
     772               0 :                 eof = TRUE;
     773                 : 
     774                 :                 /* and we have finally build the whole index table */
     775               0 :                 partialIndexTable = FALSE;
     776               0 :                 return;
     777                 :             }
     778                 : 
     779               0 :             if (record->featureType == bnaFeatureType)
     780                 :             {
     781               0 :                 nFeatures++;
     782                 :                 offsetAndLineFeaturesTable =
     783               0 :                     (OffsetAndLine*)CPLRealloc(offsetAndLineFeaturesTable, nFeatures * sizeof(OffsetAndLine));
     784               0 :                 offsetAndLineFeaturesTable[nFeatures-1].offset = offset;
     785               0 :                 offsetAndLineFeaturesTable[nFeatures-1].line = line;
     786                 : 
     787               0 :                 BNA_FreeRecord(record);
     788                 : 
     789               0 :                 if (nFeatures - 1 == interestFID)
     790               0 :                   return;
     791                 :             }
     792                 :             else
     793                 :             {
     794               0 :                 BNA_FreeRecord(record);
     795                 :             }
     796                 :         }
     797                 :     }
     798                 : }
     799                 : 
     800                 : /************************************************************************/
     801                 : /*                           GetFeature()                               */
     802                 : /************************************************************************/
     803                 : 
     804               2 : OGRFeature *  OGRBNALayer::GetFeature( long nFID )
     805                 : {
     806                 :     OGRFeature  *poFeature;
     807                 :     BNARecord* record;
     808                 :     int ok;
     809                 :     
     810               2 :     if (nFID < 0)
     811               0 :         return NULL;
     812                 : 
     813               2 :     FastParseUntil(nFID);
     814                 : 
     815               2 :     if (nFID >= nFeatures)
     816               0 :         return NULL;
     817                 : 
     818               2 :     VSIFSeek( fpBNA, offsetAndLineFeaturesTable[nFID].offset, SEEK_SET );
     819               2 :     curLine = offsetAndLineFeaturesTable[nFID].line;
     820               2 :     record =  BNA_GetNextRecord(fpBNA, &ok, &curLine, TRUE, bnaFeatureType);
     821                 : 
     822               2 :     poFeature = BuildFeatureFromBNARecord(record, nFID);
     823                 : 
     824               2 :     BNA_FreeRecord(record);
     825                 : 
     826               2 :     return poFeature;
     827                 : }
     828                 : 
     829                 : /************************************************************************/
     830                 : /*                           TestCapability()                           */
     831                 : /************************************************************************/
     832                 : 
     833               0 : int OGRBNALayer::TestCapability( const char * pszCap )
     834                 : 
     835                 : {
     836               0 :     if( EQUAL(pszCap,OLCSequentialWrite) )
     837               0 :         return bWriter;
     838               0 :     else if( EQUAL(pszCap,OLCCreateField) )
     839               0 :         return bWriter && nFeatures == 0;
     840                 :     else
     841               0 :         return FALSE;
     842                 : }
     843                 : 

Generated by: LCOV version 1.7