前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Revit二次开发之异形柱翻模(读取CAD图纸一键翻模异形柱)Revit API创建族载入族

Revit二次开发之异形柱翻模(读取CAD图纸一键翻模异形柱)Revit API创建族载入族

作者头像
一席青衣卧龙城
发布2022-04-21 12:47:46
1.8K0
发布2022-04-21 12:47:46
举报
文章被收录于专栏:Revit二次开发Revit二次开发

应一位粉丝的要求,让我写一篇异形柱翻模的文章,今天来写一下,捋一捋思路和方法,当我们拿到CAD图纸,上边有很多异形柱或者约束边缘构件,手动翻模很费劲的,确实需要API来解决。目前有很多插件都有这个功能,但我在网上搜罗了一圈就一篇这类型的文章(我是歌手写的),源代码量还很少,我就顺手写了一篇,但功能不是特别完备,还需要完善一下,看一下成果:

五边形的图纸是我自己用CAD画的,使用链接到revit中,点击拾取图层自动根据图层线绘制一个异形柱的族,并加载到项目里,下面看一下全过程:

1.获取图纸对象:

代码语言:javascript
复制
 Reference reff = uiDoc.Selection.PickObject(ObjectType.PointOnElement, "请选择闭合轮廓");//获取对象
            Element el = doc.GetElement(reff);

2.获取到图纸的图层,并对该图层隐藏(这样在图纸比较乱的情况下容易分辨是否全部选中创建了)最后要不要显示,看你自己,小编这里只隐藏了。

代码语言:javascript
复制
GeometryObject geoObj = el.GetGeometryObjectFromReference(reff);
            GeometryElement geoEl = el.get_Geometry(new Options());
          

            Category ca = null;
            ElementId elid = null;
            if (geoObj.GraphicsStyleId != ElementId.InvalidElementId)
            {
                elid = geoObj.GraphicsStyleId;
                // MessageBox.Show(elid.ToString());
                GraphicsStyle gs = doc.GetElement(geoObj.GraphicsStyleId) as GraphicsStyle;
                if (gs != null)
                {
                    ca = gs.GraphicsStyleCategory;
                    var name = gs.GraphicsStyleCategory.Name;
                    // MessageBox.Show(name);
                }
            }

3.获取该图层的线

这里只是提供了一下PolyLine的获得方法,实际上还是有bug的,小编这里只测试一组图案就把Line一股脑的全放在CurveArray里了,实际上还要去区分,还要自己写算法,小编就先不测试了。

代码语言:javascript
复制
 /// <summary>
        /// 获得图纸的线集合
        /// </summary>
        /// <returns></returns>
        private CurveArrArray GetCurveArrArray(GeometryElement geoEl)
        {
            //获得线
            IList<XYZ> points = null;
            List<Line> lineLists = new List<Line>();
            CurveArray curveAr = new CurveArray();
            CurveArrArray curveArray = new CurveArrArray();
            foreach (var gobj in geoEl)
            {
                GeometryInstance geoInstance = gobj as GeometryInstance;
                Transform transform = geoInstance.Transform;
                if (geoInstance != null)
                {
                    foreach (var insObj in geoInstance.SymbolGeometry)
                    {
                        if (insObj.GetType().ToString() == "Autodesk.Revit.DB.PolyLine")
                        {
                            PolyLine polyLine = insObj as PolyLine;

                            points = polyLine.GetCoordinates();//获取坐标点
                                                               // MessageBox.Show(points.Count.ToString());
                            for (int i = 0; i < points.Count - 1; i++)
                            {
                                Line line = Line.CreateBound(points[i], points[i + 1]);
                                line = TransformLine(transform, line);
                                Line newLine = line;
                                //  MessageBox.Show(points[i].ToString() + "||||||" + points[i + 1].ToString());
                                curveAr.Append(newLine);
                                lineLists.Add(newLine);

                            }

                        }
                    }

                }
            }
            curveArray.Append(curveAr);
            return curveArray;
        }

4.确定要创建的样板

