当前位置:网站首页>Revit secondary development - wall opening

Revit secondary development - wall opening

2022-07-07 22:22:00 Hey, hey, hey, hey, hey

This function should be realized Pipelines and structures ( wall 、 beam 、 floor 、 The ceiling 、 roof ) Hole at intersection , And connect the pipeline with the hole .

The first is to open a hole , Take the wall as an example

General train of thought :1、 Get the horizontal plane of the wall

                  2、 Get the two points where the pipeline intersects with the wall , And calculate the midpoint

                  3、 Create an opening family at the midpoint and perform a cut

private void OpeningHole(Element wall,Curve line)
{
    // Get the face of the wall 
    List<Face> lstFace = Get_ElementFace(wall);
    // Get the intersection of the pipeline and the wall 
    List<XYZ> lstIntersection = Get_Intersection(line, lstFace);
    // Calculate the center point 
    XYZ ptIntersection = (lstIntersection[0] + lstIntersection[1]) / 2
    Transaction trans = new Transaction(doc, "opening");
    trans.Start();
    try
    {
        // Create an opening 
        FamilyInstance instance = doc.Create.NewFamilyInstance(ptIntersection, fs, StructuralType.NonStructural);
        // Perform the cut 
        InstanceVoidCutUtils.AddInstanceVoidCut(doc, wall, instance);
        trans.Commit();
    }
    catch
    {
        trans.RollBack();
    }
}
        /// <summary>
        ///  Find the face of the host 
        /// </summary>
        public static List<Face> Get_ElementFace(Element element)
        {
            Options opt = new Options();
            opt.ComputeReferences = true;
            opt.DetailLevel = ViewDetailLevel.Fine;
            GeometryElement geometryElement = element.get_Geometry(opt);
            Face normalFace = null;
            List<Face> lstFace = new List<Face>();
            foreach (var go in geometryElement)
            {
                if(go is Solid)
                {
                    Solid solid = go as Solid;
                    if (solid != null && solid.Faces.Size > 0)
                    {
                        foreach (Face face in solid.Faces)
                        {
                            PlanarFace planarFace = face as PlanarFace;
                            if (planarFace != null)
                            {
                                lstFace.Add(face);
                            }
                        }
                    }
                }
                else if(go is GeometryInstance)
                {
                    GeometryInstance gins = goas GeometryInstance;
                    if (gins != null)
                    {
                        GeometryElement ge = gins.GetInstanceGeometry();
                        foreach (GeometryObject go in ge)
                        {
                            Solid solid = go as Solid;
                            if (solid != null && solid.Faces.Size > 0)
                            {
                                foreach (Face face in solid.Faces)
                                {
                                    PlanarFace planarFace = face as PlanarFace;
                                    if (planarFace != null)
                                    {
                                        lstFace.Add(face);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return lstFace;
        }
        /// <summary>
        ///  Get the focus of line and structure surface 
        /// </summary>
        public static List<XYZ> Get_Intersection(Curve pipeLine, List<Face> lstFace)
        {
            List<XYZ> lstIntersection = new List<XYZ>();
            foreach (Face item in lstFace)
            {
                XYZ ptJd = CaculateIntersection(item, pipeLine);
                if (ptJd != null)
                {
                    lstIntersection.Add(ptJd);
                }
            }
            return lstIntersection;
        }
        /// <summary>
        ///  Find the intersection of surface and line 
        /// </summary>
        public XYZ CaculateIntersection(Face face, Curve curve)
        {
            XYZ intersection = null;
            try
            {
                IntersectionResultArray resultArray = new IntersectionResultArray();
                SetComparisonResult setComparisonResult = face.Intersect(curve, out resultArray);
                if (SetComparisonResult.Disjoint != setComparisonResult && resultArray != null)
                {
                    if (!resultArray.IsEmpty)
                    {
                        intersection = resultArray.get_Item(0).XYZPoint;
                    }
                }
            }
            catch (Exception ex)
            { }
            return intersection;
        }

Then there are pipelines and openings / Casing connection ,

General train of thought :1、 Statistics need data ; such as The cave id, wall id wait  

                  2、 Write the data into the pipeline extension attribute while opening the hole

                  3、 utilize “IUpdater” Interface , When the user changes the model, it will trigger , After triggering :

                        ① Get the recorded data , And get examples of openings and walls   ② Calculate the new intersection of pipeline and wall , And set it for the opening ( And the length of the pipeline / wide / radius )

In this way, the function of associating the opening with the pipeline is realized .

//key: The cave id,value: On the wall id
Dictionary<string,string> dicData = new Dictionary<string,string>();

private void OpeningHole(Element wall,Element duct)
{
    // Get the center line of the air duct 
    LocationCurve lc = duct.Location as LocationCurve;
    Curve curve = lc.Curve;
    // Get the face of the wall 
    List<Face> lstFace = Get_ElementFace(wall);
    // Get the intersection of the pipeline and the wall 
    List<XYZ> lstIntersection = Get_Intersection(curve, lstFace);
    // Calculate the center point 
    XYZ ptIntersection = (lstIntersection[0] + lstIntersection[1]) / 2
    Transaction trans = new Transaction(doc, "opening");
    trans.Start();
    try
    {
        // Create an opening 
        FamilyInstance instance = doc.Create.NewFamilyInstance(ptIntersection, fs, StructuralType.NonStructural);
        // Perform the cut 
        InstanceVoidCutUtils.AddInstanceVoidCut(doc, wall, instance);
        dicData.Add(instance.Id,wall.Id);
        // Add data to extended attributes 
        Add_Data(duct,dicData);
        trans.Commit();
    }
    catch
    {
        trans.RollBack();
    }
}

Registration update

public class OpeningApplication : IExternalApplication
    {
        ElementUpdate Updater;
        /// <summary>
        ///  Registration update 
        /// </summary>
        /// <param name="addInId"></param>
        private void Init(AddInId addInId)
        {
            try
            {
                // Set the trigger element type 
                ElementFilter pipe = new ElementCategoryFilter(BuiltInCategory.OST_PipeCurves);
                ElementFilter duct = new ElementCategoryFilter(BuiltInCategory.OST_DuctCurves);
                List<ElementFilter> lstFilters = new List<ElementFilter>();
                lstFilters.Add(pipe);
                lstFilters.Add(duct);
                // Registration update 
                Updater = new ElementUpdate(addInId);
                UpdaterRegistry.RegisterUpdater(Updater);
                LogicalOrFilter filter = new LogicalOrFilter(lstFilters);
                UpdaterRegistry.AddTrigger(Updater.GetUpdaterId(), filter, Element.GetChangeTypeAny());
            }
            catch(Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message);
            }
        }
        public Result OnShutdown(UIControlledApplication application)
        {
            if(Updater != null)
            {
                // Log out of updates 
                UpdaterRegistry.UnregisterUpdater(Updater.GetUpdaterId());
            }
            return Result.Succeeded;
        }

        public Result OnStartup(UIControlledApplication application)
        {
            Init(application.ActiveAddInId); 
            return Result.Succeeded;
        }
    }

Realization IUpdater Interface

public class ElementUpdate : IUpdater
{
    private AddInId addInId = null;
    Guid guid = new Guid("FBFBF6B2-4C06-42d4-97C1-D1B4EB593EFF");
    public ElementUpdate(AddInId addin)
    {
        this.addInId = addin;
    }
    public void Execute(UpdaterData data)
    {
        Document doc = data.GetDocument();
        List<ElementId> lstModefieIds = data.GetModifiedElementIds().ToList();
        // Update elements , Transactions cannot be opened in this interface , Because the changes in the document have not been submitted when this interface is triggered 
        foreach(ElementId eid in lstModefieIds)
        {
            Element duct = doc.GetElement(eid);
            LocationCurve lc = duct.Location as LocationCurve;
            Curve curve = lc.Curve;
            Dictionary<string,string> dicData = Get_ExtendedData(duct);
            foreach(string cid in dicData)
            {
                FamilyInstance cave = doc.GetElement(new ElementId(Convert.ToInt32(cid))) as FamilyInstance;
                Element wall = doc.GetElement(new ElementId(Convert.ToInt32(dicData[cid])));
                // Get the face of the wall 
                List<Face> lstFace = Get_ElementFace(wall);
                // Get the intersection of the pipeline and the wall 
                List<XYZ> lstIntersection = Get_Intersection(curve, lstFace);
                // Calculate the center point 
                XYZ ptIntersection = (lstIntersection[0] + lstIntersection[1]) / 2;
                LocationPoint lp = cave.Location as LocationPoint;
                lp.Point = ptIntersection;
            }
        }
    }

    public string GetAdditionalInformation()
    {
        return "add";
    }
    public ChangePriority GetChangePriority()
    {
        return ChangePriority.FloorsRoofsStructuralWalls;
    }
    public UpdaterId GetUpdaterId()
    {
        return new UpdaterId(addInId, guid);
    }
    public string GetUpdaterName()
    {
        return "update";
    }
}

Methods of operating extended attributes

        /// <summary>
        ///  Get the extended attribute data of the specified element 
        /// </summary>
        public static Dictionary<string, string> Get_ExtendedData(Element elem)
        {
            Dictionary<string, string> dicData = new Dictionary<string, string>();
            IList<Guid> listGuid = elem.GetEntitySchemaGuids();
            if (listGuid.Count == 0)
                return dicData;
            Schema sa = Schema.Lookup(listGuid[0]);
            Entity entity = elem.GetEntity(sa);
            IDictionary<string, string> dicMap = entity.Get<IDictionary<string, string>>(sa.GetField(" Fitting collection "));
            for (int i = 0; i < dicMap.Count; i++)
            {
                dicData.Add(dicMap.Keys.ElementAt(i), dicMap.Values.ElementAt(i));
            }
            return dicData;
        }
        
        /// <summary>
        ///  Overwrite the original extended attribute 
        /// </summary>
        private static void Cover_Data(Element elem, string guid, string name, IDictionary<string, string> data)
        {
            if (GbvSchema == null)
            {
                // Set up Schema Data structure framework 
                SchemaBuilder schemaBuilder = new SchemaBuilder(new Guid(guid));
                // Set the readability and Writeability of this structural framework 
                schemaBuilder.SetReadAccessLevel(AccessLevel.Public);
                schemaBuilder.SetWriteAccessLevel(AccessLevel.Public);
                // Set the general name of this framework 
                schemaBuilder.SetSchemaName(name);
                // Set the type of this framework and the name of the data 
                schemaBuilder.AddMapField(name, typeof(string), typeof(string));
                // Add the data structure framework to Schema in 
                GbvSchema = schemaBuilder.Finish();
            }
            // Create a new data object 
            Entity entity = new Entity(GbvSchema);
            // obtain Revit Data object with corresponding name in 
            Field field = GbvSchema.GetField(name);
            // Then give the data object entity assignment 
            entity.Set(field, data);
            // Finally, add data to the wall 
            elem.SetEntity(entity);
        }
        /// <summary>
        ///  Add extended properties 
        /// </summary>
        public static void Add_Data(Element elem, IDictionary<string, string> data)
        {
            Dictionary<string, string> tempData = Get_ExtendedData(elem);
            if (tempData.Count > 0)
            {
                foreach (string item in tempData.Keys)
                {
                    if (data.Keys.Contains(item))
                        continue;
                    data.Add(item, tempData[item]);
                }
            }
            if (data.Count > 0)
            {
                Cover_Data(elem, "f0c28996-670d-438f-a2be-b81b14aeb8dd", " Fitting collection ", data);
            }
        }

That's about it , The code is reduced and simplified , I haven't run   Just for reference .

Leave a message if you have any questions .

原网站

版权声明
本文为[Hey, hey, hey, hey, hey]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202130606207272.html