using System; using System.Diagnostics; using System.Linq; using System.Windows; using Autodesk.Revit.DB; namespace Szmedi.RvKits.Assists { public class CurveUtils { //private List curvesSorted; //private void SortOpenedContinuousCurves(Curve initCurve, List sourceCurves) //{ // if (sourceCurves == null) // { // return; // } // //if (sourceCurves.Count <= 2) // //{ // // return; // //} // var start = initCurve.GetEndPoint(0); // var end = initCurve.GetEndPoint(1); // //curvesSorted.Add(initCurve); // sourceCurves.Remove(initCurve); // for (var i = sourceCurves.Count - 1; i >= 0; i--) // { // if (sourceCurves.Count == 0) // { // break; // } // if (i >= sourceCurves.Count) // { // i = sourceCurves.Count - 1; // } // //var anotherCurve = sourceCurves[i]; // //当两段直线几乎平行且交于一点时,会判断错误,变成subset子集关系 // //TODO // var comparisonR = initCurve.Intersect(sourceCurves[i], out var _); // if (comparisonR == SetComparisonResult.Disjoint && initCurve is Arc && sourceCurves[i] is Arc) // { // var l = new List() { initCurve, sourceCurves[i] }; // try // { // var cl = CurveLoop.Create(l);//如果报错,说明两个半圆没形成圆,是不连续的; // curvesSorted = l; // sourceCurves.Remove(sourceCurves[i]); // return; // } // catch (Exception) // { // } // } // if (SetComparisonResult.Overlap == comparisonR) // { // //XYZ point = null; // //if (intersectionR != null && !intersectionR.IsEmpty) // //{ // // point = intersectionR.get_Item(0).XYZPoint; // //} // var start1 = sourceCurves[i].GetEndPoint(0); // var end1 = sourceCurves[i].GetEndPoint(1); // if (end.IsAlmostEqualTo(start1))//顺序连接 // { // curvesSorted.Add(sourceCurves[i]); // } // if (end.IsAlmostEqualTo(end1))//终点一样,反向加到后面 // { // sourceCurves[i] = sourceCurves[i].CreateReversed();//替换掉,才能保证移除的对象是同一个 // curvesSorted.Add(sourceCurves[i]); // } // if (start.IsAlmostEqualTo(start1))//起点一样,反向插到前面 // { // sourceCurves[i] = sourceCurves[i].CreateReversed(); // curvesSorted.Insert(curvesSorted.IndexOf(initCurve), sourceCurves[i]); // } // if (start.IsAlmostEqualTo(end1))//顺序连接,但是在前面 // { // curvesSorted.Insert(curvesSorted.IndexOf(initCurve), sourceCurves[i]); // } // SortOpenedContinuousCurves(sourceCurves[i], sourceCurves); // } // } //} /// /// 对曲线列表进行排序,使其正确排序和定向,形成闭合回路。 /// public static bool SortCurvesContiguous(IList curves, bool debug_output = false) { const double _inch = 1.0 / 12.0; const double _sixteenth = _inch / 16.0; int n = curves.Count; for (int i = 0; i < n; ++i) { Curve curve = curves[i]; XYZ endPoint = curve.GetEndPoint(1); XYZ p; // 查找起点 = 终点的曲线 bool found = (i + 1 >= n); for (int j = i + 1; j < n; ++j) { p = curves[j].GetEndPoint(0); // 如果匹配 end->start、 // 这是下一条曲线 if (_sixteenth > p.DistanceTo(endPoint)) { if (debug_output) { Debug.Print("{0} 起始点, 换成 {1}", j, i + 1); } if (i + 1 != j) { Curve tmp = curves[i + 1]; curves[i + 1] = curves[j]; curves[j] = tmp; } found = true; break; } p = curves[j].GetEndPoint(1); // 如果有匹配结果 end->end、 // 反转下一条曲线 if (_sixteenth > p.DistanceTo(endPoint)) { if (i + 1 == j) { if (debug_output) { Debug.Print("{0} 终点, 反向 {1}", j, i + 1); } curves[i + 1] = curves[j].CreateReversed(); } else { if (debug_output) { Debug.Print("{0} 终点, 倒换 {1}", j, i + 1); } Curve tmp = curves[i + 1]; curves[i + 1] = curves[j].CreateReversed(); curves[j] = tmp; } found = true; break; } } if (!found) { return false; } } return true; } /// /// 将一组离散的曲线整理成多条连续的线串。 /// /// 输入的曲线集合,可能包含直线、圆弧、样条曲线等。 /// 一个包含多条线串的列表,每条线串本身也是一个曲线列表,且内部曲线方向连续。 public static List> GroupContinuousCurves(IEnumerable curves) { // 最终返回的所有线串集合 var allChains = new List>(); // 可被消耗的曲线列表 var remainingCurves = new List(curves); // Revit API 中用于几何比较的默认精度 double tolerance = 1e-9; // 当还有未处理的曲线时,持续循环 while (remainingCurves.Any()) { // 开始一条新的线串 var currentChain = new List(); // 从剩余曲线中取第一条作为新线串的起点 var firstCurve = remainingCurves[0]; currentChain.Add(firstCurve); remainingCurves.RemoveAt(0); // 持续延长当前线串,直到无法再延长 while (true) { bool chainExtended = false; // 获取当前线串的头尾端点 XYZ chainStartPoint = currentChain.First().GetEndPoint(0); XYZ chainEndPoint = currentChain.Last().GetEndPoint(1); // 从后向前遍历以安全地在循环中移除元素 for (int i = remainingCurves.Count - 1; i >= 0; i--) { var candidate = remainingCurves[i]; XYZ candidateStartPoint = candidate.GetEndPoint(0); XYZ candidateEndPoint = candidate.GetEndPoint(1); // 尝试连接到线串的尾部 if (chainEndPoint.IsAlmostEqualTo(candidateStartPoint, tolerance)) { currentChain.Add(candidate); remainingCurves.RemoveAt(i); chainExtended = true; break; // 找到一个后就跳出内层for循环,重新获取线串端点 } else if (chainEndPoint.IsAlmostEqualTo(candidateEndPoint, tolerance)) { currentChain.Add(candidate.CreateReversed()); // 反向后添加 remainingCurves.RemoveAt(i); chainExtended = true; break; } // 尝试连接到线串的头部 else if (chainStartPoint.IsAlmostEqualTo(candidateEndPoint, tolerance)) { currentChain.Insert(0, candidate); // 插入到头部 remainingCurves.RemoveAt(i); chainExtended = true; break; } else if (chainStartPoint.IsAlmostEqualTo(candidateStartPoint, tolerance)) { currentChain.Insert(0, candidate.CreateReversed()); // 反向后插入到头部 remainingCurves.RemoveAt(i); chainExtended = true; break; } } // 如果本轮没有延长线串,说明这条线串已经构建完毕 if (!chainExtended) { break; // 跳出 while(true) 循环 } } // 将构建完成的线串添加到最终结果中 allChains.Add(currentChain); } return allChains; } //public List> GetCurvesOfLoops(List curves) //{ // List> list = new(); // for (var i = 0; i < 100; i++) // { // try // { // if (!curves.Any()) // { // break; // } // curvesSorted = new() // { // curves[0] // }; // if (!curves[0].IsBound) // { // curves.Remove(curves[0]); // list.Add(curvesSorted); // continue; // } // SortOpenedContinuousCurves(curves[0], curves); // } // catch (Exception ex) // { // MessageBox.Show(ex.StackTrace); // } // list.Add(curvesSorted); // if (!curves.Any()) // { // break; // } // } // return list; //} /// /// 递归找到所有连接在一起的线圈并分好组 /// /// 所有线 /// 用于查找与其连接的初始线 /// 初始的线串 /// 所有线串的集合 //private void SearchCurveConnected(List curves, Curve initcurve, CurveArray initCurveArray, CurveArrArray curveArrArray) //{ // if (curveArrArray.Size == 0) // { // curveArrArray.Append(initCurveArray); // } // for (int i = 0; i < curves.Count; i++) // { // Curve tempCurve = curves[i]; // XYZ baseEndXyz = initcurve.GetEndPoint(0); // //把初始的第一个添加进集合 // if (tempCurve.GetEndPoint(0).IsAlmostEqualTo(baseEndXyz) || tempCurve.GetEndPoint(1).IsAlmostEqualTo(baseEndXyz))//可以为重合的线 // { // initCurveArray.Append(tempCurve); // curves.Remove(tempCurve); // //将tempcurve作为起点继续查找 // SearchCurveConnected(curves, tempCurve, initCurveArray, curveArrArray);//最后一次执行方法在此处,因为Count为0,停止继续执行 // } // //遍历完一个线串时,寻找下一个线串,即查找到最后,都找不到相连的曲线时 // if (i == curves.Count() - 1) // { // initCurveArray = new CurveArray();//下一个线串需重新建立合集 // SearchCurveConnected(curves, curves.FirstOrDefault(), initCurveArray, curveArrArray);//每有一次新的线串时执行一次,查找与其相连的线 // ////由于最后一轮运行完递归后,所有线段均成组,只执行上面的if内容,所以没办法将剩余线加到集合中。 // if (curves.Count() == 0) // { // curveArrArray.Append(initCurveArray); // } // } // } //} } }