代码语言:javascript
复制
 //确定族样板
            string path = @"C:\ProgramData\Autodesk\RVT 2016\Family Templates\Chinese\公制结构柱.rft";
            if (path == null)
            {
                MessageBox.Show("族样板路径错误");
                return Result.Cancelled;
            }
            Document faDoc = app.NewFamilyDocument(path);

5.打开族样板后添加一个族类型

代码语言:javascript
复制
 FamilyManager manager = faDoc.FamilyManager;
            manager.NewType("异形");

6.添加材质

代码语言:javascript
复制
       //添加材质参数
            FamilyParameter mfp = manager.AddParameter("材质", BuiltInParameterGroup.PG_MATERIALS, ParameterType.Material, false);

7.利用拉伸来创建一个异形柱

代码语言:javascript
复制
 //创建拉伸
            SketchPlane skplane = GetSketchPlane(faDoc);
            Extrusion extrusion = faDoc.FamilyCreate.NewExtrusion(true, curveArrArray, skplane, 4000 / 304.8);
            faDoc.Regenerate();

8.创建约束

代码语言:javascript
复制
 //创建约束
            Reference topFaceRef = null;
            Options opt = new Options();
            opt.ComputeReferences = true;
            opt.DetailLevel = ViewDetailLevel.Fine;
            GeometryElement gelm = extrusion.get_Geometry(opt);
            foreach (GeometryObject gobj in gelm)
            {
                if (gobj is Solid)
                {
                    Solid s = gobj as Solid;
                    foreach (Face face in s.Faces)
                    {
                        if (face.ComputeNormal(new UV()).IsAlmostEqualTo(new XYZ(0, 0, 1)))
                        {
                            topFaceRef = face.Reference;
                        }
                    }
                }
            }
            Autodesk.Revit.DB.View v = GetView(faDoc);
            Reference r = GetTopLevel(faDoc);
            Dimension d = faDoc.FamilyCreate.NewAlignment(v, r, topFaceRef);
            d.IsLocked = true;
            faDoc.Regenerate();

9.关联材质

代码语言:javascript
复制
 //关联材质参数
            Parameter p = extrusion.get_Parameter(BuiltInParameter.MATERIAL_ID_PARAM);
            manager.AssociateElementParameterToFamilyParameter(p, mfp);

10.载入族

代码语言:javascript
复制
 Family fa = faDoc.LoadFamily(doc);
       
            faDoc.Close(false);

11.给族重命名

因为打开族样板,族的名称默认是族1,没办法在族文件里修改,小编没找到方法,所以只能在项目里修改族名称,要是知道的小伙伴请在文章末尾留言哦。

代码语言:javascript
复制
 fa.Name = "异形柱";

12.创建柱

代码语言:javascript
复制
/// <summary>
        /// 生成柱子
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="faSy"></param>
        /// <param name="point"></param>
        private void CreatColu(Document doc,FamilySymbol faSy, XYZ point)
        {
          

        
            FilteredElementCollector filleve = new FilteredElementCollector(doc);
            filleve.OfClass(typeof(Level));
            Level le = null;
            foreach (Level ll in filleve)//找标高
            {
                if (ll.Name.Contains("FL1"))
                {
                    le = ll;
                }

            }
            


            doc.Create.NewFamilyInstance(point, faSy, le, Autodesk.Revit.DB.Structure.StructuralType.Column);


        }

这里有一点非常值得注意,因为Revit 2016不会自动激活没有用到的族类型,因此如果没激活的话会抛出异常The symbol is not active.,解决这个问题的办法是将族类型激活即可。

代码语言:javascript
复制
 if (!fasy.IsActive)
            {
                fasy.Activate();//如果不激活会抛出族类型未激活的错误
            }

整个思路就是这样子的,下面是全部代码内容:

