C#、C++用GDAL读shp文件

C#用GDAL读shp文件

(2012-08-14 17:09:45)

标签:

杂谈

分类: c#方面的总结

1、目前使用开发环境为VS2008+GDAL1.81

public string  ReadSHP( string str)

{

string strMessage = "";

OSGeo.OGR.Ogr.RegisterAll();

OSGeo.OGR.Driver dr = OSGeo.OGR.Ogr.GetDriverByName("ESRI shapefile");

if (dr == null)

{

MessageBox.Show("文件不能打开,请检查");

}

OSGeo.OGR.DataSource ds = dr.Open(str, 0);

int layerCount = ds.GetLayerCount();

OSGeo.OGR.Layer layer = ds.GetLayerByIndex(0);

//投影信息

OSGeo.OSR .SpatialReference  coord = layer.GetSpatialRef();

string coordString;

coord.ExportToWkt(out coordString);

OSGeo.OGR.Feature feat ;

string contentString = "";

//读取shp文件

while ((feat = layer.GetNextFeature()) != null)

{

OSGeo.OGR.Geometry geometry = feat.GetGeometryRef();

OSGeo.OGR.wkbGeometryType goetype = geometry.GetGeometryType();

double x = geometry.GetX(0);

double y = geometry.GetY(0);

contentString += "{" + x.ToString() + ",";

contentString += y.ToString() + "}";

contentString += Environment.NewLine;

}

FileInfo fileinfo = new FileInfo(str);

strMessage = "文件路径为" + str;

strMessage += Environment.NewLine;

strMessage += "该文件大小为:" + fileinfo.Length + "Byte";

strMessage += Environment.NewLine;

strMessage += "该文件有:" + layerCount.ToString () + "层";

strMessage += Environment.NewLine;

strMessage += "该文件坐标信息为" + coordString.ToString();

strMessage += Environment.NewLine;

strMessage += layer.GetGeomType();//shp的类型

strMessage += Environment.NewLine;

strMessage += "该文件共有" + layer.GetFeatureCount(0).ToString() + "记录";

strMessage += contentString.ToString();

strMessage += Environment.NewLine;

return strMessage;

}

http://blog.sina.com.cn/s/blog_6e51df7f01011kic.html

GDAL读写shp文件

 

#include "gdal_include/gdal.h"

#include "gdal_include/ogr_api.h"
#include "gdal_include/ogrsf_frmts.h"

#pragma comment(lib, "lib/gdal_i.lib")

-----------------------------------------

GDAL读shp文件

(1) 注册所有的文件格式驱动

1 GDALAllRegister();2 OGRRegisterAll();

(2)得到shp文件的处理器

1 OGRSFDriver* poDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("ESRI Shapefile");

(3)打开shp文件

1 OGRDataSource* poDS = poDriver->Open( "D:\\lakes.shp", NULL );

(4)获取shp图层

1 OGRLayer* poLayer = poDS->GetLayer(0);

(5)读取几何和属性值


1 OGRFeature * pFeature;2  while ((pFeature=poLayer->GetNextFeature())!=NULL)3 {4 OGRGeometry* pGeometry = pFeature->GetGeometryRef();5 if (pGeometry == NULL)6 {7 AfxMessageBox("Geometry get failed.");8 return FALSE;9 }10 11 OGRwkbGeometryType geoType = pGeometry->getGeometryType();12 if (wkbPoint==geoType)13 CString strNodeID = pFeature->GetFieldAsString("NodeID");14 elseif (wkbLineString==geoType)15 {16 OGRLineString* pLineGeo = (OGRLineString*)pGeometry;17 double staX = pLineGeo->getX(0);18 double staY = pLineGeo->getY(0);19 }20 }

(6)资源清理

1 OGRDataSource::DestroyDataSource( poDS );2 OGRCleanupAll();

GDAL写shp文件

(1) 注册所有的文件格式驱动

(2)得到shp文件的处理器

