Revit二次開發案例之拆分梁(按照梁跨進行拆分梁打斷梁)


做爲2020的首篇文章,要給你們分享一篇小案例,關於梁如何拆分及自動遇柱拆分的方法。
這個案例的想法來源於小編平時本身手動翻模,常常是同一截面的梁直接拉通建模(如圖1),既符合設計規範,效率又快。但有些時候着實不便,尤爲在修改覈對的時候,還須要去打斷梁,那麼如何可以自動按結構梁跨自動斷梁,成了問題。

圖1
算法

要實現這個功能須要幾點思路分析:c#

  1. 梁分跨打斷的依據是什麼?
    微信

  2. 選擇哪些對象來打斷梁?app

  3. 梁打斷的API是什麼?框架

小編曾試用過某某山的插件,他也有柱斷梁工具,但有一點不便之處在於,某某山的插件斷梁是讓你選擇柱,和這個柱相交的梁都會在柱邊打斷。但沒法作到按跨打斷,也沒法修改稱本身想要的效果,其實這是目前插件的弊端所在。模型千奇百怪,每個用戶都有本身的建模習慣,也有本身的想法,一個插件的不能同時知足全部用戶的需求,品類也不夠豐富,須要安裝多款插件才能知足需求,這也是目前不少人加入revit 二次開發的緣由之一。
工具

小編實現的思路以下:
oop

  1. 梁應按主樑和次梁進行分跨打斷。不同的結構類型,梁佈置也會不同,因此要區分主次梁,若是隻是框架結構,沒有次梁倒也好辦,若是次梁較多的狀況下,按照主次梁的順序要打斷是最好的結果。
    ui

  2. 選擇須要打斷的梁。選擇對象爲梁能而不是柱能夠更好的防止漏選,柱子的排布有多是不在一條線上,用戶無法一次性框選。spa

  3. Revit2016API沒有提供梁打斷的方法,所以須要改變想法,用複製梁的方法來替換實現(這種方法也可用在管線、橋架等任何線性構件上)。固然在新版本的API中有梁打斷的API了方法叫Split,用新版本的讀者能夠本身試一下。.net


正文開始

本文主要講解主樑的拆分方法,次梁與主樑方法一致

1.利用過濾選擇獲取想要拆分的梁

這個方法在以前的文章裏講過,就很少餘講解了,以下:


2.獲取拆分主樑的依據

這裏的主樑拆分主要是得到柱子,要聲明一點的是不要試圖用Solid的相交的辦法去篩選柱子,這種方法主要存在如下兩個問題:

(1)一旦用戶框選的構建比較多,運行將會很是慢。

(2)結構構件存在相互剪切,被剪切的構件沒法經過Solid相交的方法實現過濾。

所以小編在此經過BoundingBox來過濾出與梁相交的柱子,方法以下:

3.得到柱子的四條邊

得到柱子的四條邊是爲了取得柱子和梁的交點,有些梁是斜梁,柱子有偏愛不是在柱子正中間的,所以須要計算梁和柱子的交點。

4.獲取梁和四條邊線的最小起點

梁線和柱邊線有不相交的線,也有相交的線。要注意這裏容易出錯。

5.將交點按從小到大排序
這裏使用冒泡排序,是最基礎的算法。按從小到大排序能夠能夠很容易的得到一段梁的起點和終點。

6.複製原來的梁,梁線進行替換

這裏要注意須要刪除原來的梁以及狀況柱子的集合。

按照這個思路基本實現了主樑的拆分,能夠在集合里加入剪力牆來實現更加完整地拆分。在拆分完主樑後別忘了給主樑一個標記,能夠更好地區分主樑次梁,爲下一步次梁拆分打好基礎。


看到後臺有小夥伴留言問有沒有好一點的c#基礎書籍推薦,小編在這推薦一本我的以爲比較好的一本書籍,裏面有很詳細的講解,須要的夥伴能夠點擊如下的京東連接購買。趁着別人過年,偷偷努力一下吧。

好了接下來上完整代碼:

 //開始事務

            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源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索