using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using FWindSoft.SystemExtensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FWindSoft.Revit.Mep
{
/*
* 连接相关的相代码
*/
///
/// 连接管道基础类
///
public abstract class BaseJoinConduit : IJoinCurve
{
///
/// 连接管线
///
///
///
///
protected abstract bool JoinImpl(List elements, JoinContext context);
///
/// 连接管线
///
///
///
public bool Join(List elements, JoinContext context)
{
if (elements.Any(ew => !(ew.AssociateElement is Conduit)))
{
return false;
}
return JoinImpl(elements, context);
}
}
#region 两个管道进行连接
public class Join2Conduit : BaseJoinConduit
{
protected override bool JoinImpl(List elements, JoinContext context)
{
if (elements == null || elements.Count < 2)
{
return false;
}
var conduit1 = elements[0].AssociateElement as Conduit;
var conduit2 = elements[1].AssociateElement as Conduit;
var line1 = conduit1.GetLocationLine();
var line2 = conduit2.GetLocationLine();
BaseJoinConduit joinConduit;
if (line1.IsCollinear(line2))
{
if (conduit1.Diameter.IsEqual(conduit2.Diameter))
{
joinConduit = new Join2ConduitByUnion();
}
else
{
joinConduit = new Join2ConduitByTransition();
}
}
else
{
joinConduit = new Join2ConduitByElbow();
}
if (joinConduit != null)
{
return joinConduit.Join(elements, context);
}
return false;
}
}
///
/// 使用活接头连接
///
public class Join2ConduitByUnion : BaseJoinConduit
{
protected override bool JoinImpl(List elements, JoinContext context)
{
if (elements == null || elements.Count < 2)
{
return false;
}
var conduit1 = elements[0].AssociateElement as Conduit;
var conduit2 = elements[1].AssociateElement as Conduit;
var line1 = conduit1.GetLocationLine();
var line2 = conduit2.GetLocationLine();
if (!conduit1.Diameter.IsEqual(conduit2.Diameter) || !line1.IsCollinear(line2))
{
return false;
}
//找到connector方向相反,且距离较近的一对点,创建连接
var connectors = conduit1.GetAllConnectors();
Connector useConnector1 = null, useConnector2 = null;
double distance = double.MaxValue;
foreach (Connector connector in connectors)
{
var refConnector = conduit2.GetConnectorByDirection(-connector.CoordinateSystem.BasisZ);
if (refConnector != null)
{
var tempLength = connector.Origin.DistanceTo(refConnector.Origin);
if (tempLength.Less(distance))
{
useConnector1 = connector;
useConnector2 = refConnector;
distance = tempLength;
}
}
}
FamilyInstance fi = null;
if (useConnector1 != null && useConnector1 != null)
{
var line2Other = line2.GetFarnessPoint(useConnector2.Origin);
if (line2Other.Subtract(useConnector1.Origin).GetLength().More(JoinConduitUtils.FaultTolerantLength))
{
fi = ConduitFittingCreator.NewUnionFitting(useConnector1, useConnector2, context);
}
}
return fi != null;
}
}
///
/// 使用变径连接
///
public class Join2ConduitByTransition : BaseJoinConduit
{
protected override bool JoinImpl(List elements, JoinContext context)
{
if (elements == null || elements.Count < 2)
{
return false;
}
var conduit1 = elements[0].AssociateElement as Conduit;
var conduit2 = elements[1].AssociateElement as Conduit;
var line1 = conduit1.GetLocationLine();
var line2 = conduit2.GetLocationLine();
if (conduit1.Diameter.IsEqual(conduit2.Diameter) || !line1.IsCollinear(line2))
{
return false;
}
//找到connector方向相反,且距离较近的一对点,创建连接
var connectors = conduit1.GetAllConnectors();
Connector useConnector1 = null, useConnector2 = null;
double distance = double.MaxValue;
foreach (Connector connector in connectors)
{
var refConnector = conduit2.GetConnectorByDirection(-connector.CoordinateSystem.BasisZ);
if (refConnector != null)
{
var tempLength = connector.Origin.DistanceTo(refConnector.Origin);
if (tempLength.Less(distance))
{
useConnector1 = connector;
useConnector2 = refConnector;
distance = tempLength;
}
}
}
FamilyInstance fi = null;
if (useConnector1 != null && useConnector1 != null)
{
var line2Other = line2.GetFarnessPoint(useConnector2.Origin);
if (line2Other.Subtract(useConnector1.Origin).GetLength().More(JoinConduitUtils.FaultTolerantLength))
{
fi = ConduitFittingCreator.NewTransitionFitting(useConnector1, useConnector2, context);
}
}
return fi != null;
}
}
///
/// 使用弯头连接
///
public class Join2ConduitByElbow : BaseJoinConduit
{
protected override bool JoinImpl(List elements, JoinContext context)
{
if (elements == null || elements.Count < 2)
{
return false;
}
var conduit1 = elements[0].AssociateElement as Conduit;
var conduit2 = elements[1].AssociateElement as Conduit;
var line1 = conduit1.GetLocationLine();
var line2 = conduit2.GetLocationLine();
var lineUnbound1 = line1.CloneUnbound();
var lineUnbound2 = line2.CloneUnbound();
var intersectPoint = lineUnbound1.GetSpatialIntersection(lineUnbound2);
if (null == intersectPoint)
{
return false;
}
Connector connector1 = conduit1.GetConnectorByOrigin(line1.GetNearnessPoint(intersectPoint));
Connector connector2 = conduit2.GetConnectorByOrigin(line2.GetNearnessPoint(intersectPoint));
FamilyInstance fi = ConduitFittingCreator.NewElbowFitting(connector1, connector2, context);
return fi != null;
}
}
#endregion
#region 三个管道进行连接
///
/// 连接三个管道
///
public class Join3Conduit : BaseJoinConduit
{
protected override bool JoinImpl(List elements, JoinContext context)
{
if (elements == null || elements.Count < 3)
{
return false;
}
var conduit1 = elements[0].AssociateElement as Conduit;
var conduit2 = elements[1].AssociateElement as Conduit;
var conduit3 = elements[2].AssociateElement as Conduit;
var line1 = conduit1.GetLocationLine();
var line2 = conduit2.GetLocationLine();
var line3 = conduit3.GetLocationLine();
#region 算法流程
/*
* 取到conduit使用的三通。
* 在交点位置放置三通,顶面Connector朝下。
* 旋转到相应的位置,将匹配的Connector进行连接
* 匹配Connector未能按默认连接,进行特殊处理?
*
* 尽量保证线盒横放。如果位置关系不允许横放,再考虑其他摆放
* 分类:两两垂直;一个与其中一个平行,与另一个垂直
*/
#endregion
//正常情况下,一条线,必然和其余两条线存在不平行的情况
XYZ ins = null;
if (!line1.IsParallel(line2))
{
ins = line1.GetSpatialIntersection(line2);
}
else if (!line1.IsParallel(line3))
{
ins = line1.GetSpatialIntersection(line3);
}
if (ins != null)
{
var fi = ConduitFittingCreator.NewTeeFitting(conduit1.GetNearnessConnector(ins), conduit2.GetNearnessConnector(ins), conduit3.GetNearnessConnector(ins), context);
return fi != null;
}
return false;
}
}
#endregion
#region 四个管道进行连接
///
/// 连接四个管道
///
public class Join4Conduit : BaseJoinConduit
{
protected override bool JoinImpl(List elements, JoinContext context)
{
if (elements == null || elements.Count < 3)
{
return false;
}
var conduit1 = elements[0].AssociateElement as Conduit;
var conduit2 = elements[1].AssociateElement as Conduit;
var conduit3 = elements[2].AssociateElement as Conduit;
var conduit4 = elements[3].AssociateElement as Conduit;
var line1 = conduit1.GetLocationLine();
var line2 = conduit2.GetLocationLine();
var line3 = conduit3.GetLocationLine();
var line4 = conduit4.GetLocationLine();
//正常情况下,一条线,必然和其余两条线存在不平行的情况
XYZ ins = null;
if (!line1.IsParallel(line2))
{
ins = line1.GetSpatialIntersection(line2);
}
else if (!line1.IsParallel(line3))
{
ins = line1.GetSpatialIntersection(line3);
}
if (ins != null)
{
var fi = ConduitFittingCreator.NewCrossFitting(conduit1.GetNearnessConnector(ins), conduit2.GetNearnessConnector(ins), conduit3.GetNearnessConnector(ins), conduit4.GetNearnessConnector(ins), context);
return fi != null;
}
return false;
}
}
#endregion
#region 五个个管道进行连接
///
/// 连接五个管道
///
public class Join5Conduit : BaseJoinConduit
{
protected override bool JoinImpl(List elements, JoinContext context)
{
if (elements == null || elements.Count < 3)
{
return false;
}
var conduit1 = elements[0].AssociateElement as Conduit;
var conduit2 = elements[1].AssociateElement as Conduit;
var conduit3 = elements[2].AssociateElement as Conduit;
var conduit4 = elements[3].AssociateElement as Conduit;
var conduit5 = elements[4].AssociateElement as Conduit;
var line1 = conduit1.GetLocationLine();
var line2 = conduit2.GetLocationLine();
var line3 = conduit3.GetLocationLine();
var line4 = conduit4.GetLocationLine();
var line5 = conduit5.GetLocationLine();
//正常情况下,一条线,必然和其余两条线存在不平行的情况
XYZ ins = null;
if (!line1.IsParallel(line2))
{
ins = line1.GetSpatialIntersection(line2);
}
else if (!line1.IsParallel(line3))
{
ins = line1.GetSpatialIntersection(line3);
}
if (ins != null)
{
var fi = ConduitFittingCreator.NewFiveLinksFitting(conduit1.GetNearnessConnector(ins), conduit2.GetNearnessConnector(ins), conduit3.GetNearnessConnector(ins), conduit4.GetNearnessConnector(ins), conduit5.GetNearnessConnector(ins), context);
return fi != null;
}
return false;
}
}
#endregion
}