目录
- 2.4.1 数据结果:通过流程输出或者模块输出获取数据结果的方法
- 2.4.2 流程回调:某个流程运行开始与结束的回调方法
2.4.1 数据结果:通过流程输出或者模块输出获取数据结果的方法
描述
环境:VM4.2 + VS2013及以上
现象:方案或流程运行执行之后,就可以获取结果(建议将结果获取写在回调函数里),可以通过流程或者模块的输出获取渲染结果和数据结果,推荐使用流程的输出,符合高内聚低耦合,渲染结果通过绑定渲染控件进行显示,数据结果分为整型、浮点型、字符串型和图像型等等,VM二次开发如何获取数据结果?
解答
数据结果的获取可以通过流程的输出或者模块的输出,推荐使用通过流程的输出,符合高内聚低耦合的思想,VM4.2二次开发相比较VM4.0二次开发获取数据结果有一些更新,详细介绍如下所示:
1 通过流程的输出获取数据结果
1.1 流程配置-输出设置
1.2 获取整型、浮点型、字符串型数据
C#
VmProcedure vmprocess = (VmProcedure)VmSolution.Instance["流程1"];
var moduResult = vmprocess.ModuResult;
string str = moduResult.GetOutputInt(“out”).pIntVal[0].ToString();
string str1 = moduResult.GetOutputFloat(“out0”).pFloatVal[0].ToString();
string str2 = moduResult.GetOutputString("out1").astStringVal[0].strValue;
//获取流程结果列表,str3与str2结果一致
List<VmDynamicIODefine.IoNameInfo> ioNameInfos = VmProcess.ModuResult.GetAllOutputNameInfo();
string str3 = VmProcess.ModuResult.GetOutputString(ioNameInfos[2].Name).astStringVal[0].strValue;
1.3 获取图像数据
流程输出设置中输出IMAGE类型的图像数据,能通过前面参数名称ImageD直接获取。
C#
ImageBaseData_V2 processImageData = VmProcess1.ModuResult.GetOutputImageV2("ImageD");
int width = processImageData.Width;//宽
int height = processImageData.Height;//高
IntPtr imageByte = processImageData.ImageData;//数据
VMPixelFormat pixelformat = processImageData.Pixelformat;//格式
2 通过模块的输出获取数据结果 (与4.0二次开发相比无变化)
2.1 获取模块的浮点型数据
C#
IMVSCircleFindModuTool tool = (IMVSCircleFindModuTool)VmSolution.Instance["流程1.圆查找1"];
var moduResult = tool.ModuResult;
string circleX = moduResult.OutputCircle.CenterPoint.X.ToString();
string circleY = moduResult.OutputCircle.CenterPoint.Y.ToString();
string circleR = moduResult.OutputCircle.Radius.ToString();
2.2 获取图像数据,针对有图像输出的模块,例如,输出图像模块,注意像素格式17301505为MONO8灰度图,像素格式 35127316为RGB24彩色图。
C#
SaveImageTool saveImage=(SaveImageTool)VmSolution.Instance[“流程1.输出图像1”];
Var saveImageResult=saveIamge.ModuResult.OutputImage;
byte[] imageData= saveImageResult.ImageData;
int imagePixelformat= saveImageResult.Pixelformat;
问题根因
不熟悉如何获取数据结果。
2.4.2 流程回调:某个流程运行开始与结束的回调方法
描述
环境:VM4.2 + VS2013及以上
现象:除了所有流程运行结束的回调方法,如何注册某一流程开始与结束回调函数。
解答
1、C#中调用某个流程的开始与结束回调
加载sol文件后,根据流程名称注册流程开始和结束回调函数代码如下,其中textBoxProcessName.Text为流程名。
c#
try
{
m_VmPrc = (VmProcedure)VmSolution.Instance[textBoxProcessName.Text];
if (null == m_VmPrc)
{
MessageBoxButtons msgType = MessageBoxButtons.OK;
DialogResult diagMsg = MessageBox.Show(textBoxProcessName.Text + " name procedure does't exist", "Prompt", msgType);
if (diagMsg == DialogResult.OK)
{
return;
}
}
m_VmPrc.OnWorkBeginStatusCallBack += M_VmPrc_OnWorkBeginStatusCallBack;
m_VmPrc.OnWorkEndStatusCallBack += M_VmPrc_OnWorkEndStatusCallBack;
}
catch (VmException ex)
{
string strMsg = "Process failed. Error Code: " + Convert.ToString(ex.errorCode, 16);
listBoxMsg.Items.Add(strMsg);
listBoxMsg.TopIndex = listBoxMsg.Items.Count - 1;
return;
}
注消流程开始和结束回调函数代码如下。
try
{
m_VmPrc = (VmProcedure)VmSolution.Instance[textBoxProcessName.Text];
if (null == m_VmPrc)
{
MessageBoxButtons msgType = MessageBoxButtons.OK;
DialogResult diagMsg = MessageBox.Show(textBoxProcessName.Text + " name procedure does't exist", "Prompt", msgType);
if (diagMsg == DialogResult.OK)
{
return;
}
}
m_VmPrc.OnWorkBeginStatusCallBack -= M_VmPrc_OnWorkBeginStatusCallBack;
m_VmPrc.OnWorkEndStatusCallBack -= M_VmPrc_OnWorkEndStatusCallBack;
}
catch (VmException ex)
{
string strMsg = "Process failed. Error Code: " + Convert.ToString(ex.errorCode, 16);
listBoxMsg.Items.Add(strMsg);
listBoxMsg.TopIndex = listBoxMsg.Items.Count - 1;
return;
}
测试用回调函数如下。
private void M_VmPrc_OnWorkBeginStatusCallBack(object sender, EventArgs e)
{
Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} 流程开始");
//获取此流程中的模块结果
}
private void M_VmPrc_OnWorkEndStatusCallBack(object sender, EventArgs e)
{
Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} 流程结束");
}
单次运行流程 m_VmPrc.Run(),执行效果如下,说明首先执行的是M_VmPrc_OnWorkBeginStatusCallBack函数,然后执行的是M_VmPrc_OnWorkEndStatusCallBack函数;
2、C++ 中调用某个流程的开始与结束回调
注册回调,只需要创建一个流程事件类,这个流程事件类继承IVmProcedureEvent,代码如下所示:
class MyProcedureEvent :public IVmProcedureEvent
{
public:
virtual void OnWorkBeginStatusCallBack(IN const IMVS_PF_MODULE_WORK_STAUS *const pstWorkStatus, IN void *const pUser) override;
virtual void OnWorkEndStatusCallBack(IN const IMVS_PF_MODULE_WORK_STAUS *const pstWorkStatus, IN void *const pUser) override;
};
然后用户程序在主窗口类中,创建一个MyProcedureEvent实例,如下:
MyProcedureEvent myProcedureEvent;
例如:我们要注册流程1的结果回调,只需要在流程1加载完成的地方插入代码,调用注册回调的接口,典型的代码如下:
IVmSolution* vmSolution = LoadSolution(solPath, "");
IVmProcedure* vmProcedure = (IVmProcedure*)((*vmSolution)["流程1"]);
vmProcedure->RegisterCallBackEvent((IVmProcedureEvent*)&myProcedureEvent,this);
剩下就是用户在MyProcedureEvent类中,实现OnWorkEndStatusCallBack方法即可,比如在OnWorkEndStatusCallBack中获取流程1的运行结果,代码如下:
vector matchX;
vector matchY;
vector matchR;
void MyProcedureEvent::OnWorkEndStatusCallBack(IN const IMVS_PF_MODULE_WORK_STAUS * const pstWorkStatus, IN void * const pUser)
{
try
{
CMFCVM42DemoDlg* pDlg = (CMFCVM42DemoDlg*)pUser;
ObjectList list = pDlg->m_pSolution->GetAllProcedureObjects(); //获取当前方案的所有流程
IVmProcedure* procedure1 = (IVmProcedure*)(list.pObjects[0]); //获取第一个流程
//获取配置的matchX,matchY,matchR 输出
FloatDataArray matchXArray = procedure1->GetResult()->GetOutputFloat("matchX");
FloatDataArray matchYArray = procedure1->GetResult()->GetOutputFloat("matchY");
FloatDataArray matchRArray = procedure1->GetResult()->GetOutputFloat("matchR");
for (int i = 0; i < matchXArray.nValueNum; i++)
{
matchX.push_back(matchXArray.pFloatVal[i]);
matchY.push_back(matchYArray.pFloatVal[i]);
matchR.push_back(matchRArray.pFloatVal[i]);
}
}
catch (CVmException ex)
{
throw CVmException(ex);
}
}
问题根因
不熟悉流程相关回调函。