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. java中从含反斜杠路径截取文件名的方法

    例如:获取到的文件路径为C:\Documents and Settings\Leeo\My Documents\logo.gif现在想要取得图片的名称logo.gif,我们知道反斜杠“\”是转义字符, ...

  2. Zigbee协议栈OSAL层API函数【转载】

              OSAL层提供了很多的API来对整个的协议栈进行管理.主要有下面的几类:信息管理.任务同步.时间管理.中断管理.任务管理.内存管理.电源管理以及非易失存储管理.看到这些管理是不是感 ...

  3. Arduino IDE 添加DHT11传感器第三方库的方法

    由于Arduino本身没有DHT 11温湿度传感器的的头文件,单有第三方的库可以给我门使用.方法如下: Step 1:如果你已经下载了最新版的Arduino IDE就可以使用其自带的库管理器和版型管理 ...

  4. NOI2004 郁闷的出纳员 Splay

    郁闷的出纳员 [问题描述] OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常, ...

  5. mysql基础---日志文件

    一 基本日志文件 MYSQL有不同类型的日志文件(各自存储了不同类型的日志),从它们当中可以查询到MYSQL里都做了些什么,对于MYSQL的管理工作,这些日志文件是不可缺少的. 1.错误日志(The ...

  6. Pythagorean Triples

    Pythagorean Triples time limit per test 1 second memory limit per test 256 megabytes input standard ...

  7. 省市区三级联动插件:app-jquery-cityselect.js

    (function ($) { $.fn.cityselect = function (options) { var settings = $.extend ({}, options); this.e ...

  8. Python+Selenuim测试网站,只能打开Firefox浏览器却不能打开网页的解决方法

    最开始我使用的Selenium版本为2.48,Firefox版本为37,自动化打开网站的时候,可以正常打开. 后来由于Firefox的自检测更新,版本更新为47,导致版本不兼容,自动化打开网站浏览器时 ...

  9. openstack controller ha测试环境搭建记录(七)——配置glance

    在所有集群安装glance软件:yum install -y openstack-glance python-glanceclient 在任一节点创建glance用户:mysql -u root -p ...

  10. Linux启动时显示Grub命令行及修改

    1.在启动Linux系统时,如果/boot/grub/grub.cfg文件损坏或者不存在时,启动Linux时,就会有Grub命令行的提示. 如下操作,将系统自带的grub.cfg文件改名.重新启动系统 ...