Revit SDK 介绍:AvoidObstruction 避免碰撞

前言

这个例子介绍如何让碰撞在一起的管道避免碰撞,即对管道进行调整。

内容

Revit SDK 介绍:AvoidObstruction 避免碰撞_第1张图片

调整前:
Revit SDK 介绍:AvoidObstruction 避免碰撞_第2张图片

调整后:
Revit SDK 介绍:AvoidObstruction 避免碰撞_第3张图片
Revit SDK 介绍:AvoidObstruction 避免碰撞_第4张图片
从结果来看,所有的碰撞都被调整了。作为一个例子,不会去考虑是否合理,仅仅是展示了一下 Revit API 的能力。

在 resolver.Resolve() 中处理调整的逻辑

  1. 遍历所有的管道
  2. 检查管道是否和其它管道有交叉
  3. 如果管道有交叉,创建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) 消除碰撞

  1. 检查管道是否和其它管道有交叉
  2. 如果管道有交叉,创建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);

翻弯的逻辑

找到交叉点之后,需要计算需要翻弯的范围,这些确定之后,就是绘制翻弯。有两步工作:

  1. 绘制U形翻弯
  2. 将原有管道一分为二

上述核心逻辑:

// 绘制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;
}

你可能感兴趣的:(Revit,SDK,介绍,C#)