Ticket #1735: gdal_svn_bna.patch
| File gdal_svn_bna.patch, 63.9 kB (added by rouault, 11 months ago) |
|---|
-
ogr/ogrsf_frmts/ogr_formats.html
old new 20 20 </td><td> Yes 21 21 </td></tr> 22 22 23 <tr><td> <a href="drv_bna.html">Atlas BNA</a> 24 </td><td> Yes 25 </td><td> No 26 </td></tr> 27 23 28 <tr><td> <a href="drv_csv.html">Comma Separated Value (.csv)</a> 24 29 </td><td> Yes 25 30 </td><td> No -
ogr/ogrsf_frmts/bna/makefile.vc
old new 2 2 OBJ = ogrbnadriver.obj ogrbnadatasource.obj ogrbnalayer.obj \ 3 3 ogrbnaparser.obj 4 4 5 EXTRAFLAGS = -I.. -I..\.. 5 EXTRAFLAGS = -I.. -I..\.. $(GEOS_CFLAGS) 6 6 7 7 GDAL_ROOT = ..\..\.. 8 8 -
ogr/ogrsf_frmts/bna/ogrbnadatasource.cpp
old new 42 42 { 43 43 papoLayers = NULL; 44 44 nLayers = 0; 45 46 fpOutput = NULL; 45 47 46 48 pszName = NULL; 49 50 pszCoordinateSeparator = NULL; 47 51 48 52 bUpdate = FALSE; 49 53 } … … 55 59 OGRBNADataSource::~OGRBNADataSource() 56 60 57 61 { 62 if ( fpOutput != NULL ) 63 { 64 VSIFClose( fpOutput); 65 } 66 58 67 for( int i = 0; i < nLayers; i++ ) 59 68 delete papoLayers[i]; 60 69 CPLFree( papoLayers ); 70 71 CPLFree( pszCoordinateSeparator ); 61 72 62 73 CPLFree( pszName ); 63 74 } … … 70 81 71 82 { 72 83 if( EQUAL(pszCap,ODsCCreateLayer) ) 73 return FALSE;84 return TRUE; 74 85 else if( EQUAL(pszCap,ODsCDeleteLayer) ) 75 86 return FALSE; 76 87 else … … 91 102 } 92 103 93 104 /************************************************************************/ 105 /* CreateLayer() */ 106 /************************************************************************/ 107 108 OGRLayer * OGRBNADataSource::CreateLayer( const char * pszLayerName, 109 OGRSpatialReference *poSRS, 110 OGRwkbGeometryType eType, 111 char ** papszOptions ) 112 113 { 114 BNAFeatureType bnaFeatureType; 115 116 switch(eType) 117 { 118 case wkbPolygon: 119 case wkbPolygon25D: 120 case wkbMultiPolygon: 121 case wkbMultiPolygon25D: 122 bnaFeatureType = BNA_POLYGON; 123 break; 124 125 case wkbPoint: 126 case wkbPoint25D: 127 bnaFeatureType = BNA_POINT; 128 break; 129 130 case wkbLineString: 131 case wkbLineString25D: 132 bnaFeatureType = BNA_POLYLINE; 133 break; 134 135 default: 136 CPLError( CE_Failure, CPLE_NotSupported, 137 "Geometry type of `%s' not supported in BNAs.\n", 138 OGRGeometryTypeToName(eType) ); 139 return NULL; 140 } 141 142 nLayers++; 143 papoLayers = (OGRBNALayer **) CPLRealloc(papoLayers, nLayers * sizeof(OGRBNALayer*)); 144 papoLayers[nLayers-1] = new OGRBNALayer( pszName, pszLayerName, bnaFeatureType, eType, TRUE, this ); 145 146 return papoLayers[nLayers-1]; 147 } 148 149 /************************************************************************/ 94 150 /* Open() */ 95 151 /************************************************************************/ 96 152 … … 115 171 // -------------------------------------------------------------------- 116 172 if( !EQUAL( CPLGetExtension(pszFilename), "bna" ) ) 117 173 return FALSE; 118 119 FILE* f = VSIFOpen(pszFilename, "rb");120 if (f )174 175 FILE* fp = VSIFOpen(pszFilename, "r"); 176 if (fp) 121 177 { 122 178 BNARecord* record; 123 179 int curLine = 0; 124 record = BNA_GetNextRecord(f, &ok, &curLine, 0, BNA_READ_NONE); 180 const char* layerRadixName[] = { "points", "polygons", "lines", "ellipses"}; 181 OGRwkbGeometryType wkbGeomTypes[] = { wkbPoint, wkbMultiPolygon, wkbLineString, wkbPolygon }; 182 int i; 183 #if defined(BNA_FAST_DS_OPEN) 184 record = BNA_GetNextRecord(fp, &ok, &curLine, FALSE, BNA_READ_NONE); 125 185 BNA_FreeRecord(record); 126 186 127 187 if (ok) … … 129 189 nLayers = 4; 130 190 131 191 papoLayers = (OGRBNALayer **) CPLMalloc(nLayers * sizeof(OGRBNALayer*)); 132 papoLayers[0] = new OGRBNALayer( pszFilename, "points", BNA_POINT, wkbPoint );133 papoLayers[1] = new OGRBNALayer( pszFilename, "lines", BNA_POLYLINE, wkbLineString );134 papoLayers[2] = new OGRBNALayer( pszFilename, "polygons", BNA_POLYGON, wkbMultiPolygon );135 papoLayers[3] = new OGRBNALayer( pszFilename, "ellipses", BNA_ELLIPSE, wkbPolygon);192 for(i=0;i<4;i++) 193 papoLayers[i] = new OGRBNALayer( pszFilename, 194 layerRadixName[i], 195 (BNAFeatureType)i, wkbGeomTypes[i], FALSE, this ); 136 196 } 197 #else 198 int nFeatures[4] = { 0, 0, 0, 0 }; 199 OffsetAndLine* offsetAndLineFeaturesTable[4] = { NULL, NULL, NULL, NULL }; 200 int nIDs[4] = {0, 0, 0, 0}; 201 int partialIndexTable = TRUE; 137 202 138 VSIFClose(f); 203 while(1) 204 { 205 int offset = VSIFTell(fp); 206 int line = curLine; 207 record = BNA_GetNextRecord(fp, &ok, &curLine, FALSE, BNA_READ_NONE); 208 if (ok == FALSE) 209 { 210 BNA_FreeRecord(record); 211 if (line != 0) 212 ok = TRUE; 213 break; 214 } 215 if (record == NULL) 216 { 217 /* end of file */ 218 ok = TRUE; 219 220 /* and we have finally build the whole index table */ 221 partialIndexTable = FALSE; 222 break; 223 } 224 225 if (record->nIDs > nIDs[record->featureType]) 226 nIDs[record->featureType] = record->nIDs; 227 228 nFeatures[record->featureType]++; 229 offsetAndLineFeaturesTable[record->featureType] = 230 (OffsetAndLine*)CPLRealloc(offsetAndLineFeaturesTable[record->featureType], 231 nFeatures[record->featureType] * sizeof(OffsetAndLine)); 232 offsetAndLineFeaturesTable[record->featureType][nFeatures[record->featureType]-1].offset = offset; 233 offsetAndLineFeaturesTable[record->featureType][nFeatures[record->featureType]-1].line = line; 234 235 BNA_FreeRecord(record); 236 } 237 238 nLayers = (nFeatures[0] != 0) + (nFeatures[1] != 0) + (nFeatures[2] != 0) + (nFeatures[3] != 0); 239 papoLayers = (OGRBNALayer **) CPLMalloc(nLayers * sizeof(OGRBNALayer*)); 240 int iLayer = 0; 241 for(i=0;i<4;i++) 242 { 243 if (nFeatures[i]) 244 { 245 papoLayers[iLayer] = new OGRBNALayer( pszFilename, 246 layerRadixName[i], 247 (BNAFeatureType)i, 248 wkbGeomTypes[i], 249 FALSE, 250 this, 251 nIDs[i]); 252 papoLayers[iLayer]->SetFeatureIndexTable(nFeatures[i], 253 offsetAndLineFeaturesTable[i], 254 partialIndexTable); 255 iLayer++; 256 } 257 } 258 #endif 259 VSIFClose(fp); 139 260 } 140 261 141 262 return ok; 142 263 } 143 264 265 266 /************************************************************************/ 267 /* Create() */ 268 /************************************************************************/ 269 270 int OGRBNADataSource::Create( const char *pszFilename, 271 char **papszOptions ) 272 { 273 if( fpOutput != NULL) 274 { 275 CPLAssert( FALSE ); 276 return FALSE; 277 } 278 279 /* -------------------------------------------------------------------- */ 280 /* Do not override exiting file. */ 281 /* -------------------------------------------------------------------- */ 282 VSIStatBufL sStatBuf; 283 284 if( VSIStatL( pszFilename, &sStatBuf ) == 0 ) 285 return FALSE; 286 287 /* -------------------------------------------------------------------- */ 288 /* Create the output file. */ 289 /* -------------------------------------------------------------------- */ 290 pszName = CPLStrdup( pszFilename ); 291 292 if( EQUAL(pszFilename,"stdout") ) 293 fpOutput = stdout; 294 else 295 fpOutput = VSIFOpen( pszFilename, "w" ); 296 if( fpOutput == NULL ) 297 { 298 CPLError( CE_Failure, CPLE_OpenFailed, 299 "Failed to create BNA file %s.", 300 pszFilename ); 301 return FALSE; 302 } 303 304 /* EOL token */ 305 const char *pszCRLFFormat = CSLFetchNameValue( papszOptions, "LINEFORMAT"); 306 307 if( pszCRLFFormat == NULL ) 308 { 309 #ifdef WIN32 310 bUseCRLF = TRUE; 311 #else 312 bUseCRLF = FALSE; 313 #endif 314 } 315 else if( EQUAL(pszCRLFFormat,"CRLF") ) 316 bUseCRLF = TRUE; 317 else if( EQUAL(pszCRLFFormat,"LF") ) 318 bUseCRLF = FALSE; 319 else 320 { 321 CPLError( CE_Warning, CPLE_AppDefined, 322 "LINEFORMAT=%s not understood, use one of CRLF or LF.", 323 pszCRLFFormat ); 324 #ifdef WIN32 325 bUseCRLF = TRUE; 326 #else 327 bUseCRLF = FALSE; 328 #endif 329 } 330 331 /* Multi line or single line format ? */ 332 bMultiLine = CSLFetchBoolean( papszOptions, "MULTILINE", TRUE); 333 334 /* Number of identifiers per record */ 335 const char* pszNbOutID = CSLFetchNameValue ( papszOptions, "NB_IDS"); 336 if (pszNbOutID == NULL) 337 { 338 nbOutID = NB_MIN_BNA_IDS; 339 } 340 else if (EQUAL(pszNbOutID, "NB_SOURCE_FIELDS")) 341 { 342 nbOutID = -1; 343 } 344 else 345 { 346 nbOutID = atoi(pszNbOutID); 347 if (nbOutID <= 0) 348 { 349 CPLError( CE_Warning, CPLE_AppDefined, 350 "NB_ID=%s not understood. Must be >=%d and <=%d or equal to NB_SOURCE_FIELDS", 351 pszNbOutID, NB_MIN_BNA_IDS, NB_MAX_BNA_IDS ); 352 nbOutID = NB_MIN_BNA_IDS; 353 } 354 if (nbOutID > NB_MAX_BNA_IDS) 355 { 356 CPLError( CE_Warning, CPLE_AppDefined, 357 "NB_ID=%s not understood. Must be >=%d and <=%d or equal to NB_SOURCE_FIELDS", 358 pszNbOutID, NB_MIN_BNA_IDS, NB_MAX_BNA_IDS ); 359 nbOutID = NB_MAX_BNA_IDS; 360 } 361 } 362 363 /* Ellipses export as ellipses or polygons ? */ 364 bEllipsesAsEllipses = CSLFetchBoolean( papszOptions, "ELLIPSES_AS_ELLIPSES", TRUE); 365 366 /* Number of coordinate pairs per line */ 367 const char* pszNbPairPerLine = CSLFetchNameValue( papszOptions, "NB_PAIRS_PER_LINE"); 368 if (pszNbPairPerLine) 369 { 370 nbPairPerLine = atoi(pszNbPairPerLine); 371 if (nbPairPerLine <= 0) 372 nbPairPerLine = (bMultiLine == FALSE) ? 1000000000 : 1; 373 if (bMultiLine == FALSE) 374 { 375 CPLError( CE_Warning, CPLE_AppDefined, "NB_PAIR_PER_LINE option is ignored when MULTILINE=NO"); 376 } 377 } 378 else 379 { 380 nbPairPerLine = (bMultiLine == FALSE) ? 1000000000 : 1; 381 } 382 383 /* Coordinate precision */ 384 const char* pszCoordinatePrecision = CSLFetchNameValue( papszOptions, "COORDINATE_PRECISION"); 385 if (pszCoordinatePrecision) 386 { 387 coordinatePrecision = atoi(pszCoordinatePrecision); 388 if (coordinatePrecision <= 0) 389 coordinatePrecision = 0; 390 else if (coordinatePrecision >= 20) 391 coordinatePrecision = 20; 392 } 393 else 394 { 395 coordinatePrecision = 10; 396 } 397 398 pszCoordinateSeparator = (char*)CSLFetchNameValue( papszOptions, "COORDINATE_SEPARATOR"); 399 if (pszCoordinateSeparator == NULL) 400 pszCoordinateSeparator = CPLStrdup(","); 401 else 402 pszCoordinateSeparator = CPLStrdup(pszCoordinateSeparator); 403 404 return TRUE; 405 } -
ogr/ogrsf_frmts/bna/ogrbnadriver.cpp
old new 68 68 } 69 69 70 70 /************************************************************************/ 71 /* CreateDataSource() */ 72 /************************************************************************/ 73 74 OGRDataSource *OGRBNADriver::CreateDataSource( const char * pszName, 75 char **papszOptions ) 76 77 { 78 OGRBNADataSource *poDS = new OGRBNADataSource(); 79 80 if( !poDS->Create( pszName, papszOptions ) ) 81 { 82 delete poDS; 83 poDS = NULL; 84 } 85 86 return poDS; 87 } 88 89 /************************************************************************/ 90 /* DeleteDataSource() */ 91 /************************************************************************/ 92 93 OGRErr OGRBNADriver::DeleteDataSource( const char *pszFilename ) 94 95 { 96 if( VSIUnlink( pszFilename ) == 0 ) 97 return OGRERR_NONE; 98 else 99 return OGRERR_FAILURE; 100 } 101 102 /************************************************************************/ 71 103 /* TestCapability() */ 72 104 /************************************************************************/ 73 105 … … 75 107 76 108 { 77 109 if( EQUAL(pszCap,ODrCCreateDataSource) ) 78 return FALSE;110 return TRUE; 79 111 else if( EQUAL(pszCap,ODrCDeleteDataSource) ) 80 return FALSE;112 return TRUE; 81 113 else 82 114 return FALSE; 83 115 } -
ogr/ogrsf_frmts/bna/ogrbnalayer.cpp
old new 1 1 /****************************************************************************** 2 * $Id: ogrbnalayer.cpp 10646 2007-01-18 02:38:10Z warmerdam $2 * $Id: ogrbnalayer.cpp 3 3 * 4 4 * Project: BNA Translator 5 5 * Purpose: Implements OGRBNALayer class. … … 46 46 OGRBNALayer::OGRBNALayer( const char *pszFilename, 47 47 const char* layerName, 48 48 BNAFeatureType bnaFeatureType, 49 OGRwkbGeometryType eLayerGeomType ) 49 OGRwkbGeometryType eLayerGeomType, 50 int bWriter, 51 OGRBNADataSource* poDS, 52 int nIDs) 50 53 51 54 { 52 55 eof = FALSE; 53 56 failed = FALSE; 54 57 curLine = 0; 55 58 nNextFID = 0; 59 60 this->bWriter = bWriter; 61 this->poDS = poDS; 62 this->nIDs = nIDs; 56 63 57 64 nFeatures = 0; 58 65 partialIndexTable = TRUE; … … 68 75 poFeatureDefn->SetGeomType( eLayerGeomType ); 69 76 this->bnaFeatureType = bnaFeatureType; 70 77 71 int i; 72 for(i=0;i<NB_MAX_BNA_IDS;i++) 78 if (! bWriter ) 73 79 { 74 if (i < (int) (sizeof(iKnowHowToCount)/sizeof(iKnowHowToCount[0])) ) 80 int i; 81 for(i=0;i<nIDs;i++) 75 82 { 76 sprintf(tmp, "%s ID", iKnowHowToCount[i]); 77 OGRFieldDefn oFieldID(tmp, OFTString ); 78 poFeatureDefn->AddFieldDefn( &oFieldID ); 83 if (i < (int) (sizeof(iKnowHowToCount)/sizeof(iKnowHowToCount[0])) ) 84 { 85 sprintf(tmp, "%s ID", iKnowHowToCount[i]); 86 OGRFieldDefn oFieldID(tmp, OFTString ); 87 poFeatureDefn->AddFieldDefn( &oFieldID ); 88 } 89 else 90 { 91 sprintf(tmp, "%dth ID", i+1); 92 OGRFieldDefn oFieldID(tmp, OFTString ); 93 poFeatureDefn->AddFieldDefn( &oFieldID ); 94 } 79 95 } 80 else 96 97 if (bnaFeatureType == BNA_ELLIPSE) 81 98 { 82 sprintf(tmp, "%dth ID", i+1); 83 OGRFieldDefn oFieldID(tmp, OFTString ); 84 poFeatureDefn->AddFieldDefn( &oFieldID ); 99 OGRFieldDefn oFieldMajorRadius( "Major radius", OFTReal ); 100 poFeatureDefn->AddFieldDefn( &oFieldMajorRadius ); 101 102 OGRFieldDefn oFieldMinorRadius( "Minor radius", OFTReal ); 103 poFeatureDefn->AddFieldDefn( &oFieldMinorRadius ); 85 104 } 105 106 fpBNA = VSIFOpen( pszFilename, "r" ); 107 if( fpBNA == NULL ) 108 return; 86 109 } 87 88 if (bnaFeatureType == BNA_ELLIPSE) 110 else 89 111 { 90 OGRFieldDefn oFieldMajorRadius( "Major radius", OFTReal ); 91 poFeatureDefn->AddFieldDefn( &oFieldMajorRadius ); 92 93 OGRFieldDefn oFieldMinorRadius( "Minor radius", OFTReal ); 94 poFeatureDefn->AddFieldDefn( &oFieldMinorRadius ); 112 fpBNA = NULL; 95 113 } 96 97 fpBNA = VSIFOpen( pszFilename, "rb" );98 if( fpBNA == NULL )99 return;100 114 } 101 115 102 116 /************************************************************************/ … … 115 129 } 116 130 117 131 /************************************************************************/ 132 /* SetFeatureIndexTable() */ 133 /************************************************************************/ 134 void OGRBNALayer::SetFeatureIndexTable(int nFeatures, OffsetAndLine* offsetAndLineFeaturesTable, int partialIndexTable) 135 { 136 this->nFeatures = nFeatures; 137 this->offsetAndLineFeaturesTable = offsetAndLineFeaturesTable; 138 this->partialIndexTable = partialIndexTable; 139 } 140 141 /************************************************************************/ 118 142 /* ResetReading() */ 119 143 /************************************************************************/ 120 144 … … 154 178 record = BNA_GetNextRecord(fpBNA, &ok, &curLine, TRUE, bnaFeatureType); 155 179 if (ok == FALSE) 156 180 { 181 BNA_FreeRecord(record); 157 182 failed = TRUE; 158 183 return NULL; 159 184 } … … 161 186 { 162 187 /* end of file */ 163 188 eof = TRUE; 164 189 165 190 /* and we have finally build the whole index table */ 166 191 partialIndexTable = FALSE; 167 192 return NULL; … … 169 194 170 195 if (record->featureType == bnaFeatureType) 171 196 { 172 break; 197 if (nNextFID >= nFeatures) 198 { 199 nFeatures++; 200 offsetAndLineFeaturesTable = 201 (OffsetAndLine*)CPLRealloc(offsetAndLineFeaturesTable, nFeatures * sizeof(OffsetAndLine)); 202 offsetAndLineFeaturesTable[nFeatures-1].offset = offset; 203 offsetAndLineFeaturesTable[nFeatures-1].line = line; 204 } 205 206 poFeature = BuildFeatureFromBNARecord(record, nNextFID++); 207 208 BNA_FreeRecord(record); 209 210 if( (m_poFilterGeom == NULL 211 || FilterGeometry( poFeature->GetGeometryRef() ) ) 212 && (m_poAttrQuery == NULL 213 || m_poAttrQuery->Evaluate( poFeature )) ) 214 { 215 return poFeature; 216 } 217 218 delete poFeature; 173 219 } 174 220 else 175 221 { 176 222 BNA_FreeRecord(record); 177 223 } 178 224 } 225 } 226 227 228 void OGRBNALayer::WriteFeatureAttributes(FILE* fp, OGRFeature *poFeature ) 229 { 230 int i; 231 OGRFieldDefn *poField; 232 int nbOutID = poDS->GetNbOutId(); 233 if (nbOutID < 0) 234 nbOutID = poFeatureDefn->GetFieldCount(); 235 for(i=0;i<nbOutID;i++) 236 { 237 if (i < poFeatureDefn->GetFieldCount()) 238 { 239 poField = poFeatureDefn->GetFieldDefn( i ); 240 if( poFeature->IsFieldSet( i ) ) 241 { 242 const char *pszRaw = poFeature->GetFieldAsString( i ); 243 VSIFPrintf( fp, "\"%s\",", pszRaw); 244 } 245 else 246 { 247 VSIFPrintf( fp, "\"\","); 248 } 249 } 250 else 251 { 252 VSIFPrintf( fp, "\"\","); 253 } 254 } 255 } 256 257 /************************************************************************/ 258 /* CreateFeature() */ 259 /************************************************************************/ 260 261 OGRErr OGRBNALayer::CreateFeature( OGRFeature *poFeature ) 262 263 { 264 int i,j,k,n; 265 OGRGeometry *poGeom = poFeature->GetGeometryRef(); 266 char eol[3]; 267 const char* partialEol = (poDS->GetMultiLine()) ? eol : poDS->GetCoordinateSeparator(); 179 268 180 if ( nNextFID >= nFeatures)269 if (poDS->GetUseCRLF()) 181 270 { 182 nFeatures++; 183 offsetAndLineFeaturesTable = 184 (OffsetAndLine*)CPLRealloc(offsetAndLineFeaturesTable, nFeatures * sizeof(OffsetAndLine)); 185 offsetAndLineFeaturesTable[nFeatures-1].offset = offset; 186 offsetAndLineFeaturesTable[nFeatures-1].line = line; 271 eol[0] = 13; 272 eol[1] = 10; 273 eol[2] = 0; 187 274 } 275 else 276 { 277 eol[0] = 10; 278 eol[1] = 0; 279 } 280 281 if ( ! bWriter ) 282 { 283 return OGRERR_FAILURE; 284 } 285 286 if( poFeature->GetFID() == OGRNullFID ) 287 poFeature->SetFID( nFeatures++ ); 288 289 FILE* fp = poDS->GetOutputFP(); 290 int nbPairPerLine = poDS->GetNbPairPerLine(); 291 char formatCoordinates[32]; 292 sprintf(formatCoordinates, "%%s%%.%df%s%%.%df", 293 poDS->GetCoordinatePrecision(), poDS->GetCoordinateSeparator(), poDS->GetCoordinatePrecision()); 188 294 189 poFeature = BuildFeatureFromBNARecord(record, nNextFID++); 295 switch( poGeom->getGeometryType() ) 296 { 297 case wkbPoint: 298 case wkbPoint25D: 299 { 300 OGRPoint* point = (OGRPoint*)poGeom; 301 WriteFeatureAttributes(fp, poFeature); 302 VSIFPrintf( fp, "1"); 303 VSIFPrintf( fp, formatCoordinates, partialEol, point->getX(), point->getY()); 304 VSIFPrintf( fp, "%s", eol); 305 break; 306 } 307 308 case wkbPolygon: 309 case wkbPolygon25D: 310 { 311 OGRPolygon* polygon = (OGRPolygon*)poGeom; 312 OGRLinearRing* ring = polygon->getExteriorRing(); 313 double firstX = ring->getX(0); 314 double firstY = ring->getY(0); 315 int nBNAPoints = ring->getNumPoints(); 316 int is_ellipse = FALSE; 317 318 /* This code tries to detect an ellipse in a polygon geometry */ 319 /* This will only work presumably on ellipses already read from a BNA file */ 320 /* Mostly a BNA to BNA feature... */ 321 if (poDS->GetEllipsesAsEllipses() && 322 polygon->getNumInteriorRings() == 0 && 323 nBNAPoints == 361) 324 { 325 double oppositeX = ring->getX(180); 326 double oppositeY = ring->getY(180); 327 double quarterX = ring->getX(90); 328 double quarterY = ring->getY(90); 329 double antiquarterX = ring->getX(270); 330 double antiquarterY = ring->getY(270); 331 double center1X = 0.5*(firstX + oppositeX); 332 double center1Y = 0.5*(firstY + oppositeY); 333 double center2X = 0.5*(quarterX + antiquarterX); 334 double center2Y = 0.5*(quarterY + antiquarterY); 335 if (fabs(center1X - center2X) < 1e-5 && fabs(center1Y - center2Y) < 1e-5 && 336 fabs(oppositeY - firstY) < 1e-5 && 337 fabs(quarterX - antiquarterX) < 1e-5) 338 { 339 double major_radius = fabs(firstX - center1X); 340 double minor_radius = fabs(quarterY - center1Y); 341 is_ellipse = TRUE; 342 for(i=0;i<360;i++) 343 { 344 if (!(fabs(center1X + major_radius * cos(i * (M_PI / 180)) - ring->getX(i)) < 1e-5 && 345 fabs(center1Y + minor_radius * sin(i * (M_PI / 180)) - ring->getY(i)) < 1e-5)) 346 { 347 is_ellipse = FALSE; 348 break; 349 } 350 } 351 if ( is_ellipse == TRUE ) 352 { 353 WriteFeatureAttributes(fp, poFeature); 354 VSIFPrintf( fp, "2"); 355 VSIFPrintf( fp, formatCoordinates, partialEol, center1X, center1Y); 356 VSIFPrintf( fp, formatCoordinates, partialEol, major_radius, minor_radius); 357 VSIFPrintf( fp, "%s", eol); 358 } 359 } 360 } 190 361 191 BNA_FreeRecord(record); 362 if ( is_ellipse == FALSE) 363 { 364 int nInteriorRings = polygon->getNumInteriorRings(); 365 for(i=0;i<nInteriorRings;i++) 366 { 367 nBNAPoints += polygon->getInteriorRing(i)->getNumPoints() + 1; 368 } 369 if (nBNAPoints <= 3) 370 { 371 CPLError( CE_Failure, CPLE_AppDefined, "Invalid geometry" ); 372 return OGRERR_FAILURE; 373 } 374 WriteFeatureAttributes(fp, poFeature); 375 VSIFPrintf( fp, "%d", nBNAPoints); 376 n = ring->getNumPoints(); 377 int nbPair = 0; 378 for(i=0;i<n;i++) 379 { 380 VSIFPrintf( fp, formatCoordinates, 381 ((nbPair % nbPairPerLine) == 0) ? partialEol : " ", ring->getX(i), ring->getY(i)); 382 nbPair++; 383 } 384 for(i=0;i<nInteriorRings;i++) 385 { 386 ring = polygon->getInteriorRing(i); 387 n = ring->getNumPoints(); 388 for(j=0;i<n;i++) 389 { 390 VSIFPrintf( fp, formatCoordinates, 391 ((nbPair % nbPairPerLine) == 0) ? partialEol : " ", ring->getX(j), ring->getY(j)); 392 nbPair++; 393 } 394 VSIFPrintf( fp, formatCoordinates, 395 ((nbPair % nbPairPerLine) == 0) ? partialEol : " ", firstX, firstY); 396 nbPair++; 397 } 398 VSIFPrintf( fp, "%s", eol); 399 } 400 break; 401 } 192 402 193 return poFeature; 403 case wkbMultiPolygon: 404 case wkbMultiPolygon25D: 405 { 406 OGRMultiPolygon* multipolygon = (OGRMultiPolygon*)poGeom; 407 int N = multipolygon->getNumGeometries(); 408 int nBNAPoints = 0; 409 double firstX = 0, firstY = 0; 410 for(i=0;i<N;i++) 411 { 412 OGRPolygon* polygon = (OGRPolygon*)multipolygon->getGeometryRef(i); 413 OGRLinearRing* ring = polygon->getExteriorRing(); 414 if (nBNAPoints) 415 nBNAPoints ++; 416 else 417 { 418 firstX = ring->getX(0); 419 firstY = ring->getY(0); 420 } 421 nBNAPoints += ring->getNumPoints(); 422 int nInteriorRings = polygon->getNumInteriorRings(); 423 for(j=0;j<nInteriorRings;j++) 424 { 425 nBNAPoints += polygon->getInteriorRing(j)->getNumPoints() + 1; 426 } 427 } 428 if (nBNAPoints <= 3) 429 { 430 CPLError( CE_Failure, CPLE_AppDefined, "Invalid geometry" ); 431 return OGRERR_FAILURE; 432 } 433 WriteFeatureAttributes(fp, poFeature); 434 VSIFPrintf( fp, "%d", nBNAPoints); 435 int nbPair = 0; 436 for(i=0;i<N;i++) 437 { 438 OGRPolygon* polygon = (OGRPolygon*)multipolygon->getGeometryRef(i); 439 OGRLinearRing* ring = polygon->getExteriorRing(); 440 n = ring->getNumPoints(); 441 int nInteriorRings = polygon->getNumInteriorRings(); 442 for(j=0;j<n;j++) 443 { 444 VSIFPrintf( fp, formatCoordinates, 445 ((nbPair % nbPairPerLine) == 0) ? partialEol : " ",ring->getX(j), ring->getY(j)); 446 nbPair++; 447 } 448 if (i != 0) 449 { 450 VSIFPrintf( fp, formatCoordinates, 451 ((nbPair % nbPairPerLine) == 0) ? partialEol : " ",firstX, firstY); 452 nbPair++; 453 } 454 for(j=0;j<nInteriorRings;j++) 455 { 456 ring = polygon->getInteriorRing(j); 457 n = ring->getNumPoints(); 458 for(k=0;k<n;k++) 459 { 460 VSIFPrintf( fp, formatCoordinates, 461 ((nbPair % nbPairPerLine) == 0) ? partialEol : " ", ring->getX(k), ring->getY(k)); 462 nbPair++; 463 } 464 VSIFPrintf( fp, formatCoordinates, 465 ((nbPair % nbPairPerLine) == 0) ? partialEol : " ", firstX, firstY); 466 nbPair++; 467 } 468 } 469 VSIFPrintf( fp, "%s", eol); 470 break; 471 } 472 473 case wkbLineString: 474 case wkbLineString25D: 475 { 476 OGRLineString* line = (OGRLineString*)poGeom; 477 int n = line->getNumPoints(); 478 int i; 479 if (n < 2) 480 { 481 CPLError( CE_Failure, CPLE_AppDefined, "Invalid geometry" ); 482 return OGRERR_FAILURE; 483 } 484 WriteFeatureAttributes(fp, poFeature); 485 VSIFPrintf( fp, "-%d", n); 486 int nbPair = 0; 487 for(i=0;i<n;i++) 488 { 489 VSIFPrintf( fp, formatCoordinates, 490 ((nbPair % nbPairPerLine) == 0) ? partialEol : " ", line->getX(i), line->getY(i)); 491 nbPair++; 492 } 493 VSIFPrintf( fp, "%s", eol); 494 break; 495 } 496 497 default: 498 { 499 CPLError( CE_Failure, CPLE_AppDefined, 500 "Unsupported geometry type : %s.", 501 poGeom->getGeometryName() ); 502 503 return OGRERR_UNSUPPORTED_GEOMETRY_TYPE; 504 } 505 } 506 507 return OGRERR_NONE; 194 508 } 195 509 510 511 196 512 /************************************************************************/ 197 /* BuildFeatureFromBNARecord()*/513 /* CreateField() */ 198 514 /************************************************************************/ 515 516 OGRErr OGRBNALayer::CreateField( OGRFieldDefn *poField, int bApproxOK ) 517 518 { 519 if( !bWriter || nFeatures != 0) 520 return OGRERR_FAILURE; 521 522 poFeatureDefn->AddFieldDefn( poField ); 523 524 return OGRERR_NONE; 525 } 526 527 /************************************************************************/ 528 /* MakeMultiPolygon() */ 529 /************************************************************************/ 530 531 /* This is indeed of general use and may relate really closely with bug #1217 */ 532 /* If it works correctly, maybe a candidate for upper level exposition */ 533 534 enum 535 { 536 CONTAINS, 537 IS_CONTAINED_BY, 538 NOT_RELATED 539 }; 540 541 static OGRMultiPolygon * MakeMultiPolygon (OGRPolygon** polygons, 542 int nbPolygons, 543 int* pIsValidGeometry) 544 { 545 int i, j; 546 OGRMultiPolygon* multipolygon = new OGRMultiPolygon(); 547 548 if (nbPolygons == 1) 549 { 550 multipolygon->addGeometry(polygons[0]); 551 } 552 else 553 { 554 #ifndef HAVE_GEOS 555 static int firstTime = 1; 556 if (firstTime) 557 { 558 CPLError(CE_Warning, CPLE_AppDefined, 559 "GDAL should be built with GEOS support enabled in order the " 560 "BNA driver to provide reliable results on complex polygons."); 561 firstTime = 0; 562 } 563 #endif 564 565 OGREnvelope* envelopes = new OGREnvelope[nbPolygons]; 566 int** relations = new int*[nbPolygons]; 567 double* areas = new double[nbPolygons]; 568 int go_on = 1; 569 for(i=0;i<nbPolygons;i++) 570 { 571 relations[i] = new int[nbPolygons]; 572 polygons[i]->getEnvelope(&envelopes[i]); 573 areas[i] = polygons[i]->get_Area(); 574 } 575 576 /* This a several step algorithm : 577 1) Compute in a matrix how polygons relate to each other 578 (this is the moment for detecting pathological intersections and exiting) 579 2) For each polygon, find the smallest enclosing polygon 580 3) For each polygon, compute its inclusion depth (0 means toplevel) 581 4) For each polygon of odd depth (= inner ring), add it to its outer ring 582 583 Complexity : O(nbPolygons^2) 584 */ 585 586 /* Compute how each polygon relate to the other ones 587 To save a bit of computation we always begin the computation by a test on the 588 enveloppe. We also take into account the areas to avoid some useless tests. 589 (A contains B implies envelop(A) contains envelop(B) and area(A) > area(B)) 590 In practise, we can hope that few full geometry intersection of inclusion test is done: 591 * if the polygons are well separated geographically 592 (a set of islands for example), no full geometry intersection or inclusion 593 test is done. (the envelopes don't intersect each other) 594 * if the polygons are 'lake inside an island inside a lake inside an area' and 595 that each polygon is much smaller than its enclosing one, their bounding boxes 596 are stricly contained into each oter, and thus, no full geometry intersection or inclusion 597 test is done 598 */ 599 for(i=0;go_on && i<nbPolygons;i++) 600 { 601 for(j=i+1;go_on && j<nbPolygons;j++) 602 { 603 if (envelopes[i].Contains(envelopes[j]) 604 && areas[i] > areas[j] 605 #ifdef HAVE_GEOS 606 && polygons[i]->Contains(polygons[j]) 607 #endif 608 ) 609 { 610 relations[i][j] = CONTAINS; 611 relations[j][i] = IS_CONTAINED_BY; 612 } 613 else if (envelopes[j].Contains(envelopes[i]) 614 && areas[j] > areas[i] 615 #ifdef HAVE_GEOS 616 && polygons[j]->Contains(polygons[i]) 617 #endif 618 ) 619 { 620 relations[j][i] = CONTAINS; 621 rela
