1029 lines
63 KiB
C#
1029 lines
63 KiB
C#
using System;
|
||
using System.ComponentModel.DataAnnotations;
|
||
using System.Diagnostics;
|
||
using System.Windows;
|
||
|
||
using Autodesk.Revit.DB;
|
||
using Autodesk.Revit.DB.Mechanical;
|
||
using Autodesk.Revit.DB.Plumbing;
|
||
using Autodesk.Revit.UI.Selection;
|
||
|
||
using CommunityToolkit.Mvvm.ComponentModel;
|
||
using CommunityToolkit.Mvvm.Input;
|
||
|
||
using Nice3point.Revit.Toolkit.External.Handlers;
|
||
|
||
|
||
namespace Sai.RvKits.RvMEP;
|
||
|
||
public partial class AnyConnectViewModel : ObservableValidator
|
||
{
|
||
//#if REVIT2020
|
||
// public AnyConnectViewModel()
|
||
// {
|
||
// OptionsBarAssist.ShowOptionsBar();
|
||
// }
|
||
//#endif
|
||
private readonly ActionEventHandler anyConnectHandler = new();
|
||
|
||
[ObservableProperty]
|
||
private bool activeSnackbar;
|
||
|
||
[ObservableProperty]
|
||
private bool isMultiSelect = true;
|
||
|
||
[ObservableProperty]
|
||
[NotifyCanExecuteChangedFor(nameof(ConnectCommand))]
|
||
private bool canRunning = true;
|
||
|
||
[ObservableProperty]
|
||
[Range(0, 90)]
|
||
[NotifyDataErrorInfo]
|
||
private double angle = 90;
|
||
|
||
[ObservableProperty]
|
||
private Wpf.Ui.Controls.InfoBar messageQueue = new();
|
||
|
||
[ObservableProperty]
|
||
private string message;
|
||
|
||
[RelayCommand]
|
||
private static void Closing()
|
||
{
|
||
KeyIntPtrHelper.RaiseEscTwice();
|
||
}
|
||
partial void OnIsMultiSelectChanged(bool value)
|
||
{
|
||
KeyIntPtrHelper.RaiseEscTwice();
|
||
}
|
||
|
||
[RelayCommand(CanExecute = nameof(CanRunning))]
|
||
private void Connect()
|
||
{
|
||
CanRunning = false;
|
||
|
||
anyConnectHandler.Raise(uiapp =>
|
||
{
|
||
var uidoc = uiapp.ActiveUIDocument;
|
||
var doc = uidoc.Document;
|
||
FuncFilter filter = new(e => e is MEPCurve and not InsulationLiningBase and not FlexDuct and not FlexPipe);
|
||
List<MEPCurve> list;
|
||
|
||
try
|
||
{
|
||
#if REVIT2018
|
||
list = IsMultiSelect
|
||
? uidoc.Selection
|
||
.PickObjects(ObjectType.Element, filter, "请选择管线并完成")
|
||
.Select(r => doc.GetElement(r))
|
||
.OfType<MEPCurve>()
|
||
.ToList()
|
||
: uidoc.Selection.PickElementsByRectangle(filter, "请框选管线").Cast<MEPCurve>().ToList();
|
||
#elif REVIT2020 || REVIT2025
|
||
list = uidoc.Selection
|
||
.PickObjects(ObjectType.Element, filter, "请选择管线并完成")
|
||
.Select(r => doc.GetElement(r))
|
||
.OfType<MEPCurve>()
|
||
.ToList();
|
||
#endif
|
||
|
||
|
||
|
||
var defaultType = list.FirstOrDefault()?.GetType();
|
||
if (list.Count < 2 || list.Any(t => defaultType != t.GetType()))
|
||
{
|
||
Message = "所选管线数量小于2或类别不同,不允许连接";
|
||
CanRunning = true;
|
||
#if REVIT2020
|
||
OptionsBarAssist.HideOptionsBar();
|
||
#endif
|
||
return;
|
||
}
|
||
|
||
doc.Invoke(
|
||
ts =>
|
||
{
|
||
switch (list.Count)
|
||
{
|
||
case 2:
|
||
{
|
||
var originMEPCurve1 = list[0];
|
||
var originMEPCurve2 = list[1];
|
||
var line1 = originMEPCurve1.GetCurve() as Line;
|
||
var line2 = originMEPCurve2.GetCurve() as Line;
|
||
var unboundLine1 = originMEPCurve1.GetCurve() as Line;
|
||
var unboundLine2 = originMEPCurve2.GetCurve() as Line;
|
||
unboundLine1!.MakeUnbound();
|
||
unboundLine2!.MakeUnbound();
|
||
var isPerpendicular = line1.IsPerpendicularTo(line2);
|
||
var result = line1!.Intersect(line2, out var array);
|
||
MEPCurve mainMEPCurve;
|
||
MEPCurve branchMEPCurve;
|
||
var intersectionUnbound = unboundLine1.IntersectionPoint(unboundLine2);
|
||
|
||
switch (result)
|
||
{
|
||
case SetComparisonResult.Disjoint:
|
||
|
||
{
|
||
Debug.WriteLine("管线没有交点");
|
||
var intersection1 = line1.IntersectionPoint(unboundLine2);
|
||
var intersection2 = line2.IntersectionPoint(unboundLine1);
|
||
if (intersection1 == null && intersection2 != null)
|
||
{
|
||
branchMEPCurve = originMEPCurve1;
|
||
mainMEPCurve = originMEPCurve2;
|
||
Debug.WriteLine($"共面无交点:交点在第二条线上{mainMEPCurve.Id},为主管");
|
||
if (isPerpendicular && Angle is not 0 and not 90)
|
||
{
|
||
Debug.WriteLine("使用角度");
|
||
ConnectByAngle(mainMEPCurve, branchMEPCurve, intersection2, Angle);
|
||
}
|
||
else
|
||
{
|
||
mainMEPCurve.ConnectTo(branchMEPCurve);
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
if (intersection1 != null && intersection2 == null)
|
||
{
|
||
mainMEPCurve = originMEPCurve1;
|
||
branchMEPCurve = originMEPCurve2;
|
||
Debug.WriteLine($"共面无交点:交点在第一条线上{mainMEPCurve.Id},为主管");
|
||
if (isPerpendicular && Angle is not 0 and not 90)
|
||
{
|
||
Debug.WriteLine("使用角度");
|
||
ConnectByAngle(mainMEPCurve, branchMEPCurve, intersection1, Angle);
|
||
}
|
||
else
|
||
{
|
||
mainMEPCurve.ConnectTo(branchMEPCurve);
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
|
||
if (
|
||
intersection1 == null
|
||
&& intersection2 == null
|
||
&& intersectionUnbound != null
|
||
)
|
||
{
|
||
Debug.WriteLine("共面无交点:两根线都延长才有交点,交叉成角");
|
||
var conn5 = originMEPCurve1
|
||
.GetConnectors()
|
||
.GetNearestConnector(intersectionUnbound);
|
||
var conn6 = originMEPCurve2
|
||
.GetConnectors()
|
||
.GetNearestConnector(intersectionUnbound);
|
||
var cos = conn5.CoordinateSystem.BasisZ.DotProduct(
|
||
conn6.CoordinateSystem.BasisZ
|
||
);
|
||
if (cos < -10E-8 || Math.Abs(cos) < 10E-8)
|
||
{
|
||
Debug.WriteLine("夹角大于等于90度,直接连接");
|
||
if (line1.Direction.IsAlmostEqualTo(XYZ.BasisZ))
|
||
{
|
||
mainMEPCurve = originMEPCurve1;
|
||
branchMEPCurve = originMEPCurve2;
|
||
}
|
||
else if (line2!.Direction.IsAlmostEqualTo(XYZ.BasisZ))
|
||
{
|
||
mainMEPCurve = originMEPCurve2;
|
||
branchMEPCurve = originMEPCurve1;
|
||
}
|
||
else if (line1.Length > line2!.Length)
|
||
{
|
||
mainMEPCurve = originMEPCurve1;
|
||
branchMEPCurve = originMEPCurve2;
|
||
}
|
||
else
|
||
{
|
||
mainMEPCurve = originMEPCurve2;
|
||
branchMEPCurve = originMEPCurve1;
|
||
}
|
||
|
||
if (isPerpendicular && Angle is not 0 and not 90)
|
||
{
|
||
Debug.WriteLine("使用角度");
|
||
ConnectByAngle(
|
||
mainMEPCurve,
|
||
branchMEPCurve,
|
||
intersectionUnbound,
|
||
Angle
|
||
);
|
||
}
|
||
else
|
||
{
|
||
var extendLine = line1.ExtendLine(intersectionUnbound);
|
||
originMEPCurve1.SetLocationCurve(extendLine);
|
||
var extendLine2 = line2.ExtendLine(intersectionUnbound);
|
||
originMEPCurve2.SetLocationCurve(extendLine2);
|
||
conn5.ConnectByFitting(conn6);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Debug.WriteLine($"夹角是锐角{Math.Acos(cos).ToDegree()}°,创建一条管线再连接");
|
||
var newMepCurveId = ElementTransformUtils
|
||
.CopyElement(doc, originMEPCurve1.Id, XYZ.Zero)
|
||
.FirstOrDefault();
|
||
var connectMEPCurve = doc.GetElement(newMepCurveId) as MEPCurve;
|
||
connectMEPCurve.SetLocationCurve(
|
||
Line.CreateBound(conn5.Origin, conn6.Origin)
|
||
);
|
||
var connectors = connectMEPCurve.GetConnectors().Cast<Connector>();
|
||
conn5.ConnectByFitting(connectors.ElementAt(0));
|
||
conn6.ConnectByFitting(connectors.ElementAt(1));
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
if (line1.IsParallelTo(line2))
|
||
{
|
||
var c = line1.Intersect(unboundLine2); //第一个是第二个的SubSet子集
|
||
|
||
//var c1 = unboundLine1.Intersect(line2);//第一个是第二个的SuperSet超集
|
||
//距离最近的两个连接件
|
||
var originConnectors = ConnectorAssist.GetNearestConnectors(
|
||
originMEPCurve1,
|
||
originMEPCurve2
|
||
);
|
||
|
||
if (c == SetComparisonResult.Subset)
|
||
{
|
||
Debug.WriteLine("共线平行");
|
||
|
||
originConnectors[0].ConnectByFitting(originConnectors[1]);
|
||
}
|
||
else
|
||
{
|
||
Debug.WriteLine("非共线平行");
|
||
|
||
//最近连接件距离太短时
|
||
var dis = originConnectors[0].Origin.DistanceTo(
|
||
originConnectors[1].Origin
|
||
);
|
||
if (dis < uiapp.Application.ShortCurveTolerance)
|
||
{
|
||
MessageBox.Show("连接处相距太近");
|
||
break;
|
||
}
|
||
|
||
var isOriginMEPCurve1Bigger = false;
|
||
//取小的管径,用于复制作为转弯管
|
||
switch (originConnectors[0].Shape)
|
||
{
|
||
case ConnectorProfileType.Round:
|
||
isOriginMEPCurve1Bigger = originMEPCurve1.Diameter > originMEPCurve2.Diameter;
|
||
break;
|
||
case ConnectorProfileType.Rectangular:
|
||
case ConnectorProfileType.Oval:
|
||
isOriginMEPCurve1Bigger =
|
||
originMEPCurve1.Width > originMEPCurve2.Width
|
||
|| originMEPCurve1.Height > originMEPCurve2.Height;
|
||
break;
|
||
}
|
||
|
||
var elementToCopy = isOriginMEPCurve1Bigger ? originMEPCurve2 : originMEPCurve1;
|
||
////原位复制
|
||
//var copyMepCurveId = ElementTransformUtils
|
||
// .CopyElement(doc, elementToCopy.Id, XYZ.Zero)
|
||
// .FirstOrDefault();
|
||
//var copyMepCurve = doc.GetElement(copyMepCurveId) as ElementToMove;
|
||
//取短的线作为旋转轴的基准点,保证能创建
|
||
var isFirstMEPCurveLengther = line1.Length < line2.Length;
|
||
var l = isFirstMEPCurveLengther ? Line.CreateBound(
|
||
originConnectors[0].Origin,
|
||
originConnectors[1].Origin
|
||
) : Line.CreateBound(
|
||
originConnectors[1].Origin,
|
||
originConnectors[0].Origin);
|
||
////取短的线作为旋转轴的基准点,保证能创建
|
||
//var origin = line1.Length < line2.Length
|
||
// ? originConnectors[0].Origin
|
||
// : originConnectors[1].Origin;
|
||
|
||
var copyMepCurve = elementToCopy.CopyAndSetLocationCurve(l);
|
||
|
||
doc.Regenerate();
|
||
|
||
var conns1 = ConnectorAssist.GetNearestConnectors(
|
||
originMEPCurve1,
|
||
copyMepCurve
|
||
);
|
||
|
||
var conns2 = ConnectorAssist.GetNearestConnectors(
|
||
originMEPCurve2,
|
||
copyMepCurve
|
||
);
|
||
//同向,原管线和复制转弯管线的夹角,一定是大于等于90度,单位向量等价于余弦值
|
||
var cos = conns1[0].CoordinateSystem.BasisZ.DotProduct(
|
||
conns1[1].CoordinateSystem.BasisZ
|
||
);
|
||
//平行管可以垂直连接
|
||
if (Angle != 0)
|
||
{
|
||
Debug.WriteLine("修改角度");
|
||
var radian = Angle.ToRadian() - (Math.PI - Math.Acos(cos));
|
||
//侧向的轴,反向斜管的接口向量,使其为锐角
|
||
var direction = conns1[0].CoordinateSystem.BasisZ.CrossProduct(
|
||
-conns1[1].CoordinateSystem.BasisZ
|
||
);
|
||
|
||
var axis = Line.CreateUnbound(l.Origin, direction);
|
||
ElementTransformUtils.RotateElement(
|
||
doc,
|
||
copyMepCurve!.Id,
|
||
axis,
|
||
radian
|
||
);
|
||
}
|
||
|
||
if (cos < -10E-8 || Math.Abs(cos) < 10E-8)
|
||
{
|
||
Debug.WriteLine("夹角大于等于时90度");
|
||
//var angleUnboundLine = copyMepCurve.GetCurve().Clone();
|
||
//angleUnboundLine.MakeUnbound();
|
||
//if (!conns1[0].Origin.IsAlmostEqualTo(conns1[1].Origin))
|
||
//{
|
||
// var point = unboundLine1.IntersectionPoint(angleUnboundLine);
|
||
// var newOriginMEPCurve1 = line1.ExtendLine(point);
|
||
// originMEPCurve1.SetLocationCurve(newOriginMEPCurve1);
|
||
// //copyMepCurve.SetLocationCurve()
|
||
//}
|
||
//if (!conns2[0].Origin.IsAlmostEqualTo(conns2[1].Origin))
|
||
//{
|
||
// var point = unboundLine2.IntersectionPoint(angleUnboundLine);
|
||
// var newOriginMEPCurve2 = line2.ExtendLine(point);
|
||
// originMEPCurve2.SetLocationCurve(newOriginMEPCurve2);
|
||
//}
|
||
//doc.Regenerate();
|
||
conns1[0].ConnectByFitting(conns1[1]);
|
||
conns2[0].ConnectByFitting(conns2[1]);
|
||
}
|
||
else
|
||
{
|
||
ts.RollBack();
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Debug.WriteLine("异面无交点");
|
||
var conn = originMEPCurve1
|
||
.GetConnectors()
|
||
.OfType<Connector>()
|
||
.FirstOrDefault();
|
||
if (line1.Distance(line2) > conn.GetExtensionLength())
|
||
{
|
||
//找到两条线都垂直的向量
|
||
var normal = line1.Direction.CrossProduct(line2!.Direction);
|
||
var p1 = originMEPCurve1.GetCurve().GetEndPoint(0);
|
||
//根据垂直向量,找到能投影到的同一平面
|
||
var plane = Plane.CreateByNormalAndOrigin(normal, p1);
|
||
//投影线
|
||
var newProjectLine = plane.ProjectOnto(
|
||
originMEPCurve2.GetCurve() as Line
|
||
);
|
||
//不动的线
|
||
var stableCurve = originMEPCurve1.GetCurve();
|
||
stableCurve.MakeUnbound();
|
||
newProjectLine.MakeUnbound();
|
||
//共面线关系
|
||
var comparisonResult = stableCurve.Intersect(
|
||
newProjectLine,
|
||
out var array2
|
||
);
|
||
if (comparisonResult == SetComparisonResult.Overlap)
|
||
{
|
||
Debug.WriteLine("非共面相交");
|
||
|
||
var intersectPoint1 = array2.get_Item(0).XYZPoint;
|
||
var intersectPoint2 = unboundLine2
|
||
.Project(intersectPoint1)
|
||
.XYZPoint;
|
||
if (
|
||
intersectPoint1.DistanceTo(intersectPoint2)
|
||
< uiapp.Application.ShortCurveTolerance
|
||
)
|
||
{
|
||
Debug.WriteLine("交点距离太近");
|
||
break;
|
||
}
|
||
|
||
var verticalLine = Line.CreateBound(
|
||
intersectPoint1,
|
||
intersectPoint2
|
||
);
|
||
var verticalMEPCurveId = ElementTransformUtils
|
||
.CopyElement(doc, originMEPCurve1.Id, XYZ.Zero)
|
||
.FirstOrDefault();
|
||
var verticalMEPCurve = doc.GetElement(verticalMEPCurveId);
|
||
verticalMEPCurve.SetLocationCurve(verticalLine);
|
||
if (
|
||
!line1.IsInsideEx(intersectPoint1)
|
||
&& !line2.IsInsideEx(intersectPoint2)
|
||
)
|
||
{
|
||
Debug.WriteLine("都不在直线内,直角连接");
|
||
var extendLine1 = (
|
||
originMEPCurve1.GetCurve() as Line
|
||
).ExtendLine(intersectPoint1);
|
||
originMEPCurve1.SetLocationCurve(extendLine1);
|
||
var extendLine2 = (
|
||
originMEPCurve2.GetCurve() as Line
|
||
).ExtendLine(intersectPoint2);
|
||
originMEPCurve2.SetLocationCurve(extendLine2);
|
||
var conn1 = originMEPCurve1
|
||
.GetConnectors()
|
||
.GetNearestConnector(intersectPoint1);
|
||
var conn2 = verticalMEPCurve
|
||
.GetConnectors()
|
||
.GetNearestConnector(intersectPoint1);
|
||
var conn3 = originMEPCurve2
|
||
.GetConnectors()
|
||
.GetNearestConnector(intersectPoint1);
|
||
var conn4 = verticalMEPCurve
|
||
.GetConnectors()
|
||
.GetNearestConnector(intersectPoint2);
|
||
conn1.ConnectByFitting(conn2);
|
||
conn3.ConnectByFitting(conn4);
|
||
break;
|
||
}
|
||
|
||
if (
|
||
line1.IsInsideEx(intersectPoint1, 0.5)
|
||
&& !line2.IsInsideEx(intersectPoint2, 0.1)
|
||
) //在直线一内,在直线二端点,生成一个三通,一个弯头
|
||
{
|
||
mainMEPCurve = originMEPCurve1;
|
||
branchMEPCurve = originMEPCurve2;
|
||
Debug.WriteLine($"在直线一{mainMEPCurve.Id}内,在直线一端点,生成一个三通,一个弯头");
|
||
|
||
var line = (branchMEPCurve.GetCurve() as Line).ExtendLine(
|
||
intersectPoint2
|
||
);
|
||
branchMEPCurve.SetLocationCurve(line);
|
||
ConnectBranchMEP(
|
||
intersectPoint2,
|
||
intersectPoint1,
|
||
verticalMEPCurve,
|
||
mainMEPCurve,
|
||
branchMEPCurve
|
||
);
|
||
break;
|
||
}
|
||
|
||
if (
|
||
!line1.IsInsideEx(intersectPoint1, 0.1)
|
||
&& line2.IsInsideEx(intersectPoint2, 0.5)
|
||
)
|
||
{
|
||
mainMEPCurve = originMEPCurve2;
|
||
branchMEPCurve = originMEPCurve1;
|
||
Debug.WriteLine($"在直线二内{mainMEPCurve.Id},在直线一端点,生成一个三通,一个弯头");
|
||
|
||
var line = (branchMEPCurve.GetCurve() as Line).ExtendLine(
|
||
intersectPoint1
|
||
);
|
||
branchMEPCurve.SetLocationCurve(line);
|
||
ConnectBranchMEP(
|
||
intersectPoint1,
|
||
intersectPoint2,
|
||
verticalMEPCurve,
|
||
mainMEPCurve,
|
||
branchMEPCurve
|
||
);
|
||
break;
|
||
}
|
||
|
||
if (
|
||
line1.IsInsideEx(intersectPoint1, 0.5)
|
||
&& line2.IsInsideEx(intersectPoint2, 0.5)
|
||
) //
|
||
{
|
||
Debug.WriteLine("都在直线范围内,生成两个三通");
|
||
var newMEP = doc.GetElement(
|
||
originMEPCurve1.BreakByPoint(intersectPoint1)
|
||
);
|
||
var newMEP2 = doc.GetElement(
|
||
originMEPCurve2.BreakByPoint(intersectPoint2)
|
||
);
|
||
//找到交点最近的连接件
|
||
var connector1 = originMEPCurve1
|
||
.GetConnectors()
|
||
.GetNearestConnector(intersectPoint1);
|
||
var connector2 = newMEP
|
||
.GetConnectors()
|
||
.GetNearestConnector(intersectPoint1);
|
||
var connector3 = verticalMEPCurve
|
||
.GetConnectors()
|
||
.GetNearestConnector(intersectPoint1);
|
||
var connector4 = originMEPCurve2
|
||
.GetConnectors()
|
||
.GetNearestConnector(intersectPoint2);
|
||
var connector5 = newMEP2
|
||
.GetConnectors()
|
||
.GetNearestConnector(intersectPoint2);
|
||
var connector6 = verticalMEPCurve
|
||
.GetConnectors()
|
||
.GetNearestConnector(intersectPoint2);
|
||
doc.Create.NewTeeFitting(connector1, connector2, connector3);
|
||
doc.Create.NewTeeFitting(connector4, connector5, connector6);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case SetComparisonResult.Overlap:
|
||
|
||
{
|
||
Debug.WriteLine("共面相交");
|
||
var intersectPoint = array.get_Item(0).XYZPoint;
|
||
if (
|
||
line1.IsInsideEx(intersectPoint, 0.3)
|
||
&& line2.IsInsideEx(intersectPoint, 0.3)
|
||
) //
|
||
{
|
||
Debug.WriteLine("管线交叉");
|
||
doc.Regenerate();
|
||
var mepCurve1 =
|
||
doc.GetElement(originMEPCurve1.BreakByPoint(intersectPoint))
|
||
as MEPCurve;
|
||
var mepCurve2 =
|
||
doc.GetElement(originMEPCurve2.BreakByPoint(intersectPoint))
|
||
as MEPCurve;
|
||
var conn1 = mepCurve1!.ConnectorManager.Connectors.GetNearestConnector(
|
||
intersectPoint
|
||
);
|
||
var conn2 = mepCurve2!.ConnectorManager.Connectors.GetNearestConnector(
|
||
intersectPoint
|
||
);
|
||
var conn3 = originMEPCurve1.ConnectorManager.Connectors.GetNearestConnector(
|
||
intersectPoint
|
||
);
|
||
var conn4 = originMEPCurve2.ConnectorManager.Connectors.GetNearestConnector(
|
||
intersectPoint
|
||
);
|
||
try
|
||
{
|
||
doc.Create.NewCrossFitting(conn1, conn3, conn2, conn4);
|
||
}
|
||
catch (Autodesk.Revit.Exceptions.InvalidOperationException) { }
|
||
}
|
||
else if (
|
||
!line1.IsInsideEx(intersectPoint, 0.1)
|
||
&& line2.IsInsideEx(intersectPoint, 0.3)
|
||
)
|
||
{
|
||
Debug.WriteLine($"主({originMEPCurve2.Id})次分支");
|
||
if (isPerpendicular && Angle is not 0 and not 90)
|
||
{
|
||
Debug.WriteLine("使用角度");
|
||
ConnectByAngle(
|
||
originMEPCurve2,
|
||
originMEPCurve1,
|
||
intersectionUnbound,
|
||
Angle
|
||
);
|
||
}
|
||
else
|
||
{
|
||
originMEPCurve2.ConnectTo(originMEPCurve1);
|
||
}
|
||
}
|
||
else if (
|
||
line1.IsInsideEx(intersectPoint, 0.1)
|
||
&& !line2.IsInsideEx(intersectPoint, 0.3)
|
||
)
|
||
{
|
||
Debug.WriteLine($"主({originMEPCurve1.Id})次分支");
|
||
if (isPerpendicular && Angle is not 0 and not 90)
|
||
{
|
||
Debug.WriteLine("使用角度");
|
||
ConnectByAngle(
|
||
originMEPCurve1,
|
||
originMEPCurve2,
|
||
intersectionUnbound,
|
||
Angle
|
||
);
|
||
}
|
||
else
|
||
{
|
||
originMEPCurve1.ConnectTo(originMEPCurve2);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Debug.WriteLine("端点相交");
|
||
if (line1.Direction.IsAlmostEqualTo(XYZ.BasisZ))
|
||
{
|
||
mainMEPCurve = originMEPCurve1;
|
||
branchMEPCurve = originMEPCurve2;
|
||
}
|
||
else if (line2!.Direction.IsAlmostEqualTo(XYZ.BasisZ))
|
||
{
|
||
mainMEPCurve = originMEPCurve2;
|
||
branchMEPCurve = originMEPCurve1;
|
||
}
|
||
else if (line1.Length > line2!.Length)
|
||
{
|
||
mainMEPCurve = originMEPCurve1;
|
||
branchMEPCurve = originMEPCurve2;
|
||
}
|
||
else
|
||
{
|
||
mainMEPCurve = originMEPCurve2;
|
||
branchMEPCurve = originMEPCurve1;
|
||
}
|
||
|
||
if (isPerpendicular && Angle is not 0 and not 90)
|
||
{
|
||
Debug.WriteLine("使用角度");
|
||
ConnectByAngle(
|
||
mainMEPCurve,
|
||
branchMEPCurve,
|
||
intersectionUnbound,
|
||
Angle
|
||
);
|
||
}
|
||
else
|
||
{
|
||
originMEPCurve1.ConnectTo(originMEPCurve2);
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case SetComparisonResult.Subset:
|
||
case SetComparisonResult.Superset:
|
||
case SetComparisonResult.Equal:
|
||
Debug.WriteLine("共线,且只有一个交点,即两条有边界直线共线且首尾相连或者两条直线有重合部分");
|
||
MergeParallelMEPCurve(originMEPCurve1, originMEPCurve2);
|
||
break;
|
||
}
|
||
|
||
//List<Connector> conns4 = ConnectorAssist.GetNearestConnectors(originMEPCurve1, originMEPCurve2, true);
|
||
//conns4[0].ConnectByFitting(conns4[1], true);
|
||
break;
|
||
}
|
||
case 3:
|
||
{
|
||
var unboundLine1 = list[0].GetCurve();
|
||
var unboundLine2 = list[1].GetCurve();
|
||
var unboundLine3 = list[2].GetCurve();
|
||
//无边界保证相交
|
||
unboundLine1.MakeUnbound();
|
||
unboundLine2.MakeUnbound();
|
||
unboundLine3.MakeUnbound();
|
||
var result1 = unboundLine1.Intersect(unboundLine2, out var array1);
|
||
var result2 = unboundLine1.Intersect(unboundLine3, out var array2);
|
||
var result3 = unboundLine2.Intersect(unboundLine3, out var array3);
|
||
|
||
if (result1 == SetComparisonResult.Equal && result2 == SetComparisonResult.Overlap)
|
||
{
|
||
ConnectBy3MEPCurve(list[0], list[1], list[2], array2);
|
||
}
|
||
|
||
if (result2 == SetComparisonResult.Equal && result3 == SetComparisonResult.Overlap)
|
||
{
|
||
ConnectBy3MEPCurve(list[0], list[2], list[1], array3);
|
||
}
|
||
|
||
if (result3 == SetComparisonResult.Equal && result1 == SetComparisonResult.Overlap)
|
||
{
|
||
ConnectBy3MEPCurve(list[1], list[2], list[0], array1);
|
||
}
|
||
|
||
break;
|
||
}
|
||
case 4:
|
||
{
|
||
var unboundLine1 = list[0].GetCurve() as Line;
|
||
var unboundLine2 = list[1].GetCurve() as Line;
|
||
var unboundLine3 = list[2].GetCurve() as Line;
|
||
var unboundLine4 = list[3].GetCurve() as Line;
|
||
unboundLine1!.MakeUnbound();
|
||
unboundLine2!.MakeUnbound();
|
||
unboundLine3!.MakeUnbound();
|
||
unboundLine4!.MakeUnbound();
|
||
|
||
var result1 = unboundLine1.Intersect(unboundLine2, out var array1);
|
||
var result2 = unboundLine3.Intersect(unboundLine4);
|
||
|
||
var result3 = unboundLine1.Intersect(unboundLine3, out var array3);
|
||
var result4 = unboundLine2.Intersect(unboundLine4);
|
||
|
||
var result5 = unboundLine1.Intersect(unboundLine4);
|
||
var result6 = unboundLine2.Intersect(unboundLine3);
|
||
//保证垂直关系
|
||
if (
|
||
result1 == SetComparisonResult.Equal
|
||
&& result2 == SetComparisonResult.Equal
|
||
&& result3 == SetComparisonResult.Overlap
|
||
)
|
||
{
|
||
if (unboundLine1.IsPerpendicularTo(unboundLine3))
|
||
{
|
||
ConnectBy4MEPCurve(list[0], list[1], list[2], list[3], array3);
|
||
}
|
||
}
|
||
|
||
if (
|
||
result3 == SetComparisonResult.Equal
|
||
&& result4 == SetComparisonResult.Equal
|
||
&& result1 == SetComparisonResult.Overlap
|
||
)
|
||
{
|
||
if (unboundLine1.IsPerpendicularTo(unboundLine2))
|
||
{
|
||
ConnectBy4MEPCurve(list[0], list[2], list[1], list[3], array1);
|
||
}
|
||
}
|
||
|
||
if (
|
||
result5 == SetComparisonResult.Equal
|
||
&& result6 == SetComparisonResult.Equal
|
||
&& result1 == SetComparisonResult.Overlap
|
||
)
|
||
{
|
||
if (unboundLine1.IsPerpendicularTo(unboundLine2))
|
||
{
|
||
ConnectBy4MEPCurve(list[0], list[3], list[1], list[2], array1);
|
||
}
|
||
}
|
||
|
||
break;
|
||
}
|
||
}
|
||
#if REVIT2020
|
||
OptionsBarAssist.HideOptionsBar();
|
||
#endif
|
||
},
|
||
"任意连接"
|
||
);
|
||
}
|
||
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
|
||
{
|
||
CanRunning = true;
|
||
#if REVIT2020
|
||
OptionsBarAssist.HideOptionsBar();
|
||
#endif
|
||
return;
|
||
}
|
||
catch (Exception)
|
||
{
|
||
CanRunning = true;
|
||
}
|
||
CanRunning = true;
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 连接异面两根管管
|
||
/// </summary>
|
||
/// <param name="intersectPoint1"></param>
|
||
/// <param name="intersectPoint2"></param>
|
||
/// <param name="verticalMEPCurve"></param>
|
||
/// <param name="mainMEPCurve"></param>
|
||
/// <param name="branchMEPCurve"></param>
|
||
private static void ConnectBranchMEP(
|
||
XYZ intersectPoint1,
|
||
XYZ intersectPoint2,
|
||
Element verticalMEPCurve,
|
||
MEPCurve mainMEPCurve,
|
||
MEPCurve branchMEPCurve
|
||
)
|
||
{
|
||
var doc = verticalMEPCurve.Document;
|
||
var mepId = mainMEPCurve.BreakByPoint(intersectPoint2);
|
||
var newMEP = doc.GetElement(mepId);
|
||
var conn = mainMEPCurve.GetConnectors().GetNearestConnector(intersectPoint2);
|
||
var conn2 = newMEP.GetConnectors().GetNearestConnector(intersectPoint2);
|
||
var conn3 = verticalMEPCurve.GetConnectors().GetNearestConnector(intersectPoint2);
|
||
var conn4 = verticalMEPCurve.GetConnectors().GetNearestConnector(intersectPoint1);
|
||
var conn5 = branchMEPCurve.GetConnectors().GetNearestConnector(intersectPoint1);
|
||
doc.Create.NewTeeFitting(conn, conn2, conn3);
|
||
conn4.ConnectByFitting(conn5);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 三管连接
|
||
/// </summary>
|
||
/// <param name="originMEPCurve1">主管</param>
|
||
/// <param name="originMEPCurve2">主管</param>
|
||
/// <param name="originMEPCurve3">支管</param>
|
||
/// <param name="array"></param>
|
||
private static void ConnectBy3MEPCurve(
|
||
MEPCurve originMEPCurve1,
|
||
MEPCurve originMEPCurve2,
|
||
MEPCurve originMEPCurve3,
|
||
IntersectionResultArray array
|
||
)
|
||
{
|
||
var doc = originMEPCurve1.Document;
|
||
var intersection = array.get_Item(0).XYZPoint;
|
||
var line1 = originMEPCurve1.GetCurve() as Line;
|
||
var line2 = originMEPCurve2.GetCurve() as Line;
|
||
var line3 = originMEPCurve3.GetCurve() as Line;
|
||
var extendLine = line1.ExtendLine(intersection);
|
||
originMEPCurve1.SetLocationCurve(extendLine);
|
||
var extendLine2 = line2.ExtendLine(intersection);
|
||
originMEPCurve2.SetLocationCurve(extendLine2);
|
||
var conns = ConnectorAssist.GetNearestConnectors(originMEPCurve1, originMEPCurve2);
|
||
|
||
if (line3.IsInsideEx(intersection, 0.5))
|
||
{
|
||
var newBranchId = originMEPCurve3.BreakByPoint(intersection);
|
||
var newBranchMEPCurve = doc.GetElement(newBranchId);
|
||
var conns2 = ConnectorAssist.GetNearestConnectors(originMEPCurve3, newBranchMEPCurve);
|
||
doc.Create.NewCrossFitting(conns[0], conns[1], conns2[0], conns2[1]);
|
||
}
|
||
else
|
||
{
|
||
var extendLine3 = line3.ExtendLine(intersection);
|
||
originMEPCurve3.SetLocationCurve(extendLine3);
|
||
var conn = originMEPCurve3.GetConnectors(true).GetNearestConnector(intersection);
|
||
conn.ConnectByTee(conns[0], conns[1]);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 四根管线连接
|
||
/// </summary>
|
||
/// <param name="originMEPCurve1"></param>
|
||
/// <param name="originMEPCurve2"></param>
|
||
/// <param name="originMEPCurve3"></param>
|
||
/// <param name="originMEPCurve4"></param>
|
||
/// <param name="array"></param>
|
||
private static void ConnectBy4MEPCurve(
|
||
MEPCurve originMEPCurve1,
|
||
MEPCurve originMEPCurve2,
|
||
MEPCurve originMEPCurve3,
|
||
MEPCurve originMEPCurve4,
|
||
IntersectionResultArray array
|
||
)
|
||
{
|
||
var doc = originMEPCurve1.Document;
|
||
var intersection = array.get_Item(0).XYZPoint;
|
||
var line = originMEPCurve1.GetCurve() as Line;
|
||
var line2 = originMEPCurve2.GetCurve() as Line;
|
||
var line3 = originMEPCurve3.GetCurve() as Line;
|
||
var line4 = originMEPCurve4.GetCurve() as Line;
|
||
var extendLine = line.ExtendLine(intersection);
|
||
originMEPCurve1.SetLocationCurve(extendLine);
|
||
var extendLine2 = line2.ExtendLine(intersection);
|
||
originMEPCurve2.SetLocationCurve(extendLine2);
|
||
var extendLine3 = line3.ExtendLine(intersection);
|
||
originMEPCurve3.SetLocationCurve(extendLine3);
|
||
var extendLine4 = line4.ExtendLine(intersection);
|
||
originMEPCurve4.SetLocationCurve(extendLine4);
|
||
var conns = ConnectorAssist.GetNearestConnectors(originMEPCurve1, originMEPCurve2);
|
||
var conns2 = ConnectorAssist.GetNearestConnectors(originMEPCurve3, originMEPCurve4);
|
||
//Debug.WriteLine(string.Format("{0}-{1}", originConnectors[0].Origin, originConnectors[0].CoordinateSystem.BasisZ));
|
||
//Debug.WriteLine(string.Format("{0}-{1}", originConnectors[1].Origin, originConnectors[1].CoordinateSystem.BasisZ));
|
||
//Debug.WriteLine(string.Format("{0}-{1}", conns2[0].Origin, conns2[0].CoordinateSystem.BasisZ));
|
||
//Debug.WriteLine(string.Format("{0}-{1}", conns2[1].Origin, conns2[1].CoordinateSystem.BasisZ));
|
||
doc.Create.NewCrossFitting(conns[0], conns[1], conns2[0], conns2[1]);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 主分支角度连接
|
||
/// </summary>
|
||
/// <param name="mainMepCurve"></param>
|
||
/// <param name="branchMepCurve"></param>
|
||
/// <param name="intersection2">交点</param>
|
||
/// <param name="angle">角度</param>
|
||
private static void ConnectByAngle(MEPCurve mainMepCurve, MEPCurve branchMepCurve, XYZ intersection2, double angle)
|
||
{
|
||
var doc = mainMepCurve.Document;
|
||
|
||
var mainFarthestConnector = mainMepCurve.ConnectorManager.Connectors.GetFarthestConnector(intersection2); //获取距离交点远处的连接件
|
||
var branchNearestConnector = branchMepCurve.ConnectorManager.Connectors.GetNearestConnector(intersection2); //分支管距离主管最近的连接件
|
||
var extendLength = branchNearestConnector.GetExtensionLength();
|
||
if (branchNearestConnector.Origin.DistanceTo(intersection2) < 3 * extendLength)
|
||
{
|
||
var branchEndpoint =
|
||
branchNearestConnector.Origin - (branchNearestConnector.CoordinateSystem.BasisZ * extendLength);
|
||
var branchLine = (branchMepCurve.GetCurve() as Line).ExtendLine(branchEndpoint);
|
||
branchMepCurve.SetLocationCurve(branchLine);
|
||
}
|
||
|
||
doc.Regenerate();
|
||
var normal = branchNearestConnector.CoordinateSystem.BasisZ.CrossProduct(
|
||
mainFarthestConnector.CoordinateSystem.BasisZ
|
||
);
|
||
var axis = Line.CreateUnbound(branchNearestConnector.Origin, normal);
|
||
var angleLine = Line.CreateBound(intersection2, branchNearestConnector.Origin);
|
||
if (!angleLine.Direction.IsAlmostEqualTo((branchMepCurve.GetCurve() as Line)?.Direction))
|
||
{
|
||
angleLine = angleLine.CreateReversed() as Line;
|
||
}
|
||
|
||
var id = ElementTransformUtils.CopyElement(doc, branchMepCurve.Id, XYZ.Zero).FirstOrDefault();
|
||
var angleMepCurve = doc.GetElement(id) as MEPCurve;
|
||
angleMepCurve.SetLocationCurve(angleLine);
|
||
ElementTransformUtils.RotateElement(doc, angleMepCurve!.Id, axis, angle.ToRadian());
|
||
doc.Regenerate();
|
||
var unboundMainLine = mainMepCurve.GetCurve() as Line;
|
||
unboundMainLine!.MakeUnbound();
|
||
var unboundAngleLine = angleMepCurve.GetCurve() as Line;
|
||
unboundAngleLine!.MakeUnbound();
|
||
var mainEndpoint = unboundAngleLine.IntersectionPoint(unboundMainLine);
|
||
var mainLine = (mainMepCurve.GetCurve() as Line).ExtendLine(mainEndpoint);
|
||
mainMepCurve.SetLocationCurve(mainLine);
|
||
doc.Regenerate();
|
||
mainMepCurve.ConnectTo(angleMepCurve);
|
||
angleMepCurve.ConnectTo(branchMepCurve);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 合并平行管线
|
||
/// </summary>
|
||
/// <param name="originMEPCurve1"></param>
|
||
/// <param name="originMEPCurve2"></param>
|
||
private static void MergeParallelMEPCurve(MEPCurve originMEPCurve1, MEPCurve originMEPCurve2)
|
||
{
|
||
var doc = originMEPCurve1.Document;
|
||
var conns = ConnectorAssist.GetFarthestConnectors(originMEPCurve1, originMEPCurve2, false);
|
||
var flag = false;
|
||
//判断大小管
|
||
switch (conns[0].Shape)
|
||
{
|
||
case ConnectorProfileType.Round:
|
||
flag =
|
||
originMEPCurve1.Diameter > originMEPCurve2.Diameter
|
||
|| originMEPCurve1.GetCurve().Length > originMEPCurve2.GetCurve().Length;
|
||
break;
|
||
case ConnectorProfileType.Rectangular:
|
||
case ConnectorProfileType.Oval:
|
||
flag =
|
||
originMEPCurve1.Width > originMEPCurve2.Width
|
||
|| originMEPCurve1.Height > originMEPCurve2.Height
|
||
|| originMEPCurve1.GetCurve().Length > originMEPCurve2.GetCurve().Length;
|
||
break;
|
||
}
|
||
|
||
//保留
|
||
MEPCurve reserveMEPCurve;
|
||
MEPCurve removeMEPCurve;
|
||
if (flag)
|
||
{
|
||
reserveMEPCurve = originMEPCurve1;
|
||
removeMEPCurve = originMEPCurve2;
|
||
}
|
||
else
|
||
{
|
||
reserveMEPCurve = originMEPCurve2;
|
||
removeMEPCurve = originMEPCurve1;
|
||
}
|
||
|
||
List<Connector> connsConnected = [];
|
||
//Dictionary<Connector, Connector> dict = new ();
|
||
foreach (var item in conns)
|
||
{
|
||
if (item.GetConnectedConnector() != null)
|
||
{
|
||
connsConnected.Add(item.GetConnectedConnector());
|
||
}
|
||
}
|
||
|
||
var loc = reserveMEPCurve.Location as LocationCurve;
|
||
var locLine = loc!.Curve as Line;
|
||
var newLocLine = Line.CreateBound(conns[0].Origin, conns[1].Origin);
|
||
//判断方向
|
||
loc.Curve = locLine!.Direction.IsAlmostEqualTo(newLocLine.Direction) ? newLocLine : newLocLine.CreateReversed();
|
||
//删除短管,先删除才好后续连接
|
||
doc.Delete(removeMEPCurve.Id);
|
||
doc.Regenerate();
|
||
|
||
foreach (var connConnected in connsConnected)
|
||
{
|
||
//keyValuePair.Key.ConnectByFitting(keyValuePair.Value, false);
|
||
foreach (Connector conn in reserveMEPCurve.GetConnectors(true))
|
||
{
|
||
if (
|
||
conn.Origin.IsAlmostEqualTo(connConnected.Origin)
|
||
&& conn.CoordinateSystem.BasisZ.IsAlmostEqualTo(connConnected.CoordinateSystem.BasisZ.Negate())
|
||
)
|
||
{
|
||
conn.ConnectByFitting(connConnected);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
partial void OnMessageChanged(string value)
|
||
{
|
||
ActiveSnackbar = true;
|
||
Thread.Sleep(2_000);
|
||
ActiveSnackbar = false;
|
||
//MessageQueue.Enqueue(value, null, null, null, false, true, TimeSpan.FromSeconds(2));
|
||
}
|
||
}
|