217 lines
9.3 KiB
C#
217 lines
9.3 KiB
C#
|
|
|
|||
|
|
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;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|