一、把複雜的東西炸掉吧!

不知道大家有沒有在工地看過鋁模或是鋼構,雖然我沒有實際在現場看過,但我曾經看過這類的組裝圖,我心裡只有一個想法:「這是甚麼超高難度的3D拼圖?」

我非常敬佩能夠把這些架構搭起來的工人們和工程師,除了要付出苦力外,要怎麼看著那些各個角度的2D圖說,想像出實際組起來的樣子呢?這時候爆炸圖就很有用了,它能把複雜的構件結構「拆開來」展示,讓我們更容易理解每個元件之間的關係。

為了更具體地呈現這個概念,我自己也用 Revit API 動手做了一個簡單的爆炸圖。透過這種視覺化的方式,即使是像我這樣沒有實際下過工地的人,也能更直觀地理解整體結構是怎麼搭起來的。其實只是想把建築物炸掉。

偉大的autodesk在forge上已經實現爆炸圖概念

二、怎麼實現

首先我們得紙上談兵一下,把下面的問題都先解開來,再開始寫Revit API。

  1. 要將任意某些物件炸開來,它們各自要往哪些方向移動?
  1. 說到方向,要從哪裡到哪裡呢?
  1. 似乎是從一個點,所有物件往外移動?
  1. 這個點要如何取得呢?

以上問題的答案,其實都圍繞一個答案,那就是所有物件的型心。其實爆炸的核心邏輯便是,以所有型心座標點到自己型心的座標點為方向,每個物件位移一段距離,彼此就會分開,造成類似爆炸般的效果。

接下來就是愉快的實作了。

List<BoundingBoxXYZ> allBoundings = elementsInView.Select(e => e.get_BoundingBox(view3D)).Where(box => box != null).ToList();

// 計算所有元素的型心平均值(作為爆炸原點)
var centers = allBoundings.Select(box => (box.Min + box.Max) / 2);

XYZ explodeOrigin = new XYZ(
     centers.Average(c => c.X),
     centers.Average(c => c.Y),
     centers.Average(c => c.Z)
);

得到爆炸原點之後,我們可以利用位移集來移動每個元素。位移集可以讓元素只在目前視圖中移動,而在其他視圖中還是在原位。

 // 建立每個元素的位移集
foreach (Element e in elementsInView)
{
	BoundingBoxXYZ bbox = e.get_BoundingBox(view3D);
  XYZ center = (bbox.Min + bbox.Max) / 2;
  XYZ direction = center - explodeOrigin;

  XYZ offset = new XYZ(
    (direction.X / MaxX) * xExplodeFactor,
    (direction.Y / MaxY) * yExplodeFactor,
    (direction.Z / MaxZ) * zExplodeFactor
  );
                        
	DisplacementElement.Create(doc, new List<ElementId> { e.Id }, offset, view3D, null);
}

每個方向的爆炸比例其實是不同的!為甚麼呢?這題是回家作業

現在讓我們來看看實作結果吧!

參考資料:

  1. https://www.ifbim.com/2053.html
  1. https://aps.autodesk.com/blog/view-each-floor-using-vertical-explode