明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 551|回复: 5

[几何] 简单BO实现(仅支持直线),deepseek助写

[复制链接]
发表于 2025-2-12 22:33:18 | 显示全部楼层 |阅读模式
本帖最后由 wang2006zhi 于 2025-2-14 12:41 编辑
  1. /// <summary>
  2. /// BO算法实现,仅直线
  3. /// </summary>
  4. /// <param name="pointsOnLine"></param>
  5. /// <param name="targetPoint"></param>
  6. /// <returns></returns>
  7. public static Polyline? GetBPolyCurve(this Dictionary<Line, List<Point3d>> pointsOnLine, Point3d targetPoint)
  8. {
  9.     var lines = new List<Line>();
  10.     foreach (var item in pointsOnLine)
  11.     {
  12.         Line line = item.Key;
  13.         List<Point3d> points = item.Value;
  14.         if (points.Count < 3)
  15.             continue;
  16.         //线上有多个点,按顺序打断线
  17. var curves = line.GetSplitCurves(points);
  18.         //一个line被他上面的点打成多个line后加入列表
  19. foreach (var curve in curves)
  20.         {
  21.             if (curve is Line line2)
  22.                 lines.Add(line2);
  23.         }
  24.     }

  25.     //清除线头
  26. List<Line> goodlines = RepairLine(lines);
  27.     List<Line> goodlines2 = RecycleLine(goodlines);
  28.     if (goodlines2.Count == 0)
  29.         return null;
  30.     lines.Clear();
  31.     lines = goodlines2;
  32.     Line firstLine = lines.FindByMin(c => c.GetClosestPointTo(targetPoint, false)
  33.         .DistanceTo(targetPoint));
  34.     lines.Remove(firstLine);
  35.     Polyline polyline = new Polyline();
  36.     polyline.AddVertexAt(0,
  37.         firstLine.StartPoint.Convert2d(new Plane()), 0,0,0);
  38.     polyline.AddVertexAt(1,
  39.         firstLine.EndPoint.Convert2d(new Plane()),0,0, 0);
  40.     Vector3d v1 = firstLine.StartPoint - targetPoint;
  41.     Vector3d v2 = firstLine.EndPoint - targetPoint;
  42.     if (v1.CrossProduct(v2).Z > 0)
  43.         polyline.ReverseCurve();
  44.     while (true)
  45.     {
  46.         List<Line> tmps = new List<Line>();
  47.         foreach (var item in lines)
  48.         {
  49.             if (item.StartPoint == polyline.EndPoint)
  50.                 tmps.Add(item);
  51.             else if (item.EndPoint == polyline.EndPoint)
  52.             {
  53.                 item.ReverseCurve();
  54.                 tmps.Add(item);
  55.             }
  56.         }

  57.         if (tmps.Count == 0)
  58.             break;
  59.         //顺时针
  60. Vector3d vector = -polyline.GetFirstDerivative(polyline.EndPoint);
  61.         double maxAngle = 0;
  62.         Line bigLine = new Line();
  63.         foreach (var item in tmps)
  64.         {
  65.             double angle = vector.GetAngleTo(item.Delta, -Vector3d.ZAxis);
  66.             if (!(angle > maxAngle))
  67.                 continue;
  68.             maxAngle = angle;
  69.             bigLine = item;
  70.         }

  71.         polyline.JoinEntity(bigLine);
  72.         lines.Remove(bigLine);
  73.         if (polyline.EndPoint == polyline.StartPoint)
  74.             break;
  75.     }

  76.     return polyline;
  77. }
  78. private static List<Line> RepairLine(List<Line> lines)
  79. {
  80.     if (lines.Count == 0)
  81.         return new List<Line>();
  82.     List<Line> goodlines = new List<Line>();
  83.     for (int i = 0; i < lines.Count; i++)
  84.     {
  85.         var leftHandOk = false;
  86.         var rightHandOk = false;
  87.         for (int j = 0; j < lines.Count; j++)
  88.         {
  89.             if (i == j)
  90.                 continue;
  91.             if (lines.StartPoint == lines[j].StartPoint || lines.StartPoint == lines[j].EndPoint)
  92.                 leftHandOk = true;
  93.             if (lines.EndPoint == lines[j].StartPoint || lines.EndPoint == lines[j].EndPoint)
  94.                 rightHandOk = true;
  95.             if (!leftHandOk || !rightHandOk)
  96.                 continue;
  97.             if (!goodlines.Contains(lines))
  98.                 goodlines.Add(lines);
  99.         }
  100.     }

  101.     return goodlines;
  102. }
  103. private static List<Line> RecycleLine(List<Line> lines)
  104. {
  105.     if (lines.Count == 0)
  106.         return new List<Line>();
  107.     List<Line> templine = lines;
  108.     int tempnum = lines.Count;
  109.     while (true)
  110.     {
  111.         if (RepairLine(templine).Count == tempnum)
  112.             break;
  113.         templine = RepairLine(templine);
  114.         tempnum = templine.Count;
  115.     }

  116.     return templine;
  117. }
  118. public static Dictionary<Line, List<Point3d>> GetPtsOnLineDic(this List<Curve> curves)
  119. {
  120.     var lines = new List<Line>();
  121.     // 优化多段线分解为线段逻辑
  122. foreach (var item in curves)
  123.     {
  124.         switch (item)
  125.         {
  126.             case Line line0:
  127.                 lines.Add(line0);
  128.                 break;
  129.             case Polyline pl:
  130.                 AddPolylineSegments(pl,
  131.                     lines);
  132.                 break;
  133.         }
  134.     }

  135.     // 预初始化字典并指定容量
  136. var pointsOnLine = new Dictionary<Line, List<Point3d>>(lines.Count);
  137.     foreach (var line in lines)
  138.     {
  139.         pointsOnLine[line] = new List<Point3d>(8) // 预设合理容量
  140. {
  141.             line.StartPoint,
  142.             line.EndPoint
  143.         };
  144.     }

  145.     // 使用对象池重用集合对象
  146. var posPool = new ObjectPool<Point3dCollection>(() => new Point3dCollection(), Environment.ProcessorCount * 2);

  147.     // 并行计算线段交点
  148. Parallel.For(0, lines.Count, i =>
  149.     {
  150.             var lineI = lines[i];
  151.             for (int j = i + 1; j < lines.Count; j++)
  152.             {
  153.                 var lineJ = lines[j];
  154.                 var pos = posPool.Get();
  155.                 pos.Clear();
  156.                 lineI.IntersectWith(lineJ,
  157.                     Intersect.OnBothOperands,
  158.                     pos,
  159.                     IntPtr.Zero,
  160.                     IntPtr.Zero);
  161.                 if (pos.Count > 0)
  162.                 {
  163.                     // 双锁模式保证线程安全
  164. lock (pointsOnLine[lineI])
  165.                         pointsOnLine[lineI].AddRange(pos.Cast<Point3d>());
  166.                     lock (pointsOnLine[lineJ])
  167.                         pointsOnLine[lineJ].AddRange(pos.Cast<Point3d>());
  168.                 }
  169.                 posPool.Return(pos);
  170.             }
  171.     });
  172.     // 并行排序
  173. Parallel.ForEach(pointsOnLine, kvp =>
  174.     {
  175.         var line = kvp.Key;
  176.         var points = kvp.Value;
  177.         // 使用数组进行高效排序
  178. var arr = points.ToArray();
  179.         try
  180.         {
  181.             Array.Sort(arr, (a, b) => line.GetParameterAtPoint(a).CompareTo(line.GetParameterAtPoint(b)));
  182.         }
  183.         catch (Exception e)
  184.         {
  185.             Console.WriteLine(e);
  186.         }
  187.         
  188.         kvp.Value.Clear();
  189.         kvp.Value.AddRange(arr);
  190.     });

  191.     return pointsOnLine;
  192. }
  193. // 处理多段线分解
  194. private static void AddPolylineSegments(Polyline pl, List<Line> lines)
  195. {
  196.     int count = pl.NumberOfVertices;
  197.     if (count < 2)
  198.         return;
  199.     bool isClosed = pl.Closed;
  200.     for (int i = 0;
  201.          i < count;
  202.          i++)
  203.     {
  204.         int next = (i == count - 1)
  205.             ? 0
  206.             : i + 1;
  207.         if (!isClosed && i == count - 1)
  208.             break;
  209.         lines.Add(new Line(pl.GetPoint3dAt(i),
  210.             pl.GetPoint3dAt(next)));
  211.     }
  212. }
  213. // 简单对象池实现
  214. private class ObjectPool<T> where T : new()
  215. {
  216.     private readonly ConcurrentBag<T> _objects = new();
  217.     private readonly Func<T> _generator;

  218.     public ObjectPool(Func<T> generator, int initialCount = 0)
  219.     {
  220.         _generator = generator;
  221.         for (int i = 0; i < initialCount; i++)
  222.             _objects.Add(_generator());
  223.     }

  224.     public T Get() => _objects.TryTake(out T item) ? item : _generator();
  225.     public void Return(T item) => _objects.Add(item);
  226. }

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
回复

