2025-04-24 20:56:44 +08:00
|
|
|
|
using Autodesk.Revit.DB;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
using Autodesk.Revit.UI.Selection;
|
|
|
|
|
|
|
|
|
|
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
|
|
|
|
using CommunityToolkit.Mvvm.Input;
|
|
|
|
|
|
|
|
|
|
|
|
using Nice3point.Revit.Toolkit.External.Handlers;
|
|
|
|
|
|
|
2025-04-24 20:56:44 +08:00
|
|
|
|
using ShrlAlgoToolkit.Core.Assists;
|
|
|
|
|
|
|
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
using System.Windows;
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-02-10 20:53:40 +08:00
|
|
|
|
|
2025-04-24 20:56:44 +08:00
|
|
|
|
namespace ShrlAlgoToolkit.RevitAddins.RvMEP;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
public partial class ClashResolveViewModel : ObservableObject
|
|
|
|
|
|
{
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private AdjustDirection adjustDirection;
|
|
|
|
|
|
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private AdjustType adjustType = AdjustType.OneSide;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 正在执行命令
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[ObservableProperty]
|
2025-04-24 20:56:44 +08:00
|
|
|
|
[NotifyCanExecuteChangedFor(nameof(RevitAddins.RvMEP.ClashResolveViewModel.ResolveCommand))]
|
2024-09-22 11:05:41 +08:00
|
|
|
|
private bool canRunning = true;
|
|
|
|
|
|
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private double angle = 90.0;
|
|
|
|
|
|
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private double offset = 800;
|
|
|
|
|
|
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private LocationType locationType = LocationType.Manual;
|
|
|
|
|
|
|
|
|
|
|
|
public ActionEventHandler ActionEventHandler { get; } = new();
|
2024-12-22 10:26:12 +08:00
|
|
|
|
partial void OnLocationTypeChanged(LocationType value)
|
|
|
|
|
|
{
|
|
|
|
|
|
KeyIntPtrHelper.RaiseEscTwice();
|
|
|
|
|
|
}
|
2024-09-22 11:05:41 +08:00
|
|
|
|
[RelayCommand]
|
2024-12-22 10:26:12 +08:00
|
|
|
|
private static void Closing()
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
//关闭窗口退出选择
|
2024-12-22 10:26:12 +08:00
|
|
|
|
KeyIntPtrHelper.RaiseEscTwice();
|
2024-09-22 11:05:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-24 20:56:44 +08:00
|
|
|
|
[RelayCommand(CanExecute = nameof(RevitAddins.RvMEP.ClashResolveViewModel.CanRunning))]
|
2024-09-22 11:05:41 +08:00
|
|
|
|
private void Resolve()
|
|
|
|
|
|
{
|
|
|
|
|
|
CanRunning = false;
|
|
|
|
|
|
|
|
|
|
|
|
ActionEventHandler.Raise(uiapp =>
|
|
|
|
|
|
{
|
|
|
|
|
|
var uidoc = uiapp.ActiveUIDocument;
|
|
|
|
|
|
var doc = uidoc.Document;
|
|
|
|
|
|
MEPCurve mepCurveToBend = default;
|
|
|
|
|
|
XYZ breakPoint1 = default;
|
|
|
|
|
|
XYZ breakPoint2 = default;
|
|
|
|
|
|
doc.Invoke(
|
|
|
|
|
|
ts =>
|
|
|
|
|
|
{
|
2024-10-27 00:19:48 +08:00
|
|
|
|
try
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
2024-10-27 00:19:48 +08:00
|
|
|
|
switch (LocationType)
|
|
|
|
|
|
{
|
|
|
|
|
|
case LocationType.Manual:
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
{
|
2024-10-27 00:19:48 +08:00
|
|
|
|
var reference1 = uidoc.Selection.PickObject(
|
|
|
|
|
|
ObjectType.PointOnElement,
|
|
|
|
|
|
new FuncFilter(
|
|
|
|
|
|
e =>
|
|
|
|
|
|
e is MEPCurve mepCurve and not InsulationLiningBase
|
2024-12-22 10:26:12 +08:00
|
|
|
|
&& mepCurve.GetCurve() is Line line
|
2024-10-27 00:19:48 +08:00
|
|
|
|
&& !line.Direction.CrossProduct(XYZ.BasisZ).IsAlmostEqualTo(XYZ.Zero)
|
|
|
|
|
|
),
|
|
|
|
|
|
"请选择翻弯的管线上的点"
|
|
|
|
|
|
);
|
|
|
|
|
|
mepCurveToBend = doc.GetElement(reference1) as MEPCurve;
|
|
|
|
|
|
if (mepCurveToBend.Pinned)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("错误", "请解锁图元");
|
|
|
|
|
|
CanRunning = true;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
var reference2 = uidoc.Selection.PickObject(
|
|
|
|
|
|
ObjectType.PointOnElement,
|
|
|
|
|
|
new FuncFilter(e => e.Id == mepCurveToBend!.Id),
|
|
|
|
|
|
"请选择另一个翻弯管线上的点或确定单侧翻弯的需要偏移一侧"
|
|
|
|
|
|
);
|
|
|
|
|
|
//两个断点,breakPoint1距离原直线起点近,反向时,交换值
|
2024-12-22 10:26:12 +08:00
|
|
|
|
breakPoint1 = mepCurveToBend.GetCurve().Project(reference1.GlobalPoint).XYZPoint;
|
|
|
|
|
|
breakPoint2 = mepCurveToBend.GetCurve().Project(reference2.GlobalPoint).XYZPoint;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
}
|
2024-10-27 00:19:48 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case LocationType.Reference:
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
{
|
2024-10-27 00:19:48 +08:00
|
|
|
|
var reference = uidoc.Selection.PickObject(
|
|
|
|
|
|
ObjectType.Element,
|
|
|
|
|
|
new FuncFilter(
|
|
|
|
|
|
e =>
|
|
|
|
|
|
e is MEPCurve mepCurve and not InsulationLiningBase
|
2024-12-22 10:26:12 +08:00
|
|
|
|
&& mepCurve.GetCurve() is Line line
|
2024-10-27 00:19:48 +08:00
|
|
|
|
&& !line.Direction.CrossProduct(XYZ.BasisZ).IsAlmostEqualTo(XYZ.Zero)
|
|
|
|
|
|
),
|
|
|
|
|
|
"请选择参照的管线"
|
|
|
|
|
|
);
|
|
|
|
|
|
//参考的管线定位
|
|
|
|
|
|
var referenceMEPCurve = doc.GetElement(reference);
|
2024-12-22 10:26:12 +08:00
|
|
|
|
var referenceLine = referenceMEPCurve.GetCurve() as Line;
|
2024-10-27 00:19:48 +08:00
|
|
|
|
|
|
|
|
|
|
var reference1 = uidoc.Selection.PickObject(
|
|
|
|
|
|
ObjectType.PointOnElement,
|
|
|
|
|
|
new FuncFilter(
|
|
|
|
|
|
e =>
|
|
|
|
|
|
e is MEPCurve mepCurve and not InsulationLiningBase
|
2024-12-22 10:26:12 +08:00
|
|
|
|
&& mepCurve.GetCurve() is Line line
|
2024-10-27 00:19:48 +08:00
|
|
|
|
&& !line.Direction.CrossProduct(XYZ.BasisZ).IsAlmostEqualTo(XYZ.Zero)
|
|
|
|
|
|
&& e.Id != referenceMEPCurve!.Id
|
|
|
|
|
|
),
|
|
|
|
|
|
"请选择翻弯的管线或确定单侧翻弯的需要偏移一侧"
|
|
|
|
|
|
);
|
|
|
|
|
|
//翻弯的管线定位
|
|
|
|
|
|
mepCurveToBend = doc.GetElement(reference1) as MEPCurve;
|
2024-12-22 10:26:12 +08:00
|
|
|
|
var bendLine = mepCurveToBend.GetCurve() as Line;
|
2024-10-27 00:19:48 +08:00
|
|
|
|
|
|
|
|
|
|
var result = bendLine!.Intersect(referenceLine, out var array);
|
|
|
|
|
|
|
|
|
|
|
|
XYZ intersectPoint = default;
|
|
|
|
|
|
switch (result)
|
|
|
|
|
|
{
|
|
|
|
|
|
case SetComparisonResult.Overlap:
|
|
|
|
|
|
intersectPoint = array.get_Item(0).XYZPoint;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SetComparisonResult.Disjoint:
|
|
|
|
|
|
{
|
|
|
|
|
|
IList<ClosestPointsPairBetweenTwoCurves> points =
|
|
|
|
|
|
[];
|
|
|
|
|
|
bendLine.ComputeClosestPoints(referenceLine, true, true, false, out points);
|
|
|
|
|
|
var point = points.FirstOrDefault()?.XYZPointOnFirstCurve;
|
|
|
|
|
|
if (bendLine.IsInsideEx(point, 0.2))
|
|
|
|
|
|
{
|
|
|
|
|
|
intersectPoint = point;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
breakPoint1 = intersectPoint - (bendLine.Direction * Offset / 304.8);
|
|
|
|
|
|
breakPoint2 = intersectPoint + (bendLine.Direction * Offset / 304.8);
|
|
|
|
|
|
if (
|
|
|
|
|
|
reference1.GlobalPoint.DistanceTo(breakPoint1)
|
|
|
|
|
|
< reference1.GlobalPoint.DistanceTo(breakPoint2)
|
|
|
|
|
|
) //距离近的是breakpoint2
|
|
|
|
|
|
{
|
|
|
|
|
|
(breakPoint1, breakPoint2) = (breakPoint2, breakPoint1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
|
intersectPoint == default
|
|
|
|
|
|
|| !bendLine.IsInsideEx(breakPoint1, 0.2)
|
|
|
|
|
|
|| !bendLine.IsInsideEx(breakPoint2, 0.2)
|
|
|
|
|
|
)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-09-22 11:05:41 +08:00
|
|
|
|
}
|
2024-10-27 00:19:48 +08:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
|
2024-12-22 10:26:12 +08:00
|
|
|
|
var originBaseLine = mepCurveToBend.GetCurve() as Line;
|
|
|
|
|
|
var baseLine = originBaseLine!.Clone() as Line;
|
|
|
|
|
|
//原管线的方向
|
|
|
|
|
|
var direction = baseLine?.Direction;
|
|
|
|
|
|
var startPoint = baseLine!.GetEndPoint(0);
|
|
|
|
|
|
var endPoint = baseLine.GetEndPoint(1);
|
|
|
|
|
|
var breakLine = Line.CreateBound(breakPoint1, breakPoint2);
|
|
|
|
|
|
//var minLength = mepCurveToBend.GetConnectors().OfType<Connector>().FirstOrDefault().GetExtensionLength();
|
|
|
|
|
|
//if (breakLine.Length < minLength)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// return;
|
|
|
|
|
|
//}
|
|
|
|
|
|
var translateDirection = AdjustDirection switch
|
|
|
|
|
|
{
|
|
|
|
|
|
AdjustDirection.Up => XYZ.BasisZ,
|
|
|
|
|
|
AdjustDirection.Down => -XYZ.BasisZ,
|
|
|
|
|
|
AdjustDirection.Left => XYZ.BasisZ.CrossProduct(breakLine.Direction),
|
|
|
|
|
|
AdjustDirection.Right => -XYZ.BasisZ.CrossProduct(breakLine.Direction),
|
|
|
|
|
|
_ => null
|
|
|
|
|
|
};
|
|
|
|
|
|
switch (AdjustType)
|
|
|
|
|
|
{
|
|
|
|
|
|
case AdjustType.OneSide:
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
{
|
2024-12-22 10:26:12 +08:00
|
|
|
|
MEPCurve baseMepCurve1;
|
|
|
|
|
|
MEPCurve baseMepCurve2;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
2024-12-22 10:26:12 +08:00
|
|
|
|
var newMepCurveId = mepCurveToBend.BreakByPoint(breakPoint1);
|
|
|
|
|
|
var newMepCurve = doc.GetElement(newMepCurveId) as MEPCurve;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
2024-12-22 10:26:12 +08:00
|
|
|
|
//baseMepCurve2始终是打断后生成的新管线,并且是需要偏移的管线
|
|
|
|
|
|
if ((newMepCurve.GetCurve() as Line).IsInsideEx(breakPoint2))
|
|
|
|
|
|
{
|
|
|
|
|
|
baseMepCurve1 = mepCurveToBend;
|
|
|
|
|
|
baseMepCurve2 = newMepCurve;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
baseMepCurve1 = newMepCurve;
|
|
|
|
|
|
baseMepCurve2 = mepCurveToBend;
|
|
|
|
|
|
}
|
|
|
|
|
|
//移动新生成的管线
|
|
|
|
|
|
ElementTransformUtils.MoveElement(
|
|
|
|
|
|
doc,
|
|
|
|
|
|
baseMepCurve2.Id,
|
|
|
|
|
|
translateDirection * Offset / 304.8
|
|
|
|
|
|
);
|
|
|
|
|
|
doc.Regenerate();
|
|
|
|
|
|
////偏移变换
|
|
|
|
|
|
//var translateTransform = Transform.CreateTranslation(translateDirection * Offset / 304.8);
|
|
|
|
|
|
//
|
|
|
|
|
|
//var originOffsetUnboundLine = baseLine.CreateTransformed(translateTransform) as Line;
|
|
|
|
|
|
//需要偏移直线定位线
|
|
|
|
|
|
var originOffsetUnboundLine = baseMepCurve2.GetCurve();
|
|
|
|
|
|
//用于判断交点是否在偏移后的直线内,避免生成不了
|
|
|
|
|
|
var originOffsetLine = originOffsetUnboundLine.Clone() as Line;
|
|
|
|
|
|
originOffsetUnboundLine.MakeUnbound();
|
|
|
|
|
|
|
|
|
|
|
|
var radian = Angle.ToRadian();
|
|
|
|
|
|
//反向时角度取补角
|
|
|
|
|
|
if (breakLine.Direction.IsAlmostEqualTo(-direction))
|
|
|
|
|
|
{
|
|
|
|
|
|
radian = (180 - Angle).ToRadian();
|
|
|
|
|
|
}
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
2024-12-22 10:26:12 +08:00
|
|
|
|
var rotation = Transform.CreateRotationAtPoint(
|
|
|
|
|
|
direction.CrossProduct(translateDirection),
|
|
|
|
|
|
radian,
|
|
|
|
|
|
breakPoint1
|
|
|
|
|
|
);
|
|
|
|
|
|
//因为原来的管线可能被移动,所以用baseline的克隆线
|
|
|
|
|
|
var unboundAngleLine = baseLine.CreateTransformed(rotation) as Line;
|
|
|
|
|
|
unboundAngleLine!.MakeUnbound();
|
|
|
|
|
|
//偏移管线与倾斜管线交点
|
|
|
|
|
|
var offsetIntersectPoint = originOffsetUnboundLine.IntersectionPoint(unboundAngleLine);
|
|
|
|
|
|
var isInside = originOffsetLine.IsInsideEx(offsetIntersectPoint); //当角度线于偏移直线交点在偏移直线内时
|
|
|
|
|
|
//var flag2 = breakPoint1!.DistanceTo(offsetIntersectPoint) > minLength; //偏移间距大于一定一定值
|
|
|
|
|
|
if (!isInside)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("管线偏移角度过大或过小,导致交点不在偏移的管线范围内");
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
//if (!flag2)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// MessageBox.Show("管线偏移距离过近");
|
|
|
|
|
|
// break;
|
|
|
|
|
|
//}
|
|
|
|
|
|
//if (isInside)
|
|
|
|
|
|
else
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
2024-12-22 10:26:12 +08:00
|
|
|
|
var angleLine = Line.CreateBound(breakPoint1, offsetIntersectPoint);
|
|
|
|
|
|
var angleMepCurve = mepCurveToBend.CopyAndSetLocationCurve(angleLine);
|
|
|
|
|
|
|
|
|
|
|
|
//拿到角度管的偏移交点处的连接件
|
|
|
|
|
|
var angleMEPCurveIntersectPointConnector = angleMepCurve
|
|
|
|
|
|
.GetConnectors(true)
|
|
|
|
|
|
.GetNearestConnector(offsetIntersectPoint);
|
|
|
|
|
|
//移动后的管线原有的连接件中,不用连接角度曲线的连接件,用来确定移动后管线的定位线
|
|
|
|
|
|
Connector originOffsetConnector = null;
|
|
|
|
|
|
|
|
|
|
|
|
foreach (Connector conn in baseMepCurve2.GetConnectors(true))
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
2024-12-22 10:26:12 +08:00
|
|
|
|
//90度时,偏移管线的两个连接都是90度,但要选择偏移管原有的,非打断处的连接件
|
|
|
|
|
|
if (
|
|
|
|
|
|
conn.CoordinateSystem.BasisZ.DotProduct(
|
|
|
|
|
|
angleMEPCurveIntersectPointConnector.CoordinateSystem.BasisZ
|
|
|
|
|
|
) >= 0
|
|
|
|
|
|
&& !offsetIntersectPoint.IsAlmostEqualTo(conn.Origin)
|
|
|
|
|
|
) //锐角
|
|
|
|
|
|
{
|
|
|
|
|
|
originOffsetConnector = conn;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
//if (originOffsetConnector != null && offsetIntersectPoint.DistanceTo(originOffsetConnector.Origin) > minLength)
|
|
|
|
|
|
if (originOffsetConnector != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var finalOffsetLine = Line.CreateBound(
|
|
|
|
|
|
offsetIntersectPoint,
|
|
|
|
|
|
originOffsetConnector.Origin
|
|
|
|
|
|
);
|
|
|
|
|
|
baseMepCurve2.SetLocationCurve(finalOffsetLine);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-07-11 09:20:23 +08:00
|
|
|
|
var conn1 = ConnectorExtensions.GetNearestConnectors(
|
2024-12-22 10:26:12 +08:00
|
|
|
|
baseMepCurve1,
|
|
|
|
|
|
angleMepCurve
|
|
|
|
|
|
);
|
|
|
|
|
|
doc.Create.NewElbowFitting(conn1[0], conn1[1]);
|
|
|
|
|
|
|
2025-07-11 09:20:23 +08:00
|
|
|
|
var conn2 = ConnectorExtensions.GetNearestConnectors(
|
2024-12-22 10:26:12 +08:00
|
|
|
|
angleMepCurve,
|
|
|
|
|
|
baseMepCurve2
|
|
|
|
|
|
);
|
|
|
|
|
|
doc.Create.NewElbowFitting(conn2[0], conn2[1]);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.WriteLine(ex.Message);
|
|
|
|
|
|
ex.Message.ToLog();
|
2024-09-22 11:05:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-12-22 10:26:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case AdjustType.TwoSide:
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
2024-12-22 10:26:12 +08:00
|
|
|
|
{
|
|
|
|
|
|
MEPCurve baseMepCurve1;
|
|
|
|
|
|
MEPCurve baseMepCurve2;
|
|
|
|
|
|
//选择点的方向与原直线方向相反时,使得breakPoint1~breakPoint2始终与原直线同向
|
|
|
|
|
|
if (breakLine.Direction.IsAlmostEqualTo(-baseLine.Direction))
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
2024-12-22 10:26:12 +08:00
|
|
|
|
//交换值
|
|
|
|
|
|
(breakPoint1, breakPoint2) = (breakPoint2, breakPoint1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//doc.Regenerate();
|
|
|
|
|
|
//偏移变换
|
|
|
|
|
|
var translateTransform = Transform.CreateTranslation(
|
|
|
|
|
|
translateDirection * Offset / 304.8
|
|
|
|
|
|
);
|
|
|
|
|
|
//偏移直线
|
|
|
|
|
|
var offsetLine = baseLine.CreateTransformed(translateTransform) as Line;
|
|
|
|
|
|
offsetLine!.MakeUnbound();
|
|
|
|
|
|
//根据角度旋转的矩阵变换,创建变换后的直线
|
|
|
|
|
|
//第一个交点
|
|
|
|
|
|
var rotateTransform1 = Transform.CreateRotationAtPoint(
|
|
|
|
|
|
direction.CrossProduct(translateDirection),
|
|
|
|
|
|
Angle.ToRadian(),
|
|
|
|
|
|
breakPoint1
|
|
|
|
|
|
);
|
|
|
|
|
|
var angleLine1 = baseLine.CreateTransformed(rotateTransform1) as Line;
|
|
|
|
|
|
angleLine1!.MakeUnbound();
|
|
|
|
|
|
var offsetPoint1 = offsetLine.IntersectionPoint(angleLine1);
|
|
|
|
|
|
|
|
|
|
|
|
//根据角度旋转的矩阵变换,创建变换后的直线
|
|
|
|
|
|
//第二个交点
|
|
|
|
|
|
var rotateTransform2 = Transform.CreateRotationAtPoint(
|
|
|
|
|
|
direction.CrossProduct(translateDirection),
|
|
|
|
|
|
(180 - Angle).ToRadian(),
|
|
|
|
|
|
breakPoint2
|
|
|
|
|
|
);
|
|
|
|
|
|
var angleLine2 = baseLine.CreateTransformed(rotateTransform2) as Line;
|
|
|
|
|
|
angleLine2!.MakeUnbound();
|
|
|
|
|
|
var offsetPoint2 = offsetLine.IntersectionPoint(angleLine2);
|
|
|
|
|
|
var b = Line.CreateBound(offsetPoint1, offsetPoint2);
|
|
|
|
|
|
if (b.Direction.IsAlmostEqualTo(-baseLine.Direction))
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.WriteLine("翻弯的管线交叉");
|
|
|
|
|
|
MessageBox.Show(
|
|
|
|
|
|
"两点距离太近,无法翻弯",
|
|
|
|
|
|
"提醒",
|
|
|
|
|
|
MessageBoxButton.OK,
|
|
|
|
|
|
MessageBoxImage.Information
|
2024-09-22 11:05:41 +08:00
|
|
|
|
);
|
2024-12-22 10:26:12 +08:00
|
|
|
|
ts.RollBack();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var newMepCurveId = mepCurveToBend.BreakByPoint(breakPoint1);
|
|
|
|
|
|
var newMepCurve = doc.GetElement(newMepCurveId) as MEPCurve;
|
|
|
|
|
|
//判断打断生成的新管线的位置是原管线的前端还是后端
|
|
|
|
|
|
if ((newMepCurve.GetCurve() as Line).IsInsideEx(breakPoint2)) //后端
|
|
|
|
|
|
{
|
|
|
|
|
|
baseMepCurve1 = mepCurveToBend;
|
|
|
|
|
|
baseMepCurve2 = newMepCurve;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
baseMepCurve1 = newMepCurve;
|
|
|
|
|
|
baseMepCurve2 = mepCurveToBend;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-22 10:26:12 +08:00
|
|
|
|
//第一条管线
|
|
|
|
|
|
var newBaseLine1 = Line.CreateBound(startPoint, breakPoint1);
|
|
|
|
|
|
//第二条管线
|
|
|
|
|
|
var newBaseLine2 = Line.CreateBound(breakPoint2, endPoint);
|
|
|
|
|
|
baseMepCurve1.SetLocationCurve(newBaseLine1);
|
|
|
|
|
|
baseMepCurve2.SetLocationCurve(newBaseLine2);
|
|
|
|
|
|
//生成的偏移线方向相反时,会导致两条翻弯的管线交叉
|
|
|
|
|
|
|
|
|
|
|
|
//第一根翻弯管
|
|
|
|
|
|
var firstMepCurve = mepCurveToBend.CopyAndSetLocationCurve(
|
|
|
|
|
|
Line.CreateBound(breakPoint1, offsetPoint1)
|
|
|
|
|
|
);
|
|
|
|
|
|
//偏移管
|
|
|
|
|
|
var secondMepCurve = mepCurveToBend.CopyAndSetLocationCurve(
|
|
|
|
|
|
Line.CreateBound(offsetPoint1, offsetPoint2)
|
|
|
|
|
|
);
|
|
|
|
|
|
//第二根翻弯管
|
|
|
|
|
|
var thirdMepCurve = mepCurveToBend.CopyAndSetLocationCurve(
|
|
|
|
|
|
Line.CreateBound(offsetPoint2, breakPoint2)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
doc.Regenerate();
|
2024-09-22 11:05:41 +08:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2025-07-11 09:20:23 +08:00
|
|
|
|
var connectors1 = ConnectorExtensions.GetNearestConnectors(
|
2024-09-22 11:05:41 +08:00
|
|
|
|
baseMepCurve1,
|
2024-12-22 10:26:12 +08:00
|
|
|
|
firstMepCurve
|
2024-09-22 11:05:41 +08:00
|
|
|
|
);
|
2024-12-22 10:26:12 +08:00
|
|
|
|
doc.Create.NewElbowFitting(connectors1[0], connectors1[1]);
|
2025-07-11 09:20:23 +08:00
|
|
|
|
var connectors4 = ConnectorExtensions.GetNearestConnectors(
|
2024-12-22 10:26:12 +08:00
|
|
|
|
thirdMepCurve,
|
2024-09-22 11:05:41 +08:00
|
|
|
|
baseMepCurve2
|
|
|
|
|
|
);
|
2024-12-22 10:26:12 +08:00
|
|
|
|
doc.Create.NewElbowFitting(connectors4[0], connectors4[1]);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Autodesk.Revit.Exceptions.InvalidOperationException)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("角度过大或过小", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
ex.Message.ToLog();
|
|
|
|
|
|
}
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
2025-07-11 09:20:23 +08:00
|
|
|
|
var connectors2 = ConnectorExtensions.GetNearestConnectors(
|
2024-12-22 10:26:12 +08:00
|
|
|
|
firstMepCurve,
|
|
|
|
|
|
secondMepCurve
|
|
|
|
|
|
);
|
|
|
|
|
|
doc.Create.NewElbowFitting(connectors2[0], connectors2[1]);
|
2025-07-11 09:20:23 +08:00
|
|
|
|
var connectors3 = ConnectorExtensions.GetNearestConnectors(
|
2024-12-22 10:26:12 +08:00
|
|
|
|
secondMepCurve,
|
|
|
|
|
|
thirdMepCurve
|
|
|
|
|
|
);
|
|
|
|
|
|
doc.Create.NewElbowFitting(connectors3[0], connectors3[1]);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Autodesk.Revit.Exceptions.InvalidOperationException)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("角度过大或过小", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
2024-09-22 11:05:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
ex.Message.ToLog();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-12-22 10:26:12 +08:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
|
|
|
|
|
|
{
|
|
|
|
|
|
CanRunning = true;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception)
|
|
|
|
|
|
{
|
|
|
|
|
|
CanRunning = true;
|
|
|
|
|
|
return;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
"碰撞处理"
|
|
|
|
|
|
);
|
|
|
|
|
|
CanRunning = true;
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public enum LocationType
|
|
|
|
|
|
{
|
|
|
|
|
|
Manual,
|
|
|
|
|
|
Reference
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public enum AdjustType
|
|
|
|
|
|
{
|
|
|
|
|
|
TwoSide,
|
|
|
|
|
|
OneSide
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public enum AdjustDirection
|
|
|
|
|
|
{
|
|
|
|
|
|
Up,
|
|
|
|
|
|
Down,
|
|
|
|
|
|
Left,
|
|
|
|
|
|
Right
|
|
|
|
|
|
}
|