1.. _vector_api_tut: 2 3================================================================================ 4Vector API tutorial 5================================================================================ 6 7This document is intended to document using the OGR C++ classes to read 8and write data from a file. It is strongly advised that the reader first 9review the :ref:`vector_data_model` document describing 10the key classes and their roles in OGR. 11 12It also includes code snippets for the corresponding functions in C and Python. 13 14Reading From OGR 15---------------- 16 17For purposes of demonstrating reading with OGR, we will construct a small 18utility for dumping point layers from an OGR data source to stdout in 19comma-delimited format. 20 21Initially it is necessary to register all the format drivers that are desired. 22This is normally accomplished by calling :cpp:func:`GDALAllRegister` which registers 23all format drivers built into GDAL/OGR. 24 25In C++ : 26 27.. code-block:: c++ 28 29 #include "ogrsf_frmts.h" 30 31 int main() 32 33 { 34 GDALAllRegister(); 35 36 37In C : 38 39.. code-block:: c 40 41 #include "gdal.h" 42 43 int main() 44 45 { 46 GDALAllRegister(); 47 48Next we need to open the input OGR datasource. Datasources can be files, 49RDBMSes, directories full of files, or even remote web services depending on 50the driver being used. However, the datasource name is always a single 51string. In this case we are hardcoded to open a particular shapefile. 52The second argument (GDAL_OF_VECTOR) tells the :cpp:func:`OGROpen` method 53that we want a vector driver to be use and that don't require update access. 54On failure NULL is returned, and 55we report an error. 56 57In C++ : 58 59.. code-block:: c++ 60 61 GDALDataset *poDS; 62 63 poDS = (GDALDataset*) GDALOpenEx( "point.shp", GDAL_OF_VECTOR, NULL, NULL, NULL ); 64 if( poDS == NULL ) 65 { 66 printf( "Open failed.\n" ); 67 exit( 1 ); 68 } 69 70In C : 71 72.. code-block:: c 73 74 GDALDatasetH hDS; 75 76 hDS = GDALOpenEx( "point.shp", GDAL_OF_VECTOR, NULL, NULL, NULL ); 77 if( hDS == NULL ) 78 { 79 printf( "Open failed.\n" ); 80 exit( 1 ); 81 } 82 83A GDALDataset can potentially have many layers associated with it. The 84number of layers available can be queried with :cpp:func:`GDALDataset::GetLayerCount` 85and individual layers fetched by index using :cpp:func:`GDALDataset::GetLayer`. 86However, we will just fetch the layer by name. 87 88In C++ : 89 90.. code-block:: c++ 91 92 OGRLayer *poLayer; 93 94 poLayer = poDS->GetLayerByName( "point" ); 95 96In C : 97 98.. code-block:: c 99 100 OGRLayerH hLayer; 101 102 hLayer = GDALDatasetGetLayerByName( hDS, "point" ); 103 104 105Now we want to start reading features from the layer. Before we start we 106could assign an attribute or spatial filter to the layer to restrict the set 107of feature we get back, but for now we are interested in getting all features. 108 109With GDAL 2.3 and C++11: 110 111.. code-block:: c++ 112 113 for( auto& poFeature: poLayer ) 114 { 115 116With GDAL 2.3 and C: 117 118.. code-block:: c 119 120 OGR_FOR_EACH_FEATURE_BEGIN(hFeature, hLayer) 121 { 122 123If using older GDAL versions, while it isn't strictly necessary in this 124circumstance since we are starting fresh with the layer, it is often wise 125to call :cpp:func:`OGRLayer::ResetReading` to ensure we are starting at the beginning of 126the layer. We iterate through all the features in the layer using 127OGRLayer::GetNextFeature(). It will return NULL when we run out of features. 128 129With GDAL < 2.3 and C++ : 130 131.. code-block:: c++ 132 133 OGRFeature *poFeature; 134 135 poLayer->ResetReading(); 136 while( (poFeature = poLayer->GetNextFeature()) != NULL ) 137 { 138 139 140With GDAL < 2.3 and C : 141 142.. code-block:: c 143 144 OGRFeatureH hFeature; 145 146 OGR_L_ResetReading(hLayer); 147 while( (hFeature = OGR_L_GetNextFeature(hLayer)) != NULL ) 148 { 149 150In order to dump all the attribute fields of the feature, it is helpful 151to get the :cpp:class:`OGRFeatureDefn`. This is an object, associated with the layer, 152containing the definitions of all the fields. We loop over all the fields, 153and fetch and report the attributes based on their type. 154 155With GDAL 2.3 and C++11: 156 157.. code-block:: c++ 158 159 for( auto&& oField: *poFeature ) 160 { 161 switch( oField.GetType() ) 162 { 163 case OFTInteger: 164 printf( "%d,", oField.GetInteger() ); 165 break; 166 case OFTInteger64: 167 printf( CPL_FRMT_GIB ",", oField.GetInteger64() ); 168 break; 169 case OFTReal: 170 printf( "%.3f,", oField.GetDouble() ); 171 break; 172 case OFTString: 173 printf( "%s,", oField.GetString() ); 174 break; 175 default: 176 printf( "%s,", oField.GetAsString() ); 177 break; 178 } 179 } 180 181With GDAL < 2.3 and C++ : 182 183.. code-block:: c 184 185 OGRFeatureDefn *poFDefn = poLayer->GetLayerDefn(); 186 for( int iField = 0; iField < poFDefn->GetFieldCount(); iField++ ) 187 { 188 OGRFieldDefn *poFieldDefn = poFDefn->GetFieldDefn( iField ); 189 190 switch( poFieldDefn->GetType() ) 191 { 192 case OFTInteger: 193 printf( "%d,", poFeature->GetFieldAsInteger( iField ) ); 194 break; 195 case OFTInteger64: 196 printf( CPL_FRMT_GIB ",", poFeature->GetFieldAsInteger64( iField ) ); 197 break; 198 case OFTReal: 199 printf( "%.3f,", poFeature->GetFieldAsDouble(iField) ); 200 break; 201 case OFTString: 202 printf( "%s,", poFeature->GetFieldAsString(iField) ); 203 break; 204 default: 205 printf( "%s,", poFeature->GetFieldAsString(iField) ); 206 break; 207 } 208 } 209 210In C : 211 212.. code-block:: c 213 214 OGRFeatureDefnH hFDefn = OGR_L_GetLayerDefn(hLayer); 215 int iField; 216 217 for( iField = 0; iField < OGR_FD_GetFieldCount(hFDefn); iField++ ) 218 { 219 OGRFieldDefnH hFieldDefn = OGR_FD_GetFieldDefn( hFDefn, iField ); 220 221 switch( OGR_Fld_GetType(hFieldDefn) ) 222 { 223 case OFTInteger: 224 printf( "%d,", OGR_F_GetFieldAsInteger( hFeature, iField ) ); 225 break; 226 case OFTInteger64: 227 printf( CPL_FRMT_GIB ",", OGR_F_GetFieldAsInteger64( hFeature, iField ) ); 228 break; 229 case OFTReal: 230 printf( "%.3f,", OGR_F_GetFieldAsDouble( hFeature, iField) ); 231 break; 232 case OFTString: 233 printf( "%s,", OGR_F_GetFieldAsString( hFeature, iField) ); 234 break; 235 default: 236 printf( "%s,", OGR_F_GetFieldAsString( hFeature, iField) ); 237 break; 238 } 239 } 240 241There are a few more field types than those explicitly handled above, but 242a reasonable representation of them can be fetched with the 243:cpp:func:`OGRFeature::GetFieldAsString` method. In fact we could shorten the above 244by using GetFieldAsString() for all the types. 245 246Next we want to extract the geometry from the feature, and write out the point 247geometry x and y. Geometries are returned as a generic :cpp:class:`OGRGeometry` pointer. 248We then determine the specific geometry type, and if it is a point, we 249cast it to point and operate on it. If it is something else we write 250placeholders. 251 252In C++ : 253 254.. code-block:: c++ 255 256 OGRGeometry *poGeometry; 257 258 poGeometry = poFeature->GetGeometryRef(); 259 if( poGeometry != NULL 260 && wkbFlatten(poGeometry->getGeometryType()) == wkbPoint ) 261 { 262 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,3,0) 263 OGRPoint *poPoint = poGeometry->toPoint(); 264 #else 265 OGRPoint *poPoint = (OGRPoint *) poGeometry; 266 #endif 267 268 printf( "%.3f,%3.f\n", poPoint->getX(), poPoint->getY() ); 269 } 270 else 271 { 272 printf( "no point geometry\n" ); 273 } 274 275In C : 276 277.. code-block:: c 278 279 OGRGeometryH hGeometry; 280 281 hGeometry = OGR_F_GetGeometryRef(hFeature); 282 if( hGeometry != NULL 283 && wkbFlatten(OGR_G_GetGeometryType(hGeometry)) == wkbPoint ) 284 { 285 printf( "%.3f,%3.f\n", OGR_G_GetX(hGeometry, 0), OGR_G_GetY(hGeometry, 0) ); 286 } 287 else 288 { 289 printf( "no point geometry\n" ); 290 } 291 292The :cpp:func:`wkbFlatten` macro is used above to convert the type for a wkbPoint25D 293(a point with a z coordinate) into the base 2D geometry type code (wkbPoint). 294For each 2D geometry type there is a corresponding 2.5D type code. The 2D 295and 2.5D geometry cases are handled by the same C++ class, so our code will 296handle 2D or 3D cases properly. 297 298Several geometry fields can be associated to a feature. 299 300In C++ : 301 302.. code-block:: c++ 303 304 OGRGeometry *poGeometry; 305 int iGeomField; 306 int nGeomFieldCount; 307 308 nGeomFieldCount = poFeature->GetGeomFieldCount(); 309 for(iGeomField = 0; iGeomField < nGeomFieldCount; iGeomField ++ ) 310 { 311 poGeometry = poFeature->GetGeomFieldRef(iGeomField); 312 if( poGeometry != NULL 313 && wkbFlatten(poGeometry->getGeometryType()) == wkbPoint ) 314 { 315 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,3,0) 316 OGRPoint *poPoint = poGeometry->toPoint(); 317 #else 318 OGRPoint *poPoint = (OGRPoint *) poGeometry; 319 #endif 320 321 printf( "%.3f,%3.f\n", poPoint->getX(), poPoint->getY() ); 322 } 323 else 324 { 325 printf( "no point geometry\n" ); 326 } 327 } 328 329 330In C : 331 332.. code-block:: c 333 334 OGRGeometryH hGeometry; 335 int iGeomField; 336 int nGeomFieldCount; 337 338 nGeomFieldCount = OGR_F_GetGeomFieldCount(hFeature); 339 for(iGeomField = 0; iGeomField < nGeomFieldCount; iGeomField ++ ) 340 { 341 hGeometry = OGR_F_GetGeomFieldRef(hFeature, iGeomField); 342 if( hGeometry != NULL 343 && wkbFlatten(OGR_G_GetGeometryType(hGeometry)) == wkbPoint ) 344 { 345 printf( "%.3f,%3.f\n", OGR_G_GetX(hGeometry, 0), 346 OGR_G_GetY(hGeometry, 0) ); 347 } 348 else 349 { 350 printf( "no point geometry\n" ); 351 } 352 } 353 354 355In Python: 356 357.. code-block:: python 358 359 nGeomFieldCount = feat.GetGeomFieldCount() 360 for iGeomField in range(nGeomFieldCount): 361 geom = feat.GetGeomFieldRef(iGeomField) 362 if geom is not None and geom.GetGeometryType() == ogr.wkbPoint: 363 print "%.3f, %.3f" % ( geom.GetX(), geom.GetY() ) 364 else: 365 print "no point geometry\n" 366 367Note that :cpp:func:`OGRFeature::GetGeometryRef` and :cpp:func:`OGRFeature::GetGeomFieldRef` 368return a pointer to 369the internal geometry owned by the OGRFeature. There we don't actually 370delete the return geometry. 371 372 373With GDAL 2.3 and C++11, the looping over features is simply terminated by 374a closing curly bracket. 375 376.. code-block:: c++ 377 378 } 379 380With GDAL 2.3 and C, the looping over features is simply terminated by 381the following. 382 383.. code-block:: c 384 385 } 386 OGR_FOR_EACH_FEATURE_END(hFeature) 387 388 389For GDAL < 2.3, as the :cpp:func:`OGRLayer::GetNextFeature` method 390returns a copy of the feature that is now owned by us. So at the end of 391use we must free the feature. We could just "delete" it, but this can cause 392problems in windows builds where the GDAL DLL has a different "heap" from the 393main program. To be on the safe side we use a GDAL function to delete the 394feature. 395 396In C++ : 397 398.. code-block:: c++ 399 400 OGRFeature::DestroyFeature( poFeature ); 401 } 402 403In C : 404 405.. code-block:: c 406 407 OGR_F_Destroy( hFeature ); 408 } 409 410 411The OGRLayer returned by :cpp:func:`GDALDataset::GetLayerByName` is also a reference 412to an internal layer owned by the GDALDataset so we don't need to delete 413it. But we do need to delete the datasource in order to close the input file. 414Once again we do this with a custom delete method to avoid special win32 415heap issues. 416 417In C/C++ : 418 419.. code-block:: c++ 420 421 GDALClose( poDS ); 422 } 423 424 425All together our program looks like this. 426 427With GDAL 2.3 and C++11 : 428 429.. code-block:: c++ 430 431 #include "ogrsf_frmts.h" 432 433 int main() 434 435 { 436 GDALAllRegister(); 437 438 GDALDatasetUniquePtr poDS(GDALDataset::Open( "point.shp", GDAL_OF_VECTOR)); 439 if( poDS == nullptr ) 440 { 441 printf( "Open failed.\n" ); 442 exit( 1 ); 443 } 444 445 for( const OGRLayer* poLayer: poDS->GetLayers() ) 446 { 447 for( const auto& poFeature: *poLayer ) 448 { 449 for( const auto& oField: *poFeature ) 450 { 451 switch( oField.GetType() ) 452 { 453 case OFTInteger: 454 printf( "%d,", oField.GetInteger() ); 455 break; 456 case OFTInteger64: 457 printf( CPL_FRMT_GIB ",", oField.GetInteger64() ); 458 break; 459 case OFTReal: 460 printf( "%.3f,", oField.GetDouble() ); 461 break; 462 case OFTString: 463 printf( "%s,", oField.GetString() ); 464 break; 465 default: 466 printf( "%s,", oField.GetAsString() ); 467 break; 468 } 469 } 470 471 const OGRGeometry *poGeometry = poFeature->GetGeometryRef(); 472 if( poGeometry != nullptr 473 && wkbFlatten(poGeometry->getGeometryType()) == wkbPoint ) 474 { 475 const OGRPoint *poPoint = poGeometry->toPoint(); 476 477 printf( "%.3f,%3.f\n", poPoint->getX(), poPoint->getY() ); 478 } 479 else 480 { 481 printf( "no point geometry\n" ); 482 } 483 } 484 } 485 return 0; 486 } 487 488In C++ : 489 490.. code-block:: c++ 491 492 #include "ogrsf_frmts.h" 493 494 int main() 495 496 { 497 GDALAllRegister(); 498 499 GDALDataset *poDS = static_cast<GDALDataset*>( 500 GDALOpenEx( "point.shp", GDAL_OF_VECTOR, NULL, NULL, NULL )); 501 if( poDS == NULL ) 502 { 503 printf( "Open failed.\n" ); 504 exit( 1 ); 505 } 506 507 OGRLayer *poLayer = poDS->GetLayerByName( "point" ); 508 OGRFeatureDefn *poFDefn = poLayer->GetLayerDefn(); 509 510 poLayer->ResetReading(); 511 OGRFeature *poFeature; 512 while( (poFeature = poLayer->GetNextFeature()) != NULL ) 513 { 514 for( int iField = 0; iField < poFDefn->GetFieldCount(); iField++ ) 515 { 516 OGRFieldDefn *poFieldDefn = poFDefn->GetFieldDefn( iField ); 517 518 switch( poFieldDefn->GetType() ) 519 { 520 case OFTInteger: 521 printf( "%d,", poFeature->GetFieldAsInteger( iField ) ); 522 break; 523 case OFTInteger64: 524 printf( CPL_FRMT_GIB ",", poFeature->GetFieldAsInteger64( iField ) ); 525 break; 526 case OFTReal: 527 printf( "%.3f,", poFeature->GetFieldAsDouble(iField) ); 528 break; 529 case OFTString: 530 printf( "%s,", poFeature->GetFieldAsString(iField) ); 531 break; 532 default: 533 printf( "%s,", poFeature->GetFieldAsString(iField) ); 534 break; 535 } 536 } 537 538 OGRGeometry *poGeometry = poFeature->GetGeometryRef(); 539 if( poGeometry != NULL 540 && wkbFlatten(poGeometry->getGeometryType()) == wkbPoint ) 541 { 542 OGRPoint *poPoint = (OGRPoint *) poGeometry; 543 544 printf( "%.3f,%3.f\n", poPoint->getX(), poPoint->getY() ); 545 } 546 else 547 { 548 printf( "no point geometry\n" ); 549 } 550 OGRFeature::DestroyFeature( poFeature ); 551 } 552 553 GDALClose( poDS ); 554 } 555 556In C : 557 558.. code-block:: c 559 560 #include "gdal.h" 561 562 int main() 563 564 { 565 GDALAllRegister(); 566 567 GDALDatasetH hDS; 568 OGRLayerH hLayer; 569 OGRFeatureH hFeature; 570 OGRFeatureDefnH hFDefn; 571 572 hDS = GDALOpenEx( "point.shp", GDAL_OF_VECTOR, NULL, NULL, NULL ); 573 if( hDS == NULL ) 574 { 575 printf( "Open failed.\n" ); 576 exit( 1 ); 577 } 578 579 hLayer = GDALDatasetGetLayerByName( hDS, "point" ); 580 hFDefn = OGR_L_GetLayerDefn(hLayer); 581 582 OGR_L_ResetReading(hLayer); 583 while( (hFeature = OGR_L_GetNextFeature(hLayer)) != NULL ) 584 { 585 int iField; 586 OGRGeometryH hGeometry; 587 588 for( iField = 0; iField < OGR_FD_GetFieldCount(hFDefn); iField++ ) 589 { 590 OGRFieldDefnH hFieldDefn = OGR_FD_GetFieldDefn( hFDefn, iField ); 591 592 switch( OGR_Fld_GetType(hFieldDefn) ) 593 { 594 case OFTInteger: 595 printf( "%d,", OGR_F_GetFieldAsInteger( hFeature, iField ) ); 596 break; 597 case OFTInteger64: 598 printf( CPL_FRMT_GIB ",", OGR_F_GetFieldAsInteger64( hFeature, iField ) ); 599 break; 600 case OFTReal: 601 printf( "%.3f,", OGR_F_GetFieldAsDouble( hFeature, iField) ); 602 break; 603 case OFTString: 604 printf( "%s,", OGR_F_GetFieldAsString( hFeature, iField) ); 605 break; 606 default: 607 printf( "%s,", OGR_F_GetFieldAsString( hFeature, iField) ); 608 break; 609 } 610 } 611 612 hGeometry = OGR_F_GetGeometryRef(hFeature); 613 if( hGeometry != NULL 614 && wkbFlatten(OGR_G_GetGeometryType(hGeometry)) == wkbPoint ) 615 { 616 printf( "%.3f,%3.f\n", OGR_G_GetX(hGeometry, 0), OGR_G_GetY(hGeometry, 0) ); 617 } 618 else 619 { 620 printf( "no point geometry\n" ); 621 } 622 623 OGR_F_Destroy( hFeature ); 624 } 625 626 GDALClose( hDS ); 627 } 628 629 630In Python: 631 632.. code-block:: python 633 634 import sys 635 from osgeo import gdal 636 637 ds = gdal.OpenEx( "point.shp", gdal.OF_VECTOR ) 638 if ds is None: 639 print "Open failed.\n" 640 sys.exit( 1 ) 641 642 lyr = ds.GetLayerByName( "point" ) 643 644 lyr.ResetReading() 645 646 for feat in lyr: 647 648 feat_defn = lyr.GetLayerDefn() 649 for i in range(feat_defn.GetFieldCount()): 650 field_defn = feat_defn.GetFieldDefn(i) 651 652 # Tests below can be simplified with just : 653 # print feat.GetField(i) 654 if field_defn.GetType() == ogr.OFTInteger or field_defn.GetType() == ogr.OFTInteger64: 655 print "%d" % feat.GetFieldAsInteger64(i) 656 elif field_defn.GetType() == ogr.OFTReal: 657 print "%.3f" % feat.GetFieldAsDouble(i) 658 elif field_defn.GetType() == ogr.OFTString: 659 print "%s" % feat.GetFieldAsString(i) 660 else: 661 print "%s" % feat.GetFieldAsString(i) 662 663 geom = feat.GetGeometryRef() 664 if geom is not None and geom.GetGeometryType() == ogr.wkbPoint: 665 print "%.3f, %.3f" % ( geom.GetX(), geom.GetY() ) 666 else: 667 print "no point geometry\n" 668 669 ds = None 670 671Writing To OGR 672-------------- 673 674As an example of writing through OGR, we will do roughly the opposite of the 675above. A short program that reads comma separated values from input text 676will be written to a point shapefile via OGR. 677 678As usual, we start by registering all the drivers, and then fetch the 679Shapefile driver as we will need it to create our output file. 680 681In C++ : 682 683.. code-block:: c++ 684 685 #include "ogrsf_frmts.h" 686 687 int main() 688 { 689 const char *pszDriverName = "ESRI Shapefile"; 690 GDALDriver *poDriver; 691 692 GDALAllRegister(); 693 694 poDriver = GetGDALDriverManager()->GetDriverByName(pszDriverName ); 695 if( poDriver == NULL ) 696 { 697 printf( "%s driver not available.\n", pszDriverName ); 698 exit( 1 ); 699 } 700 701In C : 702 703.. code-block:: c 704 705 #include "ogr_api.h" 706 707 int main() 708 { 709 const char *pszDriverName = "ESRI Shapefile"; 710 GDALDriver *poDriver; 711 712 GDALAllRegister(); 713 714 poDriver = (GDALDriver*) GDALGetDriverByName(pszDriverName ); 715 if( poDriver == NULL ) 716 { 717 printf( "%s driver not available.\n", pszDriverName ); 718 exit( 1 ); 719 } 720 721Next we create the datasource. The ESRI Shapefile driver allows us to create 722a directory full of shapefiles, or a single shapefile as a datasource. In 723this case we will explicitly create a single file by including the extension 724in the name. Other drivers behave differently. 725The second, third, fourth and fifth argument are related to raster dimensions 726(in case the driver has raster capabilities). The last argument to 727the call is a list of option values, but we will just be using defaults in 728this case. Details of the options supported are also format specific. 729 730In C ++ : 731 732.. code-block:: c++ 733 734 GDALDataset *poDS; 735 736 poDS = poDriver->Create( "point_out.shp", 0, 0, 0, GDT_Unknown, NULL ); 737 if( poDS == NULL ) 738 { 739 printf( "Creation of output file failed.\n" ); 740 exit( 1 ); 741 } 742 743 744In C : 745 746.. code-block:: c 747 748 GDALDatasetH hDS; 749 750 hDS = GDALCreate( hDriver, "point_out.shp", 0, 0, 0, GDT_Unknown, NULL ); 751 if( hDS == NULL ) 752 { 753 printf( "Creation of output file failed.\n" ); 754 exit( 1 ); 755 } 756 757Now we create the output layer. In this case since the datasource is a 758single file, we can only have one layer. We pass wkbPoint to specify the 759type of geometry supported by this layer. In this case we aren't passing 760any coordinate system information or other special layer creation options. 761 762In C++ : 763 764.. code-block:: c++ 765 766 OGRLayer *poLayer; 767 768 poLayer = poDS->CreateLayer( "point_out", NULL, wkbPoint, NULL ); 769 if( poLayer == NULL ) 770 { 771 printf( "Layer creation failed.\n" ); 772 exit( 1 ); 773 } 774 775 776In C : 777 778.. code-block:: c 779 780 OGRLayerH hLayer; 781 782 hLayer = GDALDatasetCreateLayer( hDS, "point_out", NULL, wkbPoint, NULL ); 783 if( hLayer == NULL ) 784 { 785 printf( "Layer creation failed.\n" ); 786 exit( 1 ); 787 } 788 789 790Now that the layer exists, we need to create any attribute fields that should 791appear on the layer. Fields must be added to the layer before any features 792are written. To create a field we initialize an :cpp:union:`OGRField` object with the 793information about the field. In the case of Shapefiles, the field width and 794precision is significant in the creation of the output .dbf file, so we 795set it specifically, though generally the defaults are OK. For this example 796we will just have one attribute, a name string associated with the x,y point. 797 798Note that the template OGRField we pass to :cpp:func:`OGRLayer::CreateField` is copied internally. 799We retain ownership of the object. 800 801In C++: 802 803.. code-block:: c++ 804 805 OGRFieldDefn oField( "Name", OFTString ); 806 807 oField.SetWidth(32); 808 809 if( poLayer->CreateField( &oField ) != OGRERR_NONE ) 810 { 811 printf( "Creating Name field failed.\n" ); 812 exit( 1 ); 813 } 814 815 816In C: 817 818.. code-block:: c 819 820 OGRFieldDefnH hFieldDefn; 821 822 hFieldDefn = OGR_Fld_Create( "Name", OFTString ); 823 824 OGR_Fld_SetWidth( hFieldDefn, 32); 825 826 if( OGR_L_CreateField( hLayer, hFieldDefn, TRUE ) != OGRERR_NONE ) 827 { 828 printf( "Creating Name field failed.\n" ); 829 exit( 1 ); 830 } 831 832 OGR_Fld_Destroy(hFieldDefn); 833 834 835The following snipping loops reading lines of the form "x,y,name" from stdin, 836and parsing them. 837 838In C++ and in C : 839 840.. code-block:: c 841 842 double x, y; 843 char szName[33]; 844 845 while( !feof(stdin) 846 && fscanf( stdin, "%lf,%lf,%32s", &x, &y, szName ) == 3 ) 847 { 848 849To write a feature to disk, we must create a local OGRFeature, set attributes 850and attach geometry before trying to write it to the layer. It is 851imperative that this feature be instantiated from the OGRFeatureDefn 852associated with the layer it will be written to. 853 854In C++ : 855 856.. code-block:: c++ 857 858 OGRFeature *poFeature; 859 860 poFeature = OGRFeature::CreateFeature( poLayer->GetLayerDefn() ); 861 poFeature->SetField( "Name", szName ); 862 863In C : 864 865.. code-block:: c 866 867 OGRFeatureH hFeature; 868 869 hFeature = OGR_F_Create( OGR_L_GetLayerDefn( hLayer ) ); 870 OGR_F_SetFieldString( hFeature, OGR_F_GetFieldIndex(hFeature, "Name"), szName ); 871 872We create a local geometry object, and assign its copy (indirectly) to the feature. 873The :cpp:func:`OGRFeature::SetGeometryDirectly` differs from :cpp:func:`OGRFeature::SetGeometry` 874in that the direct method gives ownership of the geometry to the feature. 875This is generally more efficient as it avoids an extra deep object copy 876of the geometry. 877 878In C++ : 879 880.. code-block:: c++ 881 882 OGRPoint pt; 883 pt.setX( x ); 884 pt.setY( y ); 885 886 poFeature->SetGeometry( &pt ); 887 888 889In C : 890 891.. code-block:: c 892 893 OGRGeometryH hPt; 894 hPt = OGR_G_CreateGeometry(wkbPoint); 895 OGR_G_SetPoint_2D(hPt, 0, x, y); 896 897 OGR_F_SetGeometry( hFeature, hPt ); 898 OGR_G_DestroyGeometry(hPt); 899 900 901Now we create a feature in the file. The :cpp:func:`OGRLayer::CreateFeature` does not 902take ownership of our feature so we clean it up when done with it. 903 904In C++ : 905 906.. code-block:: c++ 907 908 if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE ) 909 { 910 printf( "Failed to create feature in shapefile.\n" ); 911 exit( 1 ); 912 } 913 914 OGRFeature::DestroyFeature( poFeature ); 915 } 916 917In C : 918 919.. code-block:: c 920 921 if( OGR_L_CreateFeature( hLayer, hFeature ) != OGRERR_NONE ) 922 { 923 printf( "Failed to create feature in shapefile.\n" ); 924 exit( 1 ); 925 } 926 927 OGR_F_Destroy( hFeature ); 928 } 929 930 931Finally we need to close down the datasource in order to ensure headers 932are written out in an orderly way and all resources are recovered. 933 934In C/C++ : 935 936.. code-block:: c 937 938 GDALClose( poDS ); 939 } 940 941 942The same program all in one block looks like this: 943 944In C++ : 945 946.. code-block:: c++ 947 948 #include "ogrsf_frmts.h" 949 950 int main() 951 { 952 const char *pszDriverName = "ESRI Shapefile"; 953 GDALDriver *poDriver; 954 955 GDALAllRegister(); 956 957 poDriver = GetGDALDriverManager()->GetDriverByName(pszDriverName ); 958 if( poDriver == NULL ) 959 { 960 printf( "%s driver not available.\n", pszDriverName ); 961 exit( 1 ); 962 } 963 964 GDALDataset *poDS; 965 966 poDS = poDriver->Create( "point_out.shp", 0, 0, 0, GDT_Unknown, NULL ); 967 if( poDS == NULL ) 968 { 969 printf( "Creation of output file failed.\n" ); 970 exit( 1 ); 971 } 972 973 OGRLayer *poLayer; 974 975 poLayer = poDS->CreateLayer( "point_out", NULL, wkbPoint, NULL ); 976 if( poLayer == NULL ) 977 { 978 printf( "Layer creation failed.\n" ); 979 exit( 1 ); 980 } 981 982 OGRFieldDefn oField( "Name", OFTString ); 983 984 oField.SetWidth(32); 985 986 if( poLayer->CreateField( &oField ) != OGRERR_NONE ) 987 { 988 printf( "Creating Name field failed.\n" ); 989 exit( 1 ); 990 } 991 992 double x, y; 993 char szName[33]; 994 995 while( !feof(stdin) 996 && fscanf( stdin, "%lf,%lf,%32s", &x, &y, szName ) == 3 ) 997 { 998 OGRFeature *poFeature; 999 1000 poFeature = OGRFeature::CreateFeature( poLayer->GetLayerDefn() ); 1001 poFeature->SetField( "Name", szName ); 1002 1003 OGRPoint pt; 1004 1005 pt.setX( x ); 1006 pt.setY( y ); 1007 1008 poFeature->SetGeometry( &pt ); 1009 1010 if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE ) 1011 { 1012 printf( "Failed to create feature in shapefile.\n" ); 1013 exit( 1 ); 1014 } 1015 1016 OGRFeature::DestroyFeature( poFeature ); 1017 } 1018 1019 GDALClose( poDS ); 1020 } 1021 1022 1023In C : 1024 1025.. code-block:: c 1026 1027 #include "gdal.h" 1028 1029 int main() 1030 { 1031 const char *pszDriverName = "ESRI Shapefile"; 1032 GDALDriverH hDriver; 1033 GDALDatasetH hDS; 1034 OGRLayerH hLayer; 1035 OGRFieldDefnH hFieldDefn; 1036 double x, y; 1037 char szName[33]; 1038 1039 GDALAllRegister(); 1040 1041 hDriver = GDALGetDriverByName( pszDriverName ); 1042 if( hDriver == NULL ) 1043 { 1044 printf( "%s driver not available.\n", pszDriverName ); 1045 exit( 1 ); 1046 } 1047 1048 hDS = GDALCreate( hDriver, "point_out.shp", 0, 0, 0, GDT_Unknown, NULL ); 1049 if( hDS == NULL ) 1050 { 1051 printf( "Creation of output file failed.\n" ); 1052 exit( 1 ); 1053 } 1054 1055 hLayer = GDALDatasetCreateLayer( hDS, "point_out", NULL, wkbPoint, NULL ); 1056 if( hLayer == NULL ) 1057 { 1058 printf( "Layer creation failed.\n" ); 1059 exit( 1 ); 1060 } 1061 1062 hFieldDefn = OGR_Fld_Create( "Name", OFTString ); 1063 1064 OGR_Fld_SetWidth( hFieldDefn, 32); 1065 1066 if( OGR_L_CreateField( hLayer, hFieldDefn, TRUE ) != OGRERR_NONE ) 1067 { 1068 printf( "Creating Name field failed.\n" ); 1069 exit( 1 ); 1070 } 1071 1072 OGR_Fld_Destroy(hFieldDefn); 1073 1074 while( !feof(stdin) 1075 && fscanf( stdin, "%lf,%lf,%32s", &x, &y, szName ) == 3 ) 1076 { 1077 OGRFeatureH hFeature; 1078 OGRGeometryH hPt; 1079 1080 hFeature = OGR_F_Create( OGR_L_GetLayerDefn( hLayer ) ); 1081 OGR_F_SetFieldString( hFeature, OGR_F_GetFieldIndex(hFeature, "Name"), szName ); 1082 1083 hPt = OGR_G_CreateGeometry(wkbPoint); 1084 OGR_G_SetPoint_2D(hPt, 0, x, y); 1085 1086 OGR_F_SetGeometry( hFeature, hPt ); 1087 OGR_G_DestroyGeometry(hPt); 1088 1089 if( OGR_L_CreateFeature( hLayer, hFeature ) != OGRERR_NONE ) 1090 { 1091 printf( "Failed to create feature in shapefile.\n" ); 1092 exit( 1 ); 1093 } 1094 1095 OGR_F_Destroy( hFeature ); 1096 } 1097 1098 GDALClose( hDS ); 1099 } 1100 1101 1102In Python : 1103 1104.. code-block:: python 1105 1106 import sys 1107 from osgeo import gdal 1108 from osgeo import ogr 1109 import string 1110 1111 driverName = "ESRI Shapefile" 1112 drv = gdal.GetDriverByName( driverName ) 1113 if drv is None: 1114 print "%s driver not available.\n" % driverName 1115 sys.exit( 1 ) 1116 1117 ds = drv.Create( "point_out.shp", 0, 0, 0, gdal.GDT_Unknown ) 1118 if ds is None: 1119 print "Creation of output file failed.\n" 1120 sys.exit( 1 ) 1121 1122 lyr = ds.CreateLayer( "point_out", None, ogr.wkbPoint ) 1123 if lyr is None: 1124 print "Layer creation failed.\n" 1125 sys.exit( 1 ) 1126 1127 field_defn = ogr.FieldDefn( "Name", ogr.OFTString ) 1128 field_defn.SetWidth( 32 ) 1129 1130 if lyr.CreateField ( field_defn ) != 0: 1131 print "Creating Name field failed.\n" 1132 sys.exit( 1 ) 1133 1134 # Expected format of user input: x y name 1135 linestring = raw_input() 1136 linelist = string.split(linestring) 1137 1138 while len(linelist) == 3: 1139 x = float(linelist[0]) 1140 y = float(linelist[1]) 1141 name = linelist[2] 1142 1143 feat = ogr.Feature( lyr.GetLayerDefn()) 1144 feat.SetField( "Name", name ) 1145 1146 pt = ogr.Geometry(ogr.wkbPoint) 1147 pt.SetPoint_2D(0, x, y) 1148 1149 feat.SetGeometry(pt) 1150 1151 if lyr.CreateFeature(feat) != 0: 1152 print "Failed to create feature in shapefile.\n" 1153 sys.exit( 1 ) 1154 1155 feat.Destroy() 1156 1157 linestring = raw_input() 1158 linelist = string.split(linestring) 1159 1160 ds = None 1161 1162 1163Several geometry fields can be associated to a feature. This capability 1164is just available for a few file formats, such as PostGIS. 1165 1166To create such datasources, geometry fields must be first created. 1167Spatial reference system objects can be associated to each geometry field. 1168 1169In C++ : 1170 1171.. code-block:: c++ 1172 1173 OGRGeomFieldDefn oPointField( "PointField", wkbPoint ); 1174 OGRSpatialReference* poSRS = new OGRSpatialReference(); 1175 poSRS->importFromEPSG(4326); 1176 oPointField.SetSpatialRef(poSRS); 1177 poSRS->Release(); 1178 1179 if( poLayer->CreateGeomField( &oPointField ) != OGRERR_NONE ) 1180 { 1181 printf( "Creating field PointField failed.\n" ); 1182 exit( 1 ); 1183 } 1184 1185 OGRGeomFieldDefn oFieldPoint2( "PointField2", wkbPoint ); 1186 poSRS = new OGRSpatialReference(); 1187 poSRS->importFromEPSG(32631); 1188 oPointField2.SetSpatialRef(poSRS); 1189 poSRS->Release(); 1190 1191 if( poLayer->CreateGeomField( &oPointField2 ) != OGRERR_NONE ) 1192 { 1193 printf( "Creating field PointField2 failed.\n" ); 1194 exit( 1 ); 1195 } 1196 1197 1198In C : 1199 1200.. code-block:: c 1201 1202 OGRGeomFieldDefnH hPointField; 1203 OGRGeomFieldDefnH hPointField2; 1204 OGRSpatialReferenceH hSRS; 1205 1206 hPointField = OGR_GFld_Create( "PointField", wkbPoint ); 1207 hSRS = OSRNewSpatialReference( NULL ); 1208 OSRImportFromEPSG(hSRS, 4326); 1209 OGR_GFld_SetSpatialRef(hPointField, hSRS); 1210 OSRRelease(hSRS); 1211 1212 if( OGR_L_CreateGeomField( hLayer, hPointField ) != OGRERR_NONE ) 1213 { 1214 printf( "Creating field PointField failed.\n" ); 1215 exit( 1 ); 1216 } 1217 1218 OGR_GFld_Destroy( hPointField ); 1219 1220 hPointField2 = OGR_GFld_Create( "PointField2", wkbPoint ); 1221 OSRImportFromEPSG(hSRS, 32631); 1222 OGR_GFld_SetSpatialRef(hPointField2, hSRS); 1223 OSRRelease(hSRS); 1224 1225 if( OGR_L_CreateGeomField( hLayer, hPointField2 ) != OGRERR_NONE ) 1226 { 1227 printf( "Creating field PointField2 failed.\n" ); 1228 exit( 1 ); 1229 } 1230 1231 OGR_GFld_Destroy( hPointField2 ); 1232 1233 1234To write a feature to disk, we must create a local OGRFeature, set attributes 1235and attach geometries before trying to write it to the layer. It is 1236imperative that this feature be instantiated from the OGRFeatureDefn 1237associated with the layer it will be written to. 1238 1239In C++ : 1240 1241.. code-block:: c++ 1242 1243 OGRFeature *poFeature; 1244 OGRGeometry *poGeometry; 1245 char* pszWKT; 1246 1247 poFeature = OGRFeature::CreateFeature( poLayer->GetLayerDefn() ); 1248 1249 pszWKT = (char*) "POINT (2 49)"; 1250 OGRGeometryFactory::createFromWkt( &pszWKT, NULL, &poGeometry ); 1251 poFeature->SetGeomFieldDirectly( "PointField", poGeometry ); 1252 1253 pszWKT = (char*) "POINT (500000 4500000)"; 1254 OGRGeometryFactory::createFromWkt( &pszWKT, NULL, &poGeometry ); 1255 poFeature->SetGeomFieldDirectly( "PointField2", poGeometry ); 1256 1257 if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE ) 1258 { 1259 printf( "Failed to create feature.\n" ); 1260 exit( 1 ); 1261 } 1262 1263 OGRFeature::DestroyFeature( poFeature ); 1264 1265In C : 1266 1267.. code-block:: c 1268 1269 OGRFeatureH hFeature; 1270 OGRGeometryH hGeometry; 1271 char* pszWKT; 1272 1273 poFeature = OGR_F_Create( OGR_L_GetLayerDefn(hLayer) ); 1274 1275 pszWKT = (char*) "POINT (2 49)"; 1276 OGR_G_CreateFromWkt( &pszWKT, NULL, &hGeometry ); 1277 OGR_F_SetGeomFieldDirectly( hFeature, 1278 OGR_F_GetGeomFieldIndex(hFeature, "PointField"), hGeometry ); 1279 1280 pszWKT = (char*) "POINT (500000 4500000)"; 1281 OGR_G_CreateFromWkt( &pszWKT, NULL, &hGeometry ); 1282 OGR_F_SetGeomFieldDirectly( hFeature, 1283 OGR_F_GetGeomFieldIndex(hFeature, "PointField2"), hGeometry ); 1284 1285 if( OGR_L_CreateFeature( hFeature ) != OGRERR_NONE ) 1286 { 1287 printf( "Failed to create feature.\n" ); 1288 exit( 1 ); 1289 } 1290 1291 OGR_F_Destroy( hFeature ); 1292 1293 1294In Python : 1295 1296.. code-block:: python 1297 1298 feat = ogr.Feature( lyr.GetLayerDefn() ) 1299 1300 feat.SetGeomFieldDirectly( "PointField", 1301 ogr.CreateGeometryFromWkt( "POINT (2 49)" ) ) 1302 feat.SetGeomFieldDirectly( "PointField2", 1303 ogr.CreateGeometryFromWkt( "POINT (500000 4500000)" ) ) 1304 1305 if lyr.CreateFeature( feat ) != 0: 1306 print( "Failed to create feature.\n" ); 1307 sys.exit( 1 ); 1308