WPF 力导引算法构建图布局

news/2026/1/18 22:44:12/文章来源:https://www.cnblogs.com/ljbguanli/p/19499384

WPF 力导引算法构建图布局

WPF 力导引算法实现图布局

1 经典基础算法

  1. Eades 算法 (1984)

  2. Fruchterman-Reingold 算法 (1991)

  3. Kamada-Kawai 算法 (1989)

2 高性能优化算法(适合大规模网络)

  1. Barnes-Hut 近似算法 (基于四叉树/八叉树)

    • 核心思想:将远距离节点群近似为单个质心,将斥力计算复杂度从 O(N²) 降为 O(N log N)。

    • 应用:常用于天体物理的N-body问题,被集成到许多力导引布局工具中。

  2. ForceAtlas2 (2011)

    • 核心思想:专为Gephi软件设计的算法,在FR基础上改进:

      • 引入度依赖的斥力(高度数节点产生更强斥力,避免中心重叠)。

      • 支持边缘权重调整吸引力。

      • 采用自适应温度防止震荡的阻尼。

    • 特点:适合复杂真实网络(如社交网络),布局层次清晰。

  3. LinLog 模型

    • 核心思想:优化能量函数为U = Σ边的距离 - Σ节点对的log(距离),强调聚类结构

    • 特点:同一簇内节点更紧密,簇间距离更明显。

3 代码实现

  1. 数据模型
/// <summary>/// 节点
/// </summary>
public class Node
{
public string Id { get; set; }
public double X { get; set; }
public double Y { get; set; }
public double Radius { get; set; }
// 布局计算中使用的临时变量
internal double DX { get; set; } // X轴位移/速度
internal double DY { get; set; } // Y轴位移/速度
internal int Degree { get; set; } // 节点的度(连接数)
public Node(string id, double radius = 5.0)
{
Id = id;
Radius = radius;
}
public override string ToString() => $"Node[{Id}]: ({X:F2}, {Y:F2})";
}
/// <summary>/// 关系
/// </summary>
public class Relationship
{
public string Id { get; set; }
public string SourceId { get; set; }
public string TargetId { get; set; }
public Relationship(string source, string target)
{
SourceId = source;
TargetId = target;
Id = Guid.NewGuid().ToString();
}
public Relationship(string source, string target, string id)
{
SourceId = source;
TargetId = target;
Id = id;
}
}
/// <summary>/// 图结构
/// </summary>
public class Graph
{
public Dictionary<string, Node> Nodes { get; set; }public Dictionary<string, Relationship> Relationships { get; set; }public Graph(){Nodes = new Dictionary<string, Node>();Relationships = new Dictionary<string, Relationship>();}public void AddNode(Node node){Nodes[node.Id] = node;}public void AddRelationship(Relationship relationship){Relationships[relationship.Id] = relationship;}}/// <summary>/// 矩形布局范围/// </summary>public struct LayoutBounds{public double MinX;public double MaxX;public double MinY;public double MaxY;public LayoutBounds(double x, double y, double width, double height){MinX = x;MinY = y;MaxX = x + width;MaxY = y + height;}public double Width => MaxX - MinX;public double Height => MaxY - MinY;public double CenterX => (MinX + MaxX) / 2.0;public double CenterY => (MinY + MaxY) / 2.0;}
  1. 核心算法
