博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
GP开发示例:数据库去重
阅读量:6487 次
发布时间:2019-06-24

本文共 6384 字,大约阅读时间需要 21 分钟。

这个例子专业讲解基于ArcEngine使用GP开发的过程及遇到的问题。更多GP使用方法:

功能需求:现在外业第一次数据(简称调绘.mdb)和第二次数据(简称检查.mdb)有重复。第二次是在第一次的基础上进行的,即如果调绘.mdb中LCA层有365个要素,检查时发现错误,就删除了11个错误,并新增了43个,共408个,检查.mdb相对于调绘.mdb实际上有354个重复,现在要将重复的删除,mdb中包括点、线、面三种类型的要素类。

软件实现:在ArcGIS里利用工具可以实现,使用按空间位置查询,找出重复的,然后删除即可;由于每个mdb中的要素图层比较多,所以可以使用批处理,批处理时填写参数可以。但是,mdb较多,路径各不相同,图层较多,操作起不比较费时。

程序实现

1.首先确定用什么工具来实现(先在ArcGIS里做一次):利用空间位置查询选择重复的要素,开启编辑器,删除!

2.设计界面,我每写一个功能,都要把界面整理一下,因为我不想让它很丑就出去见人。这里使用DotNetBar,节省了相当多的时间。

3.因为是直接对数据库进行操作,所以首先就要遍历数据中的要素图层,一般做法是利用GP的ListFeatureClasses方法。

GP.SetEnvironmentValue("workspace", moreDBPath.Trim());IGpEnumList pGpEnumList = GP.ListFeatureClasses("", "", "");string strFC = pGpEnumList.Next();while (strFC != ""){    System.Windows.Forms.Application.DoEvents();    Console.WriteLine(strFC);    strFC = pGpEnumList.Next();}

选择遍历数据库没有问题!

4.利用按位置选择

SelectLayerByLocation SLBL = new SelectLayerByLocation();SLBL.in_layer = moreDB + "\\" + strFC;SLBL.select_features = referDB + "\\" + strFC;SLBL.overlap_type = "ARE_IDENTICAL_TO";GPClass.Execute(SLBL); //这里使用了自定义的GPClass类,可以直接使用GPExecute

报错ERROR 000368,去官网帮助一查,竟然没有368,这是为什么?但从相邻错误信息来看,应该是哪个参数无效!

再去官网看了按空间位置查询的帮助文档。它说:输入必须是要素图层;不可以是要素类。要素图层?要素类?以前一直把它们看成是一种意思,于是去查一下了帮助,长知识了。

结果Python的示例代码,使用了MakeFeatureLayer来创建要素图层。

//创建要素图层MakeFeatureLayer MFL = new MakeFeatureLayer();MFL.in_features = moreDB + "\\" + strFC;MFL.out_layer = strFC + @"_Lyr";GPClass.Execute(MFL);//按位置选择SelectLayerByLocation SLBL = new SelectLayerByLocation();SLBL.in_layer = strFC + @"_Lyr";SLBL.select_features = referDB + "\\" + strFC;SLBL.overlap_type = "ARE_IDENTICAL_TO";GPClass.Execute(SLBL);

GP执行成功,虽然还看不到效果。因为MakeFeatureLayer是临时图层,程序结束就没有了,需要将它导出来:

//复制要素导出
CopyFeatures CF = new CopyFeatures();CF.in_features = strFC + @"_Lyr";CF.out_feature_class = resultDB + "\\" + strFC;GPClass.Execute(CF);

现在的问题是是选择类型是ARE_IDENTICAL_TO,如果输入图层中的要素与某一选择要素相同(就几何而言),则会选择这些要素。生成的mdb是重复那一部分,而需要的结果是不重复的那一部分。在ArcGIS里可以通过切换选择来操作。于是想,先把它全部选中,然后将重复的移除。代码:

//创建要素图层MakeFeatureLayer MFL = new MakeFeatureLayer();MFL.in_features = moreDB + "\\" + strFC;MFL.out_layer = strFC + @"_Lyr";GPClass.Execute(MFL);//选择所有SelectLayerByAttribute SLBA = new SelectLayerByAttribute();SLBA.in_layer_or_view = strFC + @"_Lyr";GPClass.Execute(SLBA);//按位置选择(移除)SelectLayerByLocation SLBL = new SelectLayerByLocation();SLBL.in_layer = strFC + @"_Lyr";SLBL.select_features = referDB + "\\" + strFC;SLBL.overlap_type = "ARE_IDENTICAL_TO";SLBL.selection_type = "REMOVE_FROM_SELECTION";GPClass.Execute(SLBL);//复制要素CopyFeatures CF = new CopyFeatures();CF.in_features = strFC + @"_Lyr";CF.out_feature_class = resultDB + "\\" + strFC;GPClass.Execute(CF);
终于实现了。

5.为了增加用户的体验,重写在了一个类,并把新建一个线程来处理:

