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 ShrlAlgoToolkit.RevitAddins.RvMEP; public partial class AnyConnectViewModel : ObservableValidator { //#if REVIT2020 // public AnyConnectViewModel() // { // OptionsBarAssist.ShowOptionsBar(); // } //#endif private readonly ActionEventHandler anyConnectHandler = new(); [ObservableProperty] public partial bool ActiveSnackbar { get; set; } [ObservableProperty] public partial bool IsMultiSelect { get; set; } = true; [ObservableProperty] [NotifyCanExecuteChangedFor(nameof(RevitAddins.RvMEP.AnyConnectViewModel.ConnectCommand))] public partial bool CanRunning { get; set; } = true; [ObservableProperty] [Range(0, 90)] [NotifyDataErrorInfo] public partial double Angle { get; set; } = 90; [ObservableProperty] public partial NeoUI.Controls.Alert MessageQueue { get; set; } = new(); [ObservableProperty] public partial string Message { get; set; } [RelayCommand] private static void Closing() { KeyIntPtrHelper.RaiseEscTwice(); } partial void OnIsMultiSelectChanged(bool value) { KeyIntPtrHelper.RaiseEscTwice(); } [RelayCommand(CanExecute = nameof(RevitAddins.RvMEP.AnyConnectViewModel.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 list; try { #if REVIT2018 list = IsMultiSelect ? uidoc.Selection .PickObjects(ObjectType.Element, filter, "请选择管线并完成") .Select(r => doc.GetElement(r)) .OfType() .ToList() : uidoc.Selection.PickElementsByRectangle(filter, "请框选管线").Cast().ToList(); #elif REVIT2020 || REVIT2025 list = uidoc.Selection .PickObjects(ObjectType.Element, filter, "请选择管线并完成") .Select(r => doc.GetElement(r)) .OfType() .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(); 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 = originMEPCurve1.GetNearestConnectors(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 = originMEPCurve1.GetNearestConnectors( copyMepCurve ); var conns2 = originMEPCurve2.GetNearestConnectors( 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() .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 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; }); } /// /// 连接异面两根管管 /// /// /// /// /// /// 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); } /// /// 三管连接 /// /// 主管 /// 主管 /// 支管 /// 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 = originMEPCurve1.GetNearestConnectors( originMEPCurve2); if (line3.IsInsideEx(intersection, 0.5)) { var newBranchId = originMEPCurve3.BreakByPoint(intersection); var newBranchMEPCurve = doc.GetElement(newBranchId); var conns2 = originMEPCurve3.GetNearestConnectors(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]); } } /// /// 四根管线连接 /// /// /// /// /// /// 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 = originMEPCurve1.GetNearestConnectors(originMEPCurve2); var conns2 = originMEPCurve3.GetNearestConnectors(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]); } /// /// 主分支角度连接 /// /// /// /// 交点 /// 角度 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); } /// /// 合并平行管线 /// /// /// private static void MergeParallelMEPCurve(MEPCurve originMEPCurve1, MEPCurve originMEPCurve2) { var doc = originMEPCurve1.Document; var conns = originMEPCurve1.GetFarthestConnectors(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 connsConnected = []; //Dictionary 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)); } }