356 lines
14 KiB
C#
356 lines
14 KiB
C#
|
|
using Autodesk.Revit.DB;
|
|
using Autodesk.Revit.DB.Electrical;
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
|
|
namespace Szmedi.Toolkit.RvExtensions
|
|
{
|
|
public static class ConnectorExtensions
|
|
{
|
|
/// <summary>
|
|
/// 连接件管件连接,同管径,都为管线创建活接头
|
|
/// </summary>
|
|
/// <param name="first"></param>
|
|
/// <param name="second"></param>
|
|
/// <returns></returns>
|
|
public static FamilyInstance ConnectByFitting(this Connector first, Connector second)
|
|
{
|
|
if (first == null || second == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
Document document = first.Owner.Document;
|
|
bool isSameSize = false; //活接头
|
|
if (first.Domain != second.Domain)
|
|
{
|
|
throw new ArgumentException("无法连接不同类型的管线");
|
|
}
|
|
|
|
switch (first.Domain)
|
|
{
|
|
case Domain.DomainHvac:
|
|
{
|
|
if (first.Shape == second.Shape)
|
|
{
|
|
ConnectorProfileType shape = first.Shape;
|
|
//判断管径是否一致
|
|
isSameSize = shape is ConnectorProfileType.Oval or ConnectorProfileType.Rectangular
|
|
? Math.Abs(first.Width - second.Width) < 0.0001 && Math.Abs(first.Height - second.Height) < 0.0001
|
|
: Math.Abs(first.Radius - second.Radius) < 0.0001;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case Domain.DomainPiping:
|
|
isSameSize = Math.Abs(first.Radius - second.Radius) < 0.0001;
|
|
break;
|
|
case Domain.DomainCableTrayConduit:
|
|
{
|
|
if (first.Owner.GetType() == second.Owner.GetType())
|
|
{
|
|
if (second.Owner is Conduit)
|
|
{
|
|
isSameSize = Math.Abs(first.Radius - second.Radius) < 0.0001;
|
|
}
|
|
|
|
if (second.Owner is CableTray)
|
|
{
|
|
isSameSize = Math.Abs(first.Width - second.Width) < 0.0001 && Math.Abs(first.Height - second.Height) < 0.0001;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
//平行创建过渡件和活接头
|
|
if (first.CoordinateSystem.BasisZ.IsParallelTo(second.CoordinateSystem.BasisZ))
|
|
{
|
|
//管径一致时,根据情况创建活接头
|
|
if (isSameSize)
|
|
{
|
|
//有一个是族的时候,始终直接连接,不创建活接头
|
|
if (first.Owner is MEPCurve ^ second.Owner is MEPCurve)
|
|
{
|
|
if (!first.IsConnectedTo(second))
|
|
{
|
|
first.ConnectTo(second);
|
|
}
|
|
}
|
|
//都是管线
|
|
if (first.Owner is MEPCurve && second.Owner is MEPCurve)
|
|
{
|
|
return document.Create.NewUnionFitting(first, second);
|
|
}
|
|
//都是族的连接件
|
|
if (first.Owner is FamilyInstance && second.Owner is FamilyInstance)
|
|
{
|
|
first.ConnectTo(second);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
else
|
|
{
|
|
//管径不一致时,创建过渡件
|
|
if (first.Owner is MEPCurve)
|
|
{
|
|
return document.Create.NewTransitionFitting(first, second);
|
|
}
|
|
if (second.Owner is MEPCurve)
|
|
{
|
|
return document.Create.NewTransitionFitting(second, first);
|
|
}
|
|
//都是族的连接件
|
|
if (first.Owner is FamilyInstance && second.Owner is FamilyInstance)
|
|
{
|
|
first.ConnectTo(second);
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
return document.Create.NewElbowFitting(first, second);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 获取与当前连接件已连接的连接件
|
|
/// </summary>
|
|
/// <param name="connector">当前连接件</param>
|
|
/// <returns></returns>
|
|
public static Connector GetConnectedConnector(this Connector connector)
|
|
{
|
|
return connector.IsConnected
|
|
? connector.AllRefs
|
|
.Cast<Connector>()
|
|
.FirstOrDefault(c => ConnectorType.End == c.ConnectorType && !c.Owner.Id.Equals(connector.Owner.Id))
|
|
: null;
|
|
}
|
|
/// <summary>
|
|
/// 获取最近的连接件(顺序与参数对应)
|
|
/// </summary>
|
|
/// <param name="element1"></param>
|
|
/// <param name="element2"></param>
|
|
/// <param name="isUnused"></param>
|
|
/// <returns></returns>
|
|
public static List<Connector> GetNearestConnectors(Element element1, Element element2, bool isUnused = true)
|
|
{
|
|
List<Connector> list = new();
|
|
Connector conn = null;
|
|
Connector conn2 = null;
|
|
double distance = double.MaxValue;
|
|
foreach (Connector connTemp in element1.GetConnectors(isUnused))
|
|
{
|
|
foreach (Connector connTemp2 in element2.GetConnectors(isUnused))
|
|
{
|
|
double tempDistance = connTemp.Origin.DistanceTo(connTemp2.Origin);
|
|
if (distance > tempDistance)
|
|
{
|
|
distance = tempDistance;
|
|
conn = connTemp;
|
|
conn2 = connTemp2;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (conn != null)
|
|
{
|
|
list.Add(conn);
|
|
}
|
|
|
|
if (conn2 != null)
|
|
{
|
|
list.Add(conn2);
|
|
}
|
|
|
|
return list;
|
|
}
|
|
/// <summary>
|
|
/// 分支连接
|
|
/// </summary>
|
|
/// <param name="branch"></param>
|
|
/// <param name="connector"></param>
|
|
/// <param name="connector1"></param>
|
|
/// <returns></returns>
|
|
public static FamilyInstance ConnectByTee(this Connector branch, Connector connector, Connector connector1)
|
|
{
|
|
Document document = branch.Owner.Document;
|
|
//获取垂直主管的向量
|
|
XYZ normal = connector.CoordinateSystem.BasisZ.CrossProduct(branch.CoordinateSystem.BasisZ);
|
|
XYZ vertical = connector.CoordinateSystem.BasisZ.CrossProduct(normal);
|
|
|
|
Line mainLine = Line.CreateUnbound(connector.Origin, connector.CoordinateSystem.BasisZ);
|
|
Line branchLine = Line.CreateUnbound(branch.Origin, branch.CoordinateSystem.BasisZ);
|
|
//分支和主管的角度
|
|
double cos = branch.CoordinateSystem.BasisZ.DotProduct(connector.CoordinateSystem.BasisZ);
|
|
double angle = Math.Acos(cos);
|
|
//主管和分支管的交点
|
|
XYZ intersect = mainLine.IntersectionPoint(branchLine);
|
|
//垂直主管的分支管,为了创建默认三通
|
|
Line verticalLine = Line.CreateBound(intersect, intersect + 3.0 * vertical);
|
|
//延长管线到交点处
|
|
branch.Owner.SetLocationCurve((branch.Owner.GetLocCurve() as Line).ExtendLine(intersect));
|
|
connector.Owner.SetLocationCurve((connector.Owner.GetLocCurve() as Line).ExtendLine(intersect));
|
|
connector1.Owner.SetLocationCurve((connector1.Owner.GetLocCurve() as Line).ExtendLine(intersect));
|
|
//复制支管创建垂直主管的管线
|
|
ElementId verticalMEPCurveId = ElementTransformUtils.CopyElement(document, branch.Owner.Id, XYZ.Zero).FirstOrDefault();
|
|
MEPCurve verticalMEPCurve = document.GetElement(verticalMEPCurveId) as MEPCurve;
|
|
verticalMEPCurve.SetLocationCurve(verticalLine);
|
|
//获取垂直管的连接件
|
|
Connector tempBranchConnector = verticalMEPCurve.GetConnectors().GetNearestConnector(intersect);
|
|
//创建三通
|
|
FamilyInstance tee = document.Create.NewTeeFitting(connector, connector1, tempBranchConnector);
|
|
if (tempBranchConnector.GetConnectedConnector().Owner.Id != tee.Id)
|
|
{
|
|
document.Delete(tempBranchConnector.GetConnectedConnector().Owner.Id);
|
|
}
|
|
|
|
document.Delete(verticalMEPCurveId);
|
|
//三通中未连接的连接件即分支连接件
|
|
Connector teeBranchConn = tee.GetConnectors(true).OfType<Connector>().FirstOrDefault();
|
|
try
|
|
{
|
|
//设置三通角度
|
|
teeBranchConn!.Angle = Math.PI - angle;
|
|
}
|
|
catch (Autodesk.Revit.Exceptions.InvalidOperationException)
|
|
{
|
|
Debug.WriteLine("无法修改管线角度");
|
|
}
|
|
|
|
document.Regenerate();
|
|
//Connector branchFarConn = branch.Owner.GetConnectors().GetFarthestConnector(intersect);
|
|
//Line newBranch = Line.CreateBound(branchFarConn.Origin, teeBranchConn.Origin);
|
|
Line l = branch.Owner.GetLocCurve() as Line;
|
|
Line newBranchLine = l.ExtendLine(teeBranchConn!.Origin);
|
|
branch.Owner.SetLocationCurve(newBranchLine);
|
|
//Line line = branch.Owner.GetLocCurve() as Line;
|
|
//if (newBranch.Direction.IsAlmostEqualTo(line.Direction))
|
|
//{
|
|
// (branch.Owner.Location as LocationCurve).Curve = newBranch;
|
|
//}
|
|
//else if (newBranch.Direction.IsAlmostEqualTo(-line.Direction))
|
|
//{
|
|
// (branch.Owner.Location as LocationCurve).Curve = newBranch.CreateReversed();
|
|
//}
|
|
Connector newBranchConn = branch.Owner.GetConnectors().GetNearestConnector(intersect);
|
|
newBranchConn.ConnectByFitting(teeBranchConn);
|
|
return tee;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取集合中距离最近的连接件(含未连接和已连接)
|
|
/// </summary>
|
|
/// <param name="set"></param>
|
|
/// <param name="startPoint"></param>
|
|
/// <returns></returns>
|
|
public static Connector GetNearestConnector(this ConnectorSet set, XYZ startPoint)
|
|
{
|
|
Connector result = null;
|
|
double num = double.MaxValue;
|
|
foreach (Connector connector in set)
|
|
{
|
|
double num2 = connector.Origin.DistanceTo(startPoint);
|
|
if (num2 < num)
|
|
{
|
|
num = num2;
|
|
result = connector;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
/// <summary>
|
|
/// 从连接件延伸长度
|
|
/// </summary>
|
|
/// <param name="connector"></param>
|
|
/// <returns></returns>
|
|
public static double GetExtensionLength(this Connector connector)
|
|
{
|
|
return connector.Domain switch
|
|
{
|
|
Domain.DomainHvac when connector.Shape == ConnectorProfileType.Rectangular
|
|
=> connector.Width * 0.2 + connector.Height * 0.2,
|
|
Domain.DomainHvac when connector.Shape == ConnectorProfileType.Oval => connector.Width * 0.2 + connector.Height * 0.2,
|
|
Domain.DomainHvac when connector.Shape == ConnectorProfileType.Round => connector.Radius * 1.5,
|
|
Domain.DomainPiping => connector.Radius * 1.5,
|
|
Domain.DomainCableTrayConduit => 1,
|
|
_ => 0.5
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取两个元素最远的连接件
|
|
/// </summary>
|
|
/// <param name="element1"></param>
|
|
/// <param name="element2"></param>
|
|
/// <param name="isUnused"></param>
|
|
/// <returns></returns>
|
|
public static List<Connector> GetFarestConnectors(Element element1, Element element2, bool isUnused = true)
|
|
{
|
|
List<Connector> list = new();
|
|
Connector conn = null;
|
|
Connector conn2 = null;
|
|
double distance = double.MinValue;
|
|
foreach (Connector connTemp in element1.GetConnectors(isUnused))
|
|
{
|
|
foreach (Connector connTemp2 in element2.GetConnectors(isUnused))
|
|
{
|
|
double tempDistance = connTemp.Origin.DistanceTo(connTemp2.Origin);
|
|
if (distance < tempDistance)
|
|
{
|
|
distance = tempDistance;
|
|
conn = connTemp;
|
|
conn2 = connTemp2;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (conn != null)
|
|
{
|
|
list.Add(conn);
|
|
}
|
|
|
|
if (conn2 != null)
|
|
{
|
|
list.Add(conn2);
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 距离所选点最远的连接件
|
|
/// </summary>
|
|
/// <param name="set"></param>
|
|
/// <param name="startPoint">选择点</param>
|
|
/// <returns></returns>
|
|
public static Connector GetFarthestConnector(this ConnectorSet set, XYZ startPoint)
|
|
{
|
|
Connector result = null;
|
|
double minValue = double.MinValue;
|
|
foreach (Connector connector in set)
|
|
{
|
|
double d = connector.Origin.DistanceTo(startPoint);
|
|
if (d > minValue)
|
|
{
|
|
minValue = d;
|
|
result = connector;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
} |