File GeoDataBase API

1.引言

项目中有个功能需要导出gdb数据,借助GIS软件读写gdb数据,所接触的也是ARCEngine咯。由于功能单一,不想依赖GIS软件,考虑能不能直接去读写gdb数据,这才找到 File GeoDatabase API (下面简称API)。也是因为自己懒散,没有关注ESRI这方面的消息更新。下面将这两天的研究成果简单的记录一下,不为高台教化,只是方便日后复习查找,若文章有什么纰漏或者错误,请留言指出,不必留情哦!

2.说明

API可以抛开GIS软件直接代码操作gdb数据,除了省钱之外,对于惯用盗版的我们来说,主要是省事儿,官方的下载地址:http://appsforms.esri.com/products/download/#File_Geodatabase_API_1.3
在这里插入图片描述
API支持创建、打开、删除gdb对象,读取gdb里面的Schema,创建简单的gdb对象,诸如:普通表、点线面、数据集、子类、域等,简单数据集的增删改查,进行属性和空间查询;API不支持注记和多维要素、关系类、几何网络、拓扑等(详细情况可以自行去查找验证)!

3.代码

下载解压之后发现是C++的相关文件,好在还是支持C#的,相关的文档说明在 \doc 里面(不要抱太大希望哦,文档说明很简单的,但是还是有点用的,毕竟免费的,没办法):
在这里插入图片描述
打开sampleC#的示例代码研究一番,其实代码很简单的,但是在研究过程中还是遇到了一些坑,下面贴出部分代码,以及对遇到问题的一些说明:

坑 3.1 dll引用问题
实际上这个问题也不能说是个坑,归根到底是自己代码功底的问题。down下来之后直接奔着示例代码和dll去了,dll有32位和64位的:
在这里插入图片描述

可以看到有三个dll,分别是Esri.FileGDBAPI.dll、FileGDBAPI.dll、FileGDBAPID.dll,满心欢喜的去写自己的Demo,仿照示例代码直接引用Esri.FileGDBAPI.dll(32位或者64位可以根据项目的需求),打开了一个gdb,然后就报错了,什么“无法加载引用什么之类的…”。一开始以为是项目的“目标平台”与dll冲突了,怎么调整都不行,哪怕是保证引用的dll与目标平台保持一致也是报错!懵逼了,整了一通之后才发现提供的dll有三个,为什么源码里面只用到一个啊?另外两个(FileGDBAPI.dll、FileGDBAPID.dll)是C++的dll还不能引用,把它们丢到了demo的生成目录下面,运行正常了,存在一个依赖关系啊原来,也就是说引用的时候只需要引用 Esri.FileGDBAPI.dll,但是在运行目录下面必须有有FileGDBAPI.dll、FileGDBAPID.dll,否则会一直报错哦,至于说这两个程序集是干嘛的,还是没有弄明白,请大牛指教!

坑 3.2 坐标系问题
示例代码中不管是创建Dataset还是创建Field还是其他相关的东西都是把定义写在xml中然后直接去创建就行:

public void CreateFeatureDataset(string featureDatasetDef);
public void CreateFeatureDataset(string path, SpatialReference spatialReference);

由于项目中需要选择坐标系文件*.prj,这样一来就没有办法提前把坐标系写到xml中,就自己创建一个SpatialReference咯,坑了个爹的,SpatialReference居然没有指定prj文件路径的属性参数,调试示例代码才知道SpatialReference.spatialReferenceText属性存储的是坐标属性(如:PROJCS[“Xian_1980_3_Degree_GK_CM_120E”,GEOGCS[“GCS_Xian_1980”,DATUM[“D_Xian_1980”,SPHEROID[“Xian_1980”,6378140.0,298.257]],PRIMEM[“Greenwich”,0.0],UNIT[“Degree”,0.0174532925199433]],PROJECTION[“Gauss_Kruger”],PARAMETER[“False_Easting”,500000.0],PARAMETER[“False_Northing”,0.0],PARAMETER[“Central_Meridian”,120.0],PARAMETER[“Scale_Factor”,1.0],PARAMETER[“Latitude_Of_Origin”,0.0],UNIT[“Meter”,1.0]]),没办法,手动把prj文件直接读成字符串,然后传进去,哟西,可以哦!

string path_gdb = "E:\\数据\\demo.gdb";
string path_prj = "E:\\数据\\Xian 1980 3 Degree GK CM 120E.prj";
Geodatabase _database = Geodatabase.Create(path_gdb);
            
SpatialReference spatialReference = new SpatialReference();
spatialReference.spatialReferenceText = File.ReadAllText(path_prj);
_database.CreateFeatureDataset(@"\dataset1", spatialReference);

