using Autodesk.Revit.DB; using FWindSoft.Data; using FWindSoft.SystemExtensions; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using HorizontalAlign = FWindSoft.Data.HorizontalAlign; namespace FWindSoft.Revit.Utils { public static class ConnectorUtils { /// ///根据点获取Connector /// /// /// /// public static Connector GetConnectorByOrigin(List connectors, XYZ origin) { return connectors.FirstOrDefault(c => c.ConnectorType == ConnectorType.End && c.Origin.IsEqual(origin)); } /// /// 根据方向获取Connector /// /// /// /// public static Connector GetConnectorByDirection(List connectors, XYZ direction) { return connectors.FirstOrDefault(c => c.ConnectorType == ConnectorType.End && c.CoordinateSystem.BasisZ.IsSameDirection(direction)); } /// /// 获取与给定方向,夹角最小的点 /// /// /// /// public static Connector GetConnectorByMinAngle(List connectors, XYZ direction) { return GetConnectorByMinAngle(connectors, direction, double.MinValue); } /// /// 获取与给定方向,夹角最小的点 /// /// /// /// 夹角下限的Cos值,如果direction不是单位向量,该值未direction.length*夹角下限cos值 /// public static Connector GetConnectorByMinAngle(List connectors, XYZ direction, double minAngleCosValue) { Connector useConnector = null; double angle = minAngleCosValue;// double.MinValue; foreach (Connector connector in connectors) { var tempDirection = connector.CoordinateSystem.BasisZ; var tempAngle = direction.DotProduct(tempDirection); //点乘值越大,角度越小 if (tempAngle.More(angle)) { useConnector = connector; angle = tempAngle; } } return useConnector; } /// /// 获取给点附近的Connector /// /// /// /// public static Connector GetNearConnector(List connectors, XYZ position) { Connector resultConnector = null; double minDistance = double.MaxValue; foreach (var connector in connectors) { if (connector.ConnectorType != ConnectorType.End) { //只计算端点 continue; } var tempLength = connector.Origin.DistanceTo(position); if (tempLength < minDistance) { resultConnector = connector; minDistance = tempLength; } } return resultConnector; } /// /// 计算两个风管的矩形对齐方式 /// /// /// /// public static RectangleAlignment CalcAlignment(Connector baseConnector, Connector otherConnector) { #region 确定Connector基准数据 var firstConnector = baseConnector; var secondConnector = otherConnector; //如果两个Connector中出现圆形和非圆形的组合,则让非圆形Connector充当基准点 if (firstConnector.Shape == ConnectorProfileType.Round && secondConnector.Shape != ConnectorProfileType.Round) { firstConnector = otherConnector; secondConnector = baseConnector; } #endregion #region 判断规则 /* 1、Y平行,判断上下对齐方式 2、X平行,判断左右对齐方式 不平行的情况下,取居中设定 Connector中上为-Y,左为-X 如果是圆形管道的话,要自定义上下,左右的方向; 圆形判定:中心点位置相同(连线与延伸方向平行),则为中心对齐。 两个中心在投影到平面内,做一个方向为左右对齐方向; 特殊如果,中心延长线与世界坐标Z轴垂直,则取Z轴为上下对齐方式 */ #endregion if (firstConnector.Shape == ConnectorProfileType.Round && secondConnector.Shape == ConnectorProfileType.Round) { //都是圆形特殊处理,圆形形式上而言只有中心对齐和边对齐 #region 圆形连接件判定 if (firstConnector.CoordinateSystem.BasisZ.IsParallel(secondConnector.CoordinateSystem.BasisZ)) { var secondProject = secondConnector.Origin.GetPlaneProject(firstConnector.CoordinateSystem.BasisZ, firstConnector.Origin); var linkVector = secondProject - firstConnector.Origin; //简化处理 #region 圆形构件对齐处理,中心对齐,或者左中对齐 if (linkVector.IsParallel(secondConnector.CoordinateSystem.BasisZ)) { return RectangleAlignment.CenterMiddle; } else { if (firstConnector.Radius.IsEqual(secondConnector.Radius + linkVector.GetLength())) { return RectangleAlignment.LeftMiddle; } } return RectangleAlignment.CenterMiddle; #endregion } else { //返回边对齐形式,边对齐是左右对齐。 var baseDirection = firstConnector.CoordinateSystem.BasisZ.CrossProduct(secondConnector.CoordinateSystem.BasisZ); var secondProject = secondConnector.Origin.GetLineProject(baseDirection, firstConnector.Origin); var linkVector = secondProject - firstConnector.Origin; if (linkVector.GetLength().IsEqual(0)) { return RectangleAlignment.CenterMiddle; } else if (firstConnector.Radius.IsEqual(secondConnector.Radius + linkVector.GetLength())) { return RectangleAlignment.LeftMiddle; } return RectangleAlignment.CenterMiddle; } #endregion } else { bool useUpDown = false, useLeftRight = false; XYZ upDownDirection = null, leftRightDirection = null; #region 方形连接件判定 if (firstConnector.CoordinateSystem.BasisY.IsParallel(secondConnector.CoordinateSystem.BasisY)) { useUpDown = true; upDownDirection = firstConnector.CoordinateSystem.BasisY.Negate(); } if (firstConnector.CoordinateSystem.BasisX.IsParallel(secondConnector.CoordinateSystem.BasisX)) { useLeftRight = true; leftRightDirection = firstConnector.CoordinateSystem.BasisX.Negate(); } if (!useUpDown && !useLeftRight) { //默认返回正中对齐样式 return RectangleAlignment.CenterMiddle; } #region 判断上下对齐 VerticalAlign verticalAlignment = VerticalAlign.Middle; if (useUpDown) { var baseDirection = upDownDirection.Normalize(); var secondProject = secondConnector.Origin.GetLineProject(baseDirection, firstConnector.Origin); var linkVector = secondProject - firstConnector.Origin; do { var secondDotValue = linkVector.DotProduct(baseDirection); if (secondDotValue.IsEqual(0)) { verticalAlignment = VerticalAlign.Middle; break; } var firstLength = firstConnector.Height / 2; var secondLength = secondConnector.Shape == ConnectorProfileType.Round ? secondConnector.Radius : (secondConnector.Height / 2); if (firstLength.IsEqual(secondLength + secondDotValue)) { verticalAlignment = VerticalAlign.Top; break; } if ((-firstLength).IsEqual(-secondLength + secondDotValue)) { verticalAlignment = VerticalAlign.Bottom; break; } } while (false); } #endregion #region 判断左对齐 HorizontalAlign horizontalAlignment = HorizontalAlign.Center; if (useLeftRight) { var baseDirection = leftRightDirection.Normalize(); var secondProject = secondConnector.Origin.GetLineProject(baseDirection, firstConnector.Origin); var linkVector = secondProject - firstConnector.Origin; do { var secondDotValue = linkVector.DotProduct(baseDirection); if (secondDotValue.IsEqual(0)) { horizontalAlignment = HorizontalAlign.Center; break; } var firstLength = firstConnector.Width / 2; var secondLength = secondConnector.Shape == ConnectorProfileType.Round ? secondConnector.Radius : (secondConnector.Width / 2); if (firstLength.IsEqual(secondLength + secondDotValue)) { horizontalAlignment = HorizontalAlign.Left; break; } if ((-firstLength).IsEqual(-secondLength + secondDotValue)) { horizontalAlignment = HorizontalAlign.Right; break; } } while (false); } #endregion #endregion return (RectangleAlignment)((int)horizontalAlignment | (int)verticalAlignment); } return RectangleAlignment.CenterMiddle; } } }