Files
ShrlAlgoToolkit/ShrlAlgoToolkit.RevitAddins/RvMEP/AnyConnectViewModel.cs

1022 lines
62 KiB
C#
Raw Normal View History

2025-04-24 20:56:44 +08:00
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Windows;
2024-09-22 11:05:41 +08:00
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;
2024-09-22 11:05:41 +08:00
2025-04-24 20:56:44 +08:00
namespace ShrlAlgoToolkit.RevitAddins.RvMEP;
2024-09-22 11:05:41 +08:00
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]
2025-04-24 20:56:44 +08:00
[NotifyCanExecuteChangedFor(nameof(RevitAddins.RvMEP.AnyConnectViewModel.ConnectCommand))]
2024-09-22 11:05:41 +08:00
private bool canRunning = true;
[ObservableProperty]
[Range(0, 90)]
[NotifyDataErrorInfo]
private double angle = 90;
[ObservableProperty]
2025-08-24 13:49:55 +08:00
private NeoUI.Controls.Alert messageQueue = new();
2024-09-22 11:05:41 +08:00
[ObservableProperty]
private string message;
[RelayCommand]
2024-12-22 10:26:12 +08:00
private static void Closing()
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
KeyIntPtrHelper.RaiseEscTwice();
}
partial void OnIsMultiSelectChanged(bool value)
{
KeyIntPtrHelper.RaiseEscTwice();
2024-09-22 11:05:41 +08:00
}
2025-04-24 20:56:44 +08:00
[RelayCommand(CanExecute = nameof(RevitAddins.RvMEP.AnyConnectViewModel.CanRunning))]
2024-09-22 11:05:41 +08:00
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
2024-12-22 10:26:12 +08:00
list = IsMultiSelect
? uidoc.Selection
2024-09-22 11:05:41 +08:00
.PickObjects(ObjectType.Element, filter, "请选择管线并完成")
.Select(r => doc.GetElement(r))
.OfType<MEPCurve>()
2024-12-22 10:26:12 +08:00
.ToList()
: uidoc.Selection.PickElementsByRectangle(filter, "请框选管线").Cast<MEPCurve>().ToList();
#elif REVIT2020 || REVIT2025
2024-09-22 11:05:41 +08:00
list = uidoc.Selection
.PickObjects(ObjectType.Element, filter, "请选择管线并完成")
.Select(r => doc.GetElement(r))
.OfType<MEPCurve>()
.ToList();
#endif
2024-12-22 10:26:12 +08:00
var defaultType = list.FirstOrDefault()?.GetType();
if (list.Count < 2 || list.Any(t => defaultType != t.GetType()))
{
Message = "所选管线数量小于2或类别不同不允许连接";
CanRunning = true;
2024-09-22 11:05:41 +08:00
#if REVIT2020
OptionsBarAssist.HideOptionsBar();
#endif
2024-12-22 10:26:12 +08:00
return;
}
2024-09-22 11:05:41 +08:00
2024-12-22 10:26:12 +08:00
doc.Invoke(
ts =>
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
switch (list.Count)
{
case 2:
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
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:
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
Debug.WriteLine("管线没有交点");
var intersection1 = line1.IntersectionPoint(unboundLine2);
var intersection2 = line2.IntersectionPoint(unboundLine1);
if (intersection1 == null && intersection2 != null)
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
branchMEPCurve = originMEPCurve1;
mainMEPCurve = originMEPCurve2;
Debug.WriteLine($"共面无交点:交点在第二条线上{mainMEPCurve.Id},为主管");
if (isPerpendicular && Angle is not 0 and not 90)
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
Debug.WriteLine("使用角度");
ConnectByAngle(mainMEPCurve, branchMEPCurve, intersection2, Angle);
2024-09-22 11:05:41 +08:00
}
else
{
2024-12-22 10:26:12 +08:00
mainMEPCurve.ConnectTo(branchMEPCurve);
2024-09-22 11:05:41 +08:00
}
2024-12-22 10:26:12 +08:00
break;
}
if (intersection1 != null && intersection2 == null)
{
mainMEPCurve = originMEPCurve1;
branchMEPCurve = originMEPCurve2;
Debug.WriteLine($"共面无交点:交点在第一条线上{mainMEPCurve.Id},为主管");
2024-09-22 11:05:41 +08:00
if (isPerpendicular && Angle is not 0 and not 90)
{
Debug.WriteLine("使用角度");
2024-12-22 10:26:12 +08:00
ConnectByAngle(mainMEPCurve, branchMEPCurve, intersection1, Angle);
2024-09-22 11:05:41 +08:00
}
else
{
2024-12-22 10:26:12 +08:00
mainMEPCurve.ConnectTo(branchMEPCurve);
2024-09-22 11:05:41 +08:00
}
2024-12-22 10:26:12 +08:00
break;
2024-09-22 11:05:41 +08:00
}
2024-12-22 10:26:12 +08:00
// 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
2024-09-22 11:05:41 +08:00
);
2024-12-22 10:26:12 +08:00
if (cos < -10E-8 || Math.Abs(cos) < 10E-8)
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
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;
}
2024-09-22 11:05:41 +08:00
2024-12-22 10:26:12 +08:00
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
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
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));
2024-09-22 11:05:41 +08:00
}
2024-12-22 10:26:12 +08:00
break;
}
2024-09-22 11:05:41 +08:00
2024-12-22 10:26:12 +08:00
if (line1.IsParallelTo(line2))
{
var c = line1.Intersect(unboundLine2); //第一个是第二个的SubSet子集
2024-09-22 11:05:41 +08:00
2024-12-22 10:26:12 +08:00
//var c1 = unboundLine1.Intersect(line2);//第一个是第二个的SuperSet超集
//距离最近的两个连接件
2025-07-11 09:20:23 +08:00
var originConnectors = originMEPCurve1.GetNearestConnectors(originMEPCurve2
2024-12-22 10:26:12 +08:00
);
2024-09-22 11:05:41 +08:00
2024-12-22 10:26:12 +08:00
if (c == SetComparisonResult.Subset)
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
Debug.WriteLine("共线平行");
2024-09-22 11:05:41 +08:00
2024-12-22 10:26:12 +08:00
originConnectors[0].ConnectByFitting(originConnectors[1]);
2024-09-22 11:05:41 +08:00
}
else
{
2024-12-22 10:26:12 +08:00
Debug.WriteLine("非共线平行");
2024-09-22 11:05:41 +08:00
2024-12-22 10:26:12 +08:00
//最近连接件距离太短时
var dis = originConnectors[0].Origin.DistanceTo(
originConnectors[1].Origin
2024-09-22 11:05:41 +08:00
);
2024-12-22 10:26:12 +08:00
if (dis < uiapp.Application.ShortCurveTolerance)
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
MessageBox.Show("连接处相距太近");
2024-09-22 11:05:41 +08:00
break;
}
2024-12-22 10:26:12 +08:00
var isOriginMEPCurve1Bigger = false;
//取小的管径,用于复制作为转弯管
switch (originConnectors[0].Shape)
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
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;
2024-09-22 11:05:41 +08:00
}
2024-12-22 10:26:12 +08:00
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();
2025-07-11 09:20:23 +08:00
var conns1 = originMEPCurve1.GetNearestConnectors(
2024-12-22 10:26:12 +08:00
copyMepCurve
);
2024-09-22 11:05:41 +08:00
2025-07-11 09:20:23 +08:00
var conns2 = originMEPCurve2.GetNearestConnectors(
2024-12-22 10:26:12 +08:00
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
2024-09-22 11:05:41 +08:00
);
2024-12-22 10:26:12 +08:00
var axis = Line.CreateUnbound(l.Origin, direction);
ElementTransformUtils.RotateElement(
doc,
copyMepCurve!.Id,
axis,
radian
2024-09-22 11:05:41 +08:00
);
}
2024-12-22 10:26:12 +08:00
if (cos < -10E-8 || Math.Abs(cos) < 10E-8)
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
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();
2024-09-22 11:05:41 +08:00
}
}
}
else
{
2024-12-22 10:26:12 +08:00
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);
}
}
}
2024-09-22 11:05:41 +08:00
}
}
2024-12-22 10:26:12 +08:00
break;
case SetComparisonResult.Overlap:
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
Debug.WriteLine("共面相交");
var intersectPoint = array.get_Item(0).XYZPoint;
if (
line1.IsInsideEx(intersectPoint, 0.3)
&& line2.IsInsideEx(intersectPoint, 0.3)
) //
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
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
2024-09-22 11:05:41 +08:00
);
2024-12-22 10:26:12 +08:00
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) { }
2024-09-22 11:05:41 +08:00
}
2024-12-22 10:26:12 +08:00
else if (
!line1.IsInsideEx(intersectPoint, 0.1)
&& line2.IsInsideEx(intersectPoint, 0.3)
)
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
Debug.WriteLine($"主({originMEPCurve2.Id})次分支");
if (isPerpendicular && Angle is not 0 and not 90)
{
Debug.WriteLine("使用角度");
ConnectByAngle(
originMEPCurve2,
originMEPCurve1,
intersectionUnbound,
Angle
);
}
else
{
originMEPCurve2.ConnectTo(originMEPCurve1);
}
2024-09-22 11:05:41 +08:00
}
2024-12-22 10:26:12 +08:00
else if (
line1.IsInsideEx(intersectPoint, 0.1)
&& !line2.IsInsideEx(intersectPoint, 0.3)
)
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
Debug.WriteLine($"主({originMEPCurve1.Id})次分支");
if (isPerpendicular && Angle is not 0 and not 90)
{
Debug.WriteLine("使用角度");
ConnectByAngle(
originMEPCurve1,
originMEPCurve2,
intersectionUnbound,
Angle
);
}
else
{
originMEPCurve1.ConnectTo(originMEPCurve2);
}
2024-09-22 11:05:41 +08:00
}
else
{
2024-12-22 10:26:12 +08:00
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;
}
2024-09-22 11:05:41 +08:00
2024-12-22 10:26:12 +08:00
if (isPerpendicular && Angle is not 0 and not 90)
{
Debug.WriteLine("使用角度");
ConnectByAngle(
mainMEPCurve,
branchMEPCurve,
intersectionUnbound,
Angle
);
}
else
{
originMEPCurve1.ConnectTo(originMEPCurve2);
}
2024-09-22 11:05:41 +08:00
}
}
2024-12-22 10:26:12 +08:00
break;
case SetComparisonResult.Subset:
case SetComparisonResult.Superset:
case SetComparisonResult.Equal:
Debug.WriteLine("共线,且只有一个交点,即两条有边界直线共线且首尾相连或者两条直线有重合部分");
MergeParallelMEPCurve(originMEPCurve1, originMEPCurve2);
break;
}
2024-09-22 11:05:41 +08:00
2024-12-22 10:26:12 +08:00
//List<Connector> conns4 = ConnectorAssist.GetNearestConnectors(originMEPCurve1, originMEPCurve2, true);
//conns4[0].ConnectByFitting(conns4[1], true);
break;
2024-09-22 11:05:41 +08:00
}
2024-12-22 10:26:12 +08:00
case 3:
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
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);
}
2024-09-22 11:05:41 +08:00
2024-12-22 10:26:12 +08:00
if (result2 == SetComparisonResult.Equal && result3 == SetComparisonResult.Overlap)
{
ConnectBy3MEPCurve(list[0], list[2], list[1], array3);
}
2024-09-22 11:05:41 +08:00
2024-12-22 10:26:12 +08:00
if (result3 == SetComparisonResult.Equal && result1 == SetComparisonResult.Overlap)
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
ConnectBy3MEPCurve(list[1], list[2], list[0], array1);
2024-09-22 11:05:41 +08:00
}
2024-12-22 10:26:12 +08:00
break;
}
case 4:
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
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
)
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
if (unboundLine1.IsPerpendicularTo(unboundLine3))
{
ConnectBy4MEPCurve(list[0], list[1], list[2], list[3], array3);
}
2024-09-22 11:05:41 +08:00
}
2024-12-22 10:26:12 +08:00
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
)
2024-09-22 11:05:41 +08:00
{
2024-12-22 10:26:12 +08:00
if (unboundLine1.IsPerpendicularTo(unboundLine2))
{
ConnectBy4MEPCurve(list[0], list[3], list[1], list[2], array1);
}
2024-09-22 11:05:41 +08:00
}
2024-12-22 10:26:12 +08:00
break;
}
}
2024-09-22 11:05:41 +08:00
#if REVIT2020
OptionsBarAssist.HideOptionsBar();
#endif
2024-12-22 10:26:12 +08:00
},
"任意连接"
);
}
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
{
CanRunning = true;
#if REVIT2020
OptionsBarAssist.HideOptionsBar();
#endif
return;
}
catch (Exception)
{
CanRunning = true;
}
2024-09-22 11:05:41 +08:00
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;
2024-12-22 10:26:12 +08:00
var line1 = originMEPCurve1.GetCurve() as Line;
var line2 = originMEPCurve2.GetCurve() as Line;
var line3 = originMEPCurve3.GetCurve() as Line;
2024-09-22 11:05:41 +08:00
var extendLine = line1.ExtendLine(intersection);
originMEPCurve1.SetLocationCurve(extendLine);
var extendLine2 = line2.ExtendLine(intersection);
originMEPCurve2.SetLocationCurve(extendLine2);
2025-07-11 09:20:23 +08:00
var conns = originMEPCurve1.GetNearestConnectors( originMEPCurve2);
2024-09-22 11:05:41 +08:00
if (line3.IsInsideEx(intersection, 0.5))
{
var newBranchId = originMEPCurve3.BreakByPoint(intersection);
var newBranchMEPCurve = doc.GetElement(newBranchId);
2025-07-11 09:20:23 +08:00
var conns2 = originMEPCurve3.GetNearestConnectors(newBranchMEPCurve);
2024-09-22 11:05:41 +08:00
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;
2024-12-22 10:26:12 +08:00
var line = originMEPCurve1.GetCurve() as Line;
var line2 = originMEPCurve2.GetCurve() as Line;
var line3 = originMEPCurve3.GetCurve() as Line;
var line4 = originMEPCurve4.GetCurve() as Line;
2024-09-22 11:05:41 +08:00
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);
2025-07-11 09:20:23 +08:00
var conns = originMEPCurve1.GetNearestConnectors(originMEPCurve2);
var conns2 = originMEPCurve3.GetNearestConnectors(originMEPCurve4);
2024-09-22 11:05:41 +08:00
//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);
2024-12-22 10:26:12 +08:00
var branchLine = (branchMepCurve.GetCurve() as Line).ExtendLine(branchEndpoint);
2024-09-22 11:05:41 +08:00
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);
2024-12-22 10:26:12 +08:00
if (!angleLine.Direction.IsAlmostEqualTo((branchMepCurve.GetCurve() as Line)?.Direction))
2024-09-22 11:05:41 +08:00
{
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();
2024-12-22 10:26:12 +08:00
var unboundMainLine = mainMepCurve.GetCurve() as Line;
2024-09-22 11:05:41 +08:00
unboundMainLine!.MakeUnbound();
2024-12-22 10:26:12 +08:00
var unboundAngleLine = angleMepCurve.GetCurve() as Line;
2024-09-22 11:05:41 +08:00
unboundAngleLine!.MakeUnbound();
var mainEndpoint = unboundAngleLine.IntersectionPoint(unboundMainLine);
2024-12-22 10:26:12 +08:00
var mainLine = (mainMepCurve.GetCurve() as Line).ExtendLine(mainEndpoint);
2024-09-22 11:05:41 +08:00
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;
2025-07-11 09:20:23 +08:00
var conns = originMEPCurve1.GetFarthestConnectors(originMEPCurve2, false);
2024-09-22 11:05:41 +08:00
var flag = false;
//判断大小管
switch (conns[0].Shape)
{
case ConnectorProfileType.Round:
flag =
originMEPCurve1.Diameter > originMEPCurve2.Diameter
2024-12-22 10:26:12 +08:00
|| originMEPCurve1.GetCurve().Length > originMEPCurve2.GetCurve().Length;
2024-09-22 11:05:41 +08:00
break;
case ConnectorProfileType.Rectangular:
case ConnectorProfileType.Oval:
flag =
originMEPCurve1.Width > originMEPCurve2.Width
|| originMEPCurve1.Height > originMEPCurve2.Height
2024-12-22 10:26:12 +08:00
|| originMEPCurve1.GetCurve().Length > originMEPCurve2.GetCurve().Length;
2024-09-22 11:05:41 +08:00
break;
}
//保留
MEPCurve reserveMEPCurve;
MEPCurve removeMEPCurve;
if (flag)
{
reserveMEPCurve = originMEPCurve1;
removeMEPCurve = originMEPCurve2;
}
else
{
reserveMEPCurve = originMEPCurve2;
removeMEPCurve = originMEPCurve1;
}
2024-12-22 10:26:12 +08:00
List<Connector> connsConnected = [];
2024-09-22 11:05:41 +08:00
//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));
}
}