using System.Windows; using Autodesk.Revit.Attributes; using Autodesk.Revit.DB; using Nice3point.Revit.Toolkit.External; namespace ShrlAlgo.RvKits.RvMEP; [Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] public class MoveConnectCmd : ExternalCommand { public override void Execute() { Reference baseReference; Reference moveReference; try { baseReference = UiDocument.Selection.PickObject( Autodesk.Revit.UI.Selection.ObjectType.Element, new FuncFilter(e => e.GetConnectors(true)?.Size > 0), "请选择基准的管线、管件、设备实例" ); moveReference = UiDocument.Selection.PickObject( Autodesk.Revit.UI.Selection.ObjectType.Element, new FuncFilter( e => e.Id != baseReference.ElementId && e.GetConnectors(true)?.Size > 0 ), "请选择需要移动连接的管线、管件、设备实例" ); } catch (Autodesk.Revit.Exceptions.OperationCanceledException) { return; } var baseElement = Document.GetElement(baseReference); var elementToMove = Document.GetElement(moveReference); var list = ConnectorAssist.GetNearestDomainConnectors(baseElement, elementToMove); if (list.Count != 2) { MessageBox.Show("缺少可连接的连接件", "提示"); return; } Document.Invoke( _ => { var conn1 = list[0]; var conn2 = list.Last(); //if (conn1.Domain != conn2.Domain)//类型不一样不能连接 //{ // return; //} var origin1 = conn1.Origin; var origin2 = conn2.Origin; var direction1 = conn1.CoordinateSystem.BasisZ; var direction2 = conn2.CoordinateSystem.BasisZ; //夹角 var radian = Math.Acos(direction1.DotProduct(direction2)); //都是管线,角度小于135,主次分支对齐连接,仅支持中心对齐 if ( baseElement is MEPCurve mainMEPCurve && elementToMove is MEPCurve branchMEPCurve && radian < 135.0.ToRadian() ) { //if ((conn2.Shape == ConnectorProfileType.Oval || conn2.Shape == ConnectorProfileType.Rectangular)) //{ // var verticalJustification = mainMEPCurve.get_Parameter(BuiltInParameter.RBS_CURVE_VERT_OFFSET_PARAM); // var delta = XYZ.BasisZ * (branchMEPCurve.Height / 2 - mainMEPCurve.Height / 2); // //底部 // if (verticalJustification.AsInteger() == 1) // { // origin2 -= delta; // } // //顶部 // if (verticalJustification.AsInteger() == 2) // { // origin2 += delta; // } //} //管线所在的垂直于xoy平面的面法向 var normal = XYZ.BasisZ.CrossProduct(direction2); //如果是立管,则取不移动的管线的方向,过移动管线做平面 if (normal.IsZeroLength()) { normal = direction1; } var plane = Plane.CreateByNormalAndOrigin(normal, origin2); //找到交点 var intersectPoint = plane.IntersectPoint(Line.CreateUnbound(origin1, direction1)); //不相交则直接移动 if (intersectPoint == null) { ElementTransformUtils.MoveElement(Document, elementToMove!.Id, origin1 - origin2); } else { //避免交点在原管线外,导致反向连接 if ((mainMEPCurve.GetCurve() as Line).IsInsideEx(intersectPoint, 0.5)) { ElementTransformUtils.MoveElement(Document, elementToMove!.Id, intersectPoint - origin2); } else { ElementTransformUtils.MoveElement(Document, elementToMove!.Id, origin1 - origin2); } } mainMEPCurve.ConnectTo(branchMEPCurve); } else { if (baseElement is MEPCurve baseMEPCurve && elementToMove is MEPCurve moveMEPCurve) { if ( ( conn2.Shape == ConnectorProfileType.Oval || conn2.Shape == ConnectorProfileType.Rectangular ) ) { var verticalJustification = baseMEPCurve.get_Parameter( BuiltInParameter.RBS_CURVE_VERT_OFFSET_PARAM ); var delta = XYZ.BasisZ * (baseMEPCurve.Height / 2 - moveMEPCurve.Height / 2); //底部 if (verticalJustification.AsInteger() == 1) { origin2 += delta; } //顶部 if (verticalJustification.AsInteger() == 2) { origin2 -= delta; } } } var xyz = origin1 - origin2; Document.InvokeSub(_ => { if (!xyz.IsZeroLength()) { ElementTransformUtils.MoveElement(Document, elementToMove!.Id, xyz); } }); if (direction1.IsAlmostEqualTo(direction2.Negate())) //对齐 { conn1.ConnectByFitting(conn2); } else { var xyz2 = direction1.CrossProduct(direction2); //旋转轴方向 if (direction1.IsAlmostEqualTo(direction2)) { xyz2 = conn1.CoordinateSystem.BasisY; } var line = Line.CreateUnbound(origin1, xyz2); var angle = direction1.AngleTo(direction2); //互补角 var complementaryAngle = Math.PI - angle; ElementTransformUtils.RotateElement(Document, elementToMove!.Id, line, complementaryAngle); conn1.ConnectByFitting(conn2); } } }, "移动连接" ); } }