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 }