news 2026/4/21 3:03:09

C#合并首尾相连多段线实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C#合并首尾相连多段线实战

问题解构

用户需要在C#中实现合并所有首尾相连的多段线。核心需求包括:

  1. 识别连接性:判断多段线是否首尾相连(端点重合)
  2. 合并算法:将相连的多段线合并为单一多段线
  3. CAD环境:通常在AutoCAD等CAD二次开发环境中操作

方案推演

基于CAD二次开发经验,合并首尾相连多段线的标准流程如下:

步骤关键操作技术要点
1. 收集多段线获取所有待处理的多段线对象通过选择集或遍历图元
2. 建立连接图构建端点索引关系使用字典存储端点坐标与多段线映射
3. 合并处理递归合并相连多段线处理顶点顺序和方向
4. 生成结果创建新多段线并清理原对象注意内存管理和事务提交

具体实现

1. 核心数据结构

using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Runtime; using System.Collections.Generic; using System.Linq; public class PolylineMerger { // 端点容差(用于判断是否重合) private const double Tolerance = 0.0001; // 端点信息结构 private class EndpointInfo { public Point3d Point { get; set; } public Polyline Polyline { get; set; } public bool IsStartPoint { get; set; } } }

2. 连接性检测方法

private bool ArePointsEqual(Point3d p1, Point3d p2) { return p1.DistanceTo(p2) < Tolerance; } private bool ArePolylinesConnected(Polyline pl1, Polyline pl2) { Point3d start1 = pl1.StartPoint; Point3d end1 = pl1.EndPoint; Point3d start2 = pl2.StartPoint; Point3d end2 = pl2.EndPoint; // 判断四种可能的连接情况 return ArePointsEqual(end1, start2) || ArePointsEqual(end1, end2) || ArePointsEqual(start1, start2) || ArePointsEqual(start1, end2); }

3. 多段线合并算法

public List<Polyline> MergeConnectedPolylines(List<Polyline> polylines) { if (polylines == null || polylines.Count < 2) return polylines; // 构建端点索引 Dictionary<Point3d, List<EndpointInfo>> endpointMap = new Dictionary<Point3d, List<EndpointInfo>>(); foreach (var pl in polylines) { AddEndpointToMap(pl.StartPoint, pl, true, endpointMap); AddEndpointToMap(pl.EndPoint, pl, false, endpointMap); } // 合并处理 List<Polyline> result = new List<Polyline>(); HashSet<Polyline> processed = new HashSet<Polyline>(); foreach (var pl in polylines) { if (processed.Contains(pl)) continue; Polyline merged = MergeFromPolyline(pl, endpointMap, processed); if (merged != null) { result.Add(merged); } } return result; } private void AddEndpointToMap(Point3d point, Polyline pl, bool isStart, Dictionary<Point3d, List<EndpointInfo>> map) { // 查找相近的端点 Point3d? existingKey = null; foreach (var key in map.Keys) { if (ArePointsEqual(key, point)) { existingKey = key; break; } } Point3d actualPoint = existingKey ?? point; if (!map.ContainsKey(actualPoint)) { map[actualPoint] = new List<EndpointInfo>(); } map[actualPoint].Add(new EndpointInfo { Point = actualPoint, Polyline = pl, IsStartPoint = isStart }); }

4. 递归合并实现

private Polyline MergeFromPolyline(Polyline startPl, Dictionary<Point3d, List<EndpointInfo>> endpointMap, HashSet<Polyline> processed) { List<Point3d> mergedPoints = new List<Point3d>(); List<double> mergedBulges = new List<double>(); // 收集起点多段线的顶点 CollectVertices(startPl, mergedPoints, mergedBulges); processed.Add(startPl); // 递归查找并合并相连多段线 bool foundMore = true; while (foundMore) { foundMore = false; Point3d currentEnd = mergedPoints.Last(); if (endpointMap.ContainsKey(currentEnd)) { foreach (var endpointInfo in endpointMap[currentEnd]) { if (processed.Contains(endpointInfo.Polyline)) continue; // 检查连接方向 if (ShouldConnect(currentEnd, endpointInfo)) { AppendPolylineVertices(endpointInfo.Polyline, endpointInfo.IsStartPoint, mergedPoints, mergedBulges); processed.Add(endpointInfo.Polyline); foundMore = true; break; } } } } // 创建新的合并后多段线 return CreateMergedPolyline(mergedPoints, mergedBulges); } private void CollectVertices(Polyline pl, List<Point3d> points, List<double> bulges) { for (int i = 0; i < pl.NumberOfVertices; i++) { points.Add(pl.GetPoint3dAt(i)); if (i < pl.NumberOfVertices - 1) { bulges.Add(pl.GetBulgeAt(i)); } } }

5. 完整调用示例

[CommandMethod("MergePolylines")] public void MergePolylinesCommand() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; using (Transaction tr = db.TransactionManager.StartTransaction()) { try { // 1. 选择多段线 PromptSelectionResult selResult = ed.GetSelection(); if (selResult.Status != PromptStatus.OK) return; // 2. 收集多段线对象 List<Polyline> polylines = new List<Polyline>(); foreach (SelectedObject selObj in selResult.Value) { Entity ent = tr.GetObject(selObj.ObjectId, OpenMode.ForRead) as Entity; if (ent is Polyline pl) { polylines.Add(pl); } } // 3. 执行合并 PolylineMerger merger = new PolylineMerger(); List<Polyline> mergedPolylines = merger.MergeConnectedPolylines(polylines); // 4. 创建新实体并删除原实体 BlockTableRecord btr = (BlockTableRecord)tr.GetObject( db.CurrentSpaceId, OpenMode.ForWrite); foreach (var mergedPl in mergedPolylines) { btr.AppendEntity(mergedPl); tr.AddNewlyCreatedDBObject(mergedPl, true); } // 可选:删除原多段线 foreach (var pl in polylines) { pl.UpgradeOpen(); pl.Erase(); } tr.Commit(); ed.WriteMessage($" 合并完成:{polylines.Count}条多段线合并为{mergedPolylines.Count}条"); } catch (System.Exception ex) { ed.WriteMessage($" 错误:{ex.Message}"); } } }

关键注意事项

注意事项解决方案参考依据
端点容差处理使用容差值比较坐标,避免浮点精度问题
顶点顺序保持根据连接方向调整顶点添加顺序
凸度值传递合并时保留圆弧段的凸度值
性能优化使用字典建立端点索引,避免O(n²)复杂度-
Z坐标处理忽略Z坐标或保持一致性
闭合多段线特殊处理闭合多段线的连接逻辑-

应用场景示例

  1. CAD图纸清理:将破碎的线段合并为完整轮廓
  2. 激光切割路径优化:减少路径中断点,提高加工效率
  3. 工程图处理:简化复杂的多段线结构,便于后续操作
  4. 数据交换准备:合并多段线以符合其他软件格式要求

该实现通过建立端点索引图高效识别连接关系,递归合并确保处理任意长度的连接链,容差比较解决坐标精度问题,完整支持直线和圆弧段的合并需求。


参考来源

  • cad二次开发 合并直线、圆弧、多段线
  • C# WPF界面源码框架:运动控制路径算法总结与分享
  • CAXA实体设计从零基础到高级应用实战教程
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/21 3:01:22

基于TMS320F28035的汇川变频器源码:MD290、MD380、MD500三种型号及新的...

变频器汇川的三种变频器源码&#xff0c;包括MD290,MD380,MD500变频器源码,基于TMS320F28035 新的SVC3算法&#xff0c;高速速度波动小&#xff0c;新的转子电阻&#xff0c;漏感辩识算法.系统概述 本文基于汇川技术股份有限公司开发的MD290、MD380、MD500系列变频器的嵌入式软…

作者头像 李华
网站建设 2026/4/21 3:00:25

旷世之作,云南第一书画史诗《白族创世纪》诞生,中国艺术的经典

由艺术大师范笑歌创作的云南第一书画史诗《白族创世纪》终于完成&#xff0c;作为云南艺术史册上的顶尖之作&#xff0c;从诗歌的编写到书法、绘画的精工&#xff0c;都是范先生独自完成。为何称此作品为云南第一书画史诗&#xff0c;主要因为这是书法与绘画的完美合璧&#xf…

作者头像 李华
网站建设 2026/4/21 2:59:55

【MATLAB源码-第422期】基于MATLAB的5G NR LDPC码的误码率复杂度仿真,对比BP,LBP,NMS。

操作环境&#xff1a;MATLAB 2024a1、算法描述摘要低密度奇偶校验码因其接近香农极限的纠错能力、良好的并行处理特性以及较强的速率兼容能力&#xff0c;已经成为新一代移动通信系统中共享信道的重要编码方案。5G NR标准围绕LDPC码给出了基图选择、提升因子构造、穿孔与速率匹…

作者头像 李华
网站建设 2026/4/21 2:57:15

devmgr.dll文件丢失找不到 免费下载方法分享

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

作者头像 李华
网站建设 2026/4/21 2:54:27

手把手教你用STM32和OpenMV实现两板通信(附完整代码解析)

STM32与OpenMV高效通信协议设计与实战解析 在嵌入式视觉系统中&#xff0c;摄像头模块与主控板之间的数据交互质量直接影响整个系统的响应速度和稳定性。当OpenMV识别到目标物体后&#xff0c;如何将坐标信息准确无误地传递给STM32&#xff1f;面对实时性要求高的场景&#xff…

作者头像 李华