使用道具 举报

 楼主| 发表于 2025-2-12 22:40:31 | 显示全部楼层
[CommandMethod("tt8")]
    public void Tt8()
    {
        using var tr = new DBTrans();
        if (!Env.Editor.GetEnts(out List<Curve> curList))
            return;
        var dc = curList.GetPtsOnLineDic();
        int i = 1;
        while (Env.Editor.GetPoint(out var cenpt))
        {
            if (dc.GetBPolyCurve(cenpt) is not {} pl)
                return;
            pl.ColorIndex = i++%255;
            pl.ConstantWidth = 5;
            tr.CurrentSpace.AddEntity(pl);
            pl.Redraw(BrightEntity.Draw);
        }
    }
回复 支持 反对

使用道具 举报

发表于 2025-2-13 15:26:13 | 显示全部楼层
有代码块不用,非要搞成这么丑的排版
回复 支持 反对

使用道具 举报

 楼主| 发表于 7 天前 | 显示全部楼层
d1742647821 发表于 2025-2-13 15:26
有代码块不用,非要搞成这么丑的排版

之前没注意有那么个按钮
回复 支持 反对

使用道具 举报

发表于 4 天前 | 显示全部楼层
本帖最后由 箭头_Row 于 2025-2-17 21:58 编辑

https://www.cnblogs.com/JJBox/p/12571436.html

直接看下這個博客就好了,重點是下面這句:
{
到了Acad2011: 就可以通过以下语句获取

Editor ed = Acap.DocumentManager.MdiActiveDocument.Editor;
ed.TraceBoundary(........);
}

當然不滿意自帶的api,可以按照博客里的思路手搓一個!
回复 支持 反对

使用道具 举报

 楼主| 发表于 3 天前 来自手机 | 显示全部楼层
CAD自带的后台和平面外用不了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2025-2-21 03:27 , Processed in 0.223412 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表