ComputerGraphics/20210129/zzx-20210129作业/Method/LineListMethod.cs
2021-02-25 15:53:31 +08:00

300 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
}
}
}
}