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