1 OGRSFDriver* poDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("ESRI Shapefile");
 

(3)创建shp文件

1 OGRDataSource* poDS = poDriver->CreateDataSource( "D:\\lakes.shp", NULL );

(4)创建图层

OGRLayer* poLayer= poDS->CreateLayer( "tbLine", NULL, wkbLineString, NULL );

(5)创建字段


1 // 字符串2  OGRFieldDefn oField1("GeoObjNum",OFTString);3 oField1.SetWidth(8);4  if( poLayer->CreateField( &oField1 ) != OGRERR_NONE ){5 AfxMessageBox( "Creating Name field failed.\n" );return FALSE;}6 7  // 浮点数8  OGRFieldDefn oField2("LBTG",OFTReal);9 oField2.SetPrecision(3);10  if( poLayer->CreateField( &oField2 ) != OGRERR_NONE ){11 AfxMessageBox( "Creating Name field failed.\n" );return FALSE;}12 13  // 整型14  OGRFieldDefn oField3("Number",OFTInteger);15  if( poLayer->CreateField( &oField3 ) != OGRERR_NONE ){16 AfxMessageBox( "Creating Name field failed.\n" );return FALSE;}

(6)创建几何和Feature


1 OGRFeature *poFeature;2 poFeature =new OGRFeature( poLayer->GetLayerDefn() );3 4 poFeature->SetField( "GeoObjNum", strGeoObjNum );5 poFeature->SetField( "LBTG", fLBTG );6 poFeature->SetField( "Number", number );7 8 OGRLineString *poLine =new OGRLineString();9 10 poLine->setNumPoints(2);11 poLine->setPoint(0,startX,startY, 0.0);12 poLine->setPoint(1,endX,endY, 0.0);13 14 poFeature->SetGeometryDirectly( poLine ); 15  if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE )16 {17 AfxMessageBox("Failed to create feature in shapefile.");18 return FALSE;19 }

(7)资源清理

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

这篇文档是为了说明怎样从一个文件里用OGR的C++类读取和写入数据。强烈建议在读此文档之前首先阅读介绍OGR体系结构介绍文档,里面介绍了OGR里主要的类以及他们所完成的功能。

从OGR 读取数据

为了描述如何通过OGR读取数据,我们编写一个小的示例,从OGR文件里读出数据,并按照一定格式输出。

首先我们需要注册我们渴望读取的所有格式。这个通过调用OGRRegisterAll()就能很容易完成,这个函数注册了GDAL/OGR支持的所有格式。

#i nclude"ogrsf_frmts.h"

int main()

