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