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源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索