前言
这个例子介绍如何让碰撞在一起的管道避免碰撞,即对管道进行调整。
内容
调整前:
调整后:
从结果来看,所有的碰撞都被调整了。作为一个例子,不会去考虑是否合理,仅仅是展示了一下 Revit API 的能力。
在 resolver.Resolve() 中处理调整的逻辑
- 遍历所有的管道
- 检查管道是否和其它管道有交叉
- 如果管道有交叉,创建U行翻弯,拆分原来的管道并与U行翻弯连接
Resolve 遍历所有的管道
public void Resolve(){
List<Autodesk.Revit.DB.Element> pipes = new List<Autodesk.Revit.DB.Element>();
FilteredElementCollector collector = new FilteredElementCollector(m_rvtDoc);
pipes.AddRange(collector.OfClass(typeof(Pipe)).ToElements());
foreach (Element pipe in pipes){
Resolve(pipe as Pipe);
}
}
Resolve(pipe as Pipe) 消除碰撞
- 检查管道是否和其它管道有交叉
- 如果管道有交叉,创建U行翻弯,拆分原来的管道并与U行翻弯连接
查找碰撞的逻辑
关键点在于ReferenceIntersector
,这个逻辑被使用的前提是已经提取了管道的中心线,通过中心线去找到交点:
List<ReferenceWithContext> result = new List<ReferenceWithContext>();
Autodesk.Revit.DB.XYZ startPt = boundLine.GetEndPoint(0);
Autodesk.Revit.DB.XYZ endPt = boundLine.GetEndPoint(1);
Autodesk.Revit.DB.XYZ dir = (endPt - startPt).Normalize();
ReferenceIntersector referenceIntersector = new ReferenceIntersector(m_view3d);
referenceIntersector.TargetType = FindReferenceTarget.Face;
IList<ReferenceWithContext> obstructionsOnUnboundLine = referenceIntersector.Find(startPt, dir);
foreach (ReferenceWithContext gRefWithContext in obstructionsOnUnboundLine){
Reference gRef = gRefWithContext.GetReference();
if (boundLine.Distance(gRef.GlobalPoint) < 1e-9){
if (!InArray(result, gRefWithContext)){
result.Add(gRefWithContext);
}
}
}
result.Sort(CompareReferencesWithContext);
翻弯的逻辑
找到交叉点之后,需要计算需要翻弯的范围,这些确定之后,就是绘制翻弯。有两步工作:
- 绘制U形翻弯
- 将原有管道一分为二
上述核心逻辑:
// 绘制U形翻弯
Pipe pipe1 = Pipe.Create(m_rvtDoc, systemTypeId, pipeType.Id, levelId, start, startOffset);
Pipe pipe2 = Pipe.Create(m_rvtDoc, systemTypeId, pipeType.Id, levelId, startOffset, endOffset);
Pipe pipe3 = Pipe.Create(m_rvtDoc, systemTypeId, pipeType.Id, levelId, endOffset, end);
Connector conn1 = FindConnector(pipe1, startOffset);
Connector conn2 = FindConnector(pipe2, startOffset);
m_rvtDoc.Create.NewElbowFitting(conn1, conn2);
Connector conn3 = FindConnector(pipe2, endOffset);
Connector conn4 = FindConnector(pipe3, endOffset);
m_rvtDoc.Create.NewElbowFitting(conn3, conn4);
// 将原有管道一分为二
Pipe tmpPipe = Pipe.Create(m_rvtDoc, systemTypeId, pipe.PipeType.Id, levelId, start, end);
Connector conn1 = FindConnector(sections[i - 1].Pipes[2], start);
Connector conn2 = FindConnector(tmpPipe, start);
FamilyInstance fi = m_rvtDoc.Create.NewElbowFitting(conn1, conn2);
Connector conn3 = FindConnector(sections[i].Pipes[0], end);
Connector conn4 = FindConnector(tmpPipe, end);
FamilyInstance f2 = m_rvtDoc.Create.NewElbowFitting(conn3, conn4);
查找弯头逻辑:
private Connector FindConnector(Pipe pipe, Autodesk.Revit.DB.XYZ conXYZ){
ConnectorSet conns = pipe.ConnectorManager.Connectors;
foreach (Connector conn in conns){
if (conn.Origin.IsAlmostEqualTo(conXYZ)){
return conn;
}
}
return null;
}