Revit二次开发模型生成包覆层

在实际项目构建中,很多时候需要对一个模型进行包裹,给模型生成一层包裹层,最近做的项目刚好和这个相关,把代码整理了一下提供给大家,大家可以一起看看,共同寻找不足点,以及更好的方法。具体思路如下:

  1. 选择需要包覆的模型
  2. 将模型转换成为几何模型,获取模型的每个面
  3. 循环每个面,根据每个面的BoundingUV,获取创建常规模型包覆族需要的参数
  4. 生成包裹层,Load到项目文件中

有以下几个注意点:
1.创建包覆层需要在族文档环境下,而不是打开的项目文档
2.参数添加要在生成族模型的时候添加,不然是无法完成操作的
3.因为新生成的包覆层是以族的形式加载到项目文件中,所以,在项目文件关闭之前是无法删除的,为了防止包覆层文
件一直存在,所以在包覆层生成的时候,会执行命令,自动删除日期在今天之前生成的包覆层

代码如下:


    		var dir = System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
    	        //选择模型
            Reference eleRef = uiDocument.Selection.PickObject(ObjectType.Element, "请选择需要包覆的实体模型:");
            Element pickEle = document.GetElement(eleRef);
            //创建几何选项
            Options opt = new Options();
            opt.ComputeReferences = true;
            opt.DetailLevel = ViewDetailLevel.Fine;
            //实体转换为几何元件
            GeometryElement geoElem = pickEle.get_Geometry(opt);
            FaceArray solidFaces = new FaceArray();
            foreach (GeometryObject geomObj in geoElem)
            {
                if (geomObj is Solid)
                {
                    Solid solid = geomObj as Solid;
                    if (solid != null && 0 != solid.Faces.Size)
                    {
                        //得到元素面
                        solidFaces = solid.Faces;
                    }
                }
                else if (geomObj is GeometryInstance)
                {
                    GeometryInstance geomInst = geomObj as GeometryInstance;
                    GeometryElement instGeomElem = geomInst.GetInstanceGeometry();
                    foreach (GeometryObject instGeomObj in instGeomElem)
                    {
                        if (instGeomObj is Solid)
                        {
                            Solid solid = instGeomObj as Solid;
                            if (solid != null && 0 != solid.Faces.Size)
                            {
                                //得到元素面
                                solidFaces = solid.Faces;
                            }
                        }
                    }
                }
            }
            //循环每个面,获取到法向量,原点。
            //构造工作平面,
            //根据每个面的所有边,构造常规模型,创建拉伸实体
            int count = 0;
            List<Element> newElems = new List<Element>();
			 //因为生成的包覆层模型会加载到项目文件中,在项目关闭之前无法删除,防止占用太多内存,每次执行命令时。会删除保存路径下生成日期在Today之前的文件
            DirectoryInfo dyInfo = new DirectoryInfo(Path.Combine(dir, @"RDPN"));
            FileInfo[] files = dyInfo.GetFiles();
            foreach (FileInfo file in files)
            {
                if (file.CreationTime < DateTime.Today)
                {
                    file.Delete();
                }
            }
            foreach (Face anyFace in solidFaces)
            {
                BoundingBoxUV bBox = anyFace.GetBoundingBox();
                UV uv = (bBox.Max + bBox.Min) / 2;
                //法向量
                XYZ faceVect = anyFace.ComputeNormal(uv);
                //获取构成面的边
                IList<CurveLoop> faceEdg = anyFace.GetEdgesAsCurveLoops();
                CurveLoop cl = faceEdg[0];
                List<Curve> faceCur = new List<Curve>();
                CurveLoop profileloop = CurveLoop.CreateViaOffset(faceEdg[0], 10 / 304.8, faceVect);
                CurveLoopIterator iteraor = faceEdg[0].GetCurveLoopIterator();
                while (iteraor.MoveNext())
                {
                    Curve cur = iteraor.Current;
                    faceCur.Add(cur);
                }
                //建族模型导入,每个人的导入路径都不一样,具体找一下《公制常规模型.rft》这个文件路径就行
                string runPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                string filePath = Path.Combine(runPath.Substring(0, runPath.LastIndexOf(Path.DirectorySeparatorChar)), @"Revit\Family\公制常规模型.rft");
                //创建族文档
                Autodesk.Revit.DB.Document familyDoc = revit.Application.Application.NewFamilyDocument(filePath);
                //开启事务时,使用的文档,必须是族文档
                Transaction familyTrans = new Transaction(familyDoc, "family");
                familyTrans.Start();
                CurveArrArray curveArrArr = revit.Application.Application.Create.NewCurveArrArray();
                CurveArray curveArr = revit.Application.Application.Create.NewCurveArray();
                XYZ pos = dropLocation(faceCur);
                foreach (Curve cu in faceCur)
                {
                    //将放置位置转换为原点
                    Curve cur = Line.CreateBound(new XYZ(cu.GetEndPoint(0).X - pos.X, cu.GetEndPoint(0).Y - pos.Y, cu.GetEndPoint(0).Z - pos.Z)
                                                                    , new XYZ(cu.GetEndPoint(1).X - pos.X, cu.GetEndPoint(1).Y - pos.Y, cu.GetEndPoint(1).Z - pos.Z)); 
                    curveArr.Append(cur);
                }
                curveArrArr.Append(curveArr);
                //创建平面
                Plane plane = Plane.CreateByNormalAndOrigin(faceVect, new XYZ(0, 0, 0));
                //创建草图平面,文档必须是族文档
                SketchPlane sp = SketchPlane.Create(familyDoc, plane);
                Line li = faceCur[0] as Line;
                //创建拉伸,最后的10/304.8是客户的要求10,可以后期修改
                var newEle = familyDoc.FamilyCreate.NewExtrusion(true, curveArrArr, sp, 10 / 304.8);
                 因为生成的包覆层可能还需要添加参数,所以把所有新生成的包覆层统一进行添加参数
                FamilyManager manager = familyDoc.FamilyManager;
                FamilyParameter param = manager.AddParameter("体积_手动填写", BuiltInParameterGroup.PG_DATA, ParameterType.Text, true);
                familyTrans.Commit();
                //族文件保存
                string settingFile = pickEle.Id.ToString()+"模型包覆层" + count.ToString() + ".rfa";
                string filepath = Path.Combine(dir, @"RDPN\" + settingFile);
                count++;
                familyDoc.SaveAs(filepath);
                Transaction familyTrans1 = new Transaction(document, "family2");
                familyTrans1.Start();
                Family family;
                //新建的族加载到当前项目
                document.LoadFamily(filepath, out family);
                var familySymbolIds = family.GetFamilySymbolIds();
                FamilySymbol fs = document.GetElement(familySymbolIds.First()) as FamilySymbol;
                //族实例可能需要激活,做一个判断
                if (!fs.IsActive)
                {
                    fs.Activate();
                }
                FamilyInstance fi = document.Create.NewFamilyInstance(pos, fs, pickEle, StructuralType.NonStructural);
                newElems.Add(fi);
                familyTrans1.Commit();
            }
            // 因为生成的包覆层可能还需要设置一些参数,所以把所有新生成的包覆层统一进行参数设置
            Transaction tr = new Transaction(document, "setpara");
            tr.Start();
            foreach (Element elem in newElems)
            {
                ParameterSet attributes = elem.Parameters;
                IEnumerator iter = attributes.GetEnumerator();
                iter.Reset();
                while (iter.MoveNext())
                {
                    Parameter attribute = iter.Current as Autodesk.Revit.DB.Parameter;
                    Definition information = attribute.Definition;
                    if (information.Name == "体积_手动填写")
                    {
                        //参数设置,写入参数的形式和系统自带的数据形式一样,保留小数点后三位,并且不做四舍五入处理
                        string volume = elem.get_Parameter(BuiltInParameter.HOST_AREA_COMPUTED).AsValueString();
                        volume = volume.Trim();
                        volume = volume.Substring(0,volume.Length-2);
                        double voi = double.Parse(volume)  * 0.01;
                        voi -= 0.0005;
                        attribute.Set(voi.ToString("N3"));
                    }
                }
            }
            tr.Commit();
        }
        //设置包覆层新建族的位置
        public XYZ dropLocation(List<Curve> curves)
        {
            HashSet<XYZ> allPoints = new HashSet<XYZ>();
            foreach (Curve cu in curves)
            {
                allPoints.Add(cu.GetEndPoint(0));
                allPoints.Add(cu.GetEndPoint(1));
            }
            XYZ dropLocation = allPoints.First();
            foreach (XYZ pt in allPoints)
            {
                if (pt.Y < dropLocation.Y)
                {
                    dropLocation = pt;
                }
                if (pt.Y == dropLocation.Y)
                {
                    dropLocation = pt.X < dropLocation.X ? pt : dropLocation;
                }
            }
            return dropLocation;
        }```

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Gaga.boom

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值