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 } }