坑 3.3 创建线面问题
示例代码中创建线面是个复制的过程,即从一个已经存在的gdb里面复制一个存在的gdb要素,这样就存在一个问题,线面的part和point集合的问题,创建线要素的时候,MultiPartShapeBuffer.Points存储的是线的节点很明了,MultiPartShapeBuffer.Parts存的是个啥啊,一开始以为存储的是个数,后来发现不对,调试源码下才知道存储的是段的起点:

//线图层
FieldDef shape2 = new FieldDef();
shape2.Type = FieldType.Geometry;
shape2.Name = "Shape";
shape2.Alias = "Shape";
GeometryDef geometryDef2 = new GeometryDef();
geometryDef2.HasM = false;
geometryDef2.HasZ = false;
geometryDef2.geometryType = GeometryType.Polyline;
geometryDef2.spatialReference = spatialReference;
shape2.geometryDef = geometryDef2;

FieldDef[] fieldDefs_line = new FieldDef[] { objectId, name, shape2 };
Table table_line = _database.CreateTable(@"\dataset1\layer2", fieldDefs_line, "");

Row row3 = table_line.CreateRowObject();
row3.SetString("Name", "测试点3");

MultiPartShapeBuffer lineBuffer = new MultiPartShapeBuffer();
lineBuffer.Setup(ShapeType.Polyline, 3, 6);

Point point4 = new Point(-115.78443, 33.919902);
Point point3 = new Point(-116.78443, 33.919902);
Point point5 = new Point(-117.78443, 34.919902);

Point point6 = new Point(-111.78443, 32.919902);
Point point7 = new Point(-112.78443, 32.919902);
Point point8 = new Point(-113.78443, 31.919902);

lineBuffer.Points = new Point[] { point4, point3, point5, point6, point7, point8 };
lineBuffer.Parts = new int[] { 0, 2, 4 };
lineBuffer.CalculateExtent();

row3.SetGeometry(lineBuffer);
table_line.Insert(row3);

按照上面所说,part里面存储的是起点位置,那么上述示例代码中应该是point4—point3,point5—point6,point7—point8,三个线段。这个还是很好理解的,关键在这个基础上去理解面图层的创建,那才叫坑啊,这里不买关子了,面图层的创建需要首位“闭合”,也就是说point[A,B,C,D,E,F],part[0,3]这样是创建不成功的,应该是point[A,B,C,A,D,E,F,D],part[0,4],这样闭合才能创建出两个三角面,当然了ArcMap查看节点的时候还是6个节点,不会是8个哦!

//创建面图层
FieldDef shape3 = new FieldDef();
shape3.Type = FieldType.Geometry;
shape3.Name = "Shape";
shape3.Alias = "Shape";
GeometryDef geometryDef3 = new GeometryDef();
geometryDef3.HasM = false;
geometryDef3.HasZ = false;
geometryDef3.geometryType = GeometryType.Polygon;
geometryDef3.spatialReference = spatialReference;
shape3.geometryDef = geometryDef3;

FieldDef[] fieldDefs_area = new FieldDef[] { objectId, name, shape3 };
Table table_area = _database.CreateTable(@"\dataset1\layer3", fieldDefs_area, "");
table_area.LoadOnlyMode(true);

Row row4 = table_area.CreateRowObject();
row4.SetString("Name", "测试点4");

MultiPartShapeBuffer areaBuffer = new MultiPartShapeBuffer();
areaBuffer.Setup(ShapeType.Polygon, 2, 11);

Point point9 = new Point(-71.199, 41.679);
Point point10 = new Point(-71.141, 41.655);
Point point11 = new Point(-71.117, 41.493);
Point point12 = new Point(-71.200, 41.463);


Point point13 = new Point(-71.269, 41.621);
Point point14 = new Point(-71.219, 41.636);
Point point15 = new Point(-71.239, 41.475);
Point point16 = new Point(-71.288, 41.484);
Point point17 = new Point(-71.350, 41.446);

areaBuffer.Points = new Point[] { point9, point10, point11, point12, point9, point13, point14, point15, point16, point17, point13 };
areaBuffer.Parts = new int[] { 0, 5 };
areaBuffer.CalculateExtent();
row4.SetGeometry(areaBuffer);
table_area.Insert(row4);

table_area.LoadOnlyMode(false);
4.参考引用

1. https://blog.csdn.net/linghe301/article/details/6171368
2. https://blog.csdn.net/Bear_861110453/article/details/55101935
3. https://blog.csdn.net/zh_98/article/details/51247944

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值