数据生产过程中,经常需要将图层中的数据根据某个字段分割成不同的图层,比如,一个全省的图斑数据,可能需要分割成每个市一个图层。本工具主要实现上述功能,工具界面如下:
由于功能比较简单,代码主要放在Form中实现。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.ArcMapUI;
using AddInAssiter;
namespace DayDreamInGISTool.ClassifyByAttributes
{
public partial class frmSet : Form
{
public frmSet(IMap pMap)
{
this.pMap = pMap;
InitializeComponent();
}
IMap pMap = null;
IWorkspace pWs=null;
IWorkspaceName pWsN = null;
private IFeatureLayer pToBeSplitFtLyr = null;
private void frmSet_Load(object sender, EventArgs e)
{
if (pMap.LayerCount == 0)
return;
//Combox中加载所有矢量图层
GISCommonHelper.CartoLyrHelper.setFeatureLyrCombox(ref cmbLayer, pMap,
ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryAny);
}
private void btnOk_Click(object sender, EventArgs e)
{
string result = "";
if (chkAll.Checked)
{
//处理所有的图层
for (int i = 0; i < cmbLayer.Items.Count; i++)
{
result += ExportData((IFeatureLayer)((GISCommonHelper.name_Layer)cmbLayer.Items[i]).layer);
}
}
else
{
result += ExportData((IFeatureLayer)cmbLayer.SelectedValue);
}
MessageBox.Show("处理完成\r\n"+result);
this.DialogResult = DialogResult.OK;
}
/// <summary>
/// 对要素图层进行分割
/// 该功能本质上是通过导出功能实现,大体实现流程
/// (1)根据设置的分割字段,获取该图层该字段所有的唯一值
/// (2)设置导出条件
/// (3)导出到新的工作空间
/// </summary>
/// <param name="pFeatureLayer"></param>
/// <returns></returns>
private string ExportData(IFeatureLayer pFeatureLayer)
{
string strResult = "";
string fengeFieldStr = cmbField.Items[cmbField.SelectedIndex].ToString();
//分割字段类型只能是字符类型
IField pField =pFeatureLayer.FeatureClass.Fields.get_Field(pFeatureLayer.FeatureClass.Fields.FindField(fengeFieldStr));
//获取所有可能的值类型 调用AE的统计接口
IDataStatistics pDS = new DataStatisticsClass();
pDS.Field = fengeFieldStr;
IFeatureCursor pFeatureCursor = pFeatureLayer.FeatureClass.Search(null, false);
pDS.Cursor = pFeatureCursor as ICursor;
System.Collections.IEnumerator enumerator;
enumerator = pDS.UniqueValues;
enumerator.Reset();
int UVCount = pDS.UniqueValueCount;
progressBar1.Maximum = UVCount;
int tCount = 1;
enumerator.MoveNext();
object vl = enumerator.Current;
while (vl != null)
{
//设置分割条件
IQueryFilter pqf = new QueryFilterClass();
pqf.WhereClause = string.Format("{0}=\'{1}\'",fengeFieldStr,vl);
//将此属性值的数据输出至工作空间
IDataset pInDataset = pFeatureLayer.FeatureClass as IDataset;
IFeatureClassName pInFCName = pInDataset.FullName as IFeatureClassName;
IWorkspace pInWorkspace = pInDataset.Workspace;
//IDataset pOutDataset = pWs as IDataset;
//IWorkspaceName pOutWorkspaceName = pOutDataset.FullName as IWorkspaceName;
IWorkspaceName pOutWorkspaceName = pWsN;
IFeatureClassName pOutFCName = new FeatureClassNameClass();
IDatasetName pDatasetName = pOutFCName as IDatasetName;
pDatasetName.WorkspaceName = pOutWorkspaceName;
pDatasetName.Name = pInDataset.Name + "_" + vl; //要素类名称
//可能存在图层名重复或者非法的图层名
IFieldChecker pFieldChecker = new FieldCheckerClass();
pFieldChecker.InputWorkspace = pInWorkspace;
pFieldChecker.ValidateWorkspace = pWs;
IFields pFields = pFeatureLayer.FeatureClass.Fields;
IFields pOutFields;
IEnumFieldError pEnumFieldError;
pFieldChecker.Validate(pFields, out pEnumFieldError, out pOutFields);
IFeatureDataConverter pFeatureDataConverter = new FeatureDataConverterClass();
pFeatureDataConverter.ConvertFeatureClass(pInFCName, pqf, null, pOutFCName, null, pOutFields, "", 100, 0);
progressBar1.Value = tCount;
enumerator.MoveNext();
vl = enumerator.Current;
tCount++;
}
strResult = string.Format("图层{0}分割完毕!\n", pFeatureLayer.Name);
return strResult;
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.Cancel;
}
private void btnOpen_Click(object sender, EventArgs e)
{
//shapefile工作空间,FGDB工作空间,MDB工作空间
pWsN = GISCommonHelper.GeoDatabaseHelper.BrowseWorkspace(this.Handle.ToInt32(), out pWs);
if(pWsN!=null)
this.txtPath.Text = pWsN.PathName;
}
private void cmbField_SelectedIndexChanged(object sender, EventArgs e)
{
//
}
private void cmbLayer_SelectedIndexChanged(object sender, EventArgs e)
{
cmbField.Items.Clear();
if (cmbLayer.SelectedIndex > -1)
{
pToBeSplitFtLyr = cmbLayer.SelectedValue as IFeatureLayer;
//切换字段内容
IFields pFields = pToBeSplitFtLyr.FeatureClass.Fields;
for (int i = 0; i < pFields.FieldCount; i++)
{
if (pFields.get_Field(i).Type == esriFieldType.esriFieldTypeString)
{
//分割只针对字符类型
cmbField.Items.Add(pFields.get_Field(i).Name);
}
}
}
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
}
}
打开工作空间函数,其他内容请参考上一篇帖子 这里
public static IWorkspaceName BrowseWorkspace(int hwnd, out IWorkspace ws)
{
IGxObjectFilterCollection ipFilters = new GxDialogClass();
//IGxObjectFilter ipFilter1 = new GxFilterFeatureDatasetsClass(); //要素数据集 ,导出时,IFeatureClassConverter对象无法写入Dataset中,此处隐藏掉
//ipFilters.AddFilter(ipFilter1,false);
IGxObjectFilter ifilt2 = new GxFilterWorkspacesClass(); //数据库工作空间,此类比较含糊,不知道具体指啥
ipFilters.AddFilter(ifilt2, false);
IGxObjectFilter ipFilter3 = new GxFilterFileFolderClass(); //文件工作空间
ipFilters.AddFilter(ipFilter3, false);
IGxDialog pGDialog = (IGxDialog)ipFilters;
pGDialog.RememberLocation = true;
pGDialog.Title = "请选择工作空间";
pGDialog.AllowMultiSelect = false;
IEnumGxObject pResultEnum = null;
//IWorkspace ws = null;
ws = null;
IWorkspaceName wsn = null;
if (pGDialog.DoModalOpen(hwnd, out pResultEnum) && pResultEnum != null)
{
IGxObject gxObj = pResultEnum.Next();
if (gxObj is IGxDatabase)
{
IGxDatabase gxDB = gxObj as IGxDatabase;
if (gxDB != null)
{
ws = gxDB.Workspace;
wsn = gxDB.WorkspaceName;
}
}
else if (gxObj is IGxFolder)
{
//Todo: figure out how to decide which workspace to get for
// a particular folder (shapefile, raster etc.)
//IEnumName enumName = ((IGxFolder)gxObj).FileSystemWorkspaceNames;
// for now just assume we want a shapefile ...
IWorkspaceFactory wsf = new ESRI.ArcGIS.DataSourcesFile.ShapefileWorkspaceFactoryClass();
ws = wsf.OpenFromFile(((IGxFile)gxObj).Path, hwnd);
IDataset pOutDataset = ws as IDataset;
wsn = pOutDataset.FullName as IWorkspaceName;
}
else if (gxObj is IGxDataset)
{
//如果是数据集工作空间
IGxDataset gxDs = gxObj as IGxDataset;
if (gxDs != null)
{
ws = gxDs.Dataset.Workspace;
wsn = gxDs.DatasetName.WorkspaceName;
}
}
Marshal.FinalReleaseComObject(pResultEnum);
}
pGDialog.InternalCatalog.Close();
Marshal.FinalReleaseComObject(pGDialog);
return wsn;
}
Button代码,Button代码主要实现弹出form窗体
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using ESRI.ArcGIS.Carto;
using System.Windows.Forms;
namespace DayDreamInGISTool.ClassifyByAttributes
{
public class ButtonClassifyByAttributes : ESRI.ArcGIS.Desktop.AddIns.Button
{
public ButtonClassifyByAttributes()
{
}
protected override void OnClick()
{
try
{
if (false)
{
ArcMap.Application.CurrentTool = null;
return;
}
//
// TODO: Sample code showing how to access button host
//
ArcMap.Application.CurrentTool = null;
IMap pMap = ArcMap.Document.FocusMap;
//属性分割
frmSet fs = new frmSet(pMap);
fs.ShowDialog();
}
catch (System.Exception ex)
{
MessageBox.Show("发生未知错误:"+ex.Message);
}
}
protected override void OnUpdate()
{
Enabled = ArcMap.Application != null;
}
}
}
某测试数据包含一个行政区字段,
分割之后的效果