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. Bcdedit命令使用详解使用方法

    XP,WIN2003,VISTA,万indows,WIN2008多盘多系统多引导bcdedit的使用windows出了新系统vista,2008想赏赏鲜学习学习~~但又习惯于用旧的XP,2003,然而 ...

  2. hbase port

    From "Jonathan Hsieh (JIRA)" <j...@apache.org> Subject [jira] [Updated] (HBASE-10123 ...

  3. Android 手机应用开发经验 之 通过Socket(TCP/IP)与PC通讯

    Android 是一个开源的手机操作系统平台,已经被非常多的开发者视作未来最有潜力的智能手机操作系统.而且,在很短的时间内就在Android Market上出现大量的第三方应用程序,供用户下载与使用, ...

  4. CentOS查询 杀死进程

    ps aux | grep XXX 查询进程 ps a 显示现行终端机下的所有程序,包括其他用户的程序. ps -A 显示所有程序. ps c 列出程序时,显示每个程序真正的指令名称,而不包含路径,参 ...

  5. AES加密,解决了同步问题,和随机密钥和固定密钥,多端通信加密不一致解决办法

    1.密钥随机生成. import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyEx ...

  6. VMware NAT端口映射外网访问虚拟机linux

    本文目的: 一. SSH连接 二. 访问HTTP VMware Workstation提供了两种虚拟机上网方式,一种bridge,一种NAT,bridge可以获得公网地址,而NAT只能是内网地址了. ...

  7. 写一个程序,统计自己C语言共写了多少行代码,Github基本操作

    前言 在上一篇博客中,本人提到了自己的文件操作可以说是几乎没用过.现在想想,这也算是只在OJ上做题的一个弊端吧.虽然通过OJ做题是一个学习代码好手段,但其他方面也要多多涉猎才好,而不是说OJ用不到文件 ...

  8. JS对象引用

    对象和函数都是引用的关系(改变后者会改变前者) 但是下面这个列子情况不一样了.刚开始的时候 B 引用了 A的地址,后来B又重新赋值,新占了一个地址,A   B俩的关系已经脱离. 那么有的时候,我们只有 ...

  9. MySQL:MySQL的安装

    一.Linux:MySQL的源码安装 1.安装前的准备 在安装之前需要安装一下必备的包和工具 gcc/g++:MySQL5.6开始,需要使用g++进行编译. cmake:MySQL5.5开始,使用cm ...

  10. js 中调用 Object.prototype.toString()来检测对象的类型

    1.使用toString()方法来检测对象类型 可以通过toString() 来获取每个对象的类型.为了每个对象都能通过 Object.prototype.toString() 来检测,需要以 Fun ...