ComputerGraphics/20210129/zzx-20210129作业/Method/LineListMethod.cs

300 lines
14 KiB
C#
Raw Normal View History

2021-02-25 15:53:31 +08:00
using Autodesk.Revit.DB;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GraphicsStudy
{
public static class LineListMethod
{
/// <summary>
/// 封闭轮廓线首尾相连
/// </summary>
/// <param name="lineList"></param>
/// <returns></returns>
public static List<Line> OrderLineList(this List<Line> lineList)
{
List<Autodesk.Revit.DB.Line> lines = new List<Autodesk.Revit.DB.Line> { lineList[0] };
lineList.RemoveAt(0);
XYZ firstStart = lines[0].GetEndPoint(0);
while (lineList.Count != 0)
{
XYZ lastEnd = lines.Last().GetEndPoint(1);
//回到起点
if (lastEnd.DistanceTo(firstStart) < 1 / 304.8)
{
break;
}
int index = lineList.FindIndex(m => m.GetEndPoint(0).DistanceTo(lastEnd) < 1 / 304.8);
if (index != -1)//最后一根线的终点与集合中某条线的起点相同
{
lines.Add(lineList.ElementAt(index));
//移除线
lineList.RemoveAt(index);
}
else//最后一根线的终点与集合中某条线的终点相同
{
index = lineList.FindIndex(m => m.GetEndPoint(1).DistanceTo(lastEnd) < 1 / 304.8);
if (index != -1)//如果存在就将线前后翻转一下,添加进集合
{
lines.Add(lineList.ElementAt(index).CreateReversed() as Autodesk.Revit.DB.Line);
//移除线
lineList.RemoveAt(index);
}
else//可能是没有线与它相同
{
//可能是不封闭的
break;
}
}
}
//MessageBox.Show(lines.Count.ToString());
CurveLoop cuLoop = CurveLoop.Create(lines.OfType<Curve>().ToList());
if (!cuLoop.IsOpen())
return lines;
return null;
}
/// <summary>
/// 桥接线
/// </summary>
/// <param name="lines"></param>
/// <param name="range"></param>
/// <returns></returns>
public static List<Autodesk.Revit.DB.Line> JoinLines(this List<Autodesk.Revit.DB.Line> lines, double range)
{
var newLines = new List<Autodesk.Revit.DB.Line>();
//先按是否平行且间距小于range分组
List<List<Autodesk.Revit.DB.Line>> lineListList = new List<List<Autodesk.Revit.DB.Line>>();
for (int i = 0; i < lines.Count; i++)
{
int index = -1;
for (int j = 0; j < lineListList.Count; j++)
{
XYZ midPoint = lineListList[j][0].Evaluate(0.5, true);
Autodesk.Revit.DB.Line l = Autodesk.Revit.DB.Line.CreateBound(midPoint + 1000 * lineListList[j][0].Direction, midPoint - 1000 * lineListList[j][0].Direction);
XYZ pj = l.Project(lines[i].GetEndPoint(0)).XYZPoint;
double d = pj.DistanceTo(lines[i].GetEndPoint(0));
if (lineListList[j][0].Direction.IsParallel(lines[i].Direction) && d < range)
{
index = j;
break;
}
}
if (index == -1) lineListList.Add(new List<Autodesk.Revit.DB.Line>() { lines[i] });
else lineListList[index].Add(lines[i]);
}
for (int i = 0; i < lineListList.Count; i++)
{
List<Autodesk.Revit.DB.Line> lineList = lineListList[i];
//方向
var dirt = lineList.ElementAt(0).Direction;
//点乘信息 线索引 端点坐标 坐标点乘方向
List<Tuple<int, XYZ, double>> lineEndInfoList = new List<Tuple<int, XYZ, double>>();
//点乘信息添加
for (int j = 0; j < lineList.Count; j++)
{
lineEndInfoList.Add(Tuple.Create(j, lineList[j].GetEndPoint(0), lineList[j].GetEndPoint(0).DotProduct(dirt).Round(2)));
lineEndInfoList.Add(Tuple.Create(j, lineList[j].GetEndPoint(1), lineList[j].GetEndPoint(1).DotProduct(dirt).Round(2)));
}
//排序
lineEndInfoList = lineEndInfoList.OrderBy(x => x.Item3).ToList();
List<XYZ> xyzList = new List<XYZ>();
while (lineEndInfoList.Count > 0)
{
var first = lineEndInfoList.ElementAt(0);
lineEndInfoList.RemoveAt(0);
xyzList.Add(first.Item2);
//拿到第一个线对应的另外一个点
int index = lineEndInfoList.FindIndex(x => x.Item1 == first.Item1);
while (true)
{
//拿到这部分的集合
var tempInfoList = lineEndInfoList.GetRange(0, index + 1);
//最后的一个元素
var endTemp = tempInfoList.Last();
//移除该集合
lineEndInfoList.RemoveRange(0, index + 1);
//拿到只有一个点在该区域的集合
List<Tuple<int, XYZ, double>> remainTempList = new List<Tuple<int, XYZ, double>>();
//排除掉中间有2个索引的线
while (tempInfoList.Count > 0)
{
var firstTemp = tempInfoList.ElementAt(0);
tempInfoList.RemoveAt(0);
var tempIndex = tempInfoList.FindIndex(x => x.Item1 == firstTemp.Item1);
if (tempIndex != -1)
{
tempInfoList.RemoveAt(tempIndex);
}
else
{
remainTempList.Add(firstTemp);
}
}
if (remainTempList.Count == 0)
{
xyzList.Add(endTemp.Item2);
break;
}
//找对应最后的一个点的信息
index = remainTempList.Select(x => lineEndInfoList.FindIndex(m => m.Item1 == x.Item1)).OrderBy(x => x).Last();
if (index == -1)
{
if (lineEndInfoList.Count != 0 && lineEndInfoList[0].Item2.DistanceTo(endTemp.Item2) < 1 / 304.8)
{
//两线桥接--只有一个交点的情况
var firstIndex = lineEndInfoList[0].Item1;
lineEndInfoList.RemoveAt(0);
index = lineEndInfoList.FindIndex(x => x.Item1 == firstIndex);
}
else
{
xyzList.Add(endTemp.Item2);
break;
}
}
}
}
for (int k = 0; k < xyzList.Count; k += 2)
{
XYZ pStart = xyzList[k];
XYZ pEnd = xyzList[k + 1];
if (pStart.DistanceTo(pEnd) > 1 / 304.8)
{
//var mc = Line.CreateBound(pStart, pEnd).GenerateMc(doc, true);
//mc.SetData(Properties.Resources.TestGuid, Properties.Resources.TestName, i.ToString() + " " + lineListList[i].Count);
newLines.Add(Autodesk.Revit.DB.Line.CreateBound(pStart, pEnd));
}
}
}
return newLines;
}
/// <summary>
/// 线相交打断
/// </summary>
/// <param name="curveList"></param>
/// <returns></returns>
public static List<Line> BreakInterLine(this List<Line> curveList)
{
List<Line> lineList = new List<Line>();
foreach (var m in curveList)
{
List<Line> breakLineList = new List<Line>();
int index = curveList.IndexOf(m);
//存储所需要的交点
List<XYZ> intersectPointList = new List<XYZ>();
//复制m线段然后变成无限长
Line mLine = Line.CreateBound(m.GetEndPoint(0), m.GetEndPoint(1));
mLine.MakeUnbound();
for (int i = 0; i < curveList.Count; i++)
{
if (mLine.Direction.IsParallel(curveList[i].Direction)) continue;
Line iLine = Line.CreateBound(curveList[i].GetEndPoint(0), curveList[i].GetEndPoint(1));
iLine.MakeUnbound();
mLine.Intersect(iLine, out IntersectionResultArray resultArray);
if (resultArray?.get_Item(0)?.XYZPoint != null)
{
XYZ resultPoint = resultArray.get_Item(0).XYZPoint;
double iDistance = curveList[i].GetEndPoint(0).DistanceTo(resultPoint) + curveList[i].GetEndPoint(1).DistanceTo(resultPoint);
double mDistance = m.GetEndPoint(0).DistanceTo(resultPoint) + m.GetEndPoint(1).DistanceTo(resultPoint);
if (iDistance - curveList[i].Length < 1 / 304.8 && mDistance - m.Length < 1 / 304.8)
{
intersectPointList.Add(resultArray.get_Item(0).XYZPoint);
}
}
}
//ToDo不太确定起终点不放进去会不会有问题
//点去重
intersectPointList = intersectPointList.Where((x, i) => intersectPointList.FindIndex(c => c.DistanceTo(x) < 1 / 304.8) == i).ToList();
//排列点并重新生成线段集合
intersectPointList = intersectPointList.OrderBy(x => m.GetEndPoint(0).DistanceTo(x)).ToList();
//线段集合
List<Line> lines = new List<Line>();
for (int i = 0; i < intersectPointList.Count - 1; i++)
{
Line l = Line.CreateBound(intersectPointList[i], intersectPointList[i + 1]);
lines.Add(l);
}
lineList.AddRange(lines);
}
return lineList;
}
/// <summary>
/// 去除孤线
/// </summary>
/// <param name="curveList"></param>
/// <returns></returns>
public static List<Line> DeleteSolitary(this List<Line> curveList)
{
List<Line> lineList = new List<Line>();
foreach (var m in curveList)
{
List<Line> breakLineList = new List<Line>();
int index = curveList.IndexOf(m);
//存储所需要的交点
List<XYZ> intersectPointList = new List<XYZ>();
//复制m线段然后变成无限长
Line mLine = Line.CreateBound(m.GetEndPoint(0), m.GetEndPoint(1));
mLine.MakeUnbound();
for (int i = 0; i < curveList.Count; i++)
{
if (mLine.Direction.IsParallel(curveList[i].Direction)) continue;
Line iLine = Line.CreateBound(curveList[i].GetEndPoint(0), curveList[i].GetEndPoint(1));
iLine.MakeUnbound();
mLine.Intersect(iLine, out IntersectionResultArray resultArray);
if (resultArray?.get_Item(0)?.XYZPoint != null)
{
XYZ resultPoint = resultArray.get_Item(0).XYZPoint;
double iDistance = curveList[i].GetEndPoint(0).DistanceTo(resultPoint) + curveList[i].GetEndPoint(1).DistanceTo(resultPoint);
double mDistance = m.GetEndPoint(0).DistanceTo(resultPoint) + m.GetEndPoint(1).DistanceTo(resultPoint);
if (iDistance - curveList[i].Length < 1 / 304.8 && mDistance - m.Length < 1 / 304.8)
{
intersectPointList.Add(resultArray.get_Item(0).XYZPoint);
}
}
}
//点去重
intersectPointList = intersectPointList.Where((x, i) => intersectPointList.FindIndex(c => c.DistanceTo(x) < 1 / 304.8) == i).ToList();
//排列点并重新生成线段集合
intersectPointList = intersectPointList.OrderBy(x => m.GetEndPoint(0).DistanceTo(x)).ToList();
//线段集合
List<Line> lines = new List<Line>();
for (int i = 0; i < intersectPointList.Count - 1; i++)
{
Line l = Line.CreateBound(intersectPointList[i], intersectPointList[i + 1]);
lines.Add(l);
}
lineList.AddRange(lines);
}
return lineList;
}
/// <summary>
/// 生成详图线,事务在方法外面开启
/// </summary>
/// <param name="lines"></param>
/// <param name="v"></param>
public static void CreateDetailLine(this List<Line> lines, Document doc, View v)
{
foreach (var l in lines)
{
doc.Create.NewDetailCurve(v, l);
}
}
}
}