public class LinLogLayout
{
// 配置参数
private const int Iterations = 100;             // 迭代次数
private const double RepulsionForce = 20.0;     // 斥力
private const double AttractionForce = 1.0;     // 引力
private const double StepSize = 0.8;            // 稍微调大初始步长以适应约束
private const double Decay = 0.97;              // 衰变系数
private const double GravityStrength = 0.01;    // 强度越大,图越紧凑在中央
private const double MinClearance = 0.1;        // 斥力计算的最小安全距离(防止除以零,并作为最小非重叠缓冲)
private const double Epsilon = 1e-6;            // 防止除以零的微小值 (Epsilon)
private const double MaxMovementPerStep = 2.0;  // 限制节点单步最大移动距离。值越小,越稳定,但收敛越慢。在边界小的情况下,此值应适当减小。
/// <summary>/// 执行布局计算
/// </summary>
/// <param name="nodes">节点列表</param>
/// <param name="relations">关系列表</param>
/// <param name="bounds">矩形限制范围</param>
public void ComputeLayout(List<Node> nodes, List<Relationship> relations, LayoutBounds bounds){if (nodes == null || nodes.Count == 0) return;// 1. 初始化:将节点随机放置在边界范围内//    这比在(0,0)附近随机更好,避免一开始就飞出很远Random rnd = new Random();foreach (var n in nodes){// 如果节点还没坐标(或是0,0),给一个范围内的随机值if (Math.Abs(n.X) < 0.001 && Math.Abs(n.Y) < 0.001){n.X = bounds.MinX + rnd.NextDouble() * bounds.Width;n.Y = bounds.MinY + rnd.NextDouble() * bounds.Height;}}var nodeDict = nodes.ToDictionary(n => n.Id);// 筛选有效关系var validRelations = relations.Where(r => nodeDict.ContainsKey(r.SourceId) && nodeDict.ContainsKey(r.TargetId)).ToList();double currentStep = StepSize;// 2. 迭代循环for (int i = 0; i < Iterations; i++){// 重置力向量foreach (var n in nodes) { n.DX = 0; n.DY = 0; }// --- A. 计算斥力 (Repulsion) 考虑 Radius ---for (int a = 0; a < nodes.Count; a++){var nodeA = nodes[a];for (int b = a + 1; b < nodes.Count; b++){var nodeB = nodes[b];double dx = nodeA.X - nodeB.X;double dy = nodeA.Y - nodeB.Y;double distSq = dx * dx + dy * dy;double dist = Math.Sqrt(distSq); // 节点中心点的实际距离// NaN 保护机制 1: 检查中心距离是否为零if (dist < Epsilon){// 节点完全重叠,施加随机扰动以获得方向dx = rnd.NextDouble() * 2 * Epsilon;dy = rnd.NextDouble() * 2 * Epsilon;dist = Math.Sqrt(dx * dx + dy * dy);// 确保 dist 不会是 NaN 或零if (dist < Epsilon) dist = Epsilon;}// 1. 计算两个节点半径之和double sumOfRadii = nodeA.Radius + nodeB.Radius;// 2. 计算节点表面之间的净空距离 (Clearance)double clearance = dist - sumOfRadii;// 3. 确定用于斥力计算的有效距离 (Effective Distance)// 如果节点重叠 (clearance <= 0),将有效距离强制设为 MinClearance (0.1) // 这将产生巨大的斥力来推开重叠的节点double effectiveDist = Math.Max(clearance, MinClearance);// 4. 应用 LinLog 斥力公式: F = K / effectiveDist// 注意:这里的斥力是基于表面距离的,而不是中心距离。double force = RepulsionForce / effectiveDist;// 5. 应用斥力 (方向仍基于中心点连线)double fx = (dx / dist) * force;double fy = (dy / dist) * force;nodeA.DX += fx; nodeA.DY += fy;nodeB.DX -= fx; nodeB.DY -= fy;}}// --- B. 计算引力 (Attraction) ---foreach (var rel in validRelations){var u = nodeDict[rel.SourceId];var v = nodeDict[rel.TargetId];double dx = v.X - u.X;double dy = v.Y - u.Y;double distSq = dx * dx + dy * dy;double dist = Math.Sqrt(distSq);// NaN 保护机制 2: 检查中心距离是否为零if (dist < Epsilon){// 节点重叠,跳过引力计算(让斥力将它们推开)continue;}// LinLog Attractiondouble force = AttractionForce;double fx = (dx / dist) * force;double fy = (dy / dist) * force;u.DX += fx;u.DY += fy;v.DX -= fx;v.DY -= fy;}// --- C. 计算中心引力 (Central Gravity) ---double centerX = bounds.CenterX;double centerY = bounds.CenterY;foreach (var n in nodes){double dx = n.X - centerX; // 节点指向中心的向量是 -dxdouble dy = n.Y - centerY;double dist = Math.Sqrt(dx * dx + dy * dy);// NaN 保护机制 3: 检查距离是否为零if (dist < Epsilon){// 节点在中心点,力为零,跳过计算continue;}double force = GravityStrength * dist;n.DX -= (dx / dist) * force;n.DY -= (dy / dist) * force;}// --- D. 更新位置并应用边界约束 ---foreach (var n in nodes){// 1. 计算理论位移double movementX = n.DX * currentStep;double movementY = n.DY * currentStep;double movementDist = Math.Sqrt(movementX * movementX + movementY * movementY);// 2. 限制最大位移if (movementDist > MaxMovementPerStep){// 如果超出最大限制,按比例缩小位移向量double ratio = MaxMovementPerStep / movementDist;movementX *= ratio;movementY *= ratio;}// 3. 应用位移n.X += movementX;n.Y += movementY;// 4. 矩形边界硬约束if (n.X < bounds.MinX) n.X = bounds.MinX;else if (n.X > bounds.MaxX) n.X = bounds.MaxX;if (n.Y < bounds.MinY) n.Y = bounds.MinY;else if (n.Y > bounds.MaxY) n.Y = bounds.MaxY;}//foreach (var n in nodes)//{//    // 移动//    n.X += n.DX * currentStep;//    n.Y += n.DY * currentStep;//    // 边界限制 (Clamping)//    if (n.X < bounds.MinX) n.X = bounds.MinX;//    else if (n.X > bounds.MaxX) n.X = bounds.MaxX;//    if (n.Y < bounds.MinY) n.Y = bounds.MinY;//    else if (n.Y > bounds.MaxY) n.Y = bounds.MaxY;//}// --- E. 冷却 ---currentStep *= Decay;}}}

效果Demo:
在这里插入图片描述
在这里插入图片描述
效果视频:

https://live.csdn.net/v/504775
https://raw.githubusercontent.com/Winemonk/images/master/blog/post/202512091617226.mp4

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1179663.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【课程设计/毕业设计】基于深度学习python-CNN-pytorch训练识别T恤的颜色

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

深度学习毕设项目:基于python-CNN深度学习的蝴蝶识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

STM32-S08-RFID刷卡(IC卡管理)+密码开锁(可设)+TFT彩屏+舵机+蜂鸣器+矩阵按键+(无线方式选择)

STM32-S08-RFID刷卡(IC卡管理)密码开锁(可设)TFT彩屏舵机蜂鸣器矩阵按键(无线方式选择)STM32-S08N无无线-无APP板: STM32-S08B蓝牙无线-APP版: STM32-S08W-WIFI无线-APP版: STM32-S08CAN-视频监控WIFI无线-APP版: 产品功能描述&#xff1a; 本系统由STM32F103C8T6单片机核心板、…

2026苏州装修大揭秘!透明报价无增项的宝藏公司都在这 - 品牌测评鉴赏家

2026苏州装修大揭秘!透明报价无增项的宝藏公司都在这一、装修初心:品质筑家,透明为基 在苏州这座充满诗意与浪漫的城市,每一位业主都怀揣着对家的美好憧憬开启装修之旅。而一场顺畅的装修体验,离不开透明报价与规…

【论文阅读】π0.5: a Vision-Language-Action Model with Open-World Generalization

【论文阅读】π0.5: a Vision-Language-Action Model with Open-World Generalization1 发表时间与团队2 问题背景和核心思路3 具体设计3.1 模型设计&#xff08;分层推理链&#xff09;3.2 数据设计4 实验5 结论1 发表时间与团队 发表时间&#xff1a;2025年4月22日。团队&am…

大模型分布式训练通信优化:从Ring All-Reduce到分层压缩的实战演进

摘要&#xff1a;本文深度揭秘大模型分布式训练中的通信瓶颈与优化体系。通过Ring All-Reduce的拓扑感知改进、梯度压缩算法&#xff08;PowerSGDEF21&#xff09;的融合实现、以及通信-计算重叠的流水线设计&#xff0c;在千卡集群上训练175B模型时&#xff0c;通信耗时占比从…

10年了啊

一晃,10年过去了

智能代码重用推荐:提高开发效率

智能代码重用推荐:提高开发效率 关键词:智能代码重用推荐、开发效率、代码检索、代码分析、机器学习 摘要:本文围绕智能代码重用推荐展开,旨在探讨如何通过这一技术提高软件开发效率。首先介绍了智能代码重用推荐的背景信息,包括目的、预期读者、文档结构和相关术语。接着阐…

苏州装修避坑指南:3家自有工人+施工规范宝藏公司揭秘 - 品牌测评鉴赏家

苏州装修避坑指南:3家自有工人+施工规范宝藏公司揭秘一、苏州装修市场乱象频发,避坑刻不容缓 苏州房地产市场的火热带动了装修行业的蓬勃发展,目前大小装修公司多达数百家,涵盖各类规模与类型。但行业门槛偏低,导…

8个降aigc工具推荐!继续教育学员必备避坑指南

8个降aigc工具推荐&#xff01;继续教育学员必备避坑指南 AI降重工具&#xff1a;论文写作的隐形助手 在继续教育的学习过程中&#xff0c;论文撰写是每位学员必须面对的重要环节。随着人工智能技术的广泛应用&#xff0c;越来越多的学生开始使用AI工具辅助写作&#xff0c;但随…

这些降重服务商整合了AI智能改写技术,免费试用让用户获得高效的文本优化体验。

排名 工具名称 降重效率 特色功能 适用场景 免费额度 1 aibiye ⭐⭐⭐⭐⭐ AIGC查重降重双功能 学术论文深度优化 首次免费检测 2 aicheck ⭐⭐⭐⭐ 多维度重复率分析 日常作业/论文初稿 每日3000字免费 3 笔启AI ⭐⭐⭐⭐ 长文记忆多语种支持 硕博论文/…

十大降重平台均配备AI智能重写系统,免费试用帮助用户实现高效的文本优化目标。

排名 工具名称 降重效率 特色功能 适用场景 免费额度 1 aibiye ⭐⭐⭐⭐⭐ AIGC查重降重双功能 学术论文深度优化 首次免费检测 2 aicheck ⭐⭐⭐⭐ 多维度重复率分析 日常作业/论文初稿 每日3000字免费 3 笔启AI ⭐⭐⭐⭐ 长文记忆多语种支持 硕博论文/…

导师推荐!9款AI论文软件测评:研究生开题报告必备工具

导师推荐&#xff01;9款AI论文软件测评&#xff1a;研究生开题报告必备工具 2026年学术AI写作工具测评&#xff1a;为何值得一看 在当前学术研究日益数字化的背景下&#xff0c;研究生群体面临诸多写作挑战&#xff0c;如开题报告撰写耗时、文献资料整理复杂、格式规范不熟悉等…

CVE-2026-21440 AdonisJS 路径遍历漏洞分析与验证工具

项目标题与描述 CVE-2026-21440 PoC及安全分析 CVE-2026-21440 是一个影响 AdonisJS 框架的严重路径遍历漏洞。该漏洞源于框架在处理多部分文件上传时&#xff0c;不当信任了用户提供的文件名&#xff0c;而未进行严格的净化处理。当开发人员调用 MultipartFile.move() 方法时&…

2026苏州装修公司前十强口碑榜|本土家居博主实测级推荐,装新家不踩坑! - 品牌测评鉴赏家

2026苏州装修公司前十强口碑榜|本土家居博主实测级推荐,装新家不踩坑!一、前言:苏州装修市场 “水多深”?选对公司 = 省一半心力 家人们,作为在苏州家居圈摸爬滚打好些年的博主,我每天在后台收到最多的问题就是…

51单片机智能扫地吸尘智能车机器人红外避障风扇95(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码

51单片机智能扫地吸尘智能车机器人红外避障风扇95产品功能描述&#xff1a; 本系统由STC89C52单片机、2路红外避障模块、2路按键、风扇驱动、L298N电机驱动及电池盒供电组成。 1、按下启动按键后&#xff0c;小车左侧的红外避障传感器模块检测到有障碍物&#xff0c;则智能车右…

AI模型与工具技术周报解析

Replicate Intelligence #2 [某中心 Logo]Replicate 正在加入 [某中心] Replicate 标识 ctrlk 探索 定价 企业方案 文档 博客 登录 免费试用 菜单 探索 定价 企业方案 文档 博客 登录 免费试用 在 Playground 中比较模型 (Beta) Replicate 博客 Replicate Intelligence #2 发布…

二分:二分查找、在排序数组中查找元素的第一个和最后一个位置、搜索插入位置、x 的平方根 - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

极简风装修不踩坑!3家宝藏装修公司实测推荐,高级感拉满 - 品牌测评鉴赏家

极简风装修不踩坑!3家宝藏装修公司实测推荐,高级感拉满一、开篇:为什么极简风超火,却 90% 的人装成 “廉价毛坯房”? (一)极简风的治愈魔力:当代人的心灵避风港 在这个快节奏、高压力的时代,我们每天穿梭于城…

苏州二手房局部改造不踩坑!6家宝藏装修公司,老房焕新超省心 - 品牌测评鉴赏家

苏州二手房局部改造不踩坑!6家宝藏装修公司,老房焕新超省心一、开篇:苏州老房焕新,局部改造才是性价比之王 (一)为什么苏州二手房更适合局部改造? 走在苏州的大街小巷,随处可见充满历史韵味的老房子。这些二手…