|
@@ -0,0 +1,399 @@
|
|
|
|
+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 获取直接相连接的元素
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 获取与connector相连接的元素,不包括自身
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="connector"></param>
|
|
|
|
+ /// <param name="allowConnector"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ public static List<Element> GetJoinElements(Connector connector,Predicate<Connector> allowConnector)
|
|
|
|
+ {
|
|
|
|
+ List<Element> joinElements = new List<Element>();
|
|
|
|
+ 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;
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 获取与connector相连接的元素,不包括自身
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="connector"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ public static List<Element> GetJoinElements(Connector connector)
|
|
|
|
+ {
|
|
|
|
+ return GetJoinElements(connector,null);
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 获取关联元素
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="sourceElement"></param>
|
|
|
|
+ /// <param name="allowConnector"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ public static List<Element> GetJoinElements(Element sourceElement, Predicate<Connector> allowConnector)
|
|
|
|
+ {
|
|
|
|
+ IEnumerable<Element> joinElements = new List<Element>();
|
|
|
|
+ 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();
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 获取关联元素
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="sourceElement"></param>
|
|
|
|
+ public static List<Element> GetJoinElements(Element sourceElement)
|
|
|
|
+ {
|
|
|
|
+ return GetJoinElements(sourceElement, null);
|
|
|
|
+ }
|
|
|
|
+ #endregion
|
|
|
|
+ #region 通过连接关系,找到满足条件的元素
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 根据连接关系,获取满足条件的元素
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="inputElement"></param>
|
|
|
|
+ /// <param name="inputConnector"></param>
|
|
|
|
+ /// <param name="allowConnector"></param>
|
|
|
|
+ /// <param name="endPredicate"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ public static List<Element> GetFirstMatchElements(Element inputElement, Connector inputConnector, Predicate<Connector> allowConnector, Predicate<Element> endPredicate)
|
|
|
|
+ {
|
|
|
|
+ var startElement = inputElement;
|
|
|
|
+ ConnectorSearchOptions options = new ConnectorSearchOptions() { AllowConnector = allowConnector, AllowElement = endPredicate };
|
|
|
|
+ List<Element> result = new List<Element>();
|
|
|
|
+ List<Element> reference = new List<Element>();
|
|
|
|
+ reference.Add(startElement);
|
|
|
|
+ for (int i = 0; i < reference.Count; i++)
|
|
|
|
+ {
|
|
|
|
+ var currrentElement = reference[i];
|
|
|
|
+ #region 获取可用连接件
|
|
|
|
+ List<Connector> connectors = currrentElement.GetAllConnectors().ToList();
|
|
|
|
+ if (inputConnector != null && i == 0)
|
|
|
|
+ {
|
|
|
|
+ connectors = new List<Connector> { inputConnector };
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ connectors = currrentElement.GetAllConnectors().ToList();
|
|
|
|
+ }
|
|
|
|
+ #endregion
|
|
|
|
+ foreach (var con in connectors)
|
|
|
|
+ {
|
|
|
|
+ if (!con.Searchable() || !options.ConnectorUsable(con))
|
|
|
|
+ {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ List<Element> 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;
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 根据连接关系,获取满足条件的元素
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="connector"></param>
|
|
|
|
+ /// <param name="allowConnector"></param>
|
|
|
|
+ /// <param name="endPredicate"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ public static List<Element> GetFirstMatchElements(Connector connector, Predicate<Connector> allowConnector, Predicate<Element> endPredicate)
|
|
|
|
+ {
|
|
|
|
+ return GetFirstMatchElements(connector.Owner, connector, allowConnector, endPredicate);
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 根据连接关系,获取满足条件的元素
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="inputElement"></param>
|
|
|
|
+ /// <param name="allowConnector"></param>
|
|
|
|
+ /// <param name="endPredicate"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ public static List<Element> GetFirstMatchElements(Element inputElement, Predicate<Connector> allowConnector, Predicate<Element> endPredicate)
|
|
|
|
+ {
|
|
|
|
+ return GetFirstMatchElements(inputElement,null, allowConnector, endPredicate);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 根据连接关系,获取指定类型的元素
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <typeparam name="T"></typeparam>
|
|
|
|
+ /// <param name="startElement"></param>
|
|
|
|
+ /// <param name="startConnector"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ public static List<T> GetFirstMatchElements<T>(this Element startElement,Connector startConnector = null) where T : Element
|
|
|
|
+ {
|
|
|
|
+ return GetFirstMatchElements(startElement, startConnector, null, e => e is T).OfType<T>().ToList();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ #endregion
|
|
|
|
+
|
|
|
|
+ #region 获取所有连接元素
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 获取与指定元素关联的所有元素
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="element"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ public static List<Element> GetAllJoinElements(this Element element)
|
|
|
|
+ {
|
|
|
|
+ List<Element> elements = new List<Element>();
|
|
|
|
+ element.GetAllJoinElements(ref elements, null);
|
|
|
|
+ return elements;
|
|
|
|
+ }
|
|
|
|
+ public static List<Element> GetAllJoinElements(this Element element, Predicate<Element> ignoredElement)
|
|
|
|
+ {
|
|
|
|
+ List<Element> elements = new List<Element>();
|
|
|
|
+ element.GetAllJoinElements(ref elements, ignoredElement);
|
|
|
|
+ return elements;
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 获取与元素通过connector相连接的元素
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="sourceElement"></param>
|
|
|
|
+ /// <param name="reference"></param>
|
|
|
|
+ /// <param name="ignoredElement"></param>
|
|
|
|
+ private static void GetAllJoinElements(this Element sourceElement, ref List<Element> reference, Predicate<Element> 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
|
|
|
|
+
|
|
|
|
+ //以上为最终完善代码
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 获取单线Path
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="startElement">起始元素</param>
|
|
|
|
+ /// <param name="startConnector">指定元素上一点</param>
|
|
|
|
+ /// <param name="breakCondition">断开约束条件</param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ public static List<Element> GetPathElements(this Element startElement, Connector startConnector, Predicate<Element> breakCondition)
|
|
|
|
+ {
|
|
|
|
+ /*
|
|
|
|
+ * 获取元素以指定Connector开始的Path,单点相连情况,不分叉
|
|
|
|
+ */
|
|
|
|
+ return GetPathElements(startElement, startConnector, null, breakCondition);
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 获取单线Path
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="startElement">起始元素</param>
|
|
|
|
+ /// <param name="startConnector">指定元素上一点</param>
|
|
|
|
+ /// <param name="ignoredElement">忽略点位</param>
|
|
|
|
+ /// <param name="breakCondition">断开约束条件</param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ public static List<Element> GetPathElements(this Element startElement, Connector startConnector, Predicate<Element> ignoredElement, Predicate<Element> breakCondition)
|
|
|
|
+ {
|
|
|
|
+ List<Element> useElements = new List<Element>() { 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 元素之间路由相关
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 获取到指定条件的全部路径
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="element"></param>
|
|
|
|
+ /// <param name="endPedicate"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ public static List<ElementPath> GetRouteElements(this Element element, Predicate<Element> endPedicate)
|
|
|
|
+ {
|
|
|
|
+ List<Element> temp = new List<Element>();
|
|
|
|
+ List<ElementPath> routed = new List<ElementPath>();
|
|
|
|
+ routed = element.GetRouteElements(null, endPedicate, routed, ref temp);
|
|
|
|
+ return routed;
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 获取与指定connector连接的所有分支信息
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="element"></param>
|
|
|
|
+ /// <param name="connectorSpecify"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ public static List<ElementPath> GetRouteElements(this Element element, Connector connectorSpecify, Predicate<Element> endPedicate)
|
|
|
|
+ {
|
|
|
|
+ List<Element> temp = new List<Element>();
|
|
|
|
+ List<ElementPath> routed = new List<ElementPath>();
|
|
|
|
+ routed = element.GetRouteElements(null, endPedicate, routed, ref temp);
|
|
|
|
+ return routed;
|
|
|
|
+ }
|
|
|
|
+ private static List<ElementPath> AppendElementPath(List<ElementPath> source, List<Element> elements)
|
|
|
|
+ {
|
|
|
|
+ ElementPath elementPath = new ElementPath();
|
|
|
|
+ elementPath.AddRange(elements);
|
|
|
|
+ if (source == null)
|
|
|
|
+ {
|
|
|
|
+ source = new List<ElementPath>();
|
|
|
|
+ }
|
|
|
|
+ if (!source.Any(rp => rp.Count == elementPath.Count && rp.IsMatch(elementPath)))
|
|
|
|
+ {
|
|
|
|
+ source.Add(elementPath);
|
|
|
|
+ }
|
|
|
|
+ return source;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private static List<ElementPath> GetRouteElements(this Element element, Connector connectorSpecify, Predicate<Element> endPedicate,
|
|
|
|
+ List<ElementPath> oldElementRoutes, ref List<Element> 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<Connector> useConnectors = new List<Connector>();
|
|
|
|
+ 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
|
|
|
|
+ }
|
|
|
|
+}
|