{

OGRRegisterAll();

下一步我们将打开输入的OGR数据文件。数据文件可以是文件,关系型数据库,文件路径,甚至可能是远程的网络服务,这点取决于我们使用的驱动。但是,数据源的名字通常只是一个简单的字符串。既然这样拿我们就编写一个打开shapefile的程序。第二个参数(FLALSE)告诉OGRSFDriverRegistrar::Open()函数我们不需要updateaccess。如果失败返回NULL,并报错。

OGRDataSource       *poDS;

poDS = OGRSFDriverRegistrar::Open( "point.shp", FALSE );

if( poDS == NULL )

{

printf( "Open failed.\n" );

exit( 1 );

}

一个OGRDataSource可能包含很多的层。所包含层的数量我们可以用过调OGRDataSource::GetLayerCount()得到,并且其中每一个曾我们利用索引调用OGRDataSource::GetLayer()得到。不过,我们现在利用层的名字。

OGRLayer  *poLayer;

poLayer = poDS->GetLayerByName( "point" );

现在我们开始读取层里面的features。在开始之前我们需要指定一个attribute或者spatial filter来严格控制我们得到的feature。不过现在我们只是得到所有的features。

自从我们开始fresh with这个层,就没有这么严格了。很明智地我们需要调用Layer::ResetReading()来确保我们是从层的开头开始。我们不断地调用OGRLayer::GetNextFeature()函数来遍历所有的features,当遍历完所有的features后返回NULL。

OGRFeature *poFeature;

poLayer->ResetReading();

while( (poFeature = poLayer->GetNextFeature()) != NULL )

{

为了得到一个feature的所有属性fields,调用OGRFeatureDefn将很方便。这是一个object,与层相关联,包含所有fields的定义。我们循环完所有的fields,得到属性数据并将之显示出来。

OGRFeatureDefn *poFDefn = poLayer->GetLayerDefn();

int iField;

for( iField = 0; iField < poFDefn->GetFieldCount(); iField++ )

{

OGRFieldDefn *poFieldDefn = poFDefn->GetFieldDefn( iField );

if( poFieldDefn->GetType() == OFTInteger )

printf( "%d,",poFeature->GetFieldAsInteger( iField ) );

else if( poFieldDefn->GetType() == OFTReal )

printf( "%.3f,",poFeature->GetFieldAsDouble(iField) );

else if( poFieldDefn->GetType() == OFTString )

printf( "%s,",poFeature->GetFieldAsString(iField) );

else

printf( "%s,", poFeature->GetFieldAsString(iField));

}

实际中field的种类比上面列出来的多,但是我们可以通过调用OGRFeature::GetFieldAsString()的方法将之统一提取出来。实际上如果我们用OGRFeature::GetFieldAsString()将会使程序更简短。

下一步我们想从feature里面提取出几何(geometry)数据,并且n他的x和y坐标标出。几何数据通过统一的OGRGeometry指针返回。然后我们确定这个几何数据的类型,如果是点,我们将他标为点并且进行操作,如果是其他的内省我们write占位符。

OGRGeometry *poGeometry;

poGeometry = poFeature->GetGeometryRef();

if( poGeometry != NULL

&& wkbFlatten(poGeometry->getGeometryType()) == wkbPoint )

{

OGRPoint *poPoint = (OGRPoint*) poGeometry;

printf( "%.3f,%3.f\n",poPoint->getX(), poPoint->getY() );

}

else

{

printf( "no point geometry\n" );

}

上面我们使用的这个wkbFlatten()宏是将一个wkbPoint25D(具有Z坐标的点)转化为基于2D的类型(wkbPoint)。对于每一个2D几何类型都有一个2.5D的type code。但是,我们只有基于2D和3D的C++类。因此,我们的代码可以完全处理2D或3D的例子。

注意 OGRFeature::GetGeometryRef()返回一个指向属于OGRFeature的内部几何数据的指针。我们并没有实际地删除返回的几何数据。但是,OGRLayer::GetNextFeature()函数返回了一个现在属于我们自身的feature的拷贝。因此,在用完之后,我们需要释放这个feature。我们可以仅仅“delete”它,but thiscan cause problems in windows builds where the GDAL DLL has a different"heap" from the main program.为了安全起见我们利用一个GDAL函数去删除它。

OGRFeature::DestroyFeature( poFeature );

}

OGRDataSource::GetLayerByName()函数返回的OGRLayer是OGRDataSource中的一个层,因此我们没有必要删除它,但是我们需要删除这个数据文件从而关闭输入的文件。再一次我们利用这个custom delete来避免win32 heap 问题。

OGRDataSource::DestroyDataSource( poDS );

}

以上所有的放在一起,我们的程序如下:

#i nclude"ogrsf_frmts.h"

int main()

