123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- /*-------------------------------------------------------------------------
- * 功能描述: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
- }
- }
|