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);//将对象传给Hookhelper
mapControlMain.CurrentTool = tool;
对于非交互式的运用ICommand代码如下:
ICommand cmd = new AddData();
cmd.OnCreate(mapControlMain);//将对象传给Hookhelper
cmd.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和TocControl tocControl1.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和TocControl tocControl1.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、根据数据的到FeatureDataSet
IFeatureDataset 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、栅格数据读取并转换为RasterDataset
OpenFileDialog 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、读取制定大小的RasterDataset
int 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");
中- 前一项是命名空间。
- 后一项是算法文件即第二步定义的算法类的名称。
- 算法实现
- 普通函数的调用
- 作为算法的插件
- 修改配置,增加按钮