using System; using System.Collections.Generic; using System.Threading; using TeamAAS.FlowEditor.Models; using TeamAAS.FlowEditor.Plugins; using Plugins.Halcon.Models; namespace Plugins.Halcon { // ───────────────────────────────────────────────────────────────────── // HALCON 逻辑判断分类算子(从主程序集迁入分类 DLL)。 // 显示名/类型全名保持不变 —— 工具箱、流程文件、公式绑定全部兼容。 // ───────────────────────────────────────────────────────────────────── /// H条件判断:对若干「左值 运算符 右值」条件求值,命中则执行对应后继节点(分支)。 [Serializable] [Plugin("H条件判断", PluginCategory.Halocn模块, typeof(HalconIfModel), "CallSplit", NodeShape = NodeCategory.Decision, IsSubFlowNode = true, VisionCategory = VisionPlugin.其他, Description = "逻辑判断:按数值条件命中分支,执行对应后继节点(如 面积>阈值 走 OK 分支)")] public class HalconIfPlugin : BasePlugin { public override List DeclareOutputs() { var list = new List { new OutputField("结果", typeof(bool)), new OutputField("执行分支数", typeof(int)), }; int n = Model?.Conditions?.Count ?? 0; for (int i = 1; i <= n; i++) list.Add(new OutputField($"[分支]执行流程{i}", typeof(string))); return list; } public override NodeRunStatus PluginRun(CancellationToken token, out Dictionary results) { var res = new Dictionary(); results = res; BranchTargets = new List(); int index = 0; try { var conditions = Model.Conditions ?? new List(); Log(3, $"开始条件判断,共 {conditions.Count} 个条件"); for (int i = 0; i < conditions.Count; i++) { var c = conditions[i]; double left = ToDouble(GetResolve(c.Left)); bool ok = Compare(left, c.Op, c.Right); Log(4, $"条件{i + 1}: {left:F3} {c.Op} {c.Right:F3} = {ok} → 目标[{c.TargetNodeName}]"); if (ok && !string.IsNullOrWhiteSpace(c.TargetNodeName)) { BranchTargets.Add(c.TargetNodeName); res[$"[分支]执行流程{index + 1}"] = c.TargetNodeName; index++; } } res["执行分支数"] = index; res["结果"] = index > 0; if (index == 0) { res["Error"] = "无命中分支"; Log(1, "条件判断无任何分支命中", TeamAAS.LogLevel.Warning); return NodeRunStatus.Failed; } Log(2, $"条件判断命中 {index} 个分支: {string.Join(", ", BranchTargets)}"); return NodeRunStatus.Success; } catch (Exception ex) { res["Error"] = ex.Message; res["结果"] = false; Log(1, $"条件判断异常: {ex.Message}", TeamAAS.LogLevel.Error); return NodeRunStatus.Failed; } } private static double ToDouble(object v) { if (v == null) return 0d; try { return Convert.ToDouble(v); } catch { return 0d; } } private static bool Compare(double left, HalconCompareOp op, double right) { switch (op) { case HalconCompareOp.大于: return left > right; case HalconCompareOp.大于等于: return left >= right; case HalconCompareOp.小于: return left < right; case HalconCompareOp.小于等于: return left <= right; case HalconCompareOp.等于: return Math.Abs(left - right) < 1e-9; case HalconCompareOp.不等于: return Math.Abs(left - right) >= 1e-9; default: return false; } } } } namespace Plugins.Halcon.Models { using PropertyGridLib.Attributes; using PropertyGridLib.Controls; using System.ComponentModel; using TeamAAS.FlowEditor.Plugins; using TeamAAS.FlowEngine.FormulaData; /// Halcon 条件判断:对若干「左值 运算符 右值」条件求值,命中则跳到对应后继节点(分支)。 [Serializable] public class HalconIfModel : HalconOperatorModelBase { [Category("属性")] [DisplayName("1.条件集合")] [Description("按顺序判定每个条件,命中的分支对应后继节点会被执行(可命中多个)")] [CollectionEditor(CanAdd = true, CanRemove = true, CanSort = true)] public List Conditions { get; set; } = new List(); } [Serializable] public class HalconCondition { public HalconCondition() { Left = new FormulaBound(); } [Category("条件")] [DisplayName("1.左值")] [Description("从子流程前序节点输出中选择(如 &{区域特征1.面积})")] [FormulaEditor(typeof(PluginDataProvider))] public FormulaBound Left { get; set; } [Category("条件")] [DisplayName("2.运算符")] [Description("左值与右值的比较方式")] public HalconCompareOp Op { get; set; } = HalconCompareOp.大于; [Category("条件")] [DisplayName("3.右值")] [Description("比较阈值(数值)")] public double Right { get; set; } = 0; [Category("条件")] [DisplayName("4.执行节点名")] [Description("条件命中时要执行的后继节点的「节点名称」(须与本判断节点相连)")] public string TargetNodeName { get; set; } = ""; public override string ToString() => $"{Left?.Formula ?? ""} {Op} {Right} → {TargetNodeName}"; } [Serializable] public enum HalconCompareOp { 大于 = 0, 大于等于 = 1, 小于 = 2, 小于等于 = 3, 等于 = 4, 不等于 = 5, } }