代码语言:javascript
复制
//开始事务
            Transaction ts = new Transaction(doc, "异形柱,约束边缘构件,翻模");






            //获取CAD图纸的数据

            Reference reff = uiDoc.Selection.PickObject(ObjectType.PointOnElement, "请选择闭合轮廓");//获取对象
            Element el = doc.GetElement(reff);
            GeometryObject geoObj = el.GetGeometryObjectFromReference(reff);
            GeometryElement geoEl = el.get_Geometry(new Options());
          

            Category ca = null;
            ElementId elid = null;
            if (geoObj.GraphicsStyleId != ElementId.InvalidElementId)
            {
                elid = geoObj.GraphicsStyleId;
                // MessageBox.Show(elid.ToString());
                GraphicsStyle gs = doc.GetElement(geoObj.GraphicsStyleId) as GraphicsStyle;
                if (gs != null)
                {
                    ca = gs.GraphicsStyleCategory;
                    var name = gs.GraphicsStyleCategory.Name;
                    // MessageBox.Show(name);
                }
            }
            ts.Start();
            //隐藏图层
            if (ca != null)
            {
                doc.ActiveView.SetVisibility(ca, false);
            }
            ts.Commit();

            CurveArrArray curveArrArray = GetCurveArrArray(geoEl);


            //确定族样板
            string path = @"C:\ProgramData\Autodesk\RVT 2016\Family Templates\Chinese\公制结构柱.rft";
            if (path == null)
            {
                MessageBox.Show("族样板路径错误");
                return Result.Cancelled;
            }
            Document faDoc = app.NewFamilyDocument(path);
           
            CreatColum(faDoc, curveArrArray);
            Family fa = faDoc.LoadFamily(doc);
            // MessageBox.Show(fa.Name);
            faDoc.Close(false);

            //给族重命名
            ts.Start();

            fa.Name = "异形柱";
            FamilySymbol fasy = null;
            foreach(ElementId fas in fa.GetFamilySymbolIds())
            {
               // MessageBox.Show(doc.GetElement(fas).Name);
                fasy = doc.GetElement(fas) as FamilySymbol;
            }

            if (!fasy.IsActive)
            {
                fasy.Activate();//如果不激活会抛出族类型未激活的错误
            }
           CreatColu(doc,  fasy, new XYZ(0, 0, 0));

           ts.Commit();



            return Result.Succeeded;

        }
        /// <summary>
        /// 创建族
        /// </summary>
        /// <param name="faDoc"></param>
        /// <param name="curveArrArray"></param>
        private void CreatColum(Document faDoc, CurveArrArray curveArrArray)
        {
            

            Transaction tss = new Transaction(faDoc, "异形柱, 约束边缘构件,翻模");
            tss.Start();
           
            FamilyManager manager = faDoc.FamilyManager;
            manager.NewType("异形");
          
           
            //添加材质参数
            FamilyParameter mfp = manager.AddParameter("材质", BuiltInParameterGroup.PG_MATERIALS, ParameterType.Material, false);
            //创建拉伸
            SketchPlane skplane = GetSketchPlane(faDoc);
            Extrusion extrusion = faDoc.FamilyCreate.NewExtrusion(true, curveArrArray, skplane, 4000 / 304.8);
            faDoc.Regenerate();
            //创建约束
            Reference topFaceRef = null;
            Options opt = new Options();
            opt.ComputeReferences = true;
            opt.DetailLevel = ViewDetailLevel.Fine;
            GeometryElement gelm = extrusion.get_Geometry(opt);
            foreach (GeometryObject gobj in gelm)
            {
                if (gobj is Solid)
                {
                    Solid s = gobj as Solid;
                    foreach (Face face in s.Faces)
                    {
                        if (face.ComputeNormal(new UV()).IsAlmostEqualTo(new XYZ(0, 0, 1)))
                        {
                            topFaceRef = face.Reference;
                        }
                    }
                }
            }
            Autodesk.Revit.DB.View v = GetView(faDoc);
            Reference r = GetTopLevel(faDoc);
            Dimension d = faDoc.FamilyCreate.NewAlignment(v, r, topFaceRef);
            d.IsLocked = true;
            faDoc.Regenerate();
            //关联材质参数
            Parameter p = extrusion.get_Parameter(BuiltInParameter.MATERIAL_ID_PARAM);
            manager.AssociateElementParameterToFamilyParameter(p, mfp);
           // MessageBox.Show(fa.Name);
            tss.Commit();
        }
        /// <summary>
        /// 获得图纸的线集合
        /// </summary>
        /// <returns></returns>
        private CurveArrArray GetCurveArrArray(GeometryElement geoEl)
        {
            //获得线
            IList<XYZ> points = null;
            List<Line> lineLists = new List<Line>();
            CurveArray curveAr = new CurveArray();
            CurveArrArray curveArray = new CurveArrArray();
            foreach (var gobj in geoEl)
            {
                GeometryInstance geoInstance = gobj as GeometryInstance;
                Transform transform = geoInstance.Transform;
                if (geoInstance != null)
                {
                    foreach (var insObj in geoInstance.SymbolGeometry)
                    {
                        if (insObj.GetType().ToString() == "Autodesk.Revit.DB.PolyLine")
                        {
                            PolyLine polyLine = insObj as PolyLine;

                            points = polyLine.GetCoordinates();//获取坐标点
                                                               // MessageBox.Show(points.Count.ToString());
                            for (int i = 0; i < points.Count - 1; i++)
                            {
                                Line line = Line.CreateBound(points[i], points[i + 1]);
                                line = TransformLine(transform, line);
                                Line newLine = line;
                                //  MessageBox.Show(points[i].ToString() + "||||||" + points[i + 1].ToString());
                                curveAr.Append(newLine);
                                lineLists.Add(newLine);

                            }

                        }
                    }

                }
            }
            curveArray.Append(curveAr);
            return curveArray;
        }
        /// <summary>
        /// 翻转指定线
        /// </summary>
        /// <param name="transform">矩阵</param>
        /// <param name="line">被翻转的线</param>
        /// <returns></returns>
        private Line TransformLine(Transform transform, Line line)
        {
            XYZ startPoint = transform.OfPoint(line.GetEndPoint(0));
            XYZ endPoint = transform.OfPoint(line.GetEndPoint(1));
            Line newLine = Line.CreateBound(startPoint, endPoint);
            return newLine;
        }
        /// <summary>
        /// 参照平面
        /// </summary>
        /// <param name="doc"></param>
        /// <returns></returns>
        private SketchPlane GetSketchPlane(Document doc)

        {

            FilteredElementCollector temc = new FilteredElementCollector(doc);

            temc.OfClass(typeof(SketchPlane));

            SketchPlane sketchPlane = temc.First(m => m.Name == "低于参照标高") as SketchPlane;

            return sketchPlane;

        }
        /// <summary>
        /// 获得shitu
        /// </summary>
        /// <param name="doc"></param>
        /// <returns></returns>
        private Autodesk.Revit.DB.View GetView(Document doc)

        {

            FilteredElementCollector viewFilter = new FilteredElementCollector(doc);

            viewFilter.OfClass(typeof(Autodesk.Revit.DB.View));

            Autodesk.Revit.DB.View v = viewFilter.First(m => m.Name == "前") as Autodesk.Revit.DB.View;

            return v;

        }
        /// <summary>
        /// 约束平面
        /// </summary>
        /// <param name="doc"></param>
        /// <returns></returns>
        private Reference GetTopLevel(Document doc)

        {

            FilteredElementCollector temc = new FilteredElementCollector(doc);

            temc.OfClass(typeof(Level));

            Level lvl = temc.First(m => m.Name == "高于参照标高") as Level;

            return new Reference(lvl);

        }
        //
        /// <summary>
        /// 生成柱子
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="faSy"></param>
        /// <param name="point"></param>
        private void CreatColu(Document doc,FamilySymbol faSy, XYZ point)
        {
          

        
            FilteredElementCollector filleve = new FilteredElementCollector(doc);
            filleve.OfClass(typeof(Level));
            Level le = null;
            foreach (Level ll in filleve)//找标高
            {
                if (ll.Name.Contains("FL1"))
                {
                    le = ll;
                }

            }
            


            doc.Create.NewFamilyInstance(point, faSy, le, Autodesk.Revit.DB.Structure.StructuralType.Column);


        }





    }
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-11-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 精讲Revit二次开发 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档