{

OGRRegisterAll();

OGRDataSource       *poDS;

poDS = OGRSFDriverRegistrar::Open( "point.shp", FALSE );

if( poDS == NULL )

{

printf( "Open failed.\n%s" );

exit( 1 );

}

OGRLayer  *poLayer;

poLayer = poDS->GetLayerByName( "point" );

OGRFeature *poFeature;

poLayer->ResetReading();

while( (poFeature = poLayer->GetNextFeature()) != NULL )

{

OGRFeatureDefn *poFDefn = poLayer->GetLayerDefn();

int iField;

for( iField = 0; iField < poFDefn->GetFieldCount(); iField++ )

{

OGRFieldDefn *poFieldDefn = poFDefn->GetFieldDefn( iField );

if( poFieldDefn->GetType() == OFTInteger )

printf( "%d,",poFeature->GetFieldAsInteger( iField ) );

else if( poFieldDefn->GetType() == OFTReal )

printf( "%.3f,",poFeature->GetFieldAsDouble(iField) );

else if( poFieldDefn->GetType() == OFTString )

printf( "%s,",poFeature->GetFieldAsString(iField) );

else

printf( "%s,", poFeature->GetFieldAsString(iField));

}

OGRGeometry *poGeometry;

poGeometry = poFeature->GetGeometryRef();

if( poGeometry != NULL

&& wkbFlatten(poGeometry->getGeometryType()) == wkbPoint )

{

OGRPoint *poPoint = (OGRPoint *) poGeometry;

printf( "%.3f,%3.f\n",poPoint->getX(), poPoint->getY() );

}

else

{

printf( "no point geometry\n" );

}

OGRFeature::DestroyFeature( poFeature );

}

OGRDataSource::DestroyDataSource( poDS );

}

Writing TO OGR

作为一个用OGR写的例子,我们粗略地跟上面的程序向反。这个小程序利用OGR将从文件输入的用逗号分隔的值写到一个shapefile的点文件。

通常,我们在一开始就注册所有的驱动,然后取得Shapefile的驱动创建我们的输出文件。

#i nclude"ogrsf_frmts.h"

int main()

{

const char *pszDriverName = "ESRI Shapefile";

OGRSFDriver *poDriver;

OGRRegisterAll();

poDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(

pszDriverName );

if( poDriver == NULL )

{

printf( "%s driver not available.\n", pszDriverName );

exit( 1 );

}

下一步我们创建数据文件(DataSource)。ESRI Shapefile驱动容许我们创建一个全是shapefiles的路径或者单独一个shapefile文件。在这里我们创建一个单独的文件by including theextension in the name。其他类型驱动处理不一样。第二个参数是一组参数值,但在这个例子里我们用默认的值。参数的详细值也随格式的不同而不同。

OGRDataSource *poDS;

poDS = poDriver->CreateDataSource( "point_out.shp", NULL );

if( poDS == NULL )

{

printf( "Creation of output file failed.\n" );

exit( 1 );

}

现在我们就可以创建输出图层了。由于这个例子里只是一个单独的文件,因此我们也只需要创建一个层。我们通过wkPoint来指定这个层支持的几何类型。在这个例子里我们没有传递任何坐标系统信息或者别的特殊的层的创建信息。

OGRLayer *poLayer;

poLayer = poDS->CreateLayer( "point_out", NULL, wkbPoint,NULL );

if( poLayer == NULL )

{

printf( "Layer creation failed.\n" );

exit( 1 );

}

现在层已经创建,我们需要创建任何可能出现在层里的属性fields。Fields必须在如何features在写入之前加入到图层里面。创建field我们用包含field信息的OGRField。在Shapefiles文件里,field的width和精度对于输出的.dbf文件非常重要。,因此我们特定设定它,尽管默认的也OK。在这个例子里,我们只有一个attribute,名字字串associated with x和y点。

确保我们传给CreateFidld()的OGRField模版is copied internally。我们保留这个哦oject的所有权。

OGRFieldDefn oField( "Name", OFTString );

oField.SetWidth(32);

if( poLayer->CreateField( &oField ) != OGRERR_NONE )

{

printf( "Creating Name field failed.\n" );

exit( 1 );

}

\编码(encode)

下面这个循环结构从标准输入读取"x,y,name"值,并分析他们。The following snipping loops reading lines of the form"x,y,name" from stdin, and parsing them.

\代码code

double x, y;

char szName[33];

while( !feof(stdin)

&& fscanf( stdin, "%lf,%lf,%32s", &x, &y,szName ) == 3 )

{

为了把一个feature写道磁盘上,我们必须创建一个本地的OGRFeature,在试图将之写入图层前设置属性并加载几何信息。必须注意的是这个feature必须和将要写入的图层的OGRFeatureDefn给出的事例一致。

OGRFeature *poFeature;

poFeature = new OGRFeature( poLayer->GetLayerDefn() );

poFeature->SetField( "Name", szName );

我们创建了一个本地的几何文件,并且让他直接指向feature。OGRFeature::SetGeometryDirectly()和OGRFeature::SetGeometry()的不同之处是前者给了feature对几何数据的所有权。This is generally more efficient as it avoids an extra deep objectcopy of the geometry.

OGRPoint *poPoint = new OGRPoint();

poPoint->setX( x );

poPoint->setY( y );

poFeature->SetGeometryDirectly( poPoint );

现在我们就在这个文件里创建了一个feature,OGRLayer::CreateFeature()没有取消对feature的拥有因此我们需要在创建完之后清除干净。

if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE )

{

printf( "Failed to create feature in shapefile.\n" );

exit( 1 );

}

delete poFeature;

}