string referDB = "";string moreDB = "";string resultDB = "";ProgressBarX progress = null;public NoRepeatClass(string _referDB, string _moreDB, string _resultDB, ProgressBarX _progress){    referDB = _referDB;    moreDB = _moreDB;    resultDB = _resultDB;    progress = _progress;    Thread MyThreadOne = new Thread(new ThreadStart(MainFun));    MyThreadOne.Name = "NoRepeat";    MyThreadOne.IsBackground = true;    MyThreadOne.Start();}private void MainFun(){ //主程序代码}

6.为了让用户知道处理的进度,于是添加了进度条,并更新内容为当前处理图层的名称。但这里,不能直接在一个线程里设置主线程的控件属性,于是找了一个函数:

#region 设置控件参数/// /// 设置控件参数/// /// 控件/// 参数名称/// 参数值delegate void SetControlValueCallback(Control oControl, string propName, object propValue);public static  void SetControlPropertyValue(Control oControl, string propName, object propValue){    if (oControl.InvokeRequired)    {        SetControlValueCallback d = new SetControlValueCallback(SetControlPropertyValue);        oControl.Invoke(d, new object[] { oControl, propName, propValue });    }    else    {        Type t = oControl.GetType();        System.Reflection.PropertyInfo[] props = t.GetProperties();        foreach (System.Reflection.PropertyInfo p in props)        {            if (p.Name.ToUpper() == propName.ToUpper())            {                p.SetValue(oControl, propValue, null);            }        }    }}#endregion

目前的效果如下:

7.为了提高操作效率,增加了路径拖放功能,下面是拖放类:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Windows.Forms;using System.IO;namespace GPTools{    class DragClass    {        private  Control control;        private string fileType = "";        public DragClass(Control _control,string _fileType)        {            //如果控件为空             if (_control == null)            {                return;            }            control = _control;            fileType = _fileType;            //设置是否可以拖放            control.AllowDrop = true;            //定义拖放事件            control.DragEnter += new DragEventHandler(control_DragEnter);          ontrol.DragDrop += new DragEventHandler(control_DragDrop);        }        private void control_DragEnter(object sender, DragEventArgs e)        {            if (e.Data.GetDataPresent(DataFormats.FileDrop))            {                e.Effect = DragDropEffects.Copy;            }        }        private void control_DragDrop(object sender, DragEventArgs e)        {            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);            foreach (string file in files)            {                //判断文件类型                if (Path.GetExtension(file) == fileType)                {                    Console.WriteLine(file);                    control.Text = file;                }            }        }    }}

在初始化主程序后实例化拖放类,一旦拖放就会触发DragEnter事件和DragDrop事件:

DragClass dg = new DragClass(this.txbReferDB, ".mdb");DragClass dg2 = new DragClass(this.txbMoreDB, ".mdb");

8.因为我们只遍历了检查.mdb中的图层,万一调绘.mdb中没有对应图层怎么,所以,我们得检查,如果没有则跳过。

//创建要素图层//……//检查数据object dt = "";if (GPClass.GP.Exists(referDB + "\\" + strFC, ref dt)){    //3.选择所有    //4.按位置选择(移除)}//复制要素//……
9.为了更准确的统计操作时间,添加了计时功能。效果图如下:

 

10.为了让用户快速进行执行任务,可以在执行按钮上添加Enter事件。

private void btnExcute_Enter(object sender, EventArgs e){    Excute();}private void Excute(){    referDBPath = txbReferDB.Text.Trim();    moreDBPath = txbMoreDB.Text.Trim();    resultDBPath = txbResultDB.Text.Trim();    if (referDBPath.Trim() != "" && moreDBPath.Trim() != "" && resultDBPath.Trim() != "")    {        NoRepeatClass nr = new NoRepeatClass(referDBPath, moreDBPath, resultDBPath, progressBar);    }    else    {        MessageBoxEx.EnableGlass = false;        MessageBoxEx.Show("警告:数据库路径选择有误!\n    请检查数据路径是否正确。", "提示");    }}

 

参考:

 

转载于:https://www.cnblogs.com/liweis/p/4213673.html

你可能感兴趣的文章
矩阵和向量的基本含义
查看>>
Python_文件操作
查看>>
golang 网络框架之 thrift
查看>>
JavaScript中this总结
查看>>
译:Linux 文件系统介绍
查看>>
Java泛型
查看>>
2017-10-24 前端日报
查看>>
angular2 响应式表单
查看>>
【271天】我爱刷题系列(30)
查看>>
关于Python中的日期处理
查看>>
CentOS6 mininal 安装CouchDB2 详细版
查看>>
Sequelize Docs 中文文档 v4
查看>>
TF-IDF、词袋模型与特征工程
查看>>
初入ES6-Proxy和Reflect
查看>>
XML进阶:Level 1 - XML简介
查看>>
JavaScript之类型
查看>>
Java虚拟机的内存结构
查看>>
node.js 中间件express-session使用详解
查看>>
leetcode 94. Binary Tree Inorder Traversal
查看>>
spring boot admin系统监控处理
查看>>