圖1
算法
要實現這個功能須要幾點思路分析:c#
梁分跨打斷的依據是什麼?
微信選擇哪些對象來打斷梁?app
梁打斷的API是什麼?框架
小編曾試用過某某山的插件,他也有柱斷梁工具,但有一點不便之處在於,某某山的插件斷梁是讓你選擇柱,和這個柱相交的梁都會在柱邊打斷。但沒法作到按跨打斷,也沒法修改稱本身想要的效果,其實這是目前插件的弊端所在。模型千奇百怪,每個用戶都有本身的建模習慣,也有本身的想法,一個插件的不能同時知足全部用戶的需求,品類也不夠豐富,須要安裝多款插件才能知足需求,這也是目前不少人加入revit 二次開發的緣由之一。
工具
小編實現的思路以下:
oop
梁應按主樑和次梁進行分跨打斷。不同的結構類型,梁佈置也會不同,因此要區分主次梁,若是隻是框架結構,沒有次梁倒也好辦,若是次梁較多的狀況下,按照主次梁的順序要打斷是最好的結果。
ui選擇須要打斷的梁。選擇對象爲梁能而不是柱能夠更好的防止漏選,柱子的排布有多是不在一條線上,用戶無法一次性框選。spa
Revit2016API沒有提供梁打斷的方法,所以須要改變想法,用複製梁的方法來替換實現(這種方法也可用在管線、橋架等任何線性構件上)。固然在新版本的API中有梁打斷的API了方法叫Split,用新版本的讀者能夠本身試一下。.net
正文開始
本文主要講解主樑的拆分方法,次梁與主樑方法一致
1.利用過濾選擇獲取想要拆分的梁
這個方法在以前的文章裏講過,就很少餘講解了,以下:
2.獲取拆分主樑的依據
這裏的主樑拆分主要是得到柱子,要聲明一點的是不要試圖用Solid的相交的辦法去篩選柱子,這種方法主要存在如下兩個問題:
(1)一旦用戶框選的構建比較多,運行將會很是慢。
(2)結構構件存在相互剪切,被剪切的構件沒法經過Solid相交的方法實現過濾。
所以小編在此經過BoundingBox來過濾出與梁相交的柱子,方法以下:
3.得到柱子的四條邊
得到柱子的四條邊是爲了取得柱子和梁的交點,有些梁是斜梁,柱子有偏愛不是在柱子正中間的,所以須要計算梁和柱子的交點。
4.獲取梁和四條邊線的最小起點
梁線和柱邊線有不相交的線,也有相交的線。要注意這裏容易出錯。
6.複製原來的梁,梁線進行替換
這裏要注意須要刪除原來的梁以及狀況柱子的集合。
按照這個思路基本實現了主樑的拆分,能夠在集合里加入剪力牆來實現更加完整地拆分。在拆分完主樑後別忘了給主樑一個標記,能夠更好地區分主樑次梁,爲下一步次梁拆分打好基礎。
好了接下來上完整代碼:
//開始事務
Transaction ts = new Transaction(doc, "自動斷梁-劃分梁跨");
ts.Start();
//因爲結構構件會互相剪切因此不能直接用solid去相交作實體相交,要麼取消剪切,要麼換包圍框相交過濾。
Selection sel = uiDoc.Selection;
FilteredElementCollector fil = new FilteredElementCollector(doc, doc.ActiveView.Id);
fil.OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_StructuralFraming);
BeamFilter beamFilter = new BeamFilter();
//框選要拆分的梁
IList<Element> ell = sel.PickElementsByRectangle(beamFilter, "選擇要打斷的梁");
IList<Element> colulist = new List<Element>();//裝有交點的柱子
IList<Element> beamlist = new List<Element>();//裝梁
List<XYZ> coluxyzlist = new List<XYZ>();
foreach (FamilyInstance b in ell)
{
FilteredElementCollector collector = new FilteredElementCollector(doc, doc.ActiveView.Id);
collector.OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_StructuralColumns);
BoundingBoxXYZ box = b.get_BoundingBox(doc.ActiveView);
//建立outline,經過boundingboxintersect過濾器
Outline myOutLn = new Outline(box.Min, box.Max);
BoundingBoxIntersectsFilter boxee = new BoundingBoxIntersectsFilter(myOutLn);
//過濾出相交元素
colulist = collector.WherePasses(boxee).ToElements();//柱子
if (colulist.Count > 1)
{
beamlist.Add(b);
b.GetParameters("註釋")[0].Set("KL");
//得到柱子的四根線
foreach (Element el in colulist)
{
List<Line> colulines = new List<Line>();//梁的底面的邊線
double beamZ = (b.Location as LocationCurve).Curve.GetEndPoint(0).Z;//梁的Z值
//獲取幾何對象
Options opt = new Options();
opt.ComputeReferences = true;//對幾何對象計算引用
opt.IncludeNonVisibleObjects = true;//提取隱藏的對象
opt.DetailLevel = ViewDetailLevel.Fine;//幾何對象的詳細程度
GeometryElement gem = el.get_Geometry(opt);
foreach (var gobj in gem)
{
if (gobj is Solid)
{
Solid sd = gobj as Solid;
if (sd.Volume > 0)
{
foreach (Face fa in sd.Faces)//獲取面
{
if ((fa as PlanarFace).FaceNormal.Z == -1)//得到底面
{
foreach (EdgeArray edA in fa.EdgeLoops)//獲取底面的邊
{
foreach (Edge ed in edA)
{
if (ed.AsCurve() is Line)
{
//將邊線的z值替換
Line line = ed.AsCurve() as Line;
double x1 = line.GetEndPoint(0).X;
double y1 = line.GetEndPoint(0).Y;
double x2 = line.GetEndPoint(1).X;
double y2 = line.GetEndPoint(1).Y;
XYZ xyz1 = new XYZ(x1, y1, beamZ);
XYZ xyz2 = new XYZ(x2, y2, beamZ);
Line linenew = Line.CreateBound(xyz1, xyz2);
colulines.Add(linenew);
}
}
}
}
}
}
}
}
XYZ xyzcolu = GetIntersection(((b.Location as LocationCurve).Curve) as Line, colulines);//梁和四條邊線的最小交點
coluxyzlist.Add(xyzcolu);
}
//先獲取梁和柱子的交點,而後把交點進行排序組成新的線。
List<XYZ> listxyzcoluSort = BubbleSort(coluxyzlist, (b.Location as LocationCurve).Curve.GetEndPoint(0));//按梁的起點將柱子按照重大到小的順序排列
// Line beamcoluline = Line.CreateBound((b.Location as LocationCurve).Curve.GetEndPoint(0), listxyzcoluSort[0]);
//(b.Location as LocationCurve).Curve = beamcoluline;
for (int i = 0; i < listxyzcoluSort.Count - 1; i++)
{
FamilyInstance beamcopy = (doc.GetElement(ElementTransformUtils.CopyElement(doc, b.Id, (b.Location as LocationCurve).Curve.GetEndPoint(0)).ElementAt(0))) as FamilyInstance;//複製梁
Line li = Line.CreateBound(listxyzcoluSort[i], listxyzcoluSort[i + 1]);
(beamcopy.Location as LocationCurve).Curve = li;
}
doc.Delete(b.Id);
coluxyzlist.Clear();
}
}
ts.Commit();
return Result.Succeeded;
}
運行效果:
爲了更好展現效果,畫了一根直梁和一根斜梁,使用前爲未拆分的一整根梁,使用後爲按柱跨拆分的梁。
圖1.1 使用前
圖1.2 使用後
圖1.3 三維效果
學會了,別忘了轉發分享給好友哦!
本文分享自微信公衆號 - 精講Revit二次開發(HelloRevit)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。