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;
|
||
}
|
||
}
|
||
} |