Finally we need to close down thedatasource in order to ensure headers are written out in an orderly way and allresources are recovered.

OGRDataSource::DestroyDataSource( poDS );

}

The same program all in one block lookslike this:

#i nclude"ogrsf_frmts.h"

int main()

{

const char *pszDriverName = "ESRI Shapefile";

OGRSFDriver *poDriver;

OGRRegisterAll();

poDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(

pszDriverName );

if( poDriver == NULL )

{

printf( "%s driver not available.\n", pszDriverName );

exit( 1 );

}

OGRDataSource *poDS;

poDS = poDriver->CreateDataSource( "point_out.shp", NULL );

if( poDS == NULL )

{

printf( "Creation of output file failed.\n" );

exit( 1 );

}

OGRLayer *poLayer;

poLayer = poDS->CreateLayer( "point_out", NULL, wkbPoint,NULL );

if( poLayer == NULL )

{

printf( "Layer creationfailed.\n" );

exit( 1 );

}

OGRFieldDefn oField( "Name", OFTString );

oField.SetWidth(32);

if( poLayer->CreateField( &oField ) != OGRERR_NONE )

{

printf( "Creating Name field failed.\n" );

exit( 1 );

}

double x, y;

char szName[33];

while( !feof(stdin)

&& fscanf( stdin, "%lf,%lf,%32s", &x, &y,szName ) == 3 )

{

OGRFeature *poFeature;

poFeature = new OGRFeature( poLayer->GetLayerDefn() );

poFeature->SetField( "Name",szName );

OGRPoint *poPoint = new OGRPoint();

poPoint->setX( x );

poPoint->setY( y );

poFeature->SetGeometryDirectly( poPoint );

if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE )

{

printf( "Failed to create feature in shapefile.\n" );

exit( 1 );

}

//delete poFeature; //智能指针?

}

OGRDataSource::DestroyDataSource( poDS );

}

