Hello PIE(未完成)
算法层
+ SystemAlgo库
要服务于图像处理功能的开发, 定义了ISystemAlgo接口和AlgoFactory类。 ISystemAlgo接口是算法的基础接口,它定义了算法实现的规则, AlgoFactory对象实现了对各种算法的同步或异步调用的管理和监视。
+ CommonAlgo库
其包含了PIE桌面版中几乎所有的图像处理的算法。
组件层
+ SystemUI库
定义了被PIE用户界面组件所使用的对象,ICommand、ICommandControl、ITool、 ITrackerCancel等接口。
+ AxControls库
- MapControl:主要用于地图数据的显示和分析, 其封装了一个Map对象,并提供了相应属性、方法和事件,用于管理控件的显示属性、 调整地图属性、 控制地图的显示范围、 管理数据图层、加载地图文档等。
常用方法
1).LoadPmdFile 方法
该方法用于在地图空间中加在地图文档,参数为地图文档路径
void LoadPmdFile(String pmdPath);
2).AddLayerFromFile方法
该方法用于在地图控件中添加图层,参数为图层数据路径和新加涂层的索引
bool AddLayerFromFile(String filePath,int toIndex);
附:区别LoadPmdFile
与AddLayerFromFile
,一般地图索引是随加载顺序依次递增
3).AddLayer方法
用于在地图控件中添加图层,参数为图层对象和新建图层索引
void AddLayer(ILayer layer, int toIndex);
附:
-
区别
AddLayer()
和AddLayerFromFile()
,两者传递的参数不一样,后者传递的参数是路径,前者传递的是Layer对象,需要通过LayerFactory()
函数来转化成Layer对象。 -
LayerFactory()
无论是矢量栅格数据,使用这个函数都会成为一个Layer数据。 -
使用方法
LayerFactory
(加载路径,记录索引)
private void toolStripButton1__AddData_Click(object sender, EventArgs e){//选择文件OpenFileDialog openFileDialog = new OpenFileDialog();openFileDialog.Filter = "RasterFile|*.tif;*.tiff;*.img|ShapeFile|*.shp";openFileDialog.Multiselect = false;if (openFileDialog.ShowDialog() != DialogResult.OK) return;//加载图层string FilePath = "";//@"E:\PIE软件设计\2020 PIE-SDK二次开发组件包\PIE SDK NET 201906\02.样例数据\China\中国湖泊.tif";FilePath = openFileDialog.FileName;ILayer layer = LayerFactory.CreateDefaultLayer(FilePath);//刷新图层mapControlMain.AddLayer(layer, 0);mapControlMain.PartialRefresh(ViewDrawPhaseType.ViewAll);}
4).DeleteLayer方法
该方法用于在地图控件删除图层,参数为要删除图层的索引
void DeleteLayer(int index);
5).ClearLayers方法
该方法用于删除地图控件上的所有图层
void ClearLayers();
附:对于DeleteLayer和ClearLayer主要区别就是前者是一个个删,后者是把所有地图都清除了
6).DrawShape方法
该方法在地图上绘制图形,参数为图形形状和图形样式
void DrawShape(IGeometry shape, ISymbol symbol);
IPoint point =new PIE.Geometry.Point();//定义图形
point.PutCoords(120,38,0);
ISymbol symbol=new SimpleMarkerSymbol();//定义样式
mapControlMain.DrawShape(Point as IGeometry, symbol);
7).ToMapPoint方法
屏幕坐标转化为地图坐标,参数为屏幕X坐标和屏幕Y坐标
IPoint ToMapPoint(int x, int y);
8).CenterAt方法
设置地图显示中心点
void CenterAt(IPoint centerPoint);
9).PartialRefresh方法
刷新当前地图显示控件,参数为刷新的类型
常用属性
1).FocusMap属性
2).ActiveView属性
3).Extent属性
4).FullExtent属性
5).SpatialReference属性
6).MapScale属性
实例代码:
private void toolStripButton1_SpatialReference_Click(object sender, EventArgs e){IMap map = mapControlMain.ActiveView.FocusMap;string Srname = map.SpatialReference.ExportToPrettyWkt();MessageBox.Show(Srname);}
- TOCControl(图层树控件)以树状列表的形式展示地图的图层结构,并且允许用户来调整地图的显示样式、查看地图和图层的基本信息、控制地图的图层顺序、调整地图的显示范围等。
- PageLayoutControl( 制图控件)封装了一个PageLayout对象, 并提供了一些属性、方法和事件, 用来控制制图的外观、 管理制图元素(比例尺、指北针、 图例)、输出或打印制图成果等。
实战
命令相关接口
ICommand
ICommand下的方法
方法 | 描述 |
---|---|
RasterCommand() | 加载栅格数据 |
VectorCommand() | 加载矢量数据 |
ScientificDatasetCommand() | 加载科学数据集 |
FullExtentCommand() | 全图显示 |
CenterZoomInCommand() | 居中放大 |
CenterZoomOutCommand() | 居中缩小 |
ITool
ITool下的方法
方法 | 描述 |
---|---|
MapZoomInTool() | 拉框放大 |
MapZoomOutTool() | 拉框缩小 |
PanTool() | 平移漫游 |
功能封装为ITool或ICommand
个人感觉实现很多功能不是很方便
- 创建一个类
- 继承
:BaseCommand
- 设置属性
- 重写一个
OnClick()
方法
加载数据的代码:
class AddData:BaseTool
{public AddData(){this.Caption = "加载数据";this.Name = "AddData";}public override void OnClick(){//选择文件OpenFileDialog openFileDialog = new OpenFileDialog();openFileDialog.Filter = "RasterFile|*.tif;*.tiff;*.img|ShapeFile|*.shp";openFileDialog.Multiselect = false;if (openFileDialog.ShowDialog() != DialogResult.OK) return;//加载图层string FilePath = "";//@"E:\PIE软件设计\2020 PIE-SDK二次开发组件包\PIE SDK NET 201906\02.样例数据\China\中国湖泊.tif";FilePath = openFileDialog.FileName;ILayer layer = LayerFactory.CreateDefaultLayer(FilePath);//刷新图层m_HookHelper.ActiveView.FocusMap.AddLayer(layer);//我的理解就是m_Hookhelper.ActiveView是与mapControlMain同类型但是加载数据时的另一种//mapControlMain.AddLayer(layer, 0);m_HookHelper.ActiveView.PartialRefresh(ViewDrawPhaseType.ViewAll);//m.PartialRefresh(ViewDrawPhaseType.ViewAll);}
}
- 复制粘贴一些功能
- 将重写一些方法
- 在主函数中打入调用命令的代码
对于图层交互式命令运用ITool代码如下:
ITool tool = new ZoomInTool();(tool as ICommand).OnCreate(mapControlMain);//将对象传给HookhelpermapControlMain.CurrentTool = tool;
对于非交互式的运用ICommand代码如下:
ICommand cmd = new AddData();cmd.OnCreate(mapControlMain);//将对象传给Hookhelpercmd.OnClick();
附:BaseCommand与DesktopCommand的区别:DesktopCommand在BaseCommand的基础上拓展了一个对象,IApplication,通过此对象可以调用BaseCommand不能调用主界面的内容,
如三大控件,进度条之类的。所以插件式开发常用到DesktopCommand类。
注意:组件是开发不能用到DesktopCommand命令,如果是用其中的HookHelper是空的
-
在设置按钮图片的时候可以使用
Properties
调用文件夹中存取的图片。
Properties.Resoures.Name
-
为什么创建的BaseCommand可以用ICommand创建出来?因为BaseCommand是继承了
ICommand
public class BaseCommand : ICommand
ICommand cmd = new AddData();
后期插件开发界面搭建和集成,视频四应该是必看的
插件式大概步骤
- 写一个继承BaseCommand或DesktopCommand的类
- 在类中实现一些功能
- 将程序类型改成类库,输出路径为 PIE 的
bin
目录,解决方案平台x86。 - 在PIEApplication.xml文件中添加自己刚刚写的程序集的名称
- 打开PIE主程序,即
PIEApplication.exe
组件式开发大致步骤
-
搭建基本界面
- menuStrip
- toolStrip
- SplitContaniner
- tabControl(Alignment:Buttom)
-
地图界面搭建
- TOCControl(左边)
- MapControl(右边地图模式)
- LayoutControl(右边制图模式)
-
三大控件的绑定
- 第一步
public Form1(){InitializeComponent();InitFrm();}private void InitFrm(){mapControl1.FocusMap = pageLayoutControl1.FocusMap;//绑定了mapControl和TocControltocControl1.SetBuddyControl(pageLayoutControl1);//绑定了TocControl和图层树}
Tip:
SetBuddyControl
函数最好绑定图层书与pageLayoutControl
对象,绑定MapControl
可能出现问题。-
第二步(解决切换难题)
原理:不能让地图控件和制图控件同时激活;
TabControl下的
SelectedIndexChanged()
写入判断代码:
if (tabControl1.SelectedIndex == 0){mapControl1.Activate();pageLayoutControl1.DeActivate();mapControl1.ActiveView.PartialRefresh(ViewDrawPhaseType.ViewAll);}if (tabControl1.SelectedIndex == 1){mapControl1.DeActivate();pageLayoutControl1.Activate();pageLayoutControl1.ActiveView.PartialRefresh(ViewDrawPhaseType.ViewAll);}
同时在初始话过程中只激活
MapControl
控件。private void InitFrm(){mapControl1.FocusMap = pageLayoutControl1.FocusMap;//绑定了mapControl和TocControltocControl1.SetBuddyControl(pageLayoutControl1);//绑定了TocControl和图层树mapControl1.Activate();//不能使两个空间同时激活;pageLayoutControl1.DeActivate();}
官方博客对小白比较适用的:
PIESDK技术博客
PIESDK命令一览表
完整搭建步骤见15,完整示例见链接里的百度网盘。
地图相关接口(未完成)
IMap
可以通过MapControl的FocusMap属性来获取图层的属性,返回值是一个结构体,里面存了一堆的string,如图
IActiveView
IMap定义了Map对象(图层)的数据管理监视功能,而IActiveView则定义了Map对象的数据显示功能。这个接口中经常用到的方法包括:
原型 | 说明 |
---|---|
void ZoomTo(IGeometry geometry) | 将视图平移到某集合对象的范围,参数为几何对象 |
void PartialRefresh(ViewDrawPhasetype dpType) | 刷新地图,参数为地图类型 |
IPoint ToMapPoint(System.Drawing.Point point) | 屏幕点转化为地图点,参数为屏幕点 |
System.Drawing.Point FromMapPoint(IPoint point) | 地图点转化为屏幕点,参数为地图点 |
属性 | 描述 |
FullExtent | 获取或者设置地图全图范围 |
Extent | 获取或者设置地图视图范围 |
图层添加和删除的监视代码
IActiveViewEvents
private void FormMain_Load(object sender, EventArgs e){IActiveViewEvents activeViewEvents = mapControlMain.ActiveView.FocusMap as IActiveViewEvents;activeViewEvents.OnLayerAdded += ActiveViewEvents_OnLayerAdded;//绑定activeViewEvents.OnLayerDeleted += ActiveViewEvents_OnLayerDeleted;}
关联函数:
/// <summary>
/// 图层删除事件
/// </summary>
/// <param name="layer"></param>
private void ActiveViewEvents_OnLayerDeleted(ILayer layer)
{string info = string.Format("{0}图层删除成功!", layer.Name);MessageBox.Show(info);
}/// <summary>
/// 图层的添加事件
/// </summary>
/// <param name="layer"></param>
private void ActiveViewEvents_OnLayerAdded(ILayer layer)
{string info = string.Format("{0}图层添加成功!", layer.Name);MessageBox.Show(info);
}
Tip:为了保证监视始终进行,一般将监视命令写在初始化事件中。
ILayer
需要注意的是Layer对象本身没有装载数据,而仅仅是获得了数据的引用而已,是用于管理数据源的连接。在PIE中数据始终存放在文件中,新添加的图层也只是获得了地理数据的硬盘位置而已,而没有拥有数据。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BF9kEsOI-1596515492024)(./2020-07-26_152255.jpg)]
实现添加进的图层监控ILayerEvents
在添加数据按钮的地方写入监控的代码:
private void ActiveViewEvents_OnLayerAdded(ILayer layer){string info = string.Format("{0}图层添加成功!", layer.Name);MessageBox.Show(info);ILayerEvents ilayerEvents = layer as ILayerEvents;//写在这里面是因为每添加ilayerEvents.OnPropertyChanged += IlayerEvents_OnPropertyChanged;ilayerEvents.OnRenderChanged += IlayerEvents_OnRenderChanged;ilayerEvents.OnVisibilityChanged += IlayerEvents_OnVisibilityChanged;}
写入渲染按钮单机代码
private void toolStripButton1_RGBRender_Click(object sender, EventArgs e){ILayer layer = mapControlMain.GetLayer(0);//判断是否符合操作条件if (layer == null) return;if (layer.LayerType != LayerType.LayerTypeRasterLayer) return;//对渲染方式进行修改IRasterRGBRender rgbRender = new RasterRGBRender();//实例化对象/*rgbRender.UseBlueBand = true;//使用蓝光波段rgbRender.UseAlphaBand = true;//用透明波段rgbRender.RedBandIndex = 3;红光渲染索引号;*/rgbRender.SetBandIndices(3, 2, 1);//默认是1、2、3//把原来的渲染方式修改成实例化的渲染方式IRasterLayer rasterLayer = layer as IRasterLayer;rasterLayer.Render = rgbRender as IRasterRender;mapControlMain.PartialRefresh(ViewDrawPhaseType.ViewAll);}
关联事件
private void IlayerEvents_OnRenderChanged(ILayer layer){string render = (layer as IRasterLayer).Render.ToString().Trim();string info = string.Format("{0}图层渲染方式发生改变为{1}!", layer.Name,render);MessageBox.Show(info);if (layer.LayerType != LayerType.LayerTypeRasterLayer) return;}
数据相关接口
IFeatureDataset
是可以存储空间数据的对象类,它为FeatureLayer提供了数据支持, 它是一个空间实体的集合,这些实体就是要素,在一个要素数据集中,所有的要素都使用同样的字段结构。 IFeatureDataset接口是操作要素数据集时使用的主要接口,它定义了要素数据的读取、编辑、保存等规则。
根据加载的Layer再获得FeatureData
IMap map =mapControlMain.FocusMap;
ILayer layer=mapControlMain.FocusMap;
IFeatureLayer fLayer=layer as IFeatureLayer;
IFeatureDataset fDataset =fLayer.FeatureClass.GetFeatureDataset();
反向: 根据FeatureDataset得到Layer
ILayer layer = LayerFactory.CreateDefaultFeatureLayer(featureDataSet) as ILayer;
根据路径得到FeatureDataset
IFeatureDataset featureDataSet = DatasetFactory.OpenFeatureDataset(filePath);
GetNextFeature()
获取下一个要素返回值为IFeature类型
IFeature接口
IFields接口
IFeature接口底下的方法 |
GetValue()
可以传入索引或者字段名就可以实现读取操作
GetFields()
读取当前要素的所有字段
GetFieldIndex
可以将字段名转换成索引号
IField接口
IGeometry接口
实现空间数据的可视化,图形显示,是PIE空间分析和运算功能的基础。
结构表示
数据相关功能
矢量数据的读取
private void toolStripButton1_RenderRead_Click(object sender, EventArgs e){//1、获取数据OpenFileDialog openFileDialog = new OpenFileDialog();openFileDialog.Filter = "shpFile|*.shp";if (openFileDialog.ShowDialog() != DialogResult.OK) return;string filePath = openFileDialog.FileName;//2、根据数据的到FeatureDataSetIFeatureDataset featureDataSet = DatasetFactory.OpenFeatureDataset(filePath);//3、根据字段获得字段索引IFields fields = featureDataSet.GetFields();int index = fields.GetFieldIndex("NAME");if (index == null) return;//4、根据字段索引遍历FeatureDataset,获取对应的Feature的字段值(value)IFeature feature = featureDataSet.GetNextFeature();string strValue = "";while (feature!=null){strValue+=feature.GetValue(index).ToString()+"\r\n";feature = featureDataSet.GetNextFeature();}//5、信息显示:加载到视图并刷新MessageBox.Show(strValue, "省会城市的名字");ILayer layer = LayerFactory.CreateDefaultFeatureLayer(featureDataSet) as ILayer;mapControlMain_RenderRead.ActiveView.FocusMap.AddLayer(layer);mapControlMain_RenderRead.PartialRefresh(ViewDrawPhaseType.ViewAll);}
栅格数据的读取
- 方式一 通过路径读取
OpenRasterDataset(Path)
- 方式二 通过
RasterLayer
的Dataset
属性获取
IRasterDataset接口
FullName
指全路径- GetRasterX\YSize()获取长宽
Read
读操作bool Read(int nx, int ny, int nWid, int nHei, object pData, int nBufXSize, int nBufYSize, PixelDataType eBufType, int nBandCount, int[] pBandMap);// nx: 栅格x坐标// ny: 栅格y坐标// nWid:读取的宽度// nHei:读取的高度// ptr:读取出的数据,要求必须是数组或指针// nBufXSize: 目标宽度// nBufYSize: 目标高度// eBufType:读取类型// nBandCount:波段数// pBandMap:波段映射// 返回结果: 是否成功
Write
写操作void WorldToPixel_Ex(double dblX, double dblY, ref double lCol, ref double lRow);// nx: 栅格x坐标// ny: 栅格y坐标// nWid: 写入的宽度// nHei:写入的高度// pData:数据缓冲// nBufXSize:缓冲宽度// nBufYSize: 缓冲高度// eBufType:写入类型// nBandCount: 波段数// pBandMap:波段映射// 返回结果: 是否成功
GetBandCount()
得到波段书GetRasterBand()
通过索引获取波段AddRasterBand()
添加波段PixelToWorld_Ex()
像素坐标转地图坐标WorldToPixel_Ex()
世界坐标转像素坐标
栅格数据的读取代码:
private void toolStripButton1_RasterRead_Click(object sender, EventArgs e){//1、栅格数据读取并转换为RasterDatasetOpenFileDialog openFileDialog = new OpenFileDialog();openFileDialog.Filter = "RasterFile|*.tif;*.tiff;*.img";if (openFileDialog.ShowDialog() != DialogResult.OK) return;string filePath = openFileDialog.FileName;SaveFileDialog saveDialog = new SaveFileDialog();saveDialog.Filter = "RasterFile|*.tif;*.tiff;*.img";if (saveDialog.ShowDialog() != DialogResult.OK) return;ILayer layer = LayerFactory.CreateDefaultLayer(filePath);mapControlMain_RenderRead.ActiveView.FocusMap.AddLayer(layer);mapControlMain_RenderRead.ActiveView.PartialRefresh(ViewDrawPhaseType.ViewAll);//方式一IRasterDataset rasterDataset = DatasetFactory.OpenRasterDataset(filePath, OpenMode.ReadOnly);if (rasterDataset == null) return;//方式二IRasterDataset rDataset = (layer as RasterLayer).Dataset;if (rasterDataset == null) return;//2、读取制定大小的RasterDatasetint xSize = rasterDataset.GetRasterXSize();//栅格宽度int ySize = rasterDataset.GetRasterYSize();//栅格高度int bandcount = rasterDataset.GetBandCount();//波段数量PixelDataType type = rasterDataset.GetRasterBand(0).GetRasterDataType();//数据类型Byte[] arr = new byte[xSize * ySize * bandcount];//数据缓冲数组int[] listMap = new int[bandcount];//波段映射for(int i = 0; i < bandcount; i++){listMap[i] = i + 1;}bool result = rasterDataset.Read(0, 0, xSize, ySize, arr, xSize, ySize, type, bandcount, listMap);if (result == false) return;//int a_height = 320;//int a_width = 330;//int x0 = 1440;//int y0 = 160;//3、创建新的栅格数据集IRasterDataset newDataset = DatasetFactory.CreateRasterDataset(saveDialog.FileName, xSize, ySize, bandcount, type, "GTiff", null);if (newDataset == null) return;result=newDataset.Write(0, 0, xSize, ySize, arr, xSize, ySize, type, bandcount, listMap);if (result == false) return;//4、设置新的栅格数据集的空间参考和放射六参数newDataset.SpatialReference = rasterDataset.SpatialReference;double[] geo = rasterDataset.GetGeoTransform();newDataset.SetGeoTransform(geo);//5、将读取的结果显示到地图中并刷新ILayer layer1 = LayerFactory.CreateDefaultRasterLayer(newDataset) as ILayer;mapControlMain_RenderRead.ActiveView.FocusMap.AddLayer(layer1);mapControlMain_RenderRead.PartialRefresh(ViewDrawPhaseType.ViewAll);}
Tips:
- 如果要裁剪图像那么在Read就要动手脚
- 栅格坐标系从左上角开始
- 空间参考的结构如图所示:
其中第0 3分别为x和y的坐标,2 4分别代表旋转角度,1 5分别为x和y方向的分辨率.
绘制几何图形 (这里写得不是很详细😅)
元素相关接口
IElement接口
在PIE中,可以显示在Map上的数据包括分为两大类,即地理数据和图形Element(元素) ,所有元素都实现了IElement接口, Element根据表现形式不同,可以分成不同的种类,所以IElement有众多的子类。
|
IElement的众多子类 |
ISymbol
ISymbol定义了PIE中符号的表示, GIS中离散的实体分为点、线、面三种, PIE中使用三种类型的符号MarkerSymbol、 LineSymbol、FillSymbol表示,此外还有TextSymbol用于文字标注,同一种类型的渲染方式也是千变万化的,所以PIE根据
符号的类型和渲染特性分成了众多的符号。
例子
算法相关接口和类
架构图 |
ISystemAlgo接口:负责算法的实现
ISystemAlgoEvent接口:负责算法的监控
IsystemAlgo
常用的属性有
//// 摘要:// 描述string Description { get; set; }//// 摘要:// 名称string Name { get; set; }//// 摘要:// 参数object Params { get; set; }//// 摘要:// 执行算法//// 返回结果:// 是否执行成功bool Execute();
在Execute()
下填写算法的执行步骤,返回结果为bool型,true为执行成功、false为执行失败。
IsystemAlgoEvent
为算法监控接口,其框架为
//// 摘要:// ISystemAlgoEvents系统算法事件接口public interface ISystemAlgoEvents{//// 摘要:// 执行完成事件event OnExecuteCompletedEventHandler OnExecuteCompleted;//// 摘要:// 进度变化事件event OnProgressChangedEventHandler OnProgressChanged;}
可以看出ISystemAlgoEvents
有两种监控:
- 监控算法是否完成
- 监控算法的进程(可以调用进度体属性)
BaseSystemAlgo是一个类,用于自定义算法。他的出现是方便的定义新的算法,因为接口是需要实现接口的所有方法。而类不需要。一下是BaseSystemAlgo的原码框架:
public class BaseSystemAlgo : ISystemAlgo, ISystemAlgoEvents{//.....}
可以看出来BaseSystemAlgo
继承了ISystemAlgo
, ISystemAlgoEvents
的两个接口。
AlgoFactory:实现算法管理
已有算法的调用(以裁剪算法为例子)
插件式开发的算法都需要继承PIE.Framework.DesktopCommand
基本步骤
-
算法创建
-
参数设置(PIE的自带算法是带有参数子类的,声明一个参数类,给他赋值)
DataPreImgClip_Exchange_Info info = new DataPreImgClip_Exchange_Info();info.InputFilePath = @"E:\PIE软件设计\2020 PIE-SDK二次开发组件包\PIE SDK NET 201906\02.样例数据\World\World.tif";info.OutputFilePath = @"E:\PIE软件设计\2020 PIE-SDK二次开发组件包\PIE SDK NET 201906\02.样例数据\World\China.tif";info.XStart = 1440;info.XEnd = 1770;info.YStart = 160;info.YEnd = 480;info.Type = 0;info.listBands = new List<int>() { 0, 1, 2 };info.FileType = "GTiff";
-
算法创建
ISystemAlgo algo = AlgoFactory.Instance().CreateAlgo("PIE.CommonAlgo.dll","PIE.CommonAlgo.ImageClipAlgo");if (algo == null) return;
格式为:
AlgoFactory.Instance().CreateAlgo(A,B)
需要注意的是:
A:程序集名称“PIE.CommonAlgo.dll”
B:命名空间+类名“PIE.CommonAlgo.ISODataClassificationAlgo”
最后把刚刚的参数类赋值给算法的参数子类。
-
-
算法执行
算法执行分两种:同步执行、异步执行。
同步执行ExcuteAlgo
、异步执行AsynExcuteAlgo
。
通过SystemAlgo.AlgoFactory.Instance().AsynExcuteAlgo(algo)
实现异步调用,也可通过ExcuteAlgo实现同步调用;
已有算法的调用中:算法的执行就是算法监控事件,监控算法的,因为其实已有的算法,所以执行事件一般和创建写在同一个类里。ISystemAlgoEvents algoEvents = algo as ISystemAlgoEvents;algoEvents.OnExecuteCompleted += AlgoEvents_OnExecuteCompleted;algoEvents.OnProgressChanged += AlgoEvents_OnProgressChanged;PIE.AxControls.IStatusBar status = m_Application.StatusBar;status.ShowProgress(0, 100, "");Application.DoEvents();//处理在消息中的所有Windows信息;AlgoFactory.Instance().AsynExecuteAlgo(algo);
另外还有写下两个关联函数:
关联函数
private int AlgoEvents_OnProgressChanged(double complete, string msg, ISystemAlgo algo){PIE.AxControls.IStatusBar status = m_Application.StatusBar;status.UpdateProgress((int)complete, msg);return 0;}/// <summary>/// 算法的完成事件/// </summary>/// <param name="algo"></param>private void AlgoEvents_OnExecuteCompleted(ISystemAlgo algo){DataPreImgClip_Exchange_Info info = (DataPreImgClip_Exchange_Info)algo.Params;ILayer layer = LayerFactory.CreateDefaultLayer(info.OutputFilePath);m_HookHelper.ActiveView.FocusMap.AddLayer(layer);ISystemAlgoEvents algoEvents = algo as ISystemAlgoEvents;algoEvents.OnExecuteCompleted -= AlgoEvents_OnExecuteCompleted;//解绑algoEvents.OnProgressChanged -= AlgoEvents_OnProgressChanged;//解绑PIE.AxControls.IStatusBar status = m_Application.StatusBar;status.UpdateProgress(100, "");status.HideProgress();status.UpdateProgress(0, "");m_HookHelper.ActiveView.PartialRefresh(ViewDrawPhaseType.ViewAll);}
为了避免不必要的麻烦务必在算法完成时对监控函数解绑。
所以对于已有算法的实现,相当于一个类中同时包含算法的声明(参数声明,和算法声明),算法监控,算法调用
新算法的构建(以图像复制粘贴算法为例)
算法构建的步骤如图所示 |
附上对应部分的代码:
新建算法的参数定义、算法定义、算法调用和监控是写在三个不同的类或结构体里的
参数定义
public class AlgoParams{public string InputFile { get; set; }public string OutputFile { get; set; }}
在同一命名空间下写一个存放该算法参数的类;
算法定义
/// <summary>/// 自定义算法/// </summary>public class DemoAlgo:BaseSystemAlgo{private AlgoParams m_Params;/// <summary>/// 算法参数/// </summary>public override object Params{get{return m_Params;}set{m_Params = (AlgoParams)value;}}public override bool Execute(){System.IO.File.Copy(m_Params.InputFile,m_Params.OutputFile,true);return true;}}
定义算法需要继承BaseSystemAlgo
- 定义参数字段,类型为刚刚创的参数类,重写Params方法。
- 写构造函数(空就行)。
- 写执行函数,具体而言就是你的算法想实现什么功能,记得返回值类型是是否执行成功。
调用算法
public class CopyFileCommand : PIE.Framework.DesktopCommand{public CopyFileCommand(){}public override void OnClick(){//1、参数的设置AlgoParams info = new AlgoParams();info.InputFile = @"H:\Program Files (x86)\ENVI\IDL71\examples\data\boulder.tif";info.OutputFile = @"C:\Users\lenovo\Desktop\Copy.tif";//2、算法创建ISystemAlgo Algo = AlgoFactory.Instance().CreateAlgo("ImgProcess.dll", "ImgProcess.DemoAlgo");Algo.Params = info;if (Algo == null) return;bool result =AlgoFactory.Instance().ExecuteAlgo(Algo);//3、算法执行if (result){System.Windows.Forms.MessageBox.Show("文件复制成功");}}}
调用算法的与已有算法调用写法一模一样:
- 参数设置
- 算法创建
- 算法执行(执行就包括监控)
Attention:
- 需要注意以上例子中的
CopyFileCommand
是写在xml文件的identity中的,表示按钮需要调用的文件名称 CreateAlgo("ImgProcess.dll", "ImgProcess.DemoAlgo");
中- 前一项是命名空间。
- 后一项是算法文件即第二步定义的算法类的名称。
- 算法实现
- 普通函数的调用
- 作为算法的插件
- 修改配置,增加按钮