使用gdal的ogr创建shapefile文件(c++)

1.ogr

使用ogr库创建点状要素的shapefile文件以及将经纬度坐标转为投影坐标。实例如下:

#include "ogrsf_frmts.h"
#include "gdal.h"
#include "gdal_priv.h"
#include "cpl_string.h" 
#include <string>
#include <iostream>
#include <strstream>
using namespace std;
void convertToShp(double longitude, double latitude, char *outshp)
{   
    //使属性表字段支持中文
    CPLSetConfigOption("SHAPE_ENCODING","");
    OGRRegisterAll();//注册所有的驱动
    //创建ESRI shp文件
    char *pszDriverName = "ESRI Shapefile";
    //调用对Shape文件读写的Driver
    OGRSFDriver *poDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(pszDriverName);
    if (poDriver == NULL)
    {
        cout<<pszDriverName<<"驱动不可用!"<<endl;
        return;
    }
    //创建数据源
    OGRDataSource *poDs = poDriver->CreateDataSource(outshp, NULL);
    if (poDs == NULL)
    {
        cout<<"DataSource Creation Error"<<endl;
        return;
    }
    //创建图层Layer
    string outShapName = outshp;
    string layerName = outShapName.substr(0, outShapName.length()-4);
    //layerName.c_str()表示将string转为char *类型
    //参数说明:新图层名称,坐标系,图层的几何类型,创建选项,与驱动有关
    OGRLayer *poLayer = poDs->CreateLayer(layerName.c_str(), NULL, wkbPoint, NULL);
    if (poLayer == NULL)
    {
        cout<<"Layer Creation Failed"<<endl;
        OGRDataSource::DestroyDataSource(poDs);
        return;
    }
    //下面创建属性表,我们在属性表中创建两列数据即可
    //先创建一个“ID”整型属性
    OGRFieldDefn oFieldId("ID", OFTInteger);
    oFieldId.SetWidth(5);
    poLayer->CreateField(&oFieldId);
    //再创建一个"X"double属性
    OGRFieldDefn oFieldX("X", OFTString);
    oFieldX.SetWidth(30);
    poLayer->CreateField(&oFieldX);
    //再创建一个"Y"double属性
    OGRFieldDefn oFieldY("Y", OFTString);
    oFieldY.SetWidth(30);
    poLayer->CreateField(&oFieldY);
    //创建一个feature
    OGRFeature *poFeature;  
    poFeature = OGRFeature::CreateFeature(poLayer->GetLayerDefn());//GetLayerDefn()获取当前图层的属性表结构
    //给属性表中我们刚创建的列赋值
    int i = 0;
    poFeature->SetField("ID", i);
    poFeature->SetField("X", longitude);
    poFeature->SetField("Y", latitude);
    i++;
    //创建一个OGRPoint对象
    OGRPoint point;
    point.setX(longitude);
    point.setY(latitude);
    //point.setZ(0);

    poFeature->SetGeometry(&point);

    if(poLayer->CreateFeature(poFeature) != OGRERR_NONE )
    {
        printf( "Failed to create feature in shapefile.\n" );
        exit( 1 );
    }
    OGRFeature::DestroyFeature(poFeature);
    OGRDataSource::DestroyDataSource(poDs);     
}
//======= 经纬度转化为投影坐标=============
double* transfer(double longitude, double latitude)
{
    OGRSpatialReference oSourceSRS;
    //EPSG code 代表特定的椭球体、单位、地理坐标系或投影坐标系等信息
    //This method will initialize the spatial reference based on the passed in EPSG GCS or PCS code
    oSourceSRS.importFromEPSG(4326);//EPSG:4326代表地理坐标系WGS1984
    OGRSpatialReference oTargetSRS;
    oTargetSRS.importFromEPSG(2029);// utm zone 17N
    OGRCoordinateTransformation *poTransform;
    poTransform = OGRCreateCoordinateTransformation(&oSourceSRS, &oTargetSRS);
    if (poTransform == NULL)
    {
        cout<<"poTransform is null"<<endl;
        exit(1);
    }   
    if (!poTransform->Transform(1, &longitude, &latitude, NULL))
    {
        cout<<"transform failed"<<endl;
        exit(1);
    }
    //poTransform->Transform(1, &longitude, &latitude, NULL);
    double *inout = new double[2];
    inout[0] = longitude;
    inout[1] = latitude;
    return inout;
}
int main(int argc, char *argv[])
{       
    char *xCoordinate = argv[1];
    char *yCoordinate = argv[2];
    char *outShp = argv[3];
    double x = atof(xCoordinate);
    double y = atof(yCoordinate);
    convertToShp(x, y, outShp);
    cout<<"success! file is saved to "<<outShp<<endl;
    double *transferedLongLat = transfer(116.246742, 40.022211);
    cout<<"转换后的投影坐标为:"<<transferedLongLat[0]<<","<<transferedLongLat[1]<<endl;

    getchar();
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120

程序运行结束后即在我们指定的目录下生成点状要素的shp文件。 
关于坐标转换,可以参考:http://blog.csdn.net/jingss_3/article/details/8240328

本文介绍如何使用GDAL/OGR 库对shapefile文件进行简单的操作,包括读取、创建、修改等.在GDAL官网上有读写shp文件的介绍,主要是针对点要素的操作例子:点击打开链接


2.读取shp文件

[cpp]  view plain  copy
  1. void ExtracInfo::ReadShapeFile()  
  2. {  
  3.     OGRRegisterAll();  
  4.   
  5.     OGRDataSource *poDS;  
  6.     poDS = OGRSFDriverRegistrar::Open("F:/test.shp", FALSE);  
  7.     if (poDS == NULL)  
  8.     {  
  9.     //  printf("Open failed \n");  
  10.   
  11.     }  
  12.   
  13.     OGRLayer *poLayer;  
  14.     poLayer = poDS->GetLayerByName("test");  
  15.     int layercount = poDS->GetLayerCount();  
  16. //  printf("layer count is : %d\n", layercount);  
  17.   
  18.     OGRFeature *poFeature;  
  19.     poLayer->ResetReading();  
  20.     while((poFeature = poLayer->GetNextFeature()) != NULL)  
  21.     {  
  22.         //printf("hello!\n");  
  23.         //get field  
  24.         OGRFeatureDefn *poFDefn = poLayer->GetLayerDefn();  
  25.         int iField;  
  26.         int fieldcount = poFDefn->GetFieldCount();  
  27. //      printf("Field count is : %d\n", poFDefn->GetFieldCount());  
  28.         int fieldv1;  
  29.         double fieldv2;  
  30.         string feildv3;  
  31.         for (iField = 0; iField < poFDefn->GetFieldCount(); iField ++)  
  32.         {  
  33.             OGRFieldDefn * poFieldDefn = poFDefn->GetFieldDefn(iField);  
  34.             if (poFieldDefn->GetType() == OFTInteger)  
  35.             {  
  36.                 fieldv1 = poFeature->GetFieldAsInteger(iField);  
  37. //              printf("%d ", poFeature->GetFieldAsInteger(iField));  
  38.             }  
  39.             else if (poFieldDefn->GetType() == OFTReal)  
  40.             {  
  41.                 fieldv2 = poFeature->GetFieldAsDouble(iField);  
  42. //              printf("%3f ", poFeature->GetFieldAsDouble(iField));  
  43.             }  
  44.             else if (poFieldDefn->GetType() == OFTString)  
  45.             {  
  46.                 feildv3 = poFeature->GetFieldAsString(iField);  
  47. //              printf("%s ", poFeature->GetFieldAsString(iField));  
  48.             }  
  49. //          else  
  50. //              printf("%s", poFeature->GetFieldAsString(iField));  
  51.         }  
  52. //以上操作与gdal官网一样  
  53.         //get Geometry获取polygon的信息  
  54.         OGRGeometry *poGeometry;  
  55.         poGeometry = poFeature->GetGeometryRef();  
  56.         double x, y;double area;  
  57.         if (poGeometry != NULL && wkbFlatten(poGeometry->getGeometryType()) == wkbPolygon)  
  58.         {  
  59.             OGRPolygon *poPolygon = (OGRPolygon * )poGeometry;  
  60.             area = poPolygon->get_Area();  
  61.             OGRPoint point;  
  62.             OGRLinearRing *pOGRLinearRing = poPolygon->getExteriorRing();  
  63.             pOGRLinearRing->getPoint(0,&point);//得到第一个点的坐标  
  64.             x = point.getX();  
  65.             y = point.getY();  
  66. //          printf("%.6f, %.6f\n", poPoint->getX(), poPoint->getY());  
  67.         }  
  68.         else  
  69. //          printf("no point geometry\n");  
  70.   
  71.           
  72.         OGRFeature::DestroyFeature(poFeature);  
  73.     }  
  74.       
  75.   
  76.     OGRDataSource::DestroyDataSource(poDS);  
  77.   
  78.   
  79. }  

3.shp文件添加字段

有时需要对已经存在的shp文件进行添加字段操作。代码如下:

[cpp]  view plain  copy
  1.     OGRDataSource *poDS;  
  2.     poDS = OGRSFDriverRegistrar::Open("F:/test.shp", TRUE);//第二个参数表示只读还是可读写  
  3.     if (poDS == NULL)  
  4.     {  
  5.         //  printf("Open failed \n");  
  6.   
  7.     }  
  8.     OGRLayer *poLayer;  
  9.     poLayer = poDS->GetLayerByName("test");  
  10.     int layercount = poDS->GetLayerCount();  
  11.   
  12.     OGRFieldDefn poField("NewField", OFTReal);  
  13. //  poField.SetWidth(1); //设置的是格式化输出时的位数  
  14.     poField.SetPrecision(8);//设置精度,除了real类型,其他的一般为0  
  15.     if (poLayer->CreateField(&poField) != OGRERR_NONE)  
  16.     {  
  17. //      printf("Creating Name Field Failed\n");  
  18. //      exit(1);  
  19.     }  
  20.     OGRFeature *poFeature;  
  21.     poLayer->ResetReading();//设置从第0个要素开始读  
  22.   
  23.     int featureNum = 0;  
  24.     while((poFeature = poLayer->GetNextFeature()) != NULL)  
  25.     {  
  26.         OGRFeatureDefn *poFDefn = poLayer->GetLayerDefn();  
  27.         int fieldcount = poFDefn->GetFieldCount();  
  28.   
  29.         poFeature->SetField(fieldcount - 1,  featureNum);  
  30.   
  31.         poLayer->SetFeature(poFeature);  
  32.         OGRFeature::DestroyFeature(poFeature);  
  33.         featureNum ++;  
  34.     }  
  35.     OGRDataSource::DestroyDataSource(poDS);  
刚开始老是添加不成功,最后发现是open函数里第二个参数,如果默认设置为FALSE,则表示只读;需要把它设置为TRUE才可读写。

4.创建shp文件

下面主要说说创建多边形shp文件。创建的方法:使用的WKT格式的字符串来进行创建。也可以使用其他的方式进行创建(参考大神博客:点击打开链接)。但是它是wkt方法的C#、Python代码,c++代码对应的函数没查到。所以用另一种方法创建如下:

[cpp]  view plain  copy
  1.     const char *pszDriverName = "ESRI Shapefile";  
  2.     OGRSFDriver *poDriver;  
  3.   
  4.     OGRRegisterAll();  
  5.   
  6.     poDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(pszDriverName);  
  7.     if (poDriver == NULL)  
  8.     {  
  9. //      printf("%s driver not available \n", pszDriverName);  
  10.     }  
  11.   
  12.     OGRDataSource *poDS;  
  13.     poDS = poDriver->CreateDataSource("F:/zjq/testProject/ogrtest/polygon.shp", NULL);  
  14.     if (poDS == NULL)  
  15.     {  
  16. //      printf("Create shapefile failed\n");  
  17. //      exit(1);  
  18.     }  
  19.   
  20.     OGRLayer *poLayer;  
  21.     poLayer = poDS->CreateLayer("polygon1", NULL, wkbPolygon, NULL);  
  22.     if (poLayer == NULL)  
  23.     {  
  24. //      printf("Layer create failed\n");  
  25. //      exit(1);  
  26.     }  
  27.     //下面创建属性表  
  28.     OGRFieldDefn poFieldID("ID", OFTInteger);//创建ID字段  
  29.     poLayer->CreateField(&poFieldID);  
  30.   
  31.     OGRFieldDefn poFieldname("Name", OFTString);//创建Name字段  
  32.     poFieldname.SetWidth(32);  
  33.     poLayer->CreateField(&poFieldname);  
  34.   
  35.     double x = 0.0, y = 0.0;  
  36.     for (int i  = 0; i < 10; i++)  
  37.     {  
  38.         string szname = "a_" + QString::number(i).toStdString();  
  39.         OGRFeature *poFeature;  
  40.         poFeature = OGRFeature::CreateFeature( poLayer->GetLayerDefn() );  
  41.         poFeature->SetField(0, i);  
  42.         poFeature->SetField(1, szname.c_str());  
  43.   
  44.         OGRLinearRing ring;  
  45.   
  46.         ring.addPoint(0 + 10 * i, 0 + 10 *i);  
  47.         ring.addPoint(0 +10 * i, 10 + 10 *i);  
  48.         ring.addPoint(10 + 10 *i, 10 + 10 *i);  
  49.         ring.addPoint(10 + 10 *i, 0 + 10*i);  
  50.   
  51.         ring.closeRings();//首尾点重合形成闭合环  
  52.           
  53.         OGRPolygon polygon;  
  54.         polygon.addRing(&ring);  
  55.         poFeature->SetGeometry(&polygon);  
  56.   
  57.         if ( poLayer->CreateFeature( poFeature) != OGRERR_NONE)  
  58.         {  
  59. //          printf("Failed to create feature in shapefile \n");  
  60. //          exit(1);  
  61.         }  
  62.         OGRFeature::DestroyFeature(poFeature);  
  63.     }  
  64.   
  65.     OGRDataSource::DestroyDataSource(poDS);  
以上创建代码的结果如下图所示:(QGIS显示)




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值