链接文件过滤检测

链接文件Iselection过滤器

详细实例

本案例使用链接文件实现链接构件的交互碰撞过滤时设置套管的功能;
由于窗口代码较简单未复制,主体代码思路可参考

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

namespace OpeningFromWall
{
    [Transaction(TransactionMode.Manual)]
    public class Class1 : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            //启动插件
            UIDocument uidoc = commandData.Application.ActiveUIDocument;
            Document doc = uidoc.Document;
            //启动窗口
            MainWindow mainWindow = new MainWindow();
            mainWindow.ShowDialog();
            //【0】载入族文件
            FamilySymbol familySymbol = FindSymbol(doc, "圆形套管族", "圆形套管族");
            if (familySymbol == null)
            {
                try
                {
                    Transaction transaction = new Transaction(doc, "载入族文件"); transaction.Start();
                    string file = @"C:\Ribbon\FamilySymbol\圆形套管族.rfa";
                    doc.LoadFamily(file);
                    familySymbol = FindSymbol(doc, "圆形套管族", "圆形套管族");
                    transaction.Commit();
                }
                catch
                {

                    TaskDialog.Show("提示", "未找到合适的族文件");
                }

            }
            //[1]获取墙
            Reference reference = uidoc.Selection.PickObject(ObjectType.Element, "选择墙");
            Element wallele = doc.GetElement(reference);
            Wall wall = wallele as Wall;
            //[2]选择与墙相交的管道
            List<ElementId> pipeListid = new List<ElementId>();
            Document linkDoc = null;

            //【2】-1在本文件内
            if (mainWindow.Rbtn1.IsChecked==true)
            {
                pipeListid = PipeIntersectElement(doc, wallele).ToList();
            }
            if (mainWindow.Rbtn2.IsChecked==true)
            {
                //【2】-2链接文件内
                #region 链接文件内数据判断
                //过滤链接文件
                FilteredElementCollector fecLinks = new FilteredElementCollector(doc);
                List<Element> lstElem = fecLinks.OfClass(typeof(RevitLinkInstance)).ToElements().ToList();
                //过滤内部构件
                Element elem = lstElem.First();
                RevitLinkInstance rvtLinkIns = elem as RevitLinkInstance;
                //得到链接文件文档
              linkDoc = rvtLinkIns.GetLinkDocument();
                //Transform transform = rvtLinkIns.GetTransform();//本插件默认两个项目坐标系相同
                pipeListid = PipeIntersectElement(linkDoc, wallele).ToList();
                #endregion
            }

            //【3】获取墙的表面
            Face face = GetWallFaces(wall).First();

            XYZ point = null;
            XYZ dir = wall.Orientation.CrossProduct(XYZ.BasisZ);
            //【4】获取管线与墙的交点
            Transaction transaction1 = new Transaction(doc, "放置管道族");
            transaction1.Start();
            foreach (ElementId pipeid in pipeListid)
            {
                Pipe pipe = null;
                if (mainWindow.Rbtn2.IsChecked==true)
                {
                    pipe = linkDoc.GetElement(pipeid) as Pipe;
                }
                else
                { 
                    pipe = doc.GetElement(pipeid) as Pipe; 
                }            
                Curve curve = (pipe.Location as LocationCurve).Curve;
                point = IntersectPointOfFaceAndCurve(face, curve);
                double fswidth = 1000 / 308.4;
                //激活族
                if (!familySymbol.IsActive)
                {
                    familySymbol.Activate();
                }
                FamilyInstance fi = doc.Create.NewFamilyInstance(face, point, dir, familySymbol);
                //设置相关参数
                fi.LookupParameter("实体厚度").Set(wall.Width);
                fi.LookupParameter("外直径").Set(fswidth);
            }
            transaction1.Commit();
            return Result.Succeeded;
        }
        #region GetWallFaces_获取墙面
        /// <summary>
        /// 取得墙侧面
        /// </summary>
        /// <param name="wall"></param>
        /// <returns></returns>
        public List<Face> GetWallFaces(Wall wall)
        {
            List<Face> faces = new List<Face>();
            Options options = new Options();
            //打开computeReferences选项
            options.ComputeReferences = true;
            GeometryElement geoEle = wall.get_Geometry(options);
            foreach (GeometryObject geometryObject in geoEle)
            {
                if (geometryObject == null || (geometryObject as Solid).Faces.Size <= 1)
                    continue;
                foreach (Face face in (geometryObject as Solid).Faces)
                {
                    XYZ normal = (face as PlanarFace).FaceNormal;
                    //比较向量夹角获取墙侧角,wall.orientation为墙的正方向
                    if (normal.AngleTo(wall.Orientation) < 0.01 || normal.AngleTo(-wall.Orientation) < 0.01)
                    {
                        faces.Add(face);
                    }
                }
            }
            return faces;
        }
        #endregion

        #region PipeIntersectElement——获取与墙相交管线的id
        public IList<ElementId> PipeIntersectElement(Document doc, Element e)
        {
            IList<ElementId> eleids = new List<ElementId>();

            //求element的boundingBox,限制范围以提高效率
            BoundingBoxXYZ box = e.get_BoundingBox(doc.ActiveView);
            Outline outline = new Outline(box.Min, box.Max);
            //建立收集器
            FilteredElementCollector collector = new FilteredElementCollector(doc);
            //相交过滤
            ElementIntersectsElementFilter eleFilter = new ElementIntersectsElementFilter(e);
            //BoundingBox相交过滤
            BoundingBoxIntersectsFilter bbFilter = new BoundingBoxIntersectsFilter(outline);
            collector.WherePasses(eleFilter).WherePasses(bbFilter);
            //类别过滤
            //由于已通过相交过滤,肯定是实体,因此无需考虑去掉族类型
            collector.OfCategory(BuiltInCategory.OST_PipeCurves);
            //加入集合
            foreach (ElementId id in collector.ToElementIds())
            {
                if (!eleids.Contains(id))
                {
                    eleids.Add(id);
                }
            }
            return eleids;
        }
        #endregion

        #region IntersectPointOfFaceAndCurve:求面与线的交点
        public XYZ IntersectPointOfFaceAndCurve(Face face, Curve curve)
        {
            //交点数组
            IntersectionResultArray result = new IntersectionResultArray();
            //枚举,用于判断相交类型
            SetComparisonResult setResult = face.Intersect(curve, out result);
            XYZ interResult = null;
            //Disjoint为不相交
            if (SetComparisonResult.Disjoint != setResult)
            {
                //isEmpty判断是否为空
                if (!result.IsEmpty)

                    interResult = result.get_Item(0).XYZPoint;

            }
            return interResult;
        }
        #endregion

        #region FindSymbol_ 名称查找族文件
        public FamilySymbol FindSymbol(Document doc, string familyName, string symbolName)
        {
            //声明变量
            Family family = null;
            FamilySymbol symbol = null;
            //用类型过滤器查找所有族
            FilteredElementCollector familyCol = new FilteredElementCollector(doc);
            familyCol.OfClass(typeof(Family));
            //按组名称查找族
            foreach (Family f in familyCol)
            {
                if (f.Name == familyName)
                {
                    family = f;
                    break;
                }
            }
            //如果没有该族则返回
            if (family == null)
                return null;
            //用family.GetFamilySymbol()取得该族所有类型ID,再遍历
            foreach (ElementId fsid in family.GetFamilySymbolIds())
            {
                FamilySymbol fs = doc.GetElement(fsid) as FamilySymbol;
                if (fs.Name == symbolName)
                {
                    symbol = fs;
                    break;
                }
            }
            return symbol;
        }
        #endregion

    }

}