当前位置: 首页 > 工具软件 > Conduit > 使用案例 >

Revit—CableTray and Conduit 桥架线管打断

朱季
2023-12-01

承接上两篇文章的讨论

第一篇:Revit—线管连接桥架

第二篇:Revit—Duct打断和Pipe打断

这篇文章讲一下实现桥架线管打断的思路,并提供可用方法代码

         打断管线并不复杂,复杂的是要恢复原有管线的连接。桥架和线管有和水管不一样的特点,上面第一篇文章写了,它能连接成你“意想不到”的样子,要恢复这种连接,也就存在一些技巧了。

        另外,根据文章二提到的Revit自带的两种管线打断方法测试可知,打断操作是保留原始管修改迹线,然后创建一个新的管补充到另外的区域。

       保留哪部分区域?这里面就会涉及一个策略问题。我下面的方法的策略是,尽量保留连接多或者复杂的一端,创建连接少或简单的一端。

       直接上代码了,考出去就能用的那种(#^.^#)

/*-------------------------------------------------------------------------
 * 功能描述: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
{
    /// <summary>
    /// 电气工具类
    /// </summary>
    public static class ElectricalUtils
    {
        /// <summary>
        /// 使用指定点打断管线
        /// </summary>
        /// <param name="document"></param>
        /// <param name="cableTrayConduitBaseId"></param>
        /// <param name="ptBreak"></param>
        /// <returns></returns>
        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<Connector> nearStartConnectors = new List<Connector>();
            List<Connector> nearEndConnectors = new List<Connector>();
            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<Connector, Connector>(c, GetRefConnector(c))).ToList();
            var nearEndTupleInfo = nearEndConnectors.Select(c => new Tuple<Connector, Connector>(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<Tuple<Connector, Connector>> 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<ConnectorJoinItem> joinItems = new List<ConnectorJoinItem>();
            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 内部方法和类型
        /// <summary>
        /// 获取关联的Connector
        /// </summary>
        /// <param name="connector"></param>
        /// <returns></returns>
        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;
        }

        /// <summary>
        /// Connector连接数据
        /// </summary>
        private class ConnectorJoinItem
        {
            public ConnectorJoinItem(MEPCurve baseCurve, XYZ basePoint)
            {
                BaseMepCurve = baseCurve;
                BasePoint = basePoint;
            }
            /// <summary>
            /// Connector连接类型
            /// </summary>
            public ConnectorJoinType JoinType { get; set; }
            /// <summary>
            /// 关联的Connector
            /// </summary>
            public Connector RefConnector { get; set; }
            /// <summary>
            /// 基础连接管线
            /// </summary>
            public MEPCurve BaseMepCurve { get; private set; }
            /// <summary>
            /// 基础的位置
            /// </summary>
            public XYZ BasePoint { get; private set; }
            /// <summary>
            /// 执行连接功能
            /// </summary>
            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;
                }
            }

            /// <summary>
            /// 获取mepCurve上距离指定location最远的end类型Connector
            /// </summary>
            /// <param name="mepCurve"></param>
            /// <param name="point"></param>
            /// <returns></returns>
            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;
            }
            /// <summary>
            /// 获取mepCurve上距离指定location最近的end类型Connector
            /// </summary>
            /// <param name="mepCurve"></param>
            /// <param name="point"></param>
            /// <returns></returns>
            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
        {
            /// <summary>
            /// 点对点连接
            /// </summary>
            EndToEnd,
            /// <summary>
            /// 点对线连接
            /// </summary>
            EndToCurve,
            /// <summary>
            /// 线对点连接
            /// </summary>
            CurveToEnd,
        } 
        #endregion
    }   
}

 

 类似资料: