【流程图】在 .NET (WPF 或 WinForms) 中实现流程图中的连线算法

在 .NET (WPF 或 WinForms) 中实现流程图中的连线算法,通常涉及 图形绘制路径计算 。常见的连线方式包括 直线折线贝塞尔曲线。以下是几种方法的介绍和示例代码。


1. 直线连接(最简单)

适用场景

  • 两个节点之间没有障碍物时,最简单的方式。

计算方式

  • 直接用起点 (x1, y1) 和终点 (x2, y2) 画一条直线。

WPF 示例代码

xml 复制代码
<Canvas x:Name="canvas" Background="White">
    <Line X1="100" Y1="100" X2="300" Y2="200"
          Stroke="Black" StrokeThickness="2"/>
</Canvas>

2. 折线连接(适用于流程图)

适用场景

  • 流程图、状态机 这类需要避开障碍的情况。

计算方式

  • 如果两个点在水平方向或垂直方向对齐,直接连线。
  • 否则,使用水平-垂直垂直-水平折线路径。

算法步骤

  1. 确定起点 (x1, y1) 和终点 (x2, y2)
  2. 选择折线拐点:
    • 中间点1 = (x1, y1 + Δy)
    • 中间点2 = (x2, y1 + Δy)

WPF 示例代码

xml 复制代码
<Canvas x:Name="canvas" Background="White">
    <Polyline Stroke="Black" StrokeThickness="2"
              Points="100,100 100,200 300,200"/>
</Canvas>

C# 代码动态生成折线

csharp 复制代码
using System.Windows;
using System.Windows.Shapes;
using System.Windows.Controls;
using System.Windows.Media;

public void DrawPolyline(Canvas canvas, Point start, Point end)
{
    Polyline polyline = new Polyline
    {
        Stroke = Brushes.Black,
        StrokeThickness = 2
    };

    // 计算拐点
    Point mid1 = new Point(start.X, (start.Y + end.Y) / 2);
    Point mid2 = new Point(end.X, (start.Y + end.Y) / 2);

    polyline.Points.Add(start);
    polyline.Points.Add(mid1);
    polyline.Points.Add(mid2);
    polyline.Points.Add(end);

    canvas.Children.Add(polyline);
}

3. 贝塞尔曲线连接(更平滑)

适用场景

  • 逻辑图、网络关系图、UML 图 ,需要平滑曲线的情况。

计算方式

  • 使用 三次贝塞尔曲线 (Cubic Bezier Curve)
    • 起点 (x1, y1)
    • 终点 (x2, y2)
    • 两个控制点 (cx1, cy1)(cx2, cy2)

算法步骤

  1. 计算控制点:
    • cx1 = x1 + Δx / 2
    • cy1 = y1
    • cx2 = x2 - Δx / 2
    • cy2 = y2
  2. 使用 Path + BezierSegment 进行绘制。

WPF 示例代码

xml 复制代码
<Path Stroke="Black" StrokeThickness="2">
    <Path.Data>
        <PathGeometry>
            <PathFigure StartPoint="100,100">
                <BezierSegment Point1="150,100" Point2="250,200" Point3="300,200"/>
            </PathFigure>
        </PathGeometry>
    </Path.Data>
</Path>

C# 代码动态生成

csharp 复制代码
using System.Windows;
using System.Windows.Shapes;
using System.Windows.Controls;
using System.Windows.Media;

public void DrawBezier(Canvas canvas, Point start, Point end)
{
    Path path = new Path
    {
        Stroke = Brushes.Black,
        StrokeThickness = 2
    };

    PathGeometry geometry = new PathGeometry();
    PathFigure figure = new PathFigure { StartPoint = start };
    
    BezierSegment bezier = new BezierSegment
    {
        Point1 = new Point(start.X + (end.X - start.X) / 2, start.Y),
        Point2 = new Point(end.X - (end.X - start.X) / 2, end.Y),
        Point3 = end
    };

    figure.Segments.Add(bezier);
    geometry.Figures.Add(figure);
    path.Data = geometry;

    canvas.Children.Add(path);
}

4. 避障碍物的连线(A*路径算法)

适用场景

  • 复杂流程图、管道布线、自动路径计算
  • 遇到障碍物时,需要智能避开

算法思路

  1. 建模:将整个画布视为网格(如 10×10 的小方块)。
  2. 路径计算
    • 使用 A 搜索算法 * 找到起点到终点的最短路径
    • 允许横向、纵向移动,但不能穿过障碍物
  3. 连线方式
    • 根据 A* 计算出的路径,在网格点之间绘制折线。

C# 实现思路

csharp 复制代码
public List<Point> AStarFindPath(Point start, Point end, List<Rect> obstacles)
{
    // 使用 A* 寻路算法,返回经过的路径点
    // 省略 A* 具体实现,可使用 AStarSharp 库
    return new List<Point> { start, new Point(200, 150), end };
}

public void DrawPath(Canvas canvas, Point start, Point end, List<Rect> obstacles)
{
    List<Point> path = AStarFindPath(start, end, obstacles);

    Polyline polyline = new Polyline
    {
        Stroke = Brushes.Black,
        StrokeThickness = 2
    };
    foreach (var point in path)
        polyline.Points.Add(point);

    canvas.Children.Add(polyline);
}

总结

方法 适用场景 优点 缺点
直线连接 简单流程图 计算简单,性能高 不能避开障碍物
折线连接 业务流程图、状态图 适应复杂布局,易控制 可能需要手动计算拐点
贝塞尔曲线 关系图、UML 平滑美观,减少交叉 控制点计算较复杂
A 避障路径* 复杂流程、自动布线 自动选择最优路径 计算复杂,性能开销大

如果你的流程图 节点不会重叠 ,可以用 折线贝塞尔曲线

如果有 障碍物 ,建议使用 A 算法* 计算路径。

你打算在哪种场景下使用?

相关推荐
rockey62721 小时前
AScript之eval函数详解
c#·.net·script·eval·expression·动态脚本
longxibo1 天前
【Flowable 7.2 源码深度解析与实战-前言】
java·后端·流程图
longxibo1 天前
【第1章 环境搭建与项目结构解析】
java·后端·流程图
周杰伦fans2 天前
AutoCAD .NET 二次开发:深入理解 EntityJig 的工作原理与正确实现
开发语言·.net
20YC编程社区2 天前
一分钟学会绘制Mermaid流程图
流程图·markdown·mermaid流程图
KmSH8umpK2 天前
Redis分布式锁从原生手写到Redisson高阶落地,附线上死锁复盘优化方案进阶第三篇
redis·分布式·wpf
SKY -dada2 天前
Understand 使用教程
开发语言·c#·流程图·软件构建·敏捷流程·代码复审·源代码管理
KmSH8umpK2 天前
Redis分布式锁从原生手写到Redisson高阶落地,附线上死锁复盘优化方案
redis·分布式·wpf
fox_lht2 天前
onPaint函数流程图
java·eclipse·流程图
William_cl2 天前
【C#/.NET 进阶】ASP.NET 架构与最佳实践:DI 依赖注入(IoC 核心)从入门到避坑
c#·asp.net·.net