摘要:伴随着测绘行业突飞猛进的发展,原先的传统操作方法面临许多的技术瓶颈,GIS技术的应用和发展使得这些瓶颈迎刃而解。为了避免重复建设,降低GIS的功能的性价比,有必要整合资源,将一些测绘项目中的共同的基于ArcEngine二次开发的功能做成通用的工具。以农村土地承包经营权项目为案例,在Microsoft Visual Studio 2010、NET的环境下,用C#和ArcEngine10.1组建实现数据库图层和字段正确性检查、不规则图斑界址点西北角开始顺时针自增编号、界址线自动生成、坐标系转换、椭球面积计算、空间分析、数据库合并等多种通用的功能,最大限度的实现GIS功能,使得测绘项目以最小的代价实现利益最大化。
关键词:二次开发;空间分析;界址点编号;数据库合并
1引言
现在许多测绘项目中都会涉及到数据库图层及字段正确性检查、界址点编号、界址线生成、坐标系转换、椭球面积计算、空间分析、数据库合并等功能。这些功能可以利用c#+ArcEngine进行二次开发基于ArcMap的插件,从而不仅保留了原ArcMap强大的制图、
图形编辑、图形处理等功能,还可以开发许多自定义的具有可扩展性的功能模块。为此,开发一套通用的具备数据库图层及字段正确性检查、界址点编号、界址线生成、坐标系转换、椭球面积计算、空间分析、数据库合并的工具条势在必行,这样不仅可以大大提高工作效率还可以提高经济效益。
当前,采用C#+ArcEngine进行二次开发的技术比较成熟,这不仅得益于Esri公司提供大量的开发接口,还得益于测绘技术的广泛应用和开发人员的不懈努力。本次案例主要依托农村土地承包经营权项目进行二次开发,介绍数据库图层及字段正确性检查、界址点编号、界址线生成、坐标系转换、椭球面积计算、空间分析、数据库合并工具条的实现。
2 工具条的算法介绍
2.1 数据库图层及字段正确性检查
采用OLEDB(Object Link and embed)即对象连接与嵌入技术读取数据库中的图层名及表结构,将读取的信息存储之后与标准数据库的图层名及表结构循环对比,把对比之后的记录格式化输出以便于查看或者导出报表。
private static void checkSourceDBfield(DataTable dt_targetMdb,DataTable dt_soueceMdb)
{
List<string> lst_target = SQLHelper.GetFiled(dt_targetMdb);
List<string> lst_source = SQLHelper.GetFiled(dt_soueceMdb);
if(lstcolEX.Count != 0)
{
for(int l = 0;l < lstcolEX.Count;l++)
{
DataRow dr_check = dt_checkFiled.NewRow(); dr_check["JCBNC"]=dt_targetMdb.Rows[0]["TABLE_NAME"].ToString();
}
}
if(lstcolEX_.Count != 0)
{
for(int l = 0;l < lstcolEX_.Count;l++)
{
DataRow dr_check = dt_checkFiled.NewRow();
dr_check["JCBNC"]= dt_soueceMdb.Rows[0]["TABLE_NAME"];
dr_check["JCZD"]= lstcolEX_[l];
dr_check["ZDSFCZ"]= "不存在";
dr_check["ZDSFCZ"]= "存在";
dr_check["JCJG"]= "字段【" + lstcolEX_[l]+ "】缺失";
dt_checkFiled.Rows.Add(dr_check);
List<string> lstcolIn = lst_target.Intersect(lst_source).ToList();
for(int i = 0;i < lstcolIn.Count;i++)
{
if(dt_targetDBfilde.Rows[0]["ZDSX"]!= dt_sourceDBfilde.Rows[0]["ZDSX "])
{
DataRow dr_check = dt_checkFiled.NewRow();
dr_check["JCBMC"]= dt_targetDBfilde.Rows[0]["TABLE_NAME"].ToString();
dr_check["JCJG"]= "字段【" + lstcolIn[i]+ "】属性:待检数据库为<" + dt_targetDBfilde.Rows[0]["ZDSX"].ToString()+ ">,标准数据库为<" + dt_sourceDBfilde.Rows[0]["ZDSX"].ToString()+ ">";
dt_checkFiled.Rows.Add(dr_check);
}
else
{
if(dt_targetDBfilde.Rows[0]["ZDSX"].ToString()== "string")
{
if(dt_targetDBfilde.Rows[0]["CHARACTER_MAXIMUM_LENGTH"].ToString()!= dt_sourceDBfilde.Rows[0]["CHARACTER_MAXIMUM_LENGTH"].ToString())
{
DataRow dr_check = dt_checkFiled.NewRow();
dr_check["检查表名称"]= dt_targetDBfilde.Rows[0]["TABLE_NAME"].ToString();
dr_check["JCZD"]= lstcolIn[i];
dr_check["ZDSFCZ"]= "存在";
dr_check["ZDSFCZ"]= "存在";
dt_checkFiled.Rows.Add(dr_check);
}
}
}
}
}
2.2界址点编号
界址点是图斑权属界线的折点,即拐点,它是标定图斑权属界线的重要标志。图斑界址点可以确定其位置、形状、面积和权属界线。在农村土地承包经营权项目工作中规范要求界址点从西北角顺时针从1开始编号,而且不能有重号。对于规则的图斑我们可以采用遍历每一个图斑,获取图斑的最大矩形的西北角的点,遍历该图斑的所有界址点到矩形西北角的距离,判断出距离最短的界址点作为该图斑的起始界址点,然后顺序获取下一个界址点直至最后一个界址点;但是对于不规则的图斑有可能取到多个距离相等的西北角点,这样会导致编号混乱,利用图斑多边形节点ID号顺序为基础的快速界址点编号方法可以有效的解决这种错误。
快速编号的方法:首先将图斑面转点得到图斑所有的节点图层,遍历每一个图斑将该图斑的节点与界址点做相交分析,把相交到的界址点号变为节点的ID号,获取图斑西北角的界址点号,将小于西北角的界址点号的界址点ID号都加图斑节点总数,再将变更后界址点顺序排号就得到从西北角开始的顺时针自增的界址点号,最后按照这个顺序在前一图斑编号的基础上累加就可以得到该图斑最终的界址点号。这种方法避免了在编号过程中大量计算两个向量的夹角有效提升编号效率。
private void btn_JZDAll_Click(object sender,EventArgs e)
{
int maxjzdh = 0;
List<int> maxlist = new List<int> { };
string sqldk = "SELECT * FROM DK WHERE OBJECTID IS NOT NULL AND DKBM IS NOT NULL ORDER BY OBJECTID";
DataTable dt_DK = AccessHelper.ExecuteDataTable(sqldk);
if(dt_DK.Rows.Count > 0)
{
richTextBoxJD.Visible = true;
DataView dv_JZD_ZD_Intersect = AccessHelper.ExecuteDataTable(FeatureVerticesToPoints).DefaultView;
int countzd = 0;
try
{
for(int l = 0;l < dt_DK.Rows.Count;l++){
dv_DK_ZD.RowFilter = "DKBM='" + dkbm + "'";
if(dv_DK_ZD.ToTable().Rows.Count > 0)
{
if(dv_JZD_ZD_Intersect.ToTable().Rows.Count > 0)
{
for(int u = 0;u < dv_JZD_ZD_Intersect.ToTable().Rows.Count;u++)
{
Dictionary<int,int> dic1Asc1 =(from d in jzdlast orderby d.Key ascending select d).ToDictionary(k => k.Key,v => v.Value);
foreach(KeyValuePair<int,int> kvp in dic1Asc1)
{
where += kvp.Value + ",";
if(dtwhere.Rows.Count > 0)
{
string lx = "3";
for(int h = 0;h < dtwhere.Rows.Count;h++)
{
string jzdh = dtwhere.Rows[h]["JZDH"].ToString();
if(jzdh.Trim()== "")
maxjzdh++;listSql.Add(ss);
if(listSql.Count > 0)
{
AccessHelper.ExecuteSqlTran(listSql);
}
MessageBox.Show("成功!","系统提示!");
}
richTextBoxJD.Visible = false;
}
2.3界址线生成
将图斑面转线之后再界址点处分割线,然后将形成的结果追加到界址线层从而形成界址线。如图1所示。
图1
public static void MadeJzxLine(string toolPath,string mdbPath)
{
Geoprocessor GP = new Geoprocessor();
GP.OverwriteOutput = true;GP.AddToolbox(toolPath);
IVariantArray parameters = new VarArrayClass();
parameters.Add(mdbPath + "\\" + "DS" + "\\" + "JZD");
parameters.Add(mdbPath + "\\" + "DS" + "\\" + "DK");
parameters.Add(mdbPath + "\\" + "DS" + "\\" + "JZX");
GP.Execute("MadeJzx",parameters,null);
}
2.4坐标系转换
测绘项目中的许多数据来源比较广泛,坐标系不一致导致无法使用。坐标转换变成不可或缺的功能,ArcMap自带的坐标转换基本已经满足项目需求,但是许多的数据是地方坐标系或者不是标准带号的坐标,就需要使用三参或者七参进行坐标转换。常见的转化类型有地理坐标和投影坐标互转、不同投影坐标之间的转换、不同地理坐标之间的转换。
public static void CoordinateSystemChang(IGeographicCoordinateSystem iGeographicCoordinateSystem,double inx,double iny,ref string outx,ref string outy)
{
SpatialReferenceEnvironment pSpRE = new SpatialReferenceEnvironment();
IGeographicCoordinateSystem pGeoCS = iGeographicCoordinateSystem
ISpatialReference pSpr = pGeoCS;
IPoint pPoint = new ESRI.ArcGIS.Geometry.Point();
pPoint.X = inx;pPoint.Y = iny;IGeometry pGeo = pPoint;
pGeo.SpatialReference = pMap.SpatialReference;
pGeo.Project(pSpr);outx = pPoint.X;outy = pPoint.Y;
}
2.5椭球面积计算
图2 椭球面上任意多边形计算面积图
求封闭区域(多边形如图2)ABCD的面积,其具体方法为:
(1)对封闭区域(多边形)的界址点连续编号(顺时针或逆时针)ABCD,提取各界址点的高斯平面坐标A(X1,Y1),B(X2,Y2),C(X3,Y3),D(X4,Y4);
(2)利用高斯投影反解变换模型公式将高斯平面坐标换算为相应椭球的大地坐标A(B1,L1),B(B2,L2),C(B3,L3),D(B4,L4);
(3)任意给定一经线L0(如L0=60°),这样多边形ABCD的各边AB、BC、CD、DA与L0就围成了4个梯形图块(ABB1A1、BCC1B1、CDD1C1、DAA1D1);
(4)将梯形图块ABB1A1按分割成许多个小梯形图块AEiFiA1,将高斯平面坐标E(Xi,Yi)反算为相应椭球的大地坐标E(Bi,Li)。用椭球面上任意梯形面积计算公式计算出各小梯形图块AEiFiA1的面积Si,然后累加Si就得到梯形图块ABB1A1的面积,同理,依次计算出梯形图块BCC1B1、CDD1C1、DAA1D1的面积;
(5)多边形ABCD的面积就等于4个梯形图块(ABB1A1、BCC1B1、CDD1C1、DAA1D1)面积的代数和。
则任意多边形ABCD的面积P为:
P=ABCD= BCC1B1+ CDD1C1+ DAA1D1- ABB1A1
2.6空间分析
空间分析在数据处理过程中经常使用,缓冲区分析、标识、相交、裁剪、最短路径等等分析功能。由于他们分布在不同的工具箱中,导致使用的时候查找比较麻烦而且增加记忆的负荷量,将这些常用的分析工具集中到同一个功能点下,不仅方便操作还可以优化功能。
public static IGeometry GetGeometryBuffer(IGeometry iGeometry,double Distance)
{
public static IFeatureCursor GetFeatureCursor(IFeatureClass iFeatureClass,IGeometry iGeometry,esriSpatialRelEnum SpatialType)
{
if(iFeatureClass != null)
{
ISpatialFilter iSpatialFilter = new SpatialFilterClass();
iSpatialFilter.Geometry = iGeometry;
iSpatialFilter.SpatialRel = SpatialType;
return iFeatureClass.Search(iSpatialFilter,false);
}
}
2.7数据库合并
数据合并是测绘项目数据汇交必不可少的操作,传统的做法是人工一一合并,不仅浪费大量的时间和精力还耽误工作进度。开发一个高效可视化的合并工具可以大大提高工作效率还能及时导出合并日志,以便再次检查数据的准确性、合理性。这里可以选择要合并的数据(shp、gdb、mdb),选择合并的目标数据,在选择方案类型即可追加,同时可以看到追加日志情况也可以打开追加记录进行阅读。
图3
public static bool FeatureAppend(string sourcefeaturepath,string targetfeaturepath)
{
ESRI.ArcGIS.Geoprocessor.Geoprocessor gp = new ESRI.ArcGIS.Geoprocessor.Geoprocessor();
gp.OverwriteOutput = true;
ESRI.ArcGIS.DataManagementTools.Append append = new ESRI.ArcGIS.DataManagementTools.Append();
append.inputs = sourcefeaturepath;append.target = targetfeaturepath;append.schema_type = "NO_TEST";
gp.Execute(append,null);
return true;
}
3结束语
基于ArcEngine的二次开发,不仅节省了项目成本也对新技术的不断探索。
参考文献:
【1】国家测绘局,CHT 1007-2001,基础地理信息数字产品元数据2000-04-01.
【2】国家质量监督检验检疫总局,GBT 13989-2012 国家基本比例尺地形图分幅2012-10-01.
【3】国家质量监督检验检疫总局,GBT 17798-2007 地理空间数据交换格式,2007-12-01.
【4】邱洪钢 张青莲 陆绍强,ArcGIS Engine开发从入门到精通,人民邮电出版社.
【5】Christian Nagel Bill Evjen,C#高级编程(中文第七版),清华大学出版社.
作者简介:徐永赛(1988-),男,云南宣威市人;本科,助理工程师,研究方向:GIS二次开发。
论文作者:徐永赛
论文发表刊物:《基层建设》2020年第2期
论文发表时间:2020/4/30
标签:界址论文; 椭球论文; 坐标论文; 西北角论文; 编号论文; 数据库论文; 梯形论文; 《基层建设》2020年第2期论文;