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