Files
SzmediTools/Szmedi.RvKits/MEPTools/MoveConnectCmd.cs

177 lines
8.0 KiB
C#
Raw Normal View History

2025-09-16 16:06:41 +08:00

using Autodesk.Revit.DB;
using Nice3point.Revit.Toolkit.External;
using System;
using System.Linq;
using System.Windows;
using Line = Autodesk.Revit.DB.Line;
namespace Szmedi.RvKits.MEPTools
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
public class MoveConnectCmd : ExternalCommand
{
public override void Execute()
{
Reference baseReference;
Reference moveReference;
try
{
FuncFilter filter =
new(
e => (e is not InsulationLiningBase) && e.GetConnectors(true)?.Size > 0);
baseReference = UiDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, filter, "请选择基准的管线、连接件、设备实例");
moveReference = UiDocument.Selection
.PickObject(
Autodesk.Revit.UI.Selection.ObjectType.Element,
new FuncFilter(
e =>
e.GetConnectors(true)?.Size > 0 &&
e.Id != baseReference.ElementId && !e.Pinned),
"请选择需要移动连接的管线、连接件、设备实例");
}
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
{
return;
}
var baseElement = Document.GetElement(baseReference);
var elementToMove = Document.GetElement(moveReference);
var list = ElementExtensions.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.GetLocCurve() 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);
//ConnectorExtensions.ConnectByFitting(conn1, conn2);
//ConnectorExtensions.ConnectByFitting(conn1, 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);
}
}
},
"移动连接"
);
}
}
}