调整代码
This commit is contained in:
366
ShrlAlgoToolkit.RevitAddins/Mep/ArrangeMEPCurveViewModel.cs
Normal file
366
ShrlAlgoToolkit.RevitAddins/Mep/ArrangeMEPCurveViewModel.cs
Normal file
@@ -0,0 +1,366 @@
|
||||
using System.Windows;
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.DB.Electrical;
|
||||
using Autodesk.Revit.DB.Mechanical;
|
||||
using Autodesk.Revit.DB.Plumbing;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Nice3point.Revit.Toolkit.External.Handlers;
|
||||
|
||||
using ShrlAlgoToolkit.RevitAddins.RvMEP;
|
||||
using ShrlAlgoToolkit;
|
||||
using ShrlAlgoToolkit.RevitAddins;
|
||||
|
||||
namespace ShrlAlgoToolkit.RevitAddins.Mep
|
||||
{
|
||||
public partial class ArrangeMEPCurveViewModel : ObservableObject
|
||||
{
|
||||
private readonly ActionEventHandler arrangeHandler = new();
|
||||
|
||||
[ObservableProperty]
|
||||
public partial double Gap { get; set; } = 250;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool MEPCurveCenter { get; set; } = true;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool IsHorizon { get; set; } = true;
|
||||
|
||||
[RelayCommand]
|
||||
private void Arrange()
|
||||
{
|
||||
arrangeHandler.Raise(
|
||||
uiapp =>
|
||||
{
|
||||
var uidoc = uiapp.ActiveUIDocument;
|
||||
var doc = uidoc.Document;
|
||||
doc.Invoke(
|
||||
_ =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var ids = uidoc.Selection
|
||||
.PickElementsByRectangle(
|
||||
new FuncFilter(
|
||||
e => e is MEPCurve &&
|
||||
e is not InsulationLiningBase &&
|
||||
e is not FlexDuct &&
|
||||
e is not FlexPipe &&
|
||||
!(e.GetCurve() as Line).Direction.IsParallelTo(XYZ.BasisZ)),
|
||||
"请选择要整理的管线")
|
||||
.Select(e => e.Id)
|
||||
.ToList();
|
||||
if (ids.Count <= 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var baseId = uidoc.Selection
|
||||
.PickObject(
|
||||
Autodesk.Revit.UI.Selection.ObjectType.Element,
|
||||
new FuncFilter(e => ids.Contains(e.Id)),
|
||||
"请选择基准管线")
|
||||
.ElementId;
|
||||
|
||||
var baseElement = doc.GetElement(baseId);
|
||||
var baseLine = baseElement.GetCurve() as Line;
|
||||
baseLine.MakeUnbound();
|
||||
if (IsHorizon)
|
||||
{
|
||||
//移除基准
|
||||
ids.Remove(baseId);
|
||||
|
||||
List<Mep.ArrangeElement> arranges = [];
|
||||
foreach (var id in ids)
|
||||
{
|
||||
var elem = doc.GetElement(id);
|
||||
var l = elem.GetCurve() as Line;
|
||||
if (!l.Direction.IsParallelTo(baseLine.Direction))
|
||||
{
|
||||
MessageBox.Show("所选管线不平行", "错误");
|
||||
return;
|
||||
}
|
||||
var d = baseLine.Distance(l.Origin);
|
||||
var project = baseLine.Project(l.Origin).XYZPoint;
|
||||
|
||||
var vector = l.Origin.Flatten() - project.Flatten();
|
||||
var ae = new Mep.ArrangeElement
|
||||
{
|
||||
ElementToMove = elem,
|
||||
//用来确定与基准管线的位置和方向
|
||||
HorizonDistanceVector = vector
|
||||
};
|
||||
arranges.Add(ae);
|
||||
}
|
||||
var groups = arranges.OrderBy(ar => ar.HorizonDistanceVector.GetLength())
|
||||
.GroupBy(
|
||||
ar => XYZ.BasisZ
|
||||
.CrossProduct(baseLine.Direction)
|
||||
.IsAlmostEqualTo(ar.HorizonDistanceVector.Normalize()));
|
||||
if (groups.Count() > 2)
|
||||
{
|
||||
MessageBox.Show("管线定位线存在误差");
|
||||
return;
|
||||
}
|
||||
//管中心距离
|
||||
if (MEPCurveCenter)
|
||||
{
|
||||
foreach (var group in groups)
|
||||
{
|
||||
for (var i = 0; i < group.Count(); i++)
|
||||
{
|
||||
var arrange = group.ElementAt(i);
|
||||
//当前的距离
|
||||
var dis = arrange.HorizonDistanceVector.GetLength();
|
||||
var moveUnitDir = arrange.HorizonDistanceVector.Normalize();
|
||||
//最终的距离
|
||||
var actualDis = (i + 1) * Gap / 304.8;
|
||||
var translate = moveUnitDir * (actualDis - dis);
|
||||
ElementTransformUtils.MoveElement(
|
||||
doc,
|
||||
arrange.ElementToMove.Id,
|
||||
translate);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//遍历两个方向的分组
|
||||
foreach (var group in groups)
|
||||
{
|
||||
double actualDis = 0;
|
||||
double previousHalfSize = 0;
|
||||
//基准半宽
|
||||
if (baseElement is Pipe pipe)
|
||||
{
|
||||
previousHalfSize = pipe.get_Parameter(BuiltInParameter.RBS_PIPE_OUTER_DIAMETER).AsDouble() / 2;
|
||||
}
|
||||
else if (baseElement is Conduit conduit)
|
||||
{
|
||||
previousHalfSize = conduit.get_Parameter(BuiltInParameter.RBS_CONDUIT_OUTER_DIAM_PARAM).AsDouble() / 2;
|
||||
}
|
||||
else if (baseElement is CableTray tray || baseElement is Duct duct)
|
||||
{
|
||||
var baseConnector = baseElement.GetConnectors()
|
||||
.OfType<Connector>()
|
||||
.FirstOrDefault();
|
||||
if (baseConnector.Shape == ConnectorProfileType.Oval || baseConnector.Shape == ConnectorProfileType.Rectangular)
|
||||
{
|
||||
previousHalfSize = baseConnector.Width / 2;
|
||||
}
|
||||
else if (baseConnector.Shape == ConnectorProfileType.Round)
|
||||
{
|
||||
previousHalfSize = baseConnector.Radius;
|
||||
}
|
||||
}
|
||||
if (baseElement is Pipe or Duct)
|
||||
{
|
||||
//基准保温层厚度
|
||||
var insulationId = InsulationLiningBase.GetInsulationIds(
|
||||
doc,
|
||||
baseElement.Id).FirstOrDefault();
|
||||
if (insulationId != null)
|
||||
{
|
||||
var insulation = doc.GetElement(insulationId) as InsulationLiningBase;
|
||||
previousHalfSize += insulation.Thickness;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < group.Count(); i++)
|
||||
{
|
||||
var arrange = group.ElementAt(i);
|
||||
//当前的距离
|
||||
var dis = arrange.HorizonDistanceVector.GetLength();
|
||||
var moveUnitDir = arrange.HorizonDistanceVector.Normalize();
|
||||
|
||||
double currentHalfSize = 0;
|
||||
if (arrange.ElementToMove is Pipe p)
|
||||
{
|
||||
currentHalfSize = p.get_Parameter(BuiltInParameter.RBS_PIPE_OUTER_DIAMETER).AsDouble() / 2;
|
||||
}
|
||||
else if (arrange.ElementToMove is Conduit conduit)
|
||||
{
|
||||
currentHalfSize = conduit.get_Parameter(BuiltInParameter.RBS_CONDUIT_OUTER_DIAM_PARAM).AsDouble() / 2;
|
||||
}
|
||||
else if (arrange.ElementToMove is CableTray tray || arrange.ElementToMove is Duct duct)
|
||||
{
|
||||
var conn = arrange.ElementToMove.GetConnectors()
|
||||
.OfType<Connector>()
|
||||
.FirstOrDefault();
|
||||
if (conn.Shape == ConnectorProfileType.Oval || conn.Shape == ConnectorProfileType.Rectangular)
|
||||
{
|
||||
currentHalfSize = conn.Width / 2;
|
||||
}
|
||||
else if (conn.Shape == ConnectorProfileType.Round)
|
||||
{
|
||||
currentHalfSize = conn.Radius;
|
||||
}
|
||||
}
|
||||
//只有管道和风管有保温
|
||||
if (arrange.ElementToMove is Pipe or Duct)
|
||||
{
|
||||
//考虑保温层
|
||||
var currentInsulationId = InsulationLiningBase.GetInsulationIds(
|
||||
doc,
|
||||
arrange.ElementToMove.Id).FirstOrDefault();
|
||||
if (currentInsulationId != null)
|
||||
{
|
||||
var currentInsulation = doc.GetElement(currentInsulationId) as InsulationLiningBase;
|
||||
currentHalfSize += currentInsulation.Thickness;
|
||||
}
|
||||
}
|
||||
//最终的距离叠加,附加上次的距离,使得每次只要增加一个上一个半宽+当前的半宽+间隙
|
||||
actualDis += previousHalfSize + currentHalfSize + Gap / 304.8;
|
||||
var translate = moveUnitDir * (actualDis - dis);
|
||||
ElementTransformUtils.MoveElement(
|
||||
doc,
|
||||
arrange.ElementToMove.Id,
|
||||
translate);
|
||||
//修改上个半宽,用于当前分组里下一个元素循环
|
||||
previousHalfSize = currentHalfSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//垂向
|
||||
else
|
||||
{
|
||||
//通过LocationCurve确定相对位置关系
|
||||
var orderIds = ids.Select(id => doc.GetElement(id) as MEPCurve)
|
||||
.OrderBy(c => (c.GetCurve() as Line).Origin.Z).Select(e => e.Id).ToList();
|
||||
//中心距
|
||||
if (MEPCurveCenter)
|
||||
{
|
||||
var baseIndex = orderIds.IndexOf(baseId);
|
||||
for (var i = 0; i < orderIds.Count; i++)
|
||||
{
|
||||
var currentZ = (doc.GetElement(orderIds[i]).GetCurve() as Line).Origin.Z;
|
||||
var dis = Math.Abs(baseLine.Origin.Z - currentZ);
|
||||
var actualDis = Math.Abs((baseIndex - i)) * Gap / 304.8;
|
||||
//判断方向
|
||||
var vector = i > baseIndex ? XYZ.BasisZ : -XYZ.BasisZ;
|
||||
|
||||
var translate = (actualDis - dis) * vector;
|
||||
|
||||
ElementTransformUtils.MoveElement(doc, orderIds[i], translate);
|
||||
//if (i > baseIndex)
|
||||
//{
|
||||
// var dis = currentZ - baseLine.Origin.Z;//正的
|
||||
// var actualDis = (i - baseIndex) * Gap / 304.8;//正的
|
||||
// var translate = (actualDis - dis) * XYZ.BasisZ;
|
||||
// ElementTransformUtils.MoveElement(doc, orderIds[i], translate);
|
||||
//}
|
||||
}
|
||||
}
|
||||
//外距
|
||||
else
|
||||
{
|
||||
ids.Remove(baseId);
|
||||
var groups = ids.Select(id => doc.GetElement(id) as MEPCurve)
|
||||
.OrderBy(c => (c.GetCurve() as Line).Origin.Z).GroupBy(e => (e.GetCurve() as Line).Origin.Z > baseLine.Origin.Z);
|
||||
var baseTop = baseElement.get_BoundingBox(null).Max.Z;
|
||||
var baseBottom = baseElement.get_BoundingBox(null).Min.Z;
|
||||
if (baseElement is Pipe or Duct)
|
||||
{
|
||||
//基准保温层厚度
|
||||
var insulationId = InsulationLiningBase.GetInsulationIds(
|
||||
doc,
|
||||
baseElement.Id).FirstOrDefault();
|
||||
if (insulationId != null)
|
||||
{
|
||||
var insulation = doc.GetElement(insulationId) as InsulationLiningBase;
|
||||
baseTop = insulation.get_BoundingBox(null).Max.Z;
|
||||
baseBottom = insulation.get_BoundingBox(null).Min.Z;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var group in groups)
|
||||
{
|
||||
if (group.Key)
|
||||
{
|
||||
var sumHeight = 0.0;
|
||||
var vector = XYZ.BasisZ;
|
||||
for (var i = 0; i < group.Count(); i++)
|
||||
{
|
||||
var mep = group.ElementAt(i);
|
||||
var currentTop = mep.get_BoundingBox(null).Max.Z;
|
||||
var currentBottom = mep.get_BoundingBox(null).Min.Z;
|
||||
if (mep is Pipe or Duct)
|
||||
{
|
||||
//基准保温层厚度
|
||||
var insulationId = InsulationLiningBase.GetInsulationIds(
|
||||
doc,
|
||||
mep.Id).FirstOrDefault();
|
||||
if (insulationId != null)
|
||||
{
|
||||
var insulation = doc.GetElement(insulationId) as InsulationLiningBase;
|
||||
currentTop = insulation.get_BoundingBox(null).Max.Z;
|
||||
currentBottom = insulation.get_BoundingBox(null).Min.Z;
|
||||
}
|
||||
}
|
||||
//当前间距
|
||||
var dis = currentBottom - baseTop;
|
||||
var actualDis = (i + 1) * Gap / 304.8 + sumHeight;
|
||||
var translate = (actualDis - dis) * vector;
|
||||
ElementTransformUtils.MoveElement(doc, mep.Id, translate);
|
||||
//整体高度
|
||||
sumHeight += currentTop - currentBottom;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var sumHeight = 0.0;
|
||||
var vector = -XYZ.BasisZ;
|
||||
for (var i = group.Count() - 1; i >= 0; i--)
|
||||
{
|
||||
var mep = group.ElementAt(i);
|
||||
var currentTop = mep.get_BoundingBox(null).Max.Z;
|
||||
var currentBottom = mep.get_BoundingBox(null).Min.Z;
|
||||
if (mep is Pipe or Duct)
|
||||
{
|
||||
//基准保温层厚度
|
||||
var insulationId = InsulationLiningBase.GetInsulationIds(
|
||||
doc,
|
||||
mep.Id).FirstOrDefault();
|
||||
if (insulationId != null)
|
||||
{
|
||||
var insulation = doc.GetElement(insulationId) as InsulationLiningBase;
|
||||
currentTop = insulation.get_BoundingBox(null).Max.Z;
|
||||
currentBottom = insulation.get_BoundingBox(null).Min.Z;
|
||||
}
|
||||
}
|
||||
//当前间距
|
||||
var dis = baseBottom - currentTop;
|
||||
var actualDis = (group.Count() - i) * Gap / 304.8 + sumHeight;
|
||||
var translate = (actualDis - dis) * vector;
|
||||
ElementTransformUtils.MoveElement(doc, mep.Id, translate);
|
||||
//整体高度
|
||||
sumHeight += currentTop - currentBottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
|
||||
{
|
||||
}
|
||||
},
|
||||
"整理管线");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class ArrangeElement
|
||||
{
|
||||
public double ElementHeight => ElementToMove.get_BoundingBox(null).Max.Z - ElementToMove.get_BoundingBox(null).Min.Z;
|
||||
public Element ElementToMove { get; set; }
|
||||
|
||||
public BoundingBoxXYZ Box { get; set; }
|
||||
/// <summary>
|
||||
/// 与基准元素的间距及方向向量
|
||||
/// </summary>
|
||||
public XYZ HorizonDistanceVector { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user