C#、C++用GDAL读shp文件(转载)的更多相关文章

  1. GDAL 生成shp文件

    附件:http://pan.baidu.com/s/1i3GPwrV(C#版GDAL接口.dll) 示例程序: http://pan.baidu.com/s/1jpIKQ  (程序是在vs2008 x ...

  2. python GDAL 读写shp文件

    gdal包用于处理栅格数据,ogr用于处理矢量数据. 1 #!C:\Program Files\pythonxy\python\python.exe 2 #-*- coding:gb2312 -*- ...

  3. python gdal 修改shp文件的属性值

    driver = ogr.GetDriverByName('ESRI Shapefile')datasource = driver.Open(shpFileName, 1)layer = dataso ...

  4. geotrellis使用(四十二)将 Shp 文件转为 GeoJson

    前言 一个多月没有写博客了,今天尝试着动笔写点. 原因很多,最重要的原因是我转行了.是的,我离开了开发岗位,走向了开发的天敌-产品经理.虽然名义上是产品经理,但是干的事情也很杂,除了不写代码,其他的都 ...

  5. shp系列(一)——利用C++进行shp文件的读(打开)与写(创建)开言

    博客背景和目的 最近在用C++写一个底层的东西,需要读取和创建shp文件.虽然接触shp文件已经几年了,但是对于shp文件内到底包含什么东西一直是一知半解.以前使用shp文件都是利用软件(如ArcGI ...

  6. 结合C++和GDAL实现shapefile(shp)文件的创建和写入

    工具:vs2012+GDAL 2.0 包含头文件: #include "ogrsf_frmts.h" int main() { const char *pszDriverName ...

  7. 结合C++和GDAL实现shapefile(shp)文件的读取

    工具:vs2012+GDAL 2.0 数据:中国省界SHP文件bou2_4p.shp   可点击下载 包含头文件: #include "ogrsf_frmts.h" 代码: int ...

  8. Android GIS开发系列-- 入门季(13)Gdal简单写个shp文件

    Gdal是用来读写栅格与矢量数据的,在Gdal官网,可以下载相关的资源进行平台的编译.其实Arcgis底层也是用Gdal来读取shp文件的,那在Android中可以直接读写shp文件吗,是可以的.这里 ...

  9. shp系列(二)——利用C++进行shp文件的读(打开)

    1.各数据类型及其字节数 BYTE 1;       char 1;    short 2;      int 4;    double 8; 2.位序big和little及其转换 对于位序是big的 ...

随机推荐

  1. jq中的evet.target

    1.this和event.target的区别: js中事件是会冒泡的,所以this是可以变化的,但event.target不会变化,它永远是直接接受事件的目标DOM元素: 2.this和event.t ...

  2. 7、装饰模式(Decorator)

    顾名思义,装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例,关系图如下: Source类是被装饰类,Decorator类是一个 ...

  3. dpkg -P xx

    dpkg -l | grep ^rc | cut -d' ' -f3|xargs dpkg -P http://www.linuxquestions.org/questions/debian-26/h ...

  4. 利用线程把文本文件填充到richTextBox;防止导入大文本文件窗口假死现象

    private void btnDr_Click(object sender, EventArgs e) { richTextBox1.Text = ""; //richTextB ...

  5. android-------手写签名系统的设计与实现之实现画笔设置

    引自:http://www.xuebuyuan.com/1754358.html 既然我们实现了画布和画笔,也实现了手写,为了提高可用性,我们增加了对画笔风格的设置功能,这样就可以根据自己的需要选择画 ...

  6. Win7+QTP10.0+IE9无法识别对象的解决方法

    在WIN7和IE9环境下使用QTP10,会出现识别不了web对象的情况,具体表现为:添加对象,先打开对象库,再打开IE,点击Add object to local 后,出现白色手指,将其拖拉到百度首页 ...

  7. Android studio怎么创建shape的XML文件

    drawable里面 new一个 Drawable resource xml 一般打开是selector ,把selector改成shape就OK了

  8. 项目整体说明及WBS练习

    乐谱识别研究的意义 纸质乐谱向数字化乐谱的转换,是人类音乐活动与计算机音乐处理之间进行信息交流的必经之路.光学乐谱识别是将纸质乐谱扫描输入计算机后,对乐谱图像加以处理.识别.分析,最终获得乐谱的计算机 ...

  9. LINQ to SQL语句之Union All/Union/Intersect和Top/Bottom和Paging和SqlMethods

    我们继续讲解LINQ to SQL语句,这篇我们来讨论Union All/Union/Intersect操作和Top/Bottom操作和Paging操作和SqlMethods操作 . Union Al ...

  10. Unity加载本地图片的2种方式

    1. 使用 WWW 加载,详细查看 unity3d 官方文档. 2. 使用 System.IO 加载,lua 代码如下: local File = luanet.import_type("S ...