Files
SzmediTools/Szmedi.Toolkit.Revit/RvExtensions/MEPExtensions.cs
2025-09-16 16:06:41 +08:00

217 lines
9.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
using System;
using System.Diagnostics;
using System.Linq;
namespace Szmedi.Toolkit.RvExtensions
{
public static class MEPExtensions
{
/// <summary>
/// 用点打断管线
/// </summary>
/// <param name="mepCurve"></param>
/// <param name="point"></param>
/// <returns>新的管线(定位线前端部分)</returns>
public static ElementId BreakByPoint(this MEPCurve mepCurve, XYZ point)
{
if (mepCurve is not InsulationLiningBase)
{
try
{
Document document = mepCurve.Document;
return mepCurve switch
{
Duct duct => MechanicalUtils.BreakCurve(document, duct.Id, point),
Pipe pipe => PlumbingUtils.BreakCurve(document, pipe.Id, point),
_ => mepCurve.BreakCurve(point)
};
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
return ElementId.InvalidElementId;
}
}
throw new InvalidOperationException($"{nameof(mepCurve)}不是管线或不可打断");
}
/// <summary>
/// 复制并修改定位线,并可用来连接该管线,朝上方向的一致性
/// </summary>
/// <param name="mepCurve">用来复制的管线</param>
/// <param name="line">定位线</param>
/// <param name="canNewElbow">可以创建弯头</param>
/// <returns></returns>
public static MEPCurve CopyAndSetLocationCurve(this MEPCurve mepCurve, Line line)
{
var doc = mepCurve.Document;
var elemId = ElementTransformUtils.CopyElement(doc, mepCurve.Id, XYZ.Zero).FirstOrDefault();
var newMepCurve = doc.GetElement(elemId) as MEPCurve;
newMepCurve.SetLocationCurve(line);
doc.Regenerate();
//立管的断面可能错误,需要旋转截面
if (line.Direction.CrossProduct(XYZ.BasisZ).IsZeroLength())
{
var conns = ConnectorExtensions.GetNearestConnectors(mepCurve, newMepCurve);
var hand = conns[0].CoordinateSystem.BasisX;
//取反向
var newHand = conns[1].CoordinateSystem.BasisX;
//点积
var cos = hand.DotProduct(newHand);
//夹角
var radian = Math.Acos(cos);
////旋转轴向
//var d = hand.CrossProduct(newHand);
//当两个BasisX相反时则为可正确连接的不需要旋转
if (hand.IsAlmostEqualTo(-newHand))
{
return newMepCurve;
}
//连接件的BasisZ就是轴向
var d = conns[1].CoordinateSystem.BasisZ;
//以立管或倾斜管作为参考轴
var ax = Line.CreateUnbound(conns[1].Origin, d);
//保证夹角为180度故旋转角用Π-夹角
ElementTransformUtils.RotateElement(doc, elemId, ax, Math.PI - radian);
//double radian = default;
//Line axis = null;
//foreach (Connector connector in mepCurve.ConnectorManager.Connectors)
//{
// foreach (Connector connector1 in newMepCurve.ConnectorManager.Connectors)
// {
// //侧面向量
// var dotProduct = connector1.CoordinateSystem.BasisX.DotProduct(connector.CoordinateSystem.BasisX);
// radian = Math.Acos(dotProduct);
// //为0的时候即两个侧面向量重合或相反表明要么正好合适要么需要旋转180度
// var direction =
// Math.Sin(radian) < 0.0001 ? XYZ.BasisZ : connector1.CoordinateSystem.BasisX.CrossProduct(connector.CoordinateSystem.BasisX);
// if (!direction.IsZeroLength())
// {
// axis = Line.CreateUnbound(connector1.Origin, direction);
// }
// //radian = Math.PI - radian;
// }
//}
//ElementTransformUtils.RotateElement(doc, elemId, axis, radian);
}
return newMepCurve;
}
/// <summary>
/// 打断直线管线
/// </summary>
/// <param name="electricMepCurve"></param>
/// <param name="point"></param>
/// <remarks>新创建的管线距离起点近,返回Id=-1时不能打断管线</remarks>
/// <returns></returns>
private static ElementId BreakCurve(this MEPCurve electricMepCurve, XYZ point)
{
var document = electricMepCurve.Document;
var application = document.Application;
var conns = electricMepCurve.ConnectorManager.Connectors.OfType<Connector>().Where(c => c.ConnectorType == ConnectorType.End);
//原管线连接的接头
var originConn1 = conns.ElementAt(0);
var originConn2 = conns.ElementAt(1);
//已连接的连接件
var connectedConn1 = originConn1.GetConnectedConnector();
var connectedConn2 = originConn2.GetConnectedConnector();
Debug.WriteLine($"起点连接件{connectedConn1}");
Debug.WriteLine($"终点连接件{connectedConn2}");
connectedConn1?.DisconnectFrom(originConn1);
connectedConn2?.DisconnectFrom(originConn2);
document.Regenerate();
//投影点
if (
electricMepCurve.GetLocCurve() is not Line line
|| electricMepCurve is FlexDuct
|| electricMepCurve is FlexPipe
|| electricMepCurve is PipeInsulation
|| electricMepCurve is DuctInsulation
)
{
//throw new InvalidOperationException("不可打断的类型");
return ElementId.InvalidElementId;
}
var projectPoint = line.Project(point).XYZPoint;
if ((electricMepCurve.GetLocCurve() as Line).IsInsideEx(point, application.ShortCurveTolerance))
{
var startLine = Line.CreateBound(line.GetEndPoint(0), projectPoint);
var endLine = Line.CreateBound(projectPoint, line.GetEndPoint(1));
var electricMepCurveCopyId = ElementTransformUtils.CopyElement(document, electricMepCurve.Id, XYZ.Zero).FirstOrDefault();
var electricMepCurveCopy = document.GetElement(electricMepCurveCopyId) as MEPCurve;
//起点线
electricMepCurveCopy.SetLocationCurve(startLine);
electricMepCurve.SetLocationCurve(endLine);
Debug.WriteLine($"设置定位线");
document.Regenerate();
Debug.WriteLine($"原有接头{connectedConn1?.Origin}");
Debug.WriteLine($"原有接头{connectedConn2?.Origin}");
foreach (Connector conn1 in electricMepCurveCopy!.ConnectorManager.Connectors)
{
Debug.WriteLine($"复制管连接件{conn1.Origin}");
if (connectedConn1 != null)
{
if (conn1.Origin.DistanceTo(connectedConn1.Origin) < application.ShortCurveTolerance)
{
Debug.WriteLine("复制管连接连接件1");
conn1.ConnectTo(connectedConn1);
break;
}
}
if (connectedConn2 != null)
{
if (conn1.Origin.DistanceTo(connectedConn2.Origin) < application.ShortCurveTolerance)
{
Debug.WriteLine("复制管连接连接件2");
conn1.ConnectTo(connectedConn2);
break;
}
}
}
foreach (Connector conn1 in electricMepCurve!.ConnectorManager.Connectors)
{
if (connectedConn1 != null)
{
if (conn1.Origin.DistanceTo(connectedConn1.Origin) < application.ShortCurveTolerance)
{
Debug.WriteLine("原有管连接连接件1");
conn1.ConnectTo(connectedConn1);
break;
}
}
if (connectedConn2 != null)
{
if (conn1.Origin.DistanceTo(connectedConn2.Origin) < application.ShortCurveTolerance)
{
Debug.WriteLine("原有管连接连接件2");
conn1.ConnectTo(connectedConn2);
break;
}
}
}
return electricMepCurveCopyId;
}
return ElementId.InvalidElementId;
}
}
}