/*------------------------------------------------------------------------- * 功能描述:ElectricalUtils * 作者:xulisong * 创建时间: 2019/8/4 10:57:29 * 版本号:v1.0 * -------------------------------------------------------------------------*/ using Autodesk.Revit.DB; using Autodesk.Revit.DB.Electrical; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FWindSoft.Revit.Utils { /// /// 电气工具类 /// public static class ElectricalUtils { /// /// 使用指定点打断管线 /// /// /// /// /// public static ElementId BreakCurve(Document document, ElementId cableTrayConduitBaseId, XYZ ptBreak) { #region 判断给定点的位置 var cableTrayConduitBase = document.GetElement(cableTrayConduitBaseId) as CableTrayConduitBase; if (cableTrayConduitBase == null) { return ElementId.InvalidElementId; } var location = ((cableTrayConduitBase.Location as LocationCurve).Curve as Line).Clone() as Line; var direction = location.Direction.Normalize(); var useVector = ptBreak - location.GetEndPoint(0); var dotValue = useVector.DotProduct(direction); if (dotValue <= 0 || dotValue >= location.Length) { //分割点不在迹线上 return ElementId.InvalidElementId; } var realBreak = location.GetEndPoint(0) + dotValue * direction; #endregion #region 获取原始管道的连接信息 List nearStartConnectors = new List(); List nearEndConnectors = new List(); foreach (Connector connector in cableTrayConduitBase.ConnectorManager.Connectors) { //没有连接,则不进行统计 if (connector == null || !connector.IsConnected) continue; var origin = connector.Origin; var tempVector = origin - realBreak; var tempDotValue = tempVector.DotProduct(direction); if (tempDotValue <= 0) { nearStartConnectors.Add(connector); } else { //点乘值大于0,则在靠近管线结束点的位置 nearEndConnectors.Add(connector); } } #endregion #region 复制管线,调整朝向 var newId = ElementTransformUtils.CopyElement(document, cableTrayConduitBaseId, XYZ.Zero).FirstOrDefault(); var newCableTrayConduitBase = document.GetElement(newId) as CableTrayConduitBase; if (newCableTrayConduitBase is CableTray cableTray) { //处理朝向 cableTray.CurveNormal = (cableTrayConduitBase as CableTray).CurveNormal; } #endregion #region 确定保留区域,删除区域 var nearStarTupleInfo = nearStartConnectors.Select(c => new Tuple(c, GetRefConnector(c))).ToList(); var nearEndTupleInfo = nearEndConnectors.Select(c => new Tuple(c, GetRefConnector(c))).ToList(); //当两个Conector相等时,必然是end连接End var nearStartWeight = nearStarTupleInfo.Sum(tuple => tuple.Item1.ConnectorType == tuple.Item2.ConnectorType ? 1 : 2); var nearEndWeight = nearEndTupleInfo.Sum(tuple => tuple.Item1.ConnectorType == tuple.Item2.ConnectorType ? 1 : 2); List> needResetConnectors = null; CableTrayConduitBase start = null,end=null; if (nearStartWeight> nearEndWeight) { //保留靠近Start的部分,因为这样对整个模型改动比较小 needResetConnectors = nearEndTupleInfo; start = cableTrayConduitBase; end = newCableTrayConduitBase; } else { needResetConnectors = nearStarTupleInfo; start = newCableTrayConduitBase ; end = cableTrayConduitBase; } List joinItems = new List(); foreach (var connectorTuple in needResetConnectors) { //断开连接后,Curve就不起作用了 var baseConnector = connectorTuple.Item1; var refConnector = connectorTuple.Item2; ConnectorJoinItem joinItem = new ConnectorJoinItem(newCableTrayConduitBase, baseConnector.Origin); #region 确定连接类型 if (baseConnector.ConnectorType == ConnectorType.End) { joinItem.JoinType = refConnector.ConnectorType == ConnectorType.Curve ? ConnectorJoinType.EndToCurve : ConnectorJoinType.EndToEnd; } else if (baseConnector.ConnectorType == ConnectorType.Curve) { joinItem.JoinType = ConnectorJoinType.CurveToEnd; } #endregion #region 确定RefConnector if(refConnector.ConnectorType==ConnectorType.End) { joinItem.RefConnector = refConnector; } if(refConnector.ConnectorType == ConnectorType.Curve) { joinItem.RefConnector = ConnectorJoinItem.GetFarnessEndConnector(refConnector.Owner as MEPCurve,refConnector.Origin); } #endregion joinItems.Add(joinItem); connectorTuple.Item1.DisconnectFrom(connectorTuple.Item2); } (start.Location as LocationCurve).Curve = Line.CreateBound(location.GetEndPoint(0), realBreak); (end.Location as LocationCurve).Curve = Line.CreateBound(realBreak, location.GetEndPoint(1)); #endregion #region 恢复新创建管线所在位置的连接 //document.Regenerate(); joinItems.ForEach(c => c.Connect()); #endregion return newCableTrayConduitBase?.Id; } #region 内部方法和类型 /// /// 获取关联的Connector /// /// /// private static Connector GetRefConnector(Connector connector) { if (!connector.IsConnected) { return null; } foreach (Connector refConnector in connector.AllRefs) { if (refConnector.Owner.Id != connector.Owner.Id) { return refConnector; } } return null; } /// /// Connector连接数据 /// private class ConnectorJoinItem { public ConnectorJoinItem(MEPCurve baseCurve, XYZ basePoint) { BaseMepCurve = baseCurve; BasePoint = basePoint; } /// /// Connector连接类型 /// public ConnectorJoinType JoinType { get; set; } /// /// 关联的Connector /// public Connector RefConnector { get; set; } /// /// 基础连接管线 /// public MEPCurve BaseMepCurve { get; private set; } /// /// 基础的位置 /// public XYZ BasePoint { get; private set; } /// /// 执行连接功能 /// public void Connect() { if (RefConnector == null) { return; } Connector baseConnector = null; switch (JoinType) { case ConnectorJoinType.EndToEnd: baseConnector = GetNearnessEndConnector(BaseMepCurve, BasePoint); baseConnector.ConnectTo(RefConnector); break; case ConnectorJoinType.EndToCurve: baseConnector = GetNearnessEndConnector(BaseMepCurve, BasePoint); baseConnector.Owner.Document.Create.NewTeeFitting(RefConnector, RefConnector, baseConnector); break; case ConnectorJoinType.CurveToEnd: baseConnector = GetFarnessEndConnector(BaseMepCurve, BasePoint); baseConnector.Owner.Document.Create.NewTeeFitting(baseConnector, baseConnector, RefConnector); break; } } /// /// 获取mepCurve上距离指定location最远的end类型Connector /// /// /// /// public static Connector GetFarnessEndConnector(MEPCurve mepCurve, XYZ point) { Connector useConnector = null; if (mepCurve == null) { return useConnector; } double maxDistance = -1d; foreach (Connector connector in mepCurve.ConnectorManager.Connectors) { if (connector == null || connector.ConnectorType != ConnectorType.End) continue; var origin = connector.Origin; var tempDistance = (origin - point).GetLength(); if (tempDistance > maxDistance) { maxDistance = tempDistance; useConnector = connector; } } return useConnector; } /// /// 获取mepCurve上距离指定location最近的end类型Connector /// /// /// /// public static Connector GetNearnessEndConnector(MEPCurve mepCurve, XYZ point) { Connector useConnector = null; if (mepCurve == null) { return useConnector; } double minDistance = double.MaxValue; foreach (Connector connector in mepCurve.ConnectorManager.Connectors) { if (connector == null || connector.ConnectorType != ConnectorType.End) continue; var origin = connector.Origin; var tempDistance = (origin - point).GetLength(); if (tempDistance < minDistance) { minDistance = tempDistance; useConnector = connector; } } return useConnector; } } private enum ConnectorJoinType { /// /// 点对点连接 /// EndToEnd, /// /// 点对线连接 /// EndToCurve, /// /// 线对点连接 /// CurveToEnd, } #endregion } }