- 积分
- 5972
- 明经币
- 个
- 注册时间
- 2016-10-12
- 在线时间
- 小时
- 威望
-
- 金钱
- 个
- 贡献
-
- 激情
-
|
本帖最后由 wang2006zhi 于 2025-2-14 12:41 编辑
 - /// <summary>
- /// BO算法实现,仅直线
- /// </summary>
- /// <param name="pointsOnLine"></param>
- /// <param name="targetPoint"></param>
- /// <returns></returns>
- public static Polyline? GetBPolyCurve(this Dictionary<Line, List<Point3d>> pointsOnLine, Point3d targetPoint)
- {
- var lines = new List<Line>();
- foreach (var item in pointsOnLine)
- {
- Line line = item.Key;
- List<Point3d> points = item.Value;
- if (points.Count < 3)
- continue;
- //线上有多个点,按顺序打断线
- var curves = line.GetSplitCurves(points);
- //一个line被他上面的点打成多个line后加入列表
- foreach (var curve in curves)
- {
- if (curve is Line line2)
- lines.Add(line2);
- }
- }
- //清除线头
- List<Line> goodlines = RepairLine(lines);
- List<Line> goodlines2 = RecycleLine(goodlines);
- if (goodlines2.Count == 0)
- return null;
- lines.Clear();
- lines = goodlines2;
- Line firstLine = lines.FindByMin(c => c.GetClosestPointTo(targetPoint, false)
- .DistanceTo(targetPoint));
- lines.Remove(firstLine);
- Polyline polyline = new Polyline();
- polyline.AddVertexAt(0,
- firstLine.StartPoint.Convert2d(new Plane()), 0,0,0);
- polyline.AddVertexAt(1,
- firstLine.EndPoint.Convert2d(new Plane()),0,0, 0);
- Vector3d v1 = firstLine.StartPoint - targetPoint;
- Vector3d v2 = firstLine.EndPoint - targetPoint;
- if (v1.CrossProduct(v2).Z > 0)
- polyline.ReverseCurve();
- while (true)
- {
- List<Line> tmps = new List<Line>();
- foreach (var item in lines)
- {
- if (item.StartPoint == polyline.EndPoint)
- tmps.Add(item);
- else if (item.EndPoint == polyline.EndPoint)
- {
- item.ReverseCurve();
- tmps.Add(item);
- }
- }
- if (tmps.Count == 0)
- break;
- //顺时针
- Vector3d vector = -polyline.GetFirstDerivative(polyline.EndPoint);
- double maxAngle = 0;
- Line bigLine = new Line();
- foreach (var item in tmps)
- {
- double angle = vector.GetAngleTo(item.Delta, -Vector3d.ZAxis);
- if (!(angle > maxAngle))
- continue;
- maxAngle = angle;
- bigLine = item;
- }
- polyline.JoinEntity(bigLine);
- lines.Remove(bigLine);
- if (polyline.EndPoint == polyline.StartPoint)
- break;
- }
- return polyline;
- }
- private static List<Line> RepairLine(List<Line> lines)
- {
- if (lines.Count == 0)
- return new List<Line>();
- List<Line> goodlines = new List<Line>();
- for (int i = 0; i < lines.Count; i++)
- {
- var leftHandOk = false;
- var rightHandOk = false;
- for (int j = 0; j < lines.Count; j++)
- {
- if (i == j)
- continue;
- if (lines.StartPoint == lines[j].StartPoint || lines.StartPoint == lines[j].EndPoint)
- leftHandOk = true;
- if (lines.EndPoint == lines[j].StartPoint || lines.EndPoint == lines[j].EndPoint)
- rightHandOk = true;
- if (!leftHandOk || !rightHandOk)
- continue;
- if (!goodlines.Contains(lines))
- goodlines.Add(lines);
- }
- }
- return goodlines;
- }
- private static List<Line> RecycleLine(List<Line> lines)
- {
- if (lines.Count == 0)
- return new List<Line>();
- List<Line> templine = lines;
- int tempnum = lines.Count;
- while (true)
- {
- if (RepairLine(templine).Count == tempnum)
- break;
- templine = RepairLine(templine);
- tempnum = templine.Count;
- }
- return templine;
- }
- public static Dictionary<Line, List<Point3d>> GetPtsOnLineDic(this List<Curve> curves)
- {
- var lines = new List<Line>();
- // 优化多段线分解为线段逻辑
- foreach (var item in curves)
- {
- switch (item)
- {
- case Line line0:
- lines.Add(line0);
- break;
- case Polyline pl:
- AddPolylineSegments(pl,
- lines);
- break;
- }
- }
- // 预初始化字典并指定容量
- var pointsOnLine = new Dictionary<Line, List<Point3d>>(lines.Count);
- foreach (var line in lines)
- {
- pointsOnLine[line] = new List<Point3d>(8) // 预设合理容量
- {
- line.StartPoint,
- line.EndPoint
- };
- }
- // 使用对象池重用集合对象
- var posPool = new ObjectPool<Point3dCollection>(() => new Point3dCollection(), Environment.ProcessorCount * 2);
- // 并行计算线段交点
- Parallel.For(0, lines.Count, i =>
- {
- var lineI = lines[i];
- for (int j = i + 1; j < lines.Count; j++)
- {
- var lineJ = lines[j];
- var pos = posPool.Get();
- pos.Clear();
- lineI.IntersectWith(lineJ,
- Intersect.OnBothOperands,
- pos,
- IntPtr.Zero,
- IntPtr.Zero);
- if (pos.Count > 0)
- {
- // 双锁模式保证线程安全
- lock (pointsOnLine[lineI])
- pointsOnLine[lineI].AddRange(pos.Cast<Point3d>());
- lock (pointsOnLine[lineJ])
- pointsOnLine[lineJ].AddRange(pos.Cast<Point3d>());
- }
- posPool.Return(pos);
- }
- });
- // 并行排序
- Parallel.ForEach(pointsOnLine, kvp =>
- {
- var line = kvp.Key;
- var points = kvp.Value;
- // 使用数组进行高效排序
- var arr = points.ToArray();
- try
- {
- Array.Sort(arr, (a, b) => line.GetParameterAtPoint(a).CompareTo(line.GetParameterAtPoint(b)));
- }
- catch (Exception e)
- {
- Console.WriteLine(e);
- }
-
- kvp.Value.Clear();
- kvp.Value.AddRange(arr);
- });
- return pointsOnLine;
- }
- // 处理多段线分解
- private static void AddPolylineSegments(Polyline pl, List<Line> lines)
- {
- int count = pl.NumberOfVertices;
- if (count < 2)
- return;
- bool isClosed = pl.Closed;
- for (int i = 0;
- i < count;
- i++)
- {
- int next = (i == count - 1)
- ? 0
- : i + 1;
- if (!isClosed && i == count - 1)
- break;
- lines.Add(new Line(pl.GetPoint3dAt(i),
- pl.GetPoint3dAt(next)));
- }
- }
- // 简单对象池实现
- private class ObjectPool<T> where T : new()
- {
- private readonly ConcurrentBag<T> _objects = new();
- private readonly Func<T> _generator;
- public ObjectPool(Func<T> generator, int initialCount = 0)
- {
- _generator = generator;
- for (int i = 0; i < initialCount; i++)
- _objects.Add(_generator());
- }
- public T Get() => _objects.TryTake(out T item) ? item : _generator();
- public void Return(T item) => _objects.Add(item);
- }
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?注册
x
|