using Autodesk.Revit.DB;
using FWindSoft.Revit.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FWindSoft.Revit
{
public static class ConnectorSearchUtils
{
#region 获取直接相连接的元素
///
/// 获取与connector相连接的元素,不包括自身
///
///
///
///
public static List GetJoinElements(Connector connector,Predicate allowConnector)
{
List joinElements = new List();
Element element = connector.Owner;
ConnectorSearchOptions options = new ConnectorSearchOptions() { AllowConnector = allowConnector };
if (connector.Searchable())
{
ConnectorSet conSet = connector.AllRefs;
foreach (var con in conSet.ToList())
{
if (con.Owner.Id == element.Id)
continue;
if(options.ConnectorUsable(con))
{
joinElements.Add(con.Owner);
}
}
}
return joinElements;
}
///
/// 获取与connector相连接的元素,不包括自身
///
///
///
public static List GetJoinElements(Connector connector)
{
return GetJoinElements(connector,null);
}
///
/// 获取关联元素
///
///
///
///
public static List GetJoinElements(Element sourceElement, Predicate allowConnector)
{
IEnumerable joinElements = new List();
Element element = sourceElement;
ConnectorSearchOptions options = new ConnectorSearchOptions() { AllowConnector = allowConnector };
var connectors = sourceElement.GetAllConnectors();
foreach (var baseConnector in connectors)
{
if (!options.ConnectorUsable(baseConnector))
{
continue;
}
var childJoinElements = GetJoinElements(baseConnector, allowConnector);
joinElements=joinElements.Intersect(childJoinElements, new ElementEqualityComparer());
}
return joinElements.ToList();
}
///
/// 获取关联元素
///
///
public static List GetJoinElements(Element sourceElement)
{
return GetJoinElements(sourceElement, null);
}
#endregion
#region 通过连接关系,找到满足条件的元素
///
/// 根据连接关系,获取满足条件的元素
///
///
///
///
///
///
public static List GetFirstMatchElements(Element inputElement, Connector inputConnector, Predicate allowConnector, Predicate endPredicate)
{
var startElement = inputElement;
ConnectorSearchOptions options = new ConnectorSearchOptions() { AllowConnector = allowConnector, AllowElement = endPredicate };
List result = new List();
List reference = new List();
reference.Add(startElement);
for (int i = 0; i < reference.Count; i++)
{
var currrentElement = reference[i];
#region 获取可用连接件
List connectors = currrentElement.GetAllConnectors().ToList();
if (inputConnector != null && i == 0)
{
connectors = new List { inputConnector };
}
else
{
connectors = currrentElement.GetAllConnectors().ToList();
}
#endregion
foreach (var con in connectors)
{
if (!con.Searchable() || !options.ConnectorUsable(con))
{
continue;
}
List elements = GetJoinElements(con, allowConnector);
foreach (var element in elements)
{
if (options.ElementUsable(element))
{
if (result.All(e => e.Id != element.Id))
{
result.Add(element);
}
}
else
{
if (reference.All(e => e.Id != element.Id))
{
reference.Add(element);
}
}
}
}
}
result.RemoveAll(r => r.Id.IntegerValue == startElement.Id.IntegerValue);
return result;
}
///
/// 根据连接关系,获取满足条件的元素
///
///
///
///
///
public static List GetFirstMatchElements(Connector connector, Predicate allowConnector, Predicate endPredicate)
{
return GetFirstMatchElements(connector.Owner, connector, allowConnector, endPredicate);
}
///
/// 根据连接关系,获取满足条件的元素
///
///
///
///
///
public static List GetFirstMatchElements(Element inputElement, Predicate allowConnector, Predicate endPredicate)
{
return GetFirstMatchElements(inputElement,null, allowConnector, endPredicate);
}
///
/// 根据连接关系,获取指定类型的元素
///
///
///
///
///
public static List GetFirstMatchElements(this Element startElement,Connector startConnector = null) where T : Element
{
return GetFirstMatchElements(startElement, startConnector, null, e => e is T).OfType().ToList();
}
#endregion
#region 获取所有连接元素
///
/// 获取与指定元素关联的所有元素
///
///
///
public static List GetAllJoinElements(this Element element)
{
List elements = new List();
element.GetAllJoinElements(ref elements, null);
return elements;
}
public static List GetAllJoinElements(this Element element, Predicate ignoredElement)
{
List elements = new List();
element.GetAllJoinElements(ref elements, ignoredElement);
return elements;
}
///
/// 获取与元素通过connector相连接的元素
///
///
///
///
private static void GetAllJoinElements(this Element sourceElement, ref List reference, Predicate ignoredElement)
{
//就这样使用引用类型传入,不使用返回值形式,是避免数据转来转去拖慢算法速度
reference.Add(sourceElement);
var elements = GetJoinElements(sourceElement);
foreach (var element in elements)
{
if (reference.Contains(element, new ElementEqualityComparer()))
continue;
if (ignoredElement != null && ignoredElement(element))
continue;
element.GetAllJoinElements(ref reference, ignoredElement);
}
}
#endregion
//以上为最终完善代码
///
/// 获取单线Path
///
/// 起始元素
/// 指定元素上一点
/// 断开约束条件
///
public static List GetPathElements(this Element startElement, Connector startConnector, Predicate breakCondition)
{
/*
* 获取元素以指定Connector开始的Path,单点相连情况,不分叉
*/
return GetPathElements(startElement, startConnector, null, breakCondition);
}
///
/// 获取单线Path
///
/// 起始元素
/// 指定元素上一点
/// 忽略点位
/// 断开约束条件
///
public static List GetPathElements(this Element startElement, Connector startConnector, Predicate ignoredElement, Predicate breakCondition)
{
List useElements = new List() { startElement };
Connector useConnector = startConnector;
while (useConnector != null)
{
var joinElements = GetJoinElements(useConnector);
if (joinElements.Count != 1)
{
break;
}
var nextElement = joinElements[0];
if (ignoredElement != null && ignoredElement(nextElement))
{
break;
}
useElements.Add(nextElement);
//如果原始集合中存在,如环路情况。则收尾元素相等;【理论上是只可能和第一个元素相等】
if (startElement.Id == nextElement.Id)
{
break;
}
if (breakCondition != null && breakCondition(nextElement))
{
break;
}
var connectors = nextElement.GetAllConnectors();
if (connectors.Count != 2)
{
break;
}
var preElement = useConnector.Owner;
useConnector = null;
for (int i = 0; i < connectors.Count; i++)
{
var element = connectors[i].GetJoinConnector()?.Owner;
if (element != null && element.Id != preElement.Id)
{
useConnector = connectors[i];
break;
}
}
}
return useElements;
}
#region 元素之间路由相关
///
/// 获取到指定条件的全部路径
///
///
///
///
public static List GetRouteElements(this Element element, Predicate endPedicate)
{
List temp = new List();
List routed = new List();
routed = element.GetRouteElements(null, endPedicate, routed, ref temp);
return routed;
}
///
/// 获取与指定connector连接的所有分支信息
///
///
///
///
public static List GetRouteElements(this Element element, Connector connectorSpecify, Predicate endPedicate)
{
List temp = new List();
List routed = new List();
routed = element.GetRouteElements(null, endPedicate, routed, ref temp);
return routed;
}
private static List AppendElementPath(List source, List elements)
{
ElementPath elementPath = new ElementPath();
elementPath.AddRange(elements);
if (source == null)
{
source = new List();
}
if (!source.Any(rp => rp.Count == elementPath.Count && rp.IsMatch(elementPath)))
{
source.Add(elementPath);
}
return source;
}
private static List GetRouteElements(this Element element, Connector connectorSpecify, Predicate endPedicate,
List oldElementRoutes, ref List result)
{
#region 描述
/*
* 遍历结束条件:1、指定的条件
* 2、最后端头点
* 3、遍历找回到自身
*
*返回新的路径值
*/
#endregion
var isEnd = result.Contains(element, new ElementEqualityComparer());
result.Add(element);
if (isEnd ||
(result.Count > 1 && endPedicate != null && endPedicate.Invoke(element)))
{
//结束;如果result中只有一个元素,则为开始元素。开始元素满足限定的条件时,不退出遍历
oldElementRoutes = AppendElementPath(oldElementRoutes, result);
}
else
{
//如果没有向下,递归项,则同样判定为路由寻址结束
bool hasNext = false;
Element preElement = null;
if (result.Count > 1)
{
preElement = result[result.Count - 2];//.LastOrDefault();
}
#region 连接点处理
List useConnectors = new List();
if (connectorSpecify != null)
{
useConnectors.Add(connectorSpecify);
}
else
{
useConnectors.AddRange(element.GetAllConnectors());
}
#endregion
foreach (var connector in useConnectors)
{
var elements = GetJoinElements(connector);
foreach (var joinElement in elements)
{
if (joinElement.Id == element.Id || (preElement != null && joinElement.Id == preElement.Id))
continue;
if (!hasNext)
{
hasNext = true;
}
joinElement.GetRouteElements(null, endPedicate, oldElementRoutes, ref result);
result.RemoveRange(result.Count - 1, 1);
}
}
if (!hasNext)
{
oldElementRoutes = AppendElementPath(oldElementRoutes, result);
}
}
return oldElementRoutes;
}
#endregion
}
}