【Revit二次开发】选择某点创建柱子+选择某元素并计算体积+框选若干元素得到选中墙的数量

写在前面

首先画一张图准备测试(我的是新建的建筑项目,两个标高,重命名为1F和2F,我在1F上创建的如下元素)

【Revit二次开发】选择某点创建柱子+选择某元素并计算体积+框选若干元素得到选中墙的数量_第1张图片

分析编程要求,发现需要用到的知识点

1.Selection中选中某点和框选多个元素  ——    选中某点是PickPoint  框选是PickElementsByRectangle

2.计算元素体积   ——  元素的GeometryObject的solid可以计算体积

编程思路

选择某点创建柱子

运用Selection.PickPoint得到要插入点的坐标

创建一个level和一个FamilySymbol

运用NewFamilyInstance方法创建一个柱子

 

选择某元素并计算体积

运用Selection.PickObject得到选中的元素(类型是Reference)

运用get_Geometry函数得到Element的几何形式GeometryElement

遍历GeometryElement求得Solid的体积和

 

框选若干元素得到选中墙的数量

运行Selection.PickElementsByRectangle得到选中的元素中墙的数量

以上方法的参数需要自己写个class(详见代码)

代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Structure;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;



namespace Sele
{
    [TransactionAttribute(TransactionMode.Manual)]
    [RegenerationAttribute(RegenerationOption.Manual)]
    public class Class1 : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIDocument uidoc = commandData.Application.ActiveUIDocument;
            Document doc = uidoc.Document;
            //选择一个点,在该点创建柱子
            Selection s1 = uidoc.Selection;
            XYZ point = null;
            try
            {
                //获取到鼠标点击的点的坐标
                point = s1.PickPoint("请选择某个点创建柱子!");
            }
            catch
            {
                return Result.Succeeded;
            }
            //由于要在图上画一个柱子,所以要开启一个事务
            Transaction T1 = new Transaction(doc,"T1");
            T1.Start();
            //画柱子之前需要创建柱子的FamilySymbol,还需要创建Level,因为创建柱子需要这两个参数。
            Level le = doc.GetElement(new ElementId(311)) as Level;//查看自己图上的标高的id,我是选择的我的1F的标高id
            FamilyInstance fie = doc.GetElement(new ElementId(329518)) as FamilyInstance;//获取图上已经存在的柱子的id
            FamilySymbol fbol = fie.Symbol;
            if (!fbol.IsActive) {
                fbol.Activate();//判断FamilySymbol的状态是不是Active的,如果不是就让他的状态为Active
            }
            //创建柱子
            FamilyInstance fi = doc.Create.NewFamilyInstance(point, fbol, le,StructuralType.NonStructural);
            T1.Commit();


            //得到选中的某个物体的体积
            Selection s2 = uidoc.Selection;
            Reference re = s2.PickObject(ObjectType.Edge, "请选择一个物体");
            Element ele = doc.GetElement(re);
            //GeometryElement里面存储了所有相关的几何对象,如实体、线等
            GeometryElement gelem = ele.get_Geometry(new Options()); 
            double v = 0.0;
            v = GetSolid(gelem).Sum(m => m.Volume) * 0.3048 * 0.3048 * 0.3048;
            TaskDialog.Show("Hint", "选中的物体体积为:" + v.ToString("f3"));

            //过滤元素"墙"
            IList pickedElements = s2.PickElementsByRectangle(new WallSelectionFilter(), "请框选目标物体");
            double num = pickedElements.Count();
            TaskDialog.Show("Hint", "已选中墙的数量为:" + num);

            return Result.Succeeded;
        }

        private List GetSolid(GeometryElement gelem)
        {
            List solids = new List();
            foreach (GeometryObject obj in gelem)//遍历数组gelem中每一个GeometryObject类型的对象
            {
                if (obj is Solid)//元素是实体
                {
                    solids.Add(obj as Solid);//将该元素转成实体add进list中
                }
                if (obj is GeometryElement)//GeometryElement:元素的几何表示。
                {
                    solids.AddRange(GetSolid(obj as GeometryElement));
                }
                if (obj is GeometryInstance)
                {
                    GeometryInstance gins = obj as GeometryInstance;
                    GeometryElement gelm = gins.GetInstanceGeometry();
                    solids.AddRange(GetSolid(gelem));
                }
            }
            return solids;
        }     
    }

    public class WallSelectionFilter : ISelectionFilter
    {
        public bool AllowElement(Element elem)
        {
            return elem is Wall;
        }

        public bool AllowReference(Autodesk.Revit.DB.Reference reference, Autodesk.Revit.DB.XYZ position)
        {
            return true;
        }
    }
}

实现中遇到的问题及相关知识点疑问解答!!!!

 

问题:选择某元素并计算体积时,明明选中的是一个元素,为什么最后还要遍历他,且方法GetSolid中判断的Solid,GeometryElement,GeometryInstance这些又是什么?

答:

【Revit二次开发】选择某点创建柱子+选择某元素并计算体积+框选若干元素得到选中墙的数量_第2张图片

注意看上面代码的类型变化,首先用Selection.PickObject得到的是Reference,再用GetElement得到Element,再通过get_Geometry方法得到GeometryElement这里就需要多提一句,什么是GeometryElement,是通过Geometry获取的GeometryElement的实例,其中存储了所有相关的几何对象,如实体(Solid)、线等。然后再看GetSolid这个方法中foreach遍历GeometryElement的其中的元素是GeometryObject。这里又需要提一句了,GeometryObject就是上面说的实例,其中存储了实体、线、边、面、还有GeometryElement和GeometryInstance等所以,遍历里面需要判断是不是实体(Solid),是实体的话直接保存在list里面,不是的话调用自己一直向下查找,直到找到Solid然后存放在list中。

 

 

 

你可能感兴趣的